Git, CI/CD & GitOpsCXVIII · Final Reference ArchitectureCI
The GitHub Actions control plane — the CI fleet
What you'll learn
- Identify the four primitives a production Actions fleet depends on: reusable workflows, composite actions, environment protection rules, and OIDC tokens
- Distinguish the Actions control plane (GitHub) from the runner fleet (customer-operated)
- Recognise why environment protection rules are the only admission-control mechanism built into the CI plane
- Configure an Actions workflow that authenticates to the cloud with an OIDC token scoped by sub and aud
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
The Actions fleet is the CI control plane this course is
written against: workflows, reusable workflows, composite
actions, environment protection rules, OIDC tokens, and
the runner fleet that executes them. Treating Actions as a
fleet - with named owners, an SLA, and a backlog - is what
turns CI from “scripts in .github/workflows” into the
admission-control plane for every artefact the rest of the
system deploys.
The four primitives
A production Actions fleet depends on four primitives. Forgetting any one of them turns the CI plane into a place where scripts can run but no one can prove what they did.
flowchart LR
WF["Reusable workflow"] -->|"calls"| CA["Composite action"]
CA -->|"runs on"| RUN["Ephemeral runner"]
RUN -->|"emits OIDC token"| WF
WF -->|"targets"| ENV["Environment with protection rules"]
ENV -->|"gates"| DEPLOY["Deploy step"]
- Reusable workflows. A workflow that is called by
other workflows with a typed contract. The reusable
workflow defines what inputs are accepted, what secrets
are required, and what outputs are produced. Production
teams maintain one reusable workflow per pipeline shape
- build, test, deploy, plan - and call it from every application repo rather than copying the steps.
- Composite actions. A bundle of steps that runs on the same runner and shares environment. Used for cross-cutting concerns: setting up a toolchain, signing an artefact, configuring a registry login.
- Environments and protection rules. An environment is a named target with required reviewers, wait timers, and branch restrictions. The only built-in admission-control mechanism in Actions; the gate every production deploy passes through.
- OIDC tokens. A short-lived identity issued by GitHub to the running workflow, scoped to the repository, the workflow, and the environment. The only way a production workflow should authenticate to a cloud; the alternative - long-lived secrets - is what collapses B2 and B5 into one identity.
The control plane is separate from the fleet
GitHub operates the Actions control plane: the workflow runtime, the secret store, the OIDC issuer, the protection rules. The customer operates the runner fleet: the machines that execute the steps. The split is deliberate. A team that relies entirely on GitHub-hosted runners has outsourced execution but still owns the workflow definition; a team that runs self-hosted runners owns execution as well.
The split has three consequences:
- Trust is not uniform. The workflow definition is trusted by GitHub’s controls; the runner is trusted by the customer’s controls. The two together make the audit chain.
- Pinning the runner image is the customer’s job. GitHub-hosted runners are pinned by GitHub; customer runners are pinned by the image the team builds, which is the topic of the runner-fleet lesson.
- OIDC token issuance is the control plane’s job. Anyone who can edit a workflow in the repo can cause an OIDC token to be issued; the trust placed in the workflow definition is therefore the trust placed in the people who can edit it. Branch protection is part of the fleet, not just the source plane.
Operating the fleet
The Actions fleet is operated as a product. Three operational patterns recur in mature organisations:
- One reusable workflow per pipeline shape. Build, test, plan, deploy. Application repos call into them by name; no application repo defines its own build steps from scratch.
- Environments map to deploy targets. An environment
named
productioncarries a required reviewer list and a wait timer; an environment namedstagingcarries no wait timer but is restricted to themainbranch. - OIDC audiences are namespaced. One IAM role per
environment; the audience claim of the OIDC token
selects the role. A workflow with audience
aws:prodcannot assume theaws:stagingrole.
echo "Inspect the OIDC token issued to a workflow run:"
gh run view "$RUN_ID" --json jobs \
| jq '.jobs[].steps[] | select(.name=="Configure AWS credentials") | .conclusion'
The configuration above uses gh run view and jq; both
are first-class citizens of the Actions fleet on a
production engineer’s laptop.
Production discipline
- Reusable workflows for everything that is cross-repo. Copying a workflow is a future incident waiting to happen.
- Environments for everything that is high-blast-radius. A production deploy that does not pass through an environment with required reviewers is a deploy that cannot be gated after the fact.
- OIDC audiences for everything that touches the cloud. A long-lived cloud credential in the Actions secrets is a B2/B5 violation waiting to be exploited.
Cross-course references
- This course, Part XIV (ReusableWorkflows) - the pattern this lesson applies at fleet scale.
- This course, Part XXIII (OIDC) - the trust mechanism the fleet standardises on.
- GitHub Docs - security hardening for Actions - the fleet hardening checklist.
Quiz
Knowledge check · 4 questions
Q1. A team uses GitHub Actions for both staging and production. They store one long-lived AWS access key in the repo secrets and use it from a single workflow with environment variables to choose the role. What is the audit failure?
Q2. Environment protection rules in GitHub Actions are the only built-in admission-control mechanism for production deploys and are sufficient on their own if reviewers and wait timers are configured.
Q3. Name the four primitives a production Actions fleet depends on, and explain why a workflow that defines its own build steps from scratch, instead of calling a reusable one, is a fleet-violation.
Q4. Redesign the Actions fleet so that the audit chain is intact and the cloud credentials are short-lived.
A team has 40 application repositories. Each one defines its own build workflow inline in `.github/workflows/build.yml`. The same workflow file is copied and edited 40 times. The cloud credential is a long-lived AWS access key in the repo secrets. There is no production environment; staging and production are deployed by the same workflow with environment variables. Three of the 40 builds have introduced supply-chain vulnerabilities that were patched in only some of the copies.
Passing score: 75%. Answers are checked in this browser.