Claude-skill-registry ci-cd-pipeline-patterns
Comprehensive CI/CD pipeline patterns skill covering GitHub Actions, workflows, automation, testing, deployment strategies, and release management for modern software delivery
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/ci-cd-pipeline-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-ci-cd-pipeline-patterns && rm -rf "$T"
skills/data/ci-cd-pipeline-patterns/SKILL.mdCI/CD Pipeline Patterns
A comprehensive skill for designing, implementing, and optimizing CI/CD pipelines using GitHub Actions and modern DevOps practices. Master workflow automation, testing strategies, deployment patterns, and release management for continuous software delivery.
When to Use This Skill
Use this skill when:
- Setting up continuous integration and deployment pipelines for projects
- Automating build, test, and deployment workflows
- Implementing multi-environment deployment strategies (staging, production)
- Managing release automation and versioning
- Configuring matrix builds for multi-platform testing
- Securing CI/CD pipelines with secrets and OIDC
- Optimizing pipeline performance with caching and parallelization
- Building containerized applications with Docker in CI
- Deploying to cloud platforms (AWS, Azure, GCP, Vercel, Netlify)
- Implementing infrastructure as code with Terraform/CloudFormation
- Setting up monorepo CI/CD patterns
- Creating reusable workflow templates and custom actions
- Implementing deployment strategies (blue-green, canary, rolling)
- Automating changelog generation and semantic versioning
- Integrating quality gates and code coverage checks
Core Concepts
CI/CD Fundamentals
Continuous Integration (CI): Automatically building and testing code changes as developers commit to the repository.
Continuous Deployment (CD): Automatically deploying code changes to production after passing tests.
Continuous Delivery: Keeping code in a deployable state, with manual approval for production deployment.
GitHub Actions Architecture
GitHub Actions provides event-driven automation directly integrated with your repository.
Workflows
YAML files in
.github/workflows/ that define automated processes:
name: CI Pipeline on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build project run: npm run build
Key Components:
- name: Human-readable workflow name
- on: Events that trigger the workflow (push, pull_request, schedule, workflow_dispatch)
- jobs: Collection of steps that run in sequence or parallel
- runs-on: The runner environment (ubuntu-latest, windows-latest, macos-latest)
Jobs
Groups of steps executed on the same runner:
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm test deploy: needs: test # Runs after 'test' job completes runs-on: ubuntu-latest steps: - run: npm run deploy
Job Features:
- needs: Define job dependencies (sequential execution)
- if: Conditional execution based on expressions
- strategy: Matrix builds for multiple configurations
- outputs: Share data between jobs
- environment: Deployment environments with protection rules
Steps
Individual tasks within a job:
steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Run tests run: npm test
Step Types:
- uses: Run a pre-built action from marketplace or repository
- run: Execute shell commands
- with: Provide inputs to actions
- env: Set environment variables for the step
Actions
Reusable units of code that perform specific tasks:
Official Actions:
: Check out repository codeactions/checkout@v4
: Setup Node.js environmentactions/setup-node@v4
: Cache dependenciesactions/cache@v4
: Upload build artifactsactions/upload-artifact@v4
: Download artifacts from previous jobsactions/download-artifact@v4
Marketplace Actions:
: Build and push Docker imagesdocker/build-push-action@v5
: Configure AWS credentialsaws-actions/configure-aws-credentials@v4
: Upload code coveragecodecov/codecov-action@v4
: Authenticate with Google Cloudgoogle-github-actions/auth@v2
Secrets and Variables
Secrets: Encrypted sensitive data (API keys, credentials, tokens)
steps: - name: Deploy to production env: API_KEY: ${{ secrets.API_KEY }} DATABASE_URL: ${{ secrets.DATABASE_URL }} run: npm run deploy
Variables: Non-sensitive configuration data
env: NODE_ENV: ${{ vars.NODE_ENV }} API_ENDPOINT: ${{ vars.API_ENDPOINT }}
Secret Types:
- Repository secrets: Available to all workflows in a repository
- Environment secrets: Scoped to specific environments (production, staging)
- Organization secrets: Shared across repositories in an organization
Artifacts
Files produced by workflows that can be downloaded or used by other jobs:
- name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: dist-files path: dist/ retention-days: 7 - name: Download artifacts uses: actions/download-artifact@v4 with: name: dist-files path: ./dist
Workflow Triggers
Event Triggers
Push Events:
on: push: branches: - main - develop - 'release/**' paths: - 'src/**' - 'package.json' tags: - 'v*'
Pull Request Events:
on: pull_request: types: [opened, synchronize, reopened] branches: - main paths-ignore: - 'docs/**' - '**.md'
Schedule (Cron):
on: schedule: - cron: '0 0 * * *' # Daily at midnight UTC - cron: '0 */6 * * *' # Every 6 hours
Manual Triggers (workflow_dispatch):
on: workflow_dispatch: inputs: environment: description: 'Environment to deploy to' required: true type: choice options: - staging - production version: description: 'Version to deploy' required: true type: string
Release Events:
on: release: types: [published, created, released]
Workflow Call (Reusable Workflows):
on: workflow_call: inputs: environment: required: true type: string secrets: api-key: required: true
Matrix Builds
Run jobs across multiple configurations in parallel:
jobs: test: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] node-version: [18, 20, 22] include: - os: ubuntu-latest node-version: 20 coverage: true exclude: - os: macos-latest node-version: 18 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm test - if: matrix.coverage run: npm run coverage
Matrix Features:
- Parallel execution: All combinations run simultaneously
- include: Add specific configurations
- exclude: Remove specific combinations
- fail-fast: Stop all jobs if one fails (default: true)
- max-parallel: Limit concurrent jobs
Caching Strategies
Speed up workflows by caching dependencies:
Node.js Caching:
- uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' # Automatically caches npm dependencies
Custom Caching:
- uses: actions/cache@v4 with: path: | ~/.npm ~/.cache node_modules key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-node-
Docker Layer Caching:
- uses: docker/build-push-action@v5 with: context: . cache-from: type=gha cache-to: type=gha,mode=max
Testing Strategies in CI
Unit Testing
Fast, isolated tests for individual components:
jobs: unit-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Install dependencies run: npm ci - name: Run unit tests run: npm run test:unit -- --coverage - name: Upload coverage uses: codecov/codecov-action@v4 with: files: ./coverage/coverage-final.json flags: unit-tests token: ${{ secrets.CODECOV_TOKEN }}
Integration Testing
Test interactions between components and services:
jobs: integration-tests: runs-on: ubuntu-latest services: postgres: image: postgres:16 env: POSTGRES_PASSWORD: postgres options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 redis: image: redis:7 options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 6379:6379 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Run database migrations env: DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb run: npm run migrate - name: Run integration tests env: DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb REDIS_URL: redis://localhost:6379 run: npm run test:integration
End-to-End Testing
Test complete user workflows:
jobs: e2e-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Build application run: npm run build - name: Install Playwright browsers run: npx playwright install --with-deps - name: Run E2E tests run: npm run test:e2e - name: Upload test results if: always() uses: actions/upload-artifact@v4 with: name: playwright-report path: playwright-report/ retention-days: 30
Performance Testing
Benchmark and performance regression testing:
jobs: performance-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Build for production run: npm run build - name: Run Lighthouse CI uses: treosh/lighthouse-ci-action@v11 with: urls: | http://localhost:3000 http://localhost:3000/dashboard uploadArtifacts: true temporaryPublicStorage: true - name: Run load tests run: npm run test:load
Code Quality and Linting
Enforce code standards and quality gates:
jobs: code-quality: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Run ESLint run: npm run lint - name: Run Prettier check run: npm run format:check - name: Run TypeScript check run: npm run type-check - name: Run security audit run: npm audit --audit-level=moderate - name: SonarCloud Scan uses: SonarSource/sonarcloud-github-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Deployment Patterns
Blue-Green Deployment
Zero-downtime deployment by maintaining two identical environments:
jobs: deploy-blue-green: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Deploy to Green environment run: | # Deploy new version to green environment ./deploy.sh green - name: Run smoke tests on Green run: | # Verify green environment is healthy curl -f https://green.example.com/health - name: Switch traffic to Green run: | # Update load balancer to point to green aws elbv2 modify-rule --rule-arn $RULE_ARN \ --actions Type=forward,TargetGroupArn=$GREEN_TG - name: Monitor Green environment run: | # Monitor for 5 minutes ./monitor.sh green 300 - name: Rollback if needed if: failure() run: | # Switch back to blue aws elbv2 modify-rule --rule-arn $RULE_ARN \ --actions Type=forward,TargetGroupArn=$BLUE_TG
Canary Deployment
Gradual rollout to a subset of users:
jobs: canary-deployment: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Deploy canary (10% traffic) run: | kubectl set image deployment/app app=myapp:${{ github.sha }} kubectl scale deployment/app-canary --replicas=1 kubectl annotate service app-service \ traffic-split='{"canary": 10, "stable": 90}' - name: Monitor canary metrics run: | # Monitor error rates, latency for 15 minutes ./monitor-canary.sh 900 - name: Increase canary traffic (50%) run: | kubectl annotate service app-service \ traffic-split='{"canary": 50, "stable": 50}' --overwrite - name: Monitor again run: ./monitor-canary.sh 600 - name: Full rollout (100%) run: | kubectl set image deployment/app-stable app=myapp:${{ github.sha }} kubectl scale deployment/app-canary --replicas=0 - name: Rollback canary if: failure() run: | kubectl scale deployment/app-canary --replicas=0
Rolling Deployment
Sequential update of instances:
jobs: rolling-deployment: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Deploy with rolling update run: | kubectl set image deployment/app \ app=myapp:${{ github.sha }} \ --record - name: Wait for rollout to complete run: | kubectl rollout status deployment/app --timeout=10m - name: Verify deployment run: | kubectl get pods -l app=myapp curl -f https://api.example.com/health - name: Rollback on failure if: failure() run: | kubectl rollout undo deployment/app
Multi-Environment Deployment
Deploy to staging, then production with approvals:
jobs: deploy-staging: runs-on: ubuntu-latest environment: name: staging url: https://staging.example.com steps: - uses: actions/checkout@v4 - name: Deploy to staging run: ./deploy.sh staging deploy-production: needs: deploy-staging runs-on: ubuntu-latest environment: name: production url: https://example.com steps: - uses: actions/checkout@v4 - name: Deploy to production run: ./deploy.sh production
Security Best Practices
Secret Management
Using GitHub Secrets:
steps: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-east-1
Environment-Scoped Secrets:
jobs: deploy: environment: production # Uses production-scoped secrets steps: - name: Deploy env: API_KEY: ${{ secrets.PRODUCTION_API_KEY }} run: ./deploy.sh
OIDC (OpenID Connect)
Authenticate without long-lived credentials:
jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - uses: actions/checkout@v4 - name: Configure AWS credentials (OIDC) uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole aws-region: us-east-1 - name: Deploy to AWS run: aws s3 sync ./dist s3://my-bucket
Google Cloud OIDC:
- name: Authenticate to Google Cloud uses: google-github-actions/auth@v2 with: workload_identity_provider: 'projects/123/locations/global/workloadIdentityPools/pool/providers/provider' service_account: 'github-actions@project.iam.gserviceaccount.com'
Secure Workflows
Restrict permissions:
permissions: contents: read # Read repository contents pull-requests: write # Comment on PRs id-token: write # OIDC token generation actions: read # Read workflow runs
Pin action versions to SHA:
# Less secure (tag can be moved) - uses: actions/checkout@v4 # More secure (immutable SHA) - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
Prevent script injection:
# Vulnerable to injection - run: echo "Hello ${{ github.event.issue.title }}" # Safe approach - run: echo "Hello $TITLE" env: TITLE: ${{ github.event.issue.title }}
Docker in CI/CD
Building Docker Images
jobs: build-docker: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: myorg/myapp tags: | type=ref,event=branch type=ref,event=pr type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,prefix={{branch}}- - name: Build and push uses: docker/build-push-action@v5 with: context: . platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max
Multi-Stage Docker Builds
# Build stage FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Production stage FROM node:20-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY package*.json ./ EXPOSE 3000 CMD ["npm", "start"]
Container Scanning
- name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: 'myorg/myapp:${{ github.sha }}' format: 'sarif' output: 'trivy-results.sarif' - name: Upload Trivy results to GitHub Security uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'trivy-results.sarif'
Release Automation
Semantic Versioning
Automatically version releases based on commit messages:
jobs: release: runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Semantic Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: npx semantic-release
Configuration (.releaserc.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", { "assets": ["CHANGELOG.md", "package.json"], "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" }] ] }
Changelog Generation
- name: Generate changelog uses: mikepenz/release-changelog-builder-action@v4 with: configuration: '.github/changelog-config.json' outputFile: 'CHANGELOG.md' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Create GitHub Release uses: ncipollo/release-action@v1 with: tag: ${{ steps.version.outputs.tag }} name: Release ${{ steps.version.outputs.tag }} bodyFile: 'CHANGELOG.md' artifacts: 'dist/*'
Release Notes Automation
- name: Build Release Notes id: release_notes uses: mikepenz/release-changelog-builder-action@v4 with: configurationJson: | { "categories": [ { "title": "## 🚀 Features", "labels": ["feature", "enhancement"] }, { "title": "## 🐛 Fixes", "labels": ["bug", "fix"] }, { "title": "## 📝 Documentation", "labels": ["documentation"] } ] } env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Monorepo CI/CD Patterns
Path-Based Triggers
Run workflows only when specific packages change:
name: Frontend CI on: push: paths: - 'packages/frontend/**' - 'package.json' - 'pnpm-lock.yaml' jobs: test-frontend: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Test frontend run: pnpm --filter frontend test
Affected Package Detection
jobs: detect-changes: runs-on: ubuntu-latest outputs: affected: ${{ steps.affected.outputs.packages }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Detect affected packages id: affected run: | # Use tools like Nx or Turborepo to detect changes AFFECTED=$(npx nx affected:apps --base=origin/main --plain) echo "packages=$AFFECTED" >> $GITHUB_OUTPUT test-affected: needs: detect-changes runs-on: ubuntu-latest strategy: matrix: package: ${{ fromJson(needs.detect-changes.outputs.affected) }} steps: - uses: actions/checkout@v4 - name: Test ${{ matrix.package }} run: npm run test --workspace=${{ matrix.package }}
Turborepo CI
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Build with Turborepo run: npx turbo build --cache-dir=.turbo - name: Cache Turbo uses: actions/cache@v4 with: path: .turbo key: ${{ runner.os }}-turbo-${{ github.sha }} restore-keys: | ${{ runner.os }}-turbo-
Performance Optimization
Parallel Job Execution
jobs: # These jobs run in parallel lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm run lint unit-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm run test:unit build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm run build # This job waits for all above to complete deploy: needs: [lint, unit-test, build] runs-on: ubuntu-latest steps: - run: npm run deploy
Conditional Job Execution
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm run build deploy-staging: needs: build if: github.ref == 'refs/heads/develop' runs-on: ubuntu-latest steps: - run: ./deploy.sh staging deploy-production: needs: build if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - run: ./deploy.sh production
Dependency Caching
steps: # Node.js with npm - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' # Python with pip - uses: actions/setup-python@v5 with: python-version: '3.11' cache: 'pip' # Ruby with bundler - uses: ruby/setup-ruby@v1 with: ruby-version: '3.2' bundler-cache: true # Go modules - uses: actions/setup-go@v5 with: go-version: '1.21' cache: true
Reusable Workflows
Creating Reusable Workflows
# .github/workflows/reusable-deploy.yml name: Reusable Deploy Workflow on: workflow_call: inputs: environment: required: true type: string version: required: false type: string default: 'latest' secrets: deploy-key: required: true outputs: deployment-url: description: "URL of the deployment" value: ${{ jobs.deploy.outputs.url }} jobs: deploy: runs-on: ubuntu-latest environment: ${{ inputs.environment }} outputs: url: ${{ steps.deploy.outputs.url }} steps: - uses: actions/checkout@v4 - name: Deploy id: deploy env: DEPLOY_KEY: ${{ secrets.deploy-key }} run: | ./deploy.sh ${{ inputs.environment }} ${{ inputs.version }} echo "url=https://${{ inputs.environment }}.example.com" >> $GITHUB_OUTPUT
Calling Reusable Workflows
# .github/workflows/main.yml name: Main Pipeline on: [push] jobs: deploy-staging: uses: ./.github/workflows/reusable-deploy.yml with: environment: staging version: ${{ github.sha }} secrets: deploy-key: ${{ secrets.STAGING_DEPLOY_KEY }} deploy-production: needs: deploy-staging uses: ./.github/workflows/reusable-deploy.yml with: environment: production version: ${{ github.sha }} secrets: deploy-key: ${{ secrets.PRODUCTION_DEPLOY_KEY }}
Infrastructure as Code
Terraform Deployment
jobs: terraform: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: 1.7.0 - name: Terraform Format run: terraform fmt -check - name: Terraform Init run: terraform init env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - name: Terraform Validate run: terraform validate - name: Terraform Plan run: terraform plan -out=tfplan env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - name: Terraform Apply if: github.ref == 'refs/heads/main' run: terraform apply -auto-approve tfplan env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS CloudFormation
jobs: deploy-cloudformation: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: us-east-1 - name: Deploy CloudFormation stack run: | aws cloudformation deploy \ --template-file infrastructure/template.yml \ --stack-name my-app-stack \ --parameter-overrides \ Environment=production \ Version=${{ github.sha }} \ --capabilities CAPABILITY_IAM
Best Practices
Workflow Organization
- Separate concerns: Different workflows for CI, CD, and scheduled tasks
- Use descriptive names: Clear workflow and job names
- Organize with directories: Group related workflows
- Version control: Track workflow changes like code
Efficiency
- Cache dependencies: Reduce build times significantly
- Parallel execution: Run independent jobs simultaneously
- Conditional runs: Skip unnecessary jobs
- Matrix strategies: Test multiple configurations efficiently
- Artifact reuse: Share build outputs between jobs
Security
- Minimize permissions: Use least-privilege principle
- Use OIDC: Avoid long-lived credentials
- Secret rotation: Regularly update secrets
- Pin dependencies: Use specific versions or SHAs
- Scan for vulnerabilities: Automated security checks
Reliability
- Timeout settings: Prevent hanging jobs
- Retry logic: Handle transient failures
- Failure notifications: Alert on critical failures
- Rollback mechanisms: Quick recovery from failed deployments
- Health checks: Verify deployments before marking complete
Observability
- Detailed logging: Clear, actionable logs
- Status checks: Prevent merging failing builds
- Deployment tracking: Know what's deployed where
- Metrics collection: Track pipeline performance
- Audit trails: Track who deployed what and when
Failure Handling
Retry Failed Steps
steps: - name: Deploy with retry uses: nick-fields/retry-action@v2 with: timeout_minutes: 10 max_attempts: 3 retry_wait_seconds: 30 command: npm run deploy
Continue on Error
jobs: test: runs-on: ubuntu-latest steps: - name: Run optional check continue-on-error: true run: npm run optional-check - name: Run required tests run: npm test
Conditional Cleanup
steps: - name: Deploy id: deploy run: ./deploy.sh - name: Rollback on failure if: failure() && steps.deploy.conclusion == 'failure' run: ./rollback.sh - name: Cleanup if: always() run: ./cleanup.sh
Advanced Patterns
Dynamic Matrix Generation
jobs: generate-matrix: runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - uses: actions/checkout@v4 - id: set-matrix run: | # Generate matrix based on project structure MATRIX=$(find packages -maxdepth 1 -type d -not -name packages | \ jq -R -s -c 'split("\n")[:-1]') echo "matrix=$MATRIX" >> $GITHUB_OUTPUT test: needs: generate-matrix runs-on: ubuntu-latest strategy: matrix: package: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} steps: - uses: actions/checkout@v4 - run: npm test --workspace=${{ matrix.package }}
Composite Actions
Create reusable action combinations:
# .github/actions/setup-project/action.yml name: 'Setup Project' description: 'Setup Node.js and install dependencies' inputs: node-version: description: 'Node.js version' required: false default: '20' runs: using: 'composite' steps: - uses: actions/setup-node@v4 with: node-version: ${{ inputs.node-version }} cache: 'npm' - run: npm ci shell: bash - run: npm run build shell: bash
Usage:
steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-project with: node-version: '20'
Self-Hosted Runners
jobs: deploy: runs-on: [self-hosted, linux, production] steps: - uses: actions/checkout@v4 - name: Deploy to production run: ./deploy.sh
Benefits:
- Custom hardware/software requirements
- Faster builds (pre-cached dependencies)
- Access to internal networks
- Cost savings for high-volume CI/CD
Platform-Specific Deployments
Vercel Deployment
jobs: deploy-vercel: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Deploy to Vercel uses: amondnet/vercel-action@v25 with: vercel-token: ${{ secrets.VERCEL_TOKEN }} vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} vercel-args: '--prod'
Netlify Deployment
jobs: deploy-netlify: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build run: npm run build - name: Deploy to Netlify uses: nwtgck/actions-netlify@v3 with: publish-dir: './dist' production-branch: main github-token: ${{ secrets.GITHUB_TOKEN }} deploy-message: 'Deploy from GitHub Actions' env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
AWS ECS Deployment
jobs: deploy-ecs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: us-east-1 - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 - name: Build and push Docker image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: my-app IMAGE_TAG: ${{ github.sha }} run: | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - name: Update ECS service run: | aws ecs update-service \ --cluster my-cluster \ --service my-service \ --force-new-deployment
Kubernetes Deployment
jobs: deploy-k8s: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup kubectl uses: azure/setup-kubectl@v3 with: version: 'v1.28.0' - name: Configure kubeconfig run: | echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig.yml echo "KUBECONFIG=$(pwd)/kubeconfig.yml" >> $GITHUB_ENV - name: Deploy to Kubernetes run: | kubectl set image deployment/myapp \ myapp=myregistry/myapp:${{ github.sha }} kubectl rollout status deployment/myapp
Skill Version: 1.0.0 Last Updated: October 2025 Skill Category: DevOps, CI/CD, Automation, Deployment Compatible With: GitHub Actions, Docker, Kubernetes, AWS, Azure, GCP, Vercel, Netlify