Skip to content

GitHub Actions: Org-Wide CI/CD

FieldValue
TypeSkill Resource
Source~/.copilot/skills/platform/references/github-actions.md
DescriptionNot specified

Source Content

GitHub Actions: Org-Wide CI/CD

CI as a product: versioned, reusable, observable. Copy-pasted workflows are the leading cause of CI drift — fix that once at the org level, and replace long-lived cloud secrets with OIDC.

Contents

Use me for / Don’t use me for

Use for: bootstrapping CI for a new repo, deduplicating workflows across an org via a shared .github repo, replacing static AWS_*/GCP_* secrets with OIDC, hardening branch protection, adding cosign signing / SBOM / Trivy scanning.

Don’t use for: application Dockerfile authoring (references/devops.md), Kubernetes manifests / Helm charts (references/helm/, references/kubernetes-operator.md), release-note prose (the technical-writing skill), org-level secret-rotation policy (the security skill).

How it’s built

  1. Inventory. What runs today, what’s duplicated across repos, what’s flaky, what holds long-lived secrets.
  2. Centralize. Establish org/.github with versioned reusable workflows (node-ci.yml, go-ci.yml, image-build.yml, helm-publish.yml, deploy-argocd.yml). App repos become thin callers.
  3. Federate identity. OIDC to AWS / GCP / 1Password Connect, permissions: id-token: write only where needed.
  4. Cache deliberately. setup-node with cache: pnpm, setup-go with cache: true, type=gha,mode=max,scope=... for buildx.
  5. Constrain concurrency. ${{ github.workflow }}-${{ github.ref }}, cancel PRs, never cancel main.
  6. Sign and scan. cosign sign --yes <image>@<digest>, trivy image --exit-code 1 --severity HIGH,CRITICAL, SBOM published as an artifact.
  7. Enforce. Branch-protection ruleset (YAML), required checks listed, actions pinned to SHAs.
  8. Validate. scripts/lint_workflows.sh .github/workflows.

Reusable workflows

A repo’s own workflow is a thin caller into org/.github/.github/workflows/<lang>-ci.yml@v1. This is what stops 40 copies of the same YAML from drifting independently.

OIDC federation

Replace static AWS_* / GCP_* secrets with OIDC trust to the target IAM role / Workload Identity pool. aws-actions/configure-aws-credentials (or the GCP equivalent) takes the OIDC token — no long-lived key ever lands in GitHub secrets.

Caching and concurrency

  • Cache keys are lockfile-hashed, never a bare branch name.
  • concurrency: group: ${{ github.workflow }}-${{ github.ref }} with cancel-in-progress: true on PRs — never on main.
  • paths: filters keep unrelated changes from triggering the full suite.

Signing and scanning

Every container image: cosign sign --yes <image>@<digest>, trivy image --exit-code 1 --severity HIGH,CRITICAL, and a published SBOM. Downstream deploys reference the digest, never a floating tag.

Branch protection

A ruleset (.github/rulesets/*.json or .github/settings.yml) names required status checks explicitly. Actions are pinned to a full 40-hex commit SHA — never @main, never an unpinned @v* from an untrusted publisher.

Validate

scripts/lint_workflows.sh [workflows-dir] (defaults to .github/workflows) runs actionlint if installed (else a Python/grep structural fallback), then three house-rule checks with no required external tool:

  • every uses: pinned to a full 40-hex commit SHA,
  • no bare long-lived AWS_*/GCP_* credential-shaped env var (flagged as a warning — OIDC is the house preference),
  • a ruleset file, if present, actually mentions required_status_checks / branch_protection.

References