<< All versions
Skill v1.0.1
currentAutomated scan100/1000xdarkmatter/claude-mods/ci-cd-ops
7 files
──Details
PublishedOctober 29, 2026 at 06:41 AM
Content Hashsha256:605fb27cca59ed07...
Git SHAd2211360a80d
Bump Typepatch
──Files
Files (1 file, 10.2 KB)
SKILL.md10.2 KBactive
SKILL.md · 333 lines · 10.2 KB
name: ci-cd-ops description: "CI/CD pipeline patterns with GitHub Actions, release automation, and testing strategies. Use for: github actions, workflow, CI, CD, pipeline, deploy, release, semantic release, changesets, goreleaser, matrix, cache, secrets, environment, artifact, reusable workflow, composite action." license: MIT allowed-tools: "Read Write Bash" metadata: version: "1.0.1" author: claude-mods related-skills: git-ops, docker-ops, testing-ops
CI/CD Operations
Comprehensive patterns for continuous integration, delivery, and deployment using GitHub Actions, release automation tools, and testing pipelines.
GitHub Actions Quick Reference
Workflow File Anatomy
yaml
name: CI # Display name in Actions tabon: # Trigger eventspush:branches: [main]pull_request:branches: [main]permissions: # GITHUB_TOKEN scope (least privilege)contents: readpull-requests: writeconcurrency: # Prevent duplicate runsgroup: ${{ github.workflow }}-${{ github.ref }}cancel-in-progress: trueenv: # Workflow-level environment variablesNODE_VERSION: "20"jobs:test:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- uses: actions/setup-node@v4with:node-version: ${{ env.NODE_VERSION }}cache: npm- run: npm ci- run: npm test
Core Syntax Elements
| Element | Purpose | Example | |
|---|---|---|---|
on | Event triggers | push, pull_request, schedule | |
jobs.<id>.runs-on | Runner selection | ubuntu-latest, self-hosted | |
jobs.<id>.needs | Job dependencies | needs: [build, lint] | |
jobs.<id>.if | Conditional execution | if: github.event_name == 'push' | |
jobs.<id>.strategy.matrix | Parallel variants | node-version: [18, 20, 22] | |
jobs.<id>.environment | Deployment target | environment: production | |
jobs.<id>.permissions | Token scope | contents: write | |
steps[*].uses | Use an action | uses: actions/checkout@v4 | |
steps[*].run | Run a command | run: npm test | |
steps[*].env | Step environment | env: { CI: true } |
Trigger Decision Tree
| Scenario | Trigger | Config | |
|---|---|---|---|
| Run tests on every PR | pull_request | branches: [main] | |
| Deploy on merge to main | push | branches: [main] | |
| Release on version tag | push | tags: ['v*'] | |
| Nightly builds | schedule | cron: '0 2 * * *' | |
| Manual deployment | workflow_dispatch | inputs: { environment: ... } | |
| Called by another workflow | workflow_call | inputs:, secrets: | |
| On PR label change | pull_request | types: [labeled] | |
| On issue comment | issue_comment | types: [created] | |
| On release published | release | types: [published] | |
| On package push | registry_package | types: [published] |
Trigger Filter Patterns
yaml
on:push:branches: [main, 'release/**'] # Branch patternspaths: ['src/**', '!src/**/*.test.*'] # Path filters (ignore tests)tags: ['v*'] # Tag patternspull_request:types: [opened, synchronize, reopened] # Default typespaths-ignore: ['docs/**', '*.md'] # Ignore docs-only changes
Caching Strategies
| Ecosystem | Action / Key | Path | Restore Key | |
|---|---|---|---|---|
| Node (npm) | actions/setup-node with cache: npm | Auto | Auto | |
| Node (pnpm) | actions/setup-node with cache: pnpm | Auto | Auto | |
| Go modules | actions/setup-go with cache: true | Auto | Auto | |
| Cargo | actions/cache@v4 | ~/.cargo/registry, target | cargo-${{ runner.os }}-${{ hashFiles('Cargo.lock') }} | |
| pip / uv | actions/setup-python with cache: pip | Auto | Auto | |
| Docker layers | docker/build-push-action | Uses buildx cache | type=gha or type=registry | |
| Gradle | actions/setup-java with cache: gradle | Auto | Auto | |
| Composer | actions/cache@v4 | vendor | composer-${{ hashFiles('composer.lock') }} |
Manual Cache Example
yaml
- uses: actions/cache@v4with:path: |~/.cargo/bin~/.cargo/registry~/.cargo/gittargetkey: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}restore-keys: |cargo-${{ runner.os }}-
Matrix Strategy
yaml
strategy:fail-fast: false # Don't cancel siblings on failuremax-parallel: 4 # Limit concurrent jobsmatrix:os: [ubuntu-latest, windows-latest, macos-latest]node-version: [18, 20, 22]include: # Add specific combos- os: ubuntu-latestnode-version: 22coverage: trueexclude: # Remove specific combos- os: windows-latestnode-version: 18
Dynamic Matrix
yaml
prepare:runs-on: ubuntu-latestoutputs:matrix: ${{ steps.set.outputs.matrix }}steps:- id: setrun: echo "matrix=$(jq -c . matrix.json)" >> "$GITHUB_OUTPUT"test:needs: preparestrategy:matrix: ${{ fromJson(needs.prepare.outputs.matrix) }}
Secrets Management
| Scope | Access | Use Case | |
|---|---|---|---|
| Repository secrets | All workflows in repo | API keys, tokens | |
| Environment secrets | Jobs targeting that environment | Production credentials | |
| Organization secrets | Selected repos in org | Shared service accounts | |
| OIDC tokens | Federated identity | Cloud deployment (no stored secrets) |
Secrets Best Practices
yaml
# Reference secrets - NEVER echo or log them- run: deploy --token ${{ secrets.DEPLOY_TOKEN }}# Mask custom values- run: echo "::add-mask::$CUSTOM_SECRET"# Use environments for deployment secretsjobs:deploy:environment: production # Requires approval + has secretssteps:- run: deploy --key ${{ secrets.PROD_API_KEY }}
OIDC for Cloud (No Stored Secrets)
yaml
permissions:id-token: writecontents: readsteps:- uses: aws-actions/configure-aws-credentials@v4with:role-to-assume: arn:aws:iam::123456789:role/github-actionsaws-region: us-east-1
Common Workflow Patterns
Test on Pull Request
yaml
name: Teston:pull_request:branches: [main]concurrency:group: test-${{ github.head_ref }}cancel-in-progress: truejobs:test:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- uses: actions/setup-node@v4with: { node-version: 20, cache: npm }- run: npm ci- run: npm run lint- run: npm test -- --coverage
Deploy on Merge to Main
yaml
name: Deployon:push:branches: [main]jobs:deploy:runs-on: ubuntu-latestenvironment: productionsteps:- uses: actions/checkout@v4- run: npm ci && npm run build- run: npx wrangler deployenv:CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
Release on Tag
yaml
name: Releaseon:push:tags: ['v*']permissions:contents: writejobs:release:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4with: { fetch-depth: 0 }- run: |gh release create ${{ github.ref_name }} \--generate-notes \--title "${{ github.ref_name }}"env:GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Gotchas Table
| Gotcha | Problem | Fix | |
|---|---|---|---|
| Shallow clone | git describe fails, history missing | actions/checkout@v4 with fetch-depth: 0 | |
| Default permissions | GITHUB_TOKEN is read-only by default | Set permissions: explicitly | |
| Action pinning | @main can break without warning | Pin to SHA: @abc123 or @v4 | |
| Fork PR secrets | Secrets unavailable on fork PRs | Use pull_request_target carefully | |
| Concurrent deploys | Race condition on production | Use concurrency: groups | |
| Stale caches | Cache grows unbounded | Include lockfile hash in key | |
| Node.js version | setup-node defaults vary | Always specify node-version | |
| Docker layer cache | Rebuilds everything without cache | Use cache-from: type=gha | |
| Matrix + environment | Each matrix job needs approval | Use a single deploy job after matrix | |
| Path filters + required checks | Skipped jobs block merge | Use paths-filter action or make checks non-required | |
GITHUB_TOKEN in PRs | Cannot trigger other workflows | Use a PAT or GitHub App token | |
| Windows line endings | Scripts fail with \r\n | Use .gitattributes or core.autocrlf |
Expression Syntax Quick Reference
| Expression | Result | |
|---|---|---|
${{ github.event_name }} | push, pull_request, etc. | |
${{ github.ref_name }} | Branch or tag name | |
${{ github.sha }} | Full commit SHA | |
${{ github.actor }} | User who triggered | |
${{ runner.os }} | Linux, Windows, macOS | |
${{ contains(github.event.head_commit.message, '[skip ci]') }} | Check commit message | |
${{ needs.build.outputs.version }} | Output from prior job | |
${{ fromJson(steps.meta.outputs.json) }} | Parse JSON output | |
${{ hashFiles('**/package-lock.json') }} | Hash for cache keys | |
${{ format('refs/heads/{0}', matrix.branch) }} | String formatting | |
${{ toJson(matrix) }} | Debug: print matrix config |
Step Outputs
yaml
steps:- id: versionrun: echo "value=$(cat VERSION)" >> "$GITHUB_OUTPUT"- run: echo "Version is ${{ steps.version.outputs.value }}"
Job Outputs (for Cross-Job Communication)
yaml
jobs:build:runs-on: ubuntu-latestoutputs:artifact-id: ${{ steps.upload.outputs.artifact-id }}steps:- id: uploadrun: echo "artifact-id=abc123" >> "$GITHUB_OUTPUT"deploy:needs: buildruns-on: ubuntu-lateststeps:- run: echo "Deploying ${{ needs.build.outputs.artifact-id }}"
Reference Files
| File | Contents | |
|---|---|---|
references/github-actions.md | Complete workflow syntax, reusable workflows, composite actions, OIDC, runners, debugging | |
references/release-automation.md | Semantic versioning, semantic-release, changesets, goreleaser, changelog, publishing | |
references/testing-pipelines.md | Test stages, parallelism, coverage, service containers, e2e in CI, deployment pipelines |