CI/CD pipeline setup — GitHub Actions, testing, linting, deployment. Use when setting up CI from scratch, adding GitHub Actions, automating tests, wiring up deployment, or improving an existing build pipeline.
A good CI pipeline runs the same checks a developer would run locally, in the same order, fast enough that contributors get feedback before they context-switch. Lint first, then test, then build, then deploy — and never let secrets or unpinned actions sneak in.
Order stages from cheapest to most expensive so failures surface early:
Trigger on push to main and on pull_request. Pin action versions
explicitly (, never ). Cache dependencies
(pip, npm, cargo) so reruns are fast. Set on every job
so a hung step cannot eat your minutes budget.
actions/checkout@v4@latesttimeout-minutesRun the same commands as local development — if make test works
locally, that is what CI should call. Use matrix builds for OS or
language-version combinations only when you actually need to support
them. Use fail-fast: true in matrix strategies so one failure cancels
the rest.
Never put secrets in workflow files. Store them in GitHub Secrets and
inject through ${{ secrets.NAME }}. Use the permissions key on each
job to limit the GITHUB_TOKEN scope to the minimum needed. Pin
third-party actions to a commit SHA, not just a version tag, so an
attacker who compromises a tag cannot inject code into your build.
Agent-specific failure modes — provider-neutral pause-and-self-check items:
@v4.echo ${{ secrets.FOO }} — pass secrets only through inputs or masked env vars.if: github.ref == 'refs/heads/main' or a label.timeout-minutes on jobs. A hung step runs indefinitely and eats your minutes budget. Every job and every slow step needs a timeout — not just the slow ones you expect.