pfangueiro/claude-code-agents · Archived

ci-cd-templates

Production-ready CI/CD pipeline templates for GitHub Actions and GitLab CI

First seen Mar 1, 2026

Installation

$ npx skills add pfangueiro/claude-code-agents --skill ci-cd-templates

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from pfangueiro/claude-code-agents · top by installs.

npx skills add pfangueiro/claude-code-agents

Browse all from pfangueiro/claude-code-agents

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 6
License LICENSE
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 12,723 B
  • docs SUMMARY.md 97 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 7 installs

SKILL.md

CI/CD Templates Skill

Provides production-ready CI/CD pipeline templates for GitHub Actions and GitLab CI.

Purpose

This skill provides:

  • GitHub Actions workflow templates
  • GitLab CI/CD pipeline configurations
  • Best practices for automated testing, building, and deployment
  • Security scanning integration
  • Deployment strategies (blue/green, canary, rolling)

When to Use

  • "Create a CI/CD pipeline for Node.js"
  • "Add GitHub Actions for testing and deployment"
  • "Set up automated deployments to AWS"
  • "Configure GitLab CI for Docker builds"

GitHub Actions Templates

Node.js CI/CD Pipeline

name: Node.js CI/CD

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

# An unqualified image name (`myapp`) resolves to docker.io/library/myapp —
# the Docker official-images namespace, which you cannot push to. Always
# fully qualify the image with a registry host and an owner/namespace.
# Set DOCKER_REGISTRY (e.g. ghcr.io, docker.io) and DOCKER_NAMESPACE as
# repository variables: Settings > Secrets and variables > Actions > Variables.
env:
  REGISTRY: ${{ vars.DOCKER_REGISTRY }}
  IMAGE_NAME: ${{ vars.DOCKER_REGISTRY }}/${{ vars.DOCKER_NAMESPACE }}/myapp

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18.x, 20.x]

    steps:
    - uses: actions/checkout@v4

    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'

    - name: Install dependencies
      run: npm ci

    - name: Run linter
      run: npm run lint

    - name: Run tests
      run: npm test

    - name: Upload coverage
      uses: codecov/codecov-action@v4
      if: matrix.node-version == '20.x'
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        # fail_ci_if_error defaults to false: without this, a failed upload
        # is reported as a green step and coverage silently stops arriving.
        fail_ci_if_error: true

  security:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Run Snyk security scan
      # Pinned to a release tag — @master is a mutable ref that silently
      # changes what code runs in your pipeline.
      uses: snyk/actions/[email protected]
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

    - name: Run npm audit
      run: npm audit --production

  build:
    needs: [test, security]
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
    - uses: actions/checkout@v4

    - name: Build Docker image
      run: docker build -t "$IMAGE_NAME:${{ github.sha }}" .

    - name: Log in to the container registry
      uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}

    - name: Push Docker image
      run: |
        docker tag "$IMAGE_NAME:${{ github.sha }}" "$IMAGE_NAME:latest"
        docker push "$IMAGE_NAME:${{ github.sha }}"
        docker push "$IMAGE_NAME:latest"

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
    - name: Deploy to production
      uses: appleboy/[email protected]
      with:
        host: ${{ secrets.DEPLOY_HOST }}
        username: ${{ secrets.DEPLOY_USER }}
        key: ${{ secrets.DEPLOY_KEY }}
        # Interpolated by the runner: $IMAGE_NAME does not exist on the
        # remote host, so the fully qualified name must be baked in here.
        script: |
          # The registry login in the build job happened on the RUNNER. This
          # script runs on the remote host, which has never authenticated —
          # pulling a private image there fails with 'denied: requested
          # access to the resource is denied'. Log in before pulling.
          echo "${{ secrets.DOCKER_PASSWORD }}" \
            | docker login ${{ env.REGISTRY }} -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
          docker pull ${{ env.IMAGE_NAME }}:latest
          docker-compose up -d

TypeScript + Vitest Pipeline

name: TypeScript CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: '20'
        cache: 'npm'

    - run: npm ci

    - name: Type check
      run: npm run type-check

    - name: Run tests with coverage
      run: npm run test:coverage

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v4
      with:
        # Without this the upload is fail-open — an upload error still
        # reports a green step.
        fail_ci_if_error: true

GitLab CI Templates

Full-Stack Application Pipeline

stages:
  - build
  - test
  - security
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

build:
  stage: build
  image: node:20-alpine
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour

test:unit:
  stage: test
  image: node:20-alpine
  script:
    - npm ci
    - npm run test:coverage
  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

test:e2e:
  stage: test
  image: mcr.microsoft.com/playwright:v1.40.0
  script:
    - npm ci
    - npx playwright install
    - npm run test:e2e
  artifacts:
    when: on_failure
    paths:
      - playwright-report/

security:sast:
  stage: security
  image: returntocorp/semgrep
  script:
    # --error makes semgrep exit 1 on findings. Without it semgrep exits 0
    # even when it finds something, and the gate can never fail the pipeline.
    # --gitlab-sast emits GitLab's SAST report schema; a raw --json file
    # fails schema validation and is silently not ingested.
    - semgrep --config=auto --error --gitlab-sast --output=gl-sast-report.json .
  artifacts:
    # The gate is supposed to fail, and artifacts:when defaults to on_success,
    # so without this the report is discarded exactly when it matters.
    when: always
    reports:
      sast: gl-sast-report.json

