Skill in engineering
github-actions-pipeline
Design, write, or fix GitHub Actions workflows for a project: a CI pipeline with the right triggers, concurrency, caching, matrix, and least-privilege permissions; pinned actions; reusable workflows and composite actions; deploy workflows with environments and OIDC instead of long-lived secrets; and the debugging moves for slow, flaky, or failing runs. Use when adding CI to a repository, when a pipeline is slow or flaky, when a workflow needs deploy or release steps, or when a security review flags workflow permissions.
- Arguments
- (optional) the project type, what the pipeline must do, or the failing workflow
Install
As a plugin
Bundled in the engineering plugin. Add the marketplace once, then install the bundle; it updates with the marketplace.
/plugin marketplace add KhaledSaeed18/dotclaude/plugin install engineering@dotclaudeAs a single item
Run from the project root; the skill lands under .claude/. Copy it to ~/.claude/ to make it global.
npx shadcn@latest add KhaledSaeed18/dotclaude/github-actions-pipelineFiles installed
.claude/skills/github-actions-pipeline/SKILL.md
What it does
A pipeline is trusted when it is fast enough to run on every push, deterministic enough that a red is a real failure, and locked down enough that a compromised dependency cannot use it. Design for those three before adding steps.
A CI workflow skeleton
name: ci
on:
pull_request:
push:
branches: [main]
permissions:
contents: read # top-level default; widen per job only
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
node: [20, 22]
steps:
- uses: actions/checkout@v4 # pin to a SHA in security-sensitive repos
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm typecheck
- run: pnpm test -- --reporter=junit --outputFile=junit.xml
- uses: actions/upload-artifact@v4
if: always()
with: { name: test-results-${{ matrix.node }}, path: junit.xml }
Rules
Triggers
pull_requestfor validation,pushto the default branch for post-merge and deploy,workflow_dispatchfor manual runs,schedulefor nightly or dependency checks. Path filters (paths:) to skip irrelevant runs, remembering that a required check that is skipped blocks merging unless the branch rule allows it.- Never
pull_request_targetwith a checkout of the PR head unless you understand it: it runs with write permissions on untrusted code.
Permissions
- Top-level
permissions: contents: read; each job adds only what it needs (pull-requests: writeto comment,id-token: writefor OIDC,packages: writeto publish). - No long-lived cloud keys in secrets; use OIDC federation (
aws-actions/configure-aws-credentialswith a role,google-github-actions/auth, Azure federated credentials). - Secrets never printed;
::add-mask::for derived values; noset -xin steps that touch them.
Pinning
- Third-party actions pinned to a full commit SHA with a version comment, bumped by Dependabot (
package-ecosystem: github-actions). First-partyactions/*at a major tag is an acceptable compromise in low-risk repos. - Tool versions from the repo's own files (
.nvmrc,.tool-versions,package.jsonengines), not hard-coded twice.
Speed
- Cache the package manager store via the setup action's
cache:input; cache build outputs (actions/cachekeyed on lockfile hash plus source hash) only when the build is expensive and the cache is safe. - Split into jobs that run in parallel (lint, typecheck, test, build) when each takes over a minute; keep one job when they are all fast, because job startup costs 20 to 40 seconds.
timeout-minuteson every job so a hang fails instead of consuming the runner for six hours.concurrencywithcancel-in-progresson pull requests so pushes supersede stale runs.
Determinism
--frozen-lockfile/npm ci/pip install -rwith hashes; nolatesttags; pinned runner images when the OS matters (ubuntu-24.04overubuntu-latestfor reproducibility).- Retries only for steps with known transient failure (network installs), via a retry action with a small count; a retried test is a flaky test to fix, not to hide.
Reuse
- A reusable workflow (
on: workflow_call) for a pipeline shared across repos; a composite action (action.ymlwithruns: using: composite) for a bundle of steps shared across jobs. Version them by tag.
Deploy workflows
jobs:
deploy:
needs: [test]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment:
name: production
url: https://app.example.com
permissions: { id-token: write, contents: read }
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with: { role-to-assume: arn:aws:iam::123456789012:role/gh-deploy, aws-region: eu-west-1 }
- run: ./scripts/deploy.sh
Environments carry the protection rules (required reviewers, wait timers, branch restrictions) and the environment-scoped secrets. Deploy from an artifact built in the tested job (actions/download-artifact), not from a fresh build, so what was tested is what ships.
Releases
Tag-triggered (on: push: tags: ['v*']), build, create the release with gh release create or softprops/action-gh-release, attach artifacts, publish packages with provenance (npm publish --provenance needs id-token: write).
Debugging
- Re-run with debug logging (
ACTIONS_STEP_DEBUGsecret or the "enable debug logging" checkbox) and read the raw log;gh run view <id> --log-failedgets the failing step's log locally (thefix-ciskill covers the loop). - Reproduce locally with the same commands and the same tool versions;
actfor a rough approximation of the runner. - For a flaky test, capture the seed and the artifact, and quarantine with a tracked issue rather than a retry.
- Timing: the run summary shows per-step durations; the slowest step is usually dependency install without cache or a test suite that should be sharded.
Review checklist
Least-privilege permissions; no pull_request_target misuse; actions pinned; frozen installs; caching keyed correctly; timeouts; concurrency; artifacts uploaded on failure; deploy from tested artifact with an environment and OIDC; no secrets in logs.
This is the skill as installed, rendered from its source on GitHub. Read it as Markdown.
More in engineering
- adversarial-reviewerReview code through three hostile personas - the Saboteur, the New Hire, and the Security Auditor - each required to find at least one issue. Use when a...
- api-design-reviewReview an API contract (REST or GraphQL) before or while it is implemented, checking resource naming, HTTP semantics, status codes, error shape...
- code-review-responseProcess code-review feedback with technical rigour. Understand each point, check it against the actual codebase, and respond with reasoning or...
- create-agentAuthor a new subagent for this repository end to end by scaffolding it with pnpm new, curating its tool allowlist, setting model, color, and memory in...
- create-commandAuthor a new slash command for this repository end to end by scaffolding it with pnpm new, writing the frontmatter and argument handling, drafting the...
- create-hookAuthor a new Claude Code hook for this repository end to end by scaffolding it with pnpm new, writing the hook script and its settings.json wiring...