Topic 2.3
Reusable Workflows & Composite Actions
In one line
Copy-pasting the same YAML across many repositories is the same anti-pattern Helm's own course warned against for Kubernetes manifests — reusable workflows and composite actions are how you define a pattern once and share it everywhere.
Key ideas
- 01
A genuinely common real problem once an organization has more than a handful of repositories: the SAME build-test-deploy pattern gets copy-pasted into each repository's own workflow file — and when that pattern needs to change (a new required security scan, say), every single copy needs to be found and updated individually, a genuinely error-prone, easy-to-miss process.
- 02
A REUSABLE WORKFLOW is a workflow file specifically designed to be CALLED by other workflows (
on: workflow_call), accepting INPUTS (parameters) and SECRETS explicitly passed to it — genuinely the same DRY (don't repeat yourself) principle Kubernetes' own Helm charts (Phase 7 of that course) apply to manifests, just applied to pipeline definitions instead. - 03
uses: my-org/shared-workflows/.github/workflows/build-and-test.yml@mainin a CALLING workflow invokes a reusable workflow defined in a genuinely different repository — one central, well-tested definition can be shared across an entire organization's repositories, with each one calling it and supplying only its own specific inputs. - 04
A COMPOSITE ACTION solves a related but genuinely distinct problem: bundling several STEPS (not a whole separate workflow) into one single, reusable, named action — genuinely useful for a specific, repeated sequence (checkout + setup-java + cache restore, say) that shows up as three or four steps in many different workflows, collapsed into one clean, single step everywhere it's used.
- 05
The practical distinction: reach for a REUSABLE WORKFLOW when you want to share an entire job or pipeline structure (with its own runner, its own full set of steps); reach for a COMPOSITE ACTION when you want to share a smaller, specific SEQUENCE OF STEPS that gets embedded within a larger job someone else is still defining themselves.
- 06
Both mechanisms mean an organization-wide policy change (adding a mandatory security scan step, upgrading a shared Java version) can be made ONCE, in the shared definition, and every repository calling it picks up the change automatically the next time its pipeline runs — genuinely the same 'define once, apply everywhere, update centrally' benefit Kubernetes' own StorageClasses (Phase 2.4 of that course) provide for storage provisioning.
Code & diagrams
A reusable workflow shares a whole job; a composite action shares a handful of steps within one.
A reusable workflow — defined once, called from any number of repositories.
# In my-org/shared-workflows repo: .github/workflows/build-test.yml
on:
workflow_call:
inputs:
java-version:
type: string
default: "21"
secrets:
registry-token:
required: true
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: ${{ inputs.java-version }}
distribution: "temurin"
- run: mvn clean package
- run: echo "Publishing with token" # would use secrets.registry-tokenAny repository can call the shared workflow, supplying only its own specific values.
on:
push:
branches: [main]
jobs:
ci:
uses: my-org/shared-workflows/.github/workflows/build-test.yml@main
with:
java-version: "17" # this repo specifically needs Java 17
secrets:
registry-token: ${{ secrets.REGISTRY_TOKEN }}Explain it without notes
What real, organization-wide problem do reusable workflows solve that individually copy-pasting the same YAML into every repository does not?
You need to share a repeated 3-step sequence (checkout, setup, cache) that gets embedded within many different, otherwise-different jobs. Should you use a reusable workflow or a composite action, and why?
Practice
If you have access to more than one repository, extract a common build-and-test pattern into a reusable workflow in a shared repository, and call it from at least one other repository.
Identify a repeated sequence of 2-3 steps across your own workflows (even hypothetically) that would genuinely benefit from being packaged as a composite action.
Trade-offs
- ↔
Reusable workflows and composite actions genuinely reduce duplication and centralize maintenance, but they also add a real layer of INDIRECTION — understanding what a specific repository's pipeline actually does now requires following a reference into a different, shared repository, rather than reading one self-contained file top to bottom; this is a worthwhile trade at real organizational scale, but adds genuine friction for a small team or a single, simple repository that doesn't yet have this duplication problem to solve.
Done when you can
I understand the problem reusable workflows and composite actions both solve: avoiding copy-pasted pipeline YAML.
I can distinguish when to use a reusable workflow (a whole job) versus a composite action (a sequence of steps).
I can create a reusable workflow and call it from a different repository, passing inputs and secrets.