security:dependency:
  stage: security
  image: node:20-alpine
  script:
    # npm audit exits non-zero when vulnerabilities are found, so this gate
    # does fail the pipeline.
    - npm audit --json > npm-audit.json
  artifacts:
    when: always
    # Kept as a plain artifact, NOT declared under `reports:`. Raw npm audit
    # JSON does not conform to GitLab's dependency-scanning report schema, and
    # a report that fails validation is dropped — leaving a dashboard that
    # shows a clean all-clear it never actually verified. Use GitLab's own
    # Dependency-Scanning.gitlab-ci.yml template if you need the report.
    paths:
      - npm-audit.json

deploy:staging:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache curl
  script:
    - curl --fail --show-error --silent -X POST $DEPLOY_WEBHOOK_STAGING
  only:
    - develop

deploy:production:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache curl
  script:
    - curl --fail --show-error --silent -X POST $DEPLOY_WEBHOOK_PRODUCTION
  only:
    - main
  when: manual

Deployment Strategies

Blue/Green Deployment (AWS)

name: Blue/Green Deploy

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - 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

    - name: Deploy to green environment
      id: deploy
      run: |
        # create-deployment is ASYNC — it returns a deployment ID immediately,
        # long before the revision is live. Capture the ID so the next step
        # can block on it.
        DEPLOYMENT_ID=$(aws deploy create-deployment \
          --application-name my-app \
          --deployment-group-name green-env \
          --s3-location bucket=my-bucket,key=app.zip,bundleType=zip \
          --query deploymentId --output text)
        echo "deployment-id=$DEPLOYMENT_ID" >> "$GITHUB_OUTPUT"

    - name: Wait for the green deployment to succeed
      run: |
        # Without this waiter the smoke tests below hit the PREVIOUS build
        # while the new one is still rolling out: they pass, and a broken
        # revision gets promoted. The waiter exits non-zero on a failed or
        # timed-out deployment, so the job fails closed.
        aws deploy wait deployment-successful \
          --deployment-id ${{ steps.deploy.outputs.deployment-id }}

    - name: Run smoke tests
      run: ./scripts/smoke-test.sh https://green.example.com

    - name: Switch traffic to green
      run: |
        # Every entry in --default-actions requires Type. Omitting it fails
        # client-side with 'Missing required parameter in DefaultActions[0]:
        # "Type"', so the one step that promotes green never runs.
        aws elbv2 modify-listener \
          --listener-arn ${{ secrets.LISTENER_ARN }} \
          --default-actions Type=forward,TargetGroupArn=${{ secrets.GREEN_TARGET_GROUP }}

    - name: Monitor deployment
      run: ./scripts/monitor-metrics.sh

Canary Deployment (Kubernetes)

name: Canary Deploy

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - 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

    - name: Set up kubectl
      uses: azure/setup-kubectl@v3

    - name: Configure kubeconfig
      # setup-kubectl installs the BINARY only — it writes no kubeconfig and
      # authenticates nothing. Without this step every kubectl call below
      # fails because it has no cluster to talk to.
      run: aws eks update-kubeconfig --name ${{ vars.EKS_CLUSTER_NAME }} --region us-east-1

    - name: Deploy canary (10% traffic)
      run: |
        kubectl apply -f k8s/canary-10.yaml
        # Wait on the manifest just applied, never on a hardcoded name. A literal
        # `deployment/app-canary` that does not match this file returns 0 instantly
        # against whatever else is already converged, and the gate passes vacuously.
        # (-f needs the file to hold the rollout-able workload; a mixed file errors
        # loudly, which is the correct direction to fail.)
        kubectl rollout status -f k8s/canary-10.yaml --timeout=10m

    - name: Monitor metrics for 10 minutes
      run: ./scripts/monitor-canary.sh 600

    - name: Increase to 50% traffic
      run: |
        kubectl apply -f k8s/canary-50.yaml
        # apply only records desired state. Without this wait the monitor
        # below measures the still-running 10% pods and reports the 50%
        # step healthy — the same fail-open shape as an unwaited deploy.
        kubectl rollout status -f k8s/canary-50.yaml --timeout=10m

    - name: Monitor metrics for 10 minutes
      run: ./scripts/monitor-canary.sh 600

    - name: Full rollout
      run: |
        kubectl apply -f k8s/production.yaml
        # Production must converge BEFORE the canary is deleted — removing it
        # first drops serving pods while the rollout is still in progress.
        kubectl rollout status -f k8s/production.yaml --timeout=10m
        kubectl delete -f k8s/canary-50.yaml

Best Practices

  1. Always run tests before deployment
  2. Use matrix builds for multiple environments
  3. Implement security scanning (SAST, dependency checks)
  4. Cache dependencies to speed up builds
  5. Use secrets for sensitive data
  6. Implement rollback strategies
  7. Monitor deployments with health checks
  8. Use environment-specific configurations

Integration with Agents

Works best with:

  • devops-automation agent - Generates pipelines for specific platforms
  • security-auditor agent - Adds security scanning steps
  • test-automation agent - Integrates testing frameworks

References