Skip to main content

ci-cd-patterns

CI/CD: GitHub Actions, GitLab CI, Jenkins, caching, blue-green, canary. Triggers: CI, CD, pipeline, GitHub Actions, workflow YAML, release, canary, rollout.

معلومات المصدر

المستودع
softspark/ai-toolkit
آخر نشاط في المصدر
١٢ مايو ٢٠٢٦ في ١٣:٠٢
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١٧٧
التفرعات
٢١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
ci-cd-patterns
description
CI/CD: GitHub Actions, GitLab CI, Jenkins, caching, blue-green, canary. Triggers: CI, CD, pipeline, GitHub Actions, workflow YAML, release, canary, rollout.
effort
medium
user-invocable
false
allowed-tools
Read
# CI/CD Patterns ## GitHub Actions ### Standard Pipeline ```yaml name: CI on: push: branches: [main] pull_request: branches: [main] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: 20 cache: "npm" - run: npm ci - run: npm run lint - run: npm run typecheck test: runs-on: ubuntu-latest needs: lint strategy: matrix: node-version: [18, 20, 22] steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} cache: "npm" - run: npm ci - run: npm test -- --coverage - uses: actions/upload-artifact@v4 with: name: coverage-${{ matrix.node-version }} path: coverage/ build: runs-on: ubuntu-latest needs: test steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: 20 cache: "npm" - run: npm ci - run: npm run build ``` ### Python CI ```yaml name: Python CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v5 with: python-version: "3.12" cache: "pip" - run: pip install -e ".[dev]" - run: ruff check . - run: mypy --strict src/ - run: pytest --cov=src --cov-report=xml ``` ### Docker Build & Push ```yaml build-docker: runs-on: ubuntu-latest needs: test steps: - uses: actions/checkout@v6 - uses: docker/setup-buildx-action@v3 - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/build-push-action@v5 with: context: . push: ${{ github.ref == 'refs/heads/main' }} tags: ghcr.io/${{ github.repository }}:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max ``` ## GitLab CI ```yaml stages: - lint - test - build - deploy lint: stage: lint image: node:20 cache: key: $CI_COMMIT_REF_SLUG paths: [node_modules/] script: - npm ci - npm run lint test: stage: test image: node:20 services: - postgres:16 variables: DATABASE_URL: "postgresql://postgres:postgres@postgres/test" script: - npm ci - npm test build: stage: build image: docker:24 services: - docker:24-dind script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA only: - main ``` ## Docker Multi-stage Builds ### Node.js ```dockerfile # Stage 1: Dependencies FROM node:20-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci --production # Stage 2: Build FROM node:20-alpine AS build WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build # Stage 3: Production FROM node:20-alpine AS production WORKDIR /app ENV NODE_ENV=production COPY --from=deps /app/node_modules ./node_modules COPY --from=build /app/dist ./dist USER node EXPOSE 3000 CMD ["node", "dist/index.js"] ``` ### Python ```dockerfile FROM python:3.12-slim AS builder WORKDIR /app COPY pyproject.toml . RUN pip install --no-cache-dir --target=/deps . FROM python:3.12-slim WORKDIR /app COPY --from=builder /deps /usr/local/lib/python3.12/site-packages COPY src/ ./src/ USER nobody CMD ["python", "-m", "src.main"] ``` ## Caching Strategies ### npm/pnpm ```yaml - uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} restore-keys: ${{ runner.os }}-npm- ``` ### pip ```yaml - uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }} ``` ### Docker Layer Caching ```yaml - uses: docker/build-push-action@v5 with: cache-from: type=gha cache-to: type=gha,mode=max ``` ## Kubernetes Deployment ### Rolling Update ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: api spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 template: spec: containers: - name: api image: ghcr.io/org/api:latest readinessProbe: httpGet: path: /ready port: 3000 initialDelaySeconds: 5 livenessProbe: httpGet: path: /live port: 3000 initialDelaySeconds: 10 ``` ## Secret Management ```yaml # GitHub Actions - use secrets env: DATABASE_URL: ${{ secrets.DATABASE_URL }} API_KEY: ${{ secrets.API_KEY }} # Never hardcode secrets in pipelines # Use OIDC for cloud provider auth (no long-lived credentials) - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789:role/deploy aws-region: us-east-1 ``` ## Release Automation ### Semantic Release ```json { "branches": ["main"], "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator", "@semantic-release/changelog", "@semantic-release/npm", "@semantic-release/github", "@semantic-release/git" ] } ``` ### Conventional Commits for Auto-versioning | Prefix | Version Bump | Example | |--------|-------------|---------| | `fix:` | Patch (0.0.x) | `fix: resolve null pointer in auth` | | `feat:` | Minor (0.x.0) | `feat: add user search endpoint` | | `feat!:` / `BREAKING CHANGE:` | Major (x.0.0) | `feat!: change API response format` | ## Common Rationalizations | Excuse | Why It's Wrong | |--------|----------------| | "CI is green, ship it" | CI tests the happy path — verify edge cases, security, and performance separately | | "Manual deploys give us more control" | Manual deploys give you more human error — automate the repeatable parts | | "We'll set up CI when the project is bigger" | Small projects grow fast — CI debt compounds and retrofitting is painful | | "Caching isn't worth the complexity" | Uncached builds waste developer time daily — caching pays for itself in a week | | "Feature flags are over-engineering" | Feature flags decouple deploy from release — they're the cheapest safety net | ## Anti-Patterns - Secrets in pipeline logs or environment dumps - No caching (slow builds) - Running tests only on main (should run on PRs) - Manual deployments to production - No rollback strategy - Skipping linting/type-checking in CI ## Rules - **MUST** include lint, test, and build stages in every pipeline — deploy-only pipelines defer failure to production - **MUST** cache dependencies by lockfile hash, not by branch name — branch keys grow unbounded and leak cache across unrelated work - **NEVER** commit secrets to the pipeline config — use the platform's secret store and reference by name - **NEVER** echo secrets to job logs; GitHub Actions masks known secrets only if they came from `secrets.*`, not from arbitrary env vars - **CRITICAL**: every deployment path has a defined rollback — "we'll figure it out" is not a plan and will cost hours during an incident - **MANDATORY**: PR builds run the same checks as `main` builds; drift between the two hides failures until merge ## Gotchas - GitHub Actions masks secret values sourced from `${{ secrets.X }}` only. Secrets routed through `env:` and then transformed (base64, JSON) lose the mask and appear in logs verbatim. - Workflows triggered by `pull_request` from forks run **without** repository secrets by default (security). Jobs that need secrets either gate on `github.event.pull_request.head.repo.full_name == github.repository` or use `pull_request_target` with explicit code-review — the latter is easy to get wrong and allow token theft. - `actions/cache` restore is best-effort — a cache miss is silent. Jobs that rely on the cache (e.g., skipping tests when nothing changed) must verify cache hits explicitly via the `cache-hit` output. - GitLab CI's `rules:` and `only:/except:` are mutually exclusive at the job level. Mixing parses only at pipeline run, not at `git push`. - Semantic-release assumes a linear history. Merge commits on `main` confuse the commit parser and produce no release — stick to squash merges if you rely on it. ## When NOT to Load - For **generating** a pipeline file for the current project — use `/ci` (this skill is knowledge, not code) - For one-off deployment commands — use `/deploy` - For language-specific build toolchain nuances — pair with `/typescript-patterns`, `/python` rules, etc. - For observability or alerting around deploys — use `/observability-patterns` - For security scanning (SAST, SCA) steps in pipelines — use `/security-patterns` and `/cve-scan`
عرض على GitHub