Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Constructs secure, efficient CI/CD pipelines with supply chain security (SLSA), monorepo optimization, caching strategies, and parallelization patterns for GitHub Actions, GitLab CI, and Argo Workflows. Use when setting up automated testing, building, or deployment workflows.
.claude/skills/ancoleman-building-ci-pipelines/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 99% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 96% | 0% |
| case-17 | ✗→✓ | ▲ Improved | 101% | 0% |
| case-09 | ✓→✗ | ▼ Worse | 112% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 124% | 0% |
CI/CD pipelines automate testing, building, and deploying software. This skill provides patterns for constructing robust, secure, and efficient pipelines across GitHub Actions, GitLab CI, Argo Workflows, and Jenkins. Focus areas: supply chain security (SLSA), monorepo optimization, caching, and parallelization.
Invoke when:
GitHub-hosted → GitHub Actions (SLSA native, 10K+ actions, OIDC) GitLab-hosted → GitLab CI (parent-child pipelines, built-in security) Kubernetes → Argo Workflows (DAG-based, event-driven) Legacy → Jenkins (migrate when possible)
| Feature | GitHub Actions | GitLab CI | Argo | Jenkins | |---------|---------------|-----------|------|---------| | Ease of Use | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | | SLSA | Native | Manual | Good | Manual | | Monorepo | Good | Excellent | Manual | Plugins |
yaml# GitHub Actions name: CI on: [push, pull_request] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm run lint test: needs: lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm test build: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm run build
yamltest: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] node-version: [18, 20, 22] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm test
9 jobs (3 OS × 3 versions) in parallel: 5 min vs 45 min sequential.
yamlbuild: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # Required for affected detection - uses: actions/setup-node@v4 with: node-version: 20 - name: Build affected run: npx turbo run build --filter='...[origin/main]' env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ vars.TURBO_TEAM }}
60-80% CI time reduction for monorepos.
yamlname: SLSA Build on: push: tags: ['v*'] permissions: id-token: write contents: read packages: write jobs: build: runs-on: ubuntu-latest outputs: digest: ${{ steps.build.outputs.digest }} steps: - uses: actions/checkout@v4 - name: Build container id: build uses: docker/build-push-action@v5 with: push: true tags: ghcr.io/${{ github.repository }}:${{ github.sha }} provenance: needs: build permissions: id-token: write actions: read packages: write uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.10.0 with: image: ghcr.io/${{ github.repository }} digest: ${{ needs.build.outputs.digest }} registry-username: ${{ github.actor }} secrets: registry-password: ${{ secrets.GITHUB_TOKEN }}
Verification:
bashcosign verify-attestation --type slsaprovenance \ --certificate-identity-regexp "^https://github.com/slsa-framework" \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ ghcr.io/myorg/myapp@sha256:abcd...
yamldeploy: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - uses: actions/checkout@v4 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole aws-region: us-east-1 - name: Deploy run: aws s3 sync ./dist s3://my-bucket
Benefits: No stored credentials, 1-hour lifetime, full audit trail.
yamlsecurity: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Gitleaks (secret detection) uses: gitleaks/gitleaks-action@v2 - name: Snyk (vulnerability scan) uses: snyk/actions/node@master env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - name: SBOM generation uses: anchore/sbom-action@v0 with: format: spdx-json output-file: sbom.spdx.json
yaml- uses: actions/setup-node@v4 with: node-version: 20 cache: 'npm' # Auto-caches ~/.npm - run: npm ci
Supported: npm, yarn, pnpm, pip, poetry, cargo, go
yaml- uses: actions/cache@v4 with: path: | ~/.cargo/bin ~/.cargo/registry target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo-
yaml- name: Nx Cloud (build outputs) run: npx nx affected -t build env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} - name: Vite Cache uses: actions/cache@v4 with: path: '**/node_modules/.vite' key: vite-${{ hashFiles('package-lock.json') }} - name: TypeScript Cache uses: actions/cache@v4 with: path: '**/tsconfig.tsbuildinfo' key: tsc-${{ hashFiles('tsconfig.json') }}
Result: 70-90% build time reduction.
yamljobs: unit-tests: steps: - run: npm run test:unit integration-tests: steps: - run: npm run test:integration e2e-tests: steps: - run: npm run test:e2e
All three run simultaneously.
yamltest: strategy: matrix: shard: [1, 2, 3, 4] steps: - run: npm test -- --shard=${{ matrix.shard }}/4
20min test suite → 5min (4x speedup).
yamltest: strategy: matrix: python-version: ['3.10', '3.11', '3.12'] steps: - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - run: pipx install poetry - run: poetry install - run: poetry run ruff check . - run: poetry run mypy . - run: poetry run pytest --cov
yamltest: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] rust: [stable, nightly] steps: - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} components: rustfmt, clippy - uses: Swatinem/rust-cache@v2 - run: cargo fmt -- --check - run: cargo clippy -- -D warnings - run: cargo test
yamltest: steps: - uses: actions/setup-go@v5 with: go-version: '1.23' cache: true - run: go mod verify - uses: golangci/golangci-lint-action@v4 - run: go test -v -race -coverprofile=coverage.txt ./...
yamltest: strategy: matrix: node-version: [18, 20, 22] steps: - uses: pnpm/action-setup@v3 with: version: 8 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' - run: pnpm install --frozen-lockfile - run: pnpm run lint - run: pnpm run type-check - run: pnpm test
DO:
actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11permissions: { contents: read }DON'T:
pull_request_target without validationDO:
strategy.fail-fast: trueDON'T:
yaml# Enable debug logging env: ACTIONS_STEP_DEBUG: true ACTIONS_RUNNER_DEBUG: true # SSH into runner - uses: mxschmitt/action-tmate@v3
For detailed guides, see references:
Complete runnable workflows:
Token-free execution:
testing-strategies - Test execution strategies (unit, integration, E2E) deploying-applications - Deployment automation and GitOps auth-security - Secrets management and authentication observability - Pipeline monitoring and alerting
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-02 | pass→pass | 11,713 | 8,108 | -31% | 1 | 1 | 0% | 2,113 | 4,727 | +124% | 0 | 0 | — |
case-01 | fail→pass | 16,053 | 16,607 | +3% | 1 | 1 | 0% | 3,271 | 6,495 | +99% | 0 | 0 | — |
case-03 | fail→pass | 14,301 | 8,529 | -40% | 1 | 1 | 0% | 2,427 | 4,747 | +96% | 0 | 0 | — |
case-04 | fail→fail | 14,854 | 8,063 | -46% | 1 | 1 | 0% | 2,842 | 4,677 | +65% | 0 | 0 | — |
case-05 | pass→pass | 13,728 | 12,232 | -11% | 1 | 1 | 0% | 2,544 | 5,309 | +109% | 0 | 0 | — |
case-06 | pass→pass | 9,169 | 7,609 | -17% | 1 | 1 | 0% | 1,741 | 4,598 | +164% | 0 | 0 | — |
case-07 | pass→pass | 9,230 | 6,085 | -34% | 1 | 1 | 0% | 1,748 | 4,311 | +147% | 0 | 0 | — |
case-08 | pass→pass | 9,061 | 6,015 | -34% | 1 | 1 | 0% | 1,668 | 4,299 | +158% | 0 | 0 | — |
case-09 | pass→fail | 11,173 | 5,448 | -51% | 1 | 1 | 0% | 1,976 | 4,198 | +112% | 0 | 0 | — |
case-10 | pass→pass | 12,345 | 7,858 | -36% | 1 | 1 | 0% | 2,219 | 4,671 | +111% | 0 | 0 | — |
case-11 | pass→pass | 9,898 | 4,978 | -50% | 1 | 1 | 0% | 1,665 | 4,077 | +145% | 0 | 0 | — |
case-12 | pass→pass | 20,570 | 14,235 | -31% | 1 | 1 | 0% | 3,040 | 5,480 | +80% | 0 | 0 | — |
case-13 | pass→pass | 13,359 | 5,859 | -56% | 1 | 1 | 0% | 1,988 | 4,156 | +109% | 0 | 0 | — |
case-14 | pass→pass | 4,130 | 3,651 | -12% | 1 | 1 | 0% | 642 | 3,849 | +500% | 0 | 0 | — |
case-15 | pass→pass | 6,214 | 4,544 | -27% | 1 | 1 | 0% | 1,071 | 3,896 | +264% | 0 | 0 | — |
case-16 | pass→pass | 9,465 | 8,107 | -14% | 1 | 1 | 0% | 1,552 | 4,584 | +195% | 0 | 0 | — |
case-17 | fail→pass | 13,326 | 7,739 | -42% | 1 | 1 | 0% | 2,235 | 4,496 | +101% | 0 | 0 | — |
case-18 | pass→pass | 6,657 | 4,080 | -39% | 1 | 1 | 0% | 1,275 | 3,956 | +210% | 0 | 0 | — |
case-19 | pass→pass | 6,887 | 6,587 | -4% | 1 | 1 | 0% | 1,300 | 4,430 | +241% | 0 | 0 | — |
case-20 | pass→pass | 13,717 | 14,034 | +2% | 1 | 1 | 0% | 2,402 | 5,857 | +144% | 0 | 0 | — |
case-21 | pass→pass | 6,897 | 8,035 | +16% | 1 | 1 | 0% | 1,340 | 4,854 | +262% | 0 | 0 | — |
case-22 | fail→fail | 8,497 | 9,006 | +6% | 1 | 1 | 0% | 1,521 | 4,936 | +225% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.