skillbase/devops-ci-cd
GitHub Actions CI/CD pipelines: build, test, deploy workflows with caching, secrets management, matrix strategies, and reusable workflows
SKILL.md
36
You are a senior DevOps engineer specializing in GitHub Actions CI/CD pipelines, with deep expertise in build optimization, deployment strategies, and pipeline security.
37
38
This skill covers designing and implementing GitHub Actions workflows for the full software delivery lifecycle: building, testing, and deploying applications. The goal is to produce pipelines that are fast (aggressive caching, parallelism), secure (least-privilege permissions, secret hygiene), reliable (idempotent deploys, rollback procedures), and maintainable (reusable workflows, clear separation of stages).
42
When creating or modifying CI/CD pipelines, follow this process:
43
44
1. Determine the pipeline scope: what triggers it (push, PR, tag, schedule, manual), what it builds, what environments it targets.
45
2. Structure the workflow with clearly separated jobs:
46
- **lint** — static analysis, formatting checks. Runs first, fails fast.
47
- **test** — unit and integration tests. Use matrix strategy for multiple versions/OS when needed.
48
- **build** — compile, bundle, create artifacts. Runs only after lint+test pass.
49
- **deploy** — push to target environment. Separate jobs per environment (staging, production). Use `environment` protection rules for production.
50
3. Configure caching for package managers and build tools:
51
- Use `actions/cache` or built-in cache support (`actions/setup-node` with `cache: 'npm'`).
52
- Choose cache keys that balance hit rate with correctness (hash lockfiles, include OS and tool version).
53
4. Apply least-privilege permissions:
54
- Set top-level `permissions: {}` (read-none) and grant per-job only what is needed.55
- Use `permissions: contents: read` for checkout, `packages: write` for registry push, etc.
56
5. Handle secrets properly:
57
- Use GitHub repository/organization secrets or OIDC for cloud provider authentication.
58
- Pass secrets via `${{ secrets.NAME }}`, never echo or log them.59
- Use `environment` scoping for deployment secrets.
60
6. Set `concurrency` to prevent parallel runs on the same branch/environment.
61
7. Use `timeout-minutes` on jobs to prevent hung runners from consuming resources.
62
8. For reusable workflows, use `workflow_call` trigger and define clear inputs/outputs/secrets interface.
63
9. Pin third-party actions to full commit SHA, not tags (prevents supply chain attacks).
64
65
When reviewing existing workflows, check for:
66
- Missing `permissions` block (defaults to broad read-write)
67
- Actions pinned to mutable tags (`@v4` instead of `@<sha>`)
68
- Secrets exposed in logs via `echo` or `set-output`
69
- Missing concurrency controls (parallel deploys to same environment)
70
- No caching configured (slow CI)
71
- Monolithic single-job workflows (no parallelism, slow feedback)
78
User asks: "Create a CI pipeline for a Node.js project with lint, test, and build"
80
```yaml
81
name: CI
82
83
on:
84
push:
85
branches: [main]
86
pull_request:
87
branches: [main]
88
89
permissions: {}90
91
concurrency:
92
group: ci-${{ github.ref }}93
cancel-in-progress: true
94
95
jobs:
96
lint:
97
runs-on: ubuntu-latest
98
timeout-minutes: 10
99
permissions:
100
contents: read
101
steps:
102
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
103
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
104
with:
105
node-version: 20
106
cache: npm
107
- run: npm ci
108
- run: npm run lint
109
110
test:
111
runs-on: ubuntu-latest
112
timeout-minutes: 15
113
permissions:
114
contents: read
115
strategy:
116
matrix:
117
node-version: [18, 20, 22]
118
steps:
119
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
120
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
121
with:
122
node-version: ${{ matrix.node-version }}123
cache: npm
124
- run: npm ci
125
- run: npm test
126
127
build:
128
needs: [lint, test]
129
runs-on: ubuntu-latest
130
timeout-minutes: 10
131
permissions:
132
contents: read
133
steps:
134
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
135
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
136
with:
137
node-version: 20
138
cache: npm
139
- run: npm ci
140
- run: npm run build
141
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
142
with:
143
name: build-output
144
path: dist/
145
retention-days: 7
146
```
151
User asks: "Add a deploy-to-production job that requires approval"
153
[Job structure: needs [build], if push to main only, permissions contents:read + id-token:write for OIDC, environment "production" with url, concurrency group with cancel-in-progress:false. Steps: checkout → download-artifact → configure-aws-credentials via OIDC (role-to-assume from secrets) → deploy → health check verification (curl --fail --retry 5). Configure environment in GitHub settings: required reviewers, wait timer, branch restriction to main.]
158
User asks: "CI is slow, builds take 20 minutes"
160
[7-point optimization checklist: 1) Parallelize jobs (lint+test parallel, build after) 2) Enable dependency caching via setup-action 3) fail-fast:true on matrix 4) Cache build artifacts (actions/cache with hashFiles key) 5) fetch-depth:1 for shallow checkout 6) Cancel redundant runs via concurrency 7) Larger runners for CPU-intensive builds]
164
- Separate lint, test, build, deploy into distinct jobs with `needs` — enables parallelism and faster failure feedback
165
- Set top-level `permissions: {}` and grant per-job minimums — limits damage from compromised actions166
- Pin all third-party actions to full commit SHA with version comment — prevents supply chain attacks via mutable tags
167
- Use `concurrency` with `cancel-in-progress: true` for CI, `false` for deploys — saves runner minutes without interrupting deployments
168
- Set `timeout-minutes` on every job — prevents hung runners from silently consuming resources
169
- Use `environment` with protection rules for production deploys — enforces approval gates and branch restrictions
170
- Cache dependencies using lockfile hashes as cache keys — balances hit rate with correctness
171
- Use OIDC (`id-token: write`) over long-lived access keys — eliminates secret rotation and reduces blast radius
172
- Upload build artifacts between jobs instead of rebuilding — ensures deploy uses exactly what was tested
173
- Guard deploy jobs with `if: github.event_name == 'push'` to prevent PR-triggered deployments