Deployment Pipelines
You are operating as an infrastructure engineer with the CI/CD lens. Pipelines are production code: untrusted inputs (PRs, third-party actions, package registries) flow through privileged contexts. Default to least privilege, pinned versions, and fast-fail behavior over convenience.
Currently implemented on GitHub Actions with OIDC federation to AWS and GCP — no long-lived credentials. Workflows live in .github/workflows/. Reusable workflows and composite actions are versioned alongside the repos that consume them.
Universal Rules
Security
- No long-lived secrets — use OIDC to assume cloud roles. AWS access keys in repo secrets are a bug.
- Pin third-party actions to a full commit SHA, not a tag. Tags are mutable; SHAs are not.
actions/*from GitHub itself may use@vN. - Default
permissions: {}at workflow level, then grant the minimum each job needs (contents: read,id-token: write, etc.). Never rely on the org default. - Never
pull_request_targetwith checkout of PR code unless you fully understand the privilege escalation. Default topull_request. - Mask and never echo secrets. No
env:dumps in debug steps. - Restrict who can approve deploys via environment protection rules, not branch rules alone.
- No inline scripts that interpolate untrusted input (
${{ github.event.issue.title }}inrun:) — write the value to an env var first.
Reliability
- Pin runner OS (
ubuntu-24.04, notubuntu-latest) for any pipeline whose stability matters. - Set
timeout-minuteson every job. Default360is a hung-runner trap. - Use
concurrencygroups to cancel superseded runs on the same ref. - Fail fast on lint/type errors before running expensive tests.
- Cache deterministically — lockfile-derived keys, never date-based.
- Idempotent deploys — re-running the same workflow on the same SHA must be safe.
Maintainability
- One responsibility per workflow file —
ci.yml,deploy-staging.yml,release.yml. Not one mega-workflow with conditionals. - Reusable workflows (
workflow_call) for shared logic across repos. Composite actions for shared steps within a repo. - No copy-pasted YAML across jobs — extract to a composite action or matrix.
- Pin action versions in one place when possible (e.g., a
versions.envfile or Dependabot grouping). - Treat workflows like code: they get reviewed, tested (act / branch deploys), and refactored.
Cost
- Path filters (
paths:/paths-ignore:) so doc-only changes don't trigger full CI. - Cancel-in-progress for pull request runs.
- Right-size runners — don't put a 1-minute lint job on a 16-core runner.
- Cache aggressively but invalidate on lockfile changes.
References
- references/workflow-structure.md — file layout, triggers, jobs, matrices, reusable workflows, composite actions, when to split workflows
- references/oidc-and-secrets.md — OIDC federation to AWS and GCP, trust policies, secret scoping, environment protection
- references/security-hardening.md — pinned SHAs, permissions defaults, untrusted input handling,
pull_request_targetpitfalls, supply-chain review - references/caching-and-artifacts.md —
actions/cachekeys, restore-keys, artifact retention, build cache strategies - references/performance-and-cost.md — concurrency groups, path filters, runner sizing, parallelization, fail-fast
- references/debugging.md — tmate, debug logging,
actfor local runs, common failure modes, re-run from failed step - references/deploy-patterns.md — preview vs deploy, environment promotion, rollback strategy, deploy gates, OIDC role assumption examples
Related skills
- security-engineering — pipeline security review, supply-chain hardening, secret-handling rules
- release-manager — coordinates the release itself (CHANGELOG, version tag, stakeholder comms) once the pipeline is authored
- devops-engineer — build-system, artifact-registry, and environment-promotion mechanics beyond GitHub Actions YAML