rule-ci-cd
MANDATORY when editing files matching [".github/**/*.yml"]. When working on GitHub Actions workflows in .github/
SKILL.md.claude/skills/rule-ci-cd/SKILL.md
GitHubCI/CD Rules
Per-Application CD Workflow Structure
ALWAYS structure CD workflows as a three-job pipeline: checks -> deploy -> send-slack-notification. The deploy job MUST use max-parallel: 1 and fail-fast: false to serialize environment deployments.
Example from codebase:
# From .github/workflows/cd-nofos.yml
jobs:
checks:
uses: ./.github/workflows/ci-nofos.yml
deploy:
needs: [checks]
uses: ./.github/workflows/deploy-nofos.yml
send-slack-notification:
if: failure()
Reusable Workflow Composition
ALWAYS extract shared CI/CD logic into reusable workflows via workflow_call when the same job-level logic is needed by more than one workflow. NEVER duplicate multi-step job definitions across workflow files.
Example from codebase:
# From .github/workflows/ci-frontend-e2e.yml
create-report:
if: ${{ !cancelled() }}
needs: e2e-tests-local
uses: ./.github/workflows/e2e-create-report.yml
secrets: inherit
with:
run_id: ${{ github.run_id }}
Composite Actions for Step-Level Reuse
ALWAYS use composite actions under .github/actions/ for step-level reuse. NEVER duplicate the same sequence of steps in multiple jobs.
Example from codebase:
# From .github/actions/e2e/action.yml
name: Run Playwright
inputs:
version:
required: true
target:
default: "local"
total_shards:
default: "1"
runs:
using: "composite"
steps:
- name: Validate environment
shell: bash
run: |
if [[ $PLAYWRIGHT_TARGET_ENV != "local" && $PLAYWRIGHT_TARGET_ENV != "staging" ]]; then exit 1; fi
Workflow Naming Convention
ALWAYS name CI workflows ci-{app}.yml and CD workflows cd-{app}.yml. ALWAYS use descriptive prefixes: deploy-{app}.yml, vulnerability-scans-{app}.yml, e2e-{target}.yml, lint-{description}.yml.
Path-Filtered Triggers with Shared Modules
ALWAYS include paths: filters on push triggers. ALWAYS include infra/modules/** in the paths filter for all service CD workflows.
Example from codebase:
# From .github/workflows/cd-api.yml
on:
push:
branches: ["main"]
paths:
- "api/**"
- "infra/api/**"
- "infra/modules/**"
Environment Promotion with Prod-First Ordering
ALWAYS follow: push-to-main deploys to ["dev", "staging"], release deploys to ["prod", "training"]. ALWAYS list "prod" before "training" in the release matrix. NEVER order training before prod.
Concurrency Controls
ALWAYS set a concurrency group on deploy workflows keyed to the environment name. ALWAYS use cancel-in-progress: true on CI workflows.
Example from codebase:
# From .github/workflows/deploy-nofos.yml
concurrency: cd-nofos-${{ inputs.environment || 'dev' }}
Guard Against Null Inputs on Push Triggers
ALWAYS handle inputs.environment being null on push events. ALWAYS include a null check in expressions referencing inputs.environment.
Example from codebase:
# From cd-api.yml
fail_on_vulns: ${{ ! contains(fromJSON(inputs.environment != null && format('["{0}"]', inputs.environment) || github.ref_name == 'main' && '["staging"]' || '["dev"]'), 'staging') }}
Cross-Repo Deployment
NEVER use the generic deploy.yml for apps sourced from external repositories. ALWAYS use a dedicated deploy-{app}.yml that handles external checkout and non-standard build paths.
Docker Image Caching
ALWAYS use actions/cache/save and actions/cache/restore to pass Docker images between CI and CD jobs. ALWAYS include github.run_id in the cache key.
Example from codebase:
# From .github/workflows/ci-nofos.yml
- uses: actions/cache/save@v4
with:
path: /tmp/docker-image.tar
key: nofos-image-${{ github.sha }}-${{ github.run_id }}
App-Specific Git Hashes for Container Reuse
ALWAYS use the most recent commit hash within each app's folder (not repo-level HEAD) for container image tagging. MUST use fetch-depth: 1000 on checkout.
Dual Vulnerability Scanning
ALWAYS run Trivy + Anchore/Grype + Dockle on all deployed images. ALWAYS manage false positives through skip files and ignore lists, NEVER by disabling scans.
Explicit Minimal Permissions
ALWAYS declare explicit permissions: blocks requesting only minimum access. NEVER assume read is sufficient when the workflow updates resources.
E2E Test Sharding
ALWAYS shard Playwright tests with 4 shards. ALWAYS merge blob reports via a separate create-report job. ALWAYS use if: ${{ !cancelled() }} on the report job.
E2E Spoofed Login
ALWAYS use spoofed session cookies for authenticated e2e tests. NEVER script actual login.gov authentication in CI.
Governance Linters
ALWAYS implement governance automation as scripts under .github/linters/scripts/ with lint-*.yml workflows. ALWAYS support --dry-run mode.
Feature Flags in Terraform
ALWAYS gate new API capabilities behind ENABLE_{FEATURE}_ENDPOINTS = 1 in Terraform configs. ALWAYS enable in dev/staging first, then prod.
No Bundled Unrelated Changes
NEVER bundle unrelated changes with CD workflow modifications. Each PR touching CD workflows MUST focus on a single concern.
Context Enrichment
When generating significant CI/CD changes (new workflow, new deployment pipeline, sharding changes), enrich your context:
- Call
get_architecture_section("ci-cd")from thesimpler-grants-contextMCP server to understand CI/CD architectural principles - Call
get_rule_detail("infra")for infrastructure patterns that CI/CD interacts with - Consult Compound Knowledge for indexed documentation on pipeline conventions, deployment patterns, and environment promotion
Related Rules
When working on GitHub Actions workflows, also consult these related rules:
infra.mdc— three-layer Terraform structure, feature flags, environment configurationcross-domain.mdc— feature flag conventions, SSM parameter requirements
Specialist Validation
When generating or significantly modifying CI/CD code:
For simple changes (updating a path filter, fixing a step): No specialist invocation needed — the directives in this rule file are sufficient.
For moderate changes (new job, new composite action):
Invoke deployment-verification-agent to validate pipeline safety.
For complex changes (new workflow, new deployment pipeline, new sharding strategy): Invoke the following specialists (run in parallel where possible):
deployment-verification-agent— pipeline safety, environment promotion, concurrency controlsperformance-oracle— CI performance (caching efficiency, shard balance, unnecessary steps)security-sentinel— permissions blocks, secret handling, no token exposure in logs