CI/CD Setup
When to Use
- Setting up CI for a new project from scratch
- Replacing unreliable copied pipeline configurations that do not match the actual stack
- Transitioning between GitHub Actions and GitLab CI platforms
- Reviewing whether pipeline stages align with actual project tooling
- Optimizing slow builds (caching, parallelism, conditional steps)
- Establishing a stable CI foundation before adding specialized hardening
Context Required
From startup-context: tech stack, deployment target, team size. Also detect or ask:
- Language and framework (auto-detect from repo files before asking)
- Deployment target (Vercel, AWS, GCP, Fly.io, etc.)
- CI/CD platform (default: GitHub Actions; also supports GitLab CI)
- Environments (dev, staging, production) and existing test coverage
- Secrets and credentials needed for build or deploy
Workflow
- Detect stack from repo signals — Scan for lockfiles (package-lock.json, yarn.lock, poetry.lock, go.sum, Cargo.lock), language manifests (package.json, pyproject.toml, go.mod), and script definitions (test, lint, build commands). Lockfiles indicate package manager choice. Absent scripts trigger conservative defaults. Never assume Node for a Python project.
- Choose pipeline stages — Start with a dependable baseline: checkout, runtime setup, dependency install with caching, then sequential lint, test, build. Only add complexity after the baseline works.
- Generate pipeline config — Write CI config for the detected platform. Output machine-readable YAML with correct caching strategy for the detected package manager. Verify all referenced commands actually exist in the project.
- Configure secrets — List required secrets and how to add them. Use platform-managed secret stores. Recommend OIDC for cloud auth over long-lived keys. Never hardcode credentials in YAML.
- Add deployment stages safely — Begin CI-only (lint/test/build). Add staging deployment with explicit environment info. Add production deployment with manual approval. Maintain transparency in rollout and rollback procedures.
- Validate before merge — Confirm generated YAML is syntactically valid, all commands exist in the project, caching aligns with the package manager, and branch protections match organizational requirements.
- Deliver config and instructions — Full config file plus setup steps.
Output Format
# CI/CD Pipeline: [Project Name]
## Stack Detection Results — detected language, runtime, tools, and build commands
## Pipeline Overview — Mermaid flowchart showing stages
## Pipeline Configuration — Full YAML config file
## Secrets Required — table: name, where to get, how to add
## Setup Instructions — step-by-step to activate
## Validation Checklist — commands verified, caching confirmed, branch rules set
## Optimization Notes — caching strategy, estimated build time
Frameworks & Best Practices
Detection-First Pipeline Generation
Always detect before generating. The detector relies on concrete file signals:
- Lockfiles indicate package manager choice (npm, yarn, pip, cargo, go modules)
- Language manifests identify runtime families
- Script definitions in package.json/pyproject.toml inform lint/test/build commands
- Absent scripts trigger conservative default commands rather than assumptions
Caching Strategies by Ecosystem
| Ecosystem |
Cache Path |
Cache Key |
| Node.js |
~/.npm or node_modules |
hashFiles('**/package-lock.json') |
| Python |
~/.cache/pip |
hashFiles('**/requirements*.txt') |
| Go |
~/go/pkg/mod |
hashFiles('**/go.sum') |
| Rust |
~/.cargo/registry, target/ |
hashFiles('**/Cargo.lock') |
| Ruby |
vendor/bundle |
hashFiles('**/Gemfile.lock') |
Pipeline Architecture Principles
- Lint first — fail early before expensive test runs
- Sequential baseline — checkout, install, lint, test, build, then artifact publish
- Cache aggressively — cuts 30-60% off build times
- Pin action versions — use SHA hashes, not tags, for supply chain security
- Set timeouts (
timeout-minutes: 15) and concurrency to cancel redundant runs
- One enhancement at a time — do not add matrix builds, security scanning, and deployment in one PR
Environment Strategy
| Environment |
Trigger |
Approval |
Purpose |
| CI |
Every push/PR |
None |
Run lint + tests |
| Staging |
Merge to main |
None (auto) |
Integration testing, QA |
| Production |
Git tag or manual |
Required |
Live users |
Common Pitfalls
- Applying Node-specific pipelines to Python or Go repos (detect first)
- Enabling deployment before establishing reliable test coverage
- Overlooking dependency caching configuration
- Running full matrix builds on minor branch updates (use path filters)
- Omitting branch protections on production deployments
- Embedding credentials directly in pipeline YAML
Scaling & Platform Notes
- Split long-running jobs when execution exceeds 10 minutes
- Implement test matrices only when genuine compatibility concerns exist
- GitHub Actions for GitHub ecosystem; GitLab CI for self-hosted SCM+CI
- Maintain a single canonical pipeline source per repository
Related Skills
code-review — chain to review the CI config itself before committing
security-review — chain to add or audit security scanning stages (trivy, semgrep, npm audit)
Examples
Example prompt: "Set up CI/CD for my Next.js app deployed on Vercel."
Good output snippet:
name: CI
on:
push: { branches: [main] }
pull_request: { branches: [main] }
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'npm' }
- run: npm ci
- run: npm run lint && npx tsc --noEmit
test:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'npm' }
- run: npm ci && npm test -- --coverage
Example prompt: "My Python CI takes 8 minutes, how do I speed it up?"
Good output snippet:
Stack detection shows: Python 3.11, pytest, pip. Three fixes to cut to ~3 minutes:
(1) Add pip caching keyed on hashFiles('requirements*.txt'),
(2) split unit/integration tests into parallel jobs,
(3) add path filters to skip CI on docs-only changes.
1---2name: cicd-setup3description: When the user needs to set up or improve CI/CD pipelines — GitHub Actions, GitLab CI, deployment automation, or says "set up CI", "automate deployment", "add tests to pipeline", "fix my build".4---5
6# CI/CD Setup
7
8## When to Use
9
10- Setting up CI for a new project from scratch
11- Replacing unreliable copied pipeline configurations that do not match the actual stack
12- Transitioning between GitHub Actions and GitLab CI platforms
13- Reviewing whether pipeline stages align with actual project tooling
14- Optimizing slow builds (caching, parallelism, conditional steps)
15- Establishing a stable CI foundation before adding specialized hardening
16
17## Context Required
18
19From `startup-context`: tech stack, deployment target, team size. Also detect or ask:
20- Language and framework (auto-detect from repo files before asking)
21- Deployment target (Vercel, AWS, GCP, Fly.io, etc.)
22- CI/CD platform (default: GitHub Actions; also supports GitLab CI)
23- Environments (dev, staging, production) and existing test coverage
24- Secrets and credentials needed for build or deploy
25
26## Workflow
27
281. **Detect stack from repo signals** — Scan for lockfiles (package-lock.json, yarn.lock, poetry.lock, go.sum, Cargo.lock), language manifests (package.json, pyproject.toml, go.mod), and script definitions (test, lint, build commands). Lockfiles indicate package manager choice. Absent scripts trigger conservative defaults. Never assume Node for a Python project.
292. **Choose pipeline stages** — Start with a dependable baseline: checkout, runtime setup, dependency install with caching, then sequential lint, test, build. Only add complexity after the baseline works.
303. **Generate pipeline config** — Write CI config for the detected platform. Output machine-readable YAML with correct caching strategy for the detected package manager. Verify all referenced commands actually exist in the project.
314. **Configure secrets** — List required secrets and how to add them. Use platform-managed secret stores. Recommend OIDC for cloud auth over long-lived keys. Never hardcode credentials in YAML.
325. **Add deployment stages safely** — Begin CI-only (lint/test/build). Add staging deployment with explicit environment info. Add production deployment with manual approval. Maintain transparency in rollout and rollback procedures.
336. **Validate before merge** — Confirm generated YAML is syntactically valid, all commands exist in the project, caching aligns with the package manager, and branch protections match organizational requirements.
347. **Deliver config and instructions** — Full config file plus setup steps.
35
36## Output Format
37
38```markdown
39# CI/CD Pipeline: [Project Name]
40## Stack Detection Results — detected language, runtime, tools, and build commands
41## Pipeline Overview — Mermaid flowchart showing stages
42## Pipeline Configuration — Full YAML config file
43## Secrets Required — table: name, where to get, how to add
44## Setup Instructions — step-by-step to activate
45## Validation Checklist — commands verified, caching confirmed, branch rules set
46## Optimization Notes — caching strategy, estimated build time
47```
48
49## Frameworks & Best Practices
50
51### Detection-First Pipeline Generation
52
53Always detect before generating. The detector relies on concrete file signals:
54- Lockfiles indicate package manager choice (npm, yarn, pip, cargo, go modules)
55- Language manifests identify runtime families
56- Script definitions in package.json/pyproject.toml inform lint/test/build commands
57- Absent scripts trigger conservative default commands rather than assumptions
58
59### Caching Strategies by Ecosystem
60
61| Ecosystem | Cache Path | Cache Key |
62|-----------|-----------|-----------|
63| Node.js | `~/.npm` or `node_modules` | `hashFiles('**/package-lock.json')` |
64| Python | `~/.cache/pip` | `hashFiles('**/requirements*.txt')` |
65| Go | `~/go/pkg/mod` | `hashFiles('**/go.sum')` |
66| Rust | `~/.cargo/registry`, `target/` | `hashFiles('**/Cargo.lock')` |
67| Ruby | `vendor/bundle` | `hashFiles('**/Gemfile.lock')` |
68
69### Pipeline Architecture Principles
70
71- **Lint first** — fail early before expensive test runs
72- **Sequential baseline** — checkout, install, lint, test, build, then artifact publish
73- **Cache aggressively** — cuts 30-60% off build times
74- **Pin action versions** — use SHA hashes, not tags, for supply chain security
75- **Set timeouts** (`timeout-minutes: 15`) and **concurrency** to cancel redundant runs
76- **One enhancement at a time** — do not add matrix builds, security scanning, and deployment in one PR
77
78### Environment Strategy
79
80| Environment | Trigger | Approval | Purpose |
81|-------------|---------|----------|---------|
82| **CI** | Every push/PR | None | Run lint + tests |
83| **Staging** | Merge to `main` | None (auto) | Integration testing, QA |
84| **Production** | Git tag or manual | Required | Live users |
85
86### Common Pitfalls
87
881. Applying Node-specific pipelines to Python or Go repos (detect first)
892. Enabling deployment before establishing reliable test coverage
903. Overlooking dependency caching configuration
914. Running full matrix builds on minor branch updates (use path filters)
925. Omitting branch protections on production deployments
936. Embedding credentials directly in pipeline YAML
94
95### Scaling & Platform Notes
96
97- Split long-running jobs when execution exceeds 10 minutes
98- Implement test matrices only when genuine compatibility concerns exist
99- GitHub Actions for GitHub ecosystem; GitLab CI for self-hosted SCM+CI
100- Maintain a single canonical pipeline source per repository
101
102## Related Skills
103
104- `code-review` — chain to review the CI config itself before committing
105- `security-review` — chain to add or audit security scanning stages (trivy, semgrep, npm audit)
106
107## Examples
108
109**Example prompt:** "Set up CI/CD for my Next.js app deployed on Vercel."
110
111**Good output snippet:**
112```yaml
113name: CI
114on:
115 push: { branches: [main] }
116 pull_request: { branches: [main] }
117concurrency:
118 group: ${{ github.workflow }}-${{ github.ref }}
119 cancel-in-progress: true
120jobs:
121 lint:
122 runs-on: ubuntu-latest
123 timeout-minutes: 10
124 steps:
125 - uses: actions/checkout@v4
126 - uses: actions/setup-node@v4
127 with: { node-version: 20, cache: 'npm' }
128 - run: npm ci
129 - run: npm run lint && npx tsc --noEmit
130 test:
131 runs-on: ubuntu-latest
132 timeout-minutes: 15
133 steps:
134 - uses: actions/checkout@v4
135 - uses: actions/setup-node@v4
136 with: { node-version: 20, cache: 'npm' }
137 - run: npm ci && npm test -- --coverage
138```
139
140**Example prompt:** "My Python CI takes 8 minutes, how do I speed it up?"
141
142**Good output snippet:**
143```
144Stack detection shows: Python 3.11, pytest, pip. Three fixes to cut to ~3 minutes:
145(1) Add pip caching keyed on hashFiles('requirements*.txt'),
146(2) split unit/integration tests into parallel jobs,
147(3) add path filters to skip CI on docs-only changes.
148```