GitHub Actions: From First Workflow to Reusable
GitHub Actions in 30 minutes: enough to ship; the reusable pattern is what scales it across an org.
Step 1: First workflow
# .github/workflows/ci.yml
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: echo "hello"
Step 2: Real CI
- Add: checkout, setup-node, npm install, npm test.
- Configure caching for node_modules.
Step 3: Make it reusable
Reusable workflows are the leverage that turns Actions from a per-repo hack into a platform. Refactor once, consume many times.
- Trigger. Replace
on: [push]withon: workflow_call; the workflow becomes callable from other repos. - Inputs. Define parameters for variation (Node version, test command, environment); defaults cover the common case.
- Shared repo. Move the workflow into
org/shared-ci; treat it as production code, reviewed and tested. - Versioning. Tag releases (
v1,v2); consumers pin to a tag, not a branch, to avoid surprise breakage.
Step 4: Consume from other repos
Consumers reference the shared workflow by repo path and tag. The consumer's CI shrinks to a few lines; logic lives in the shared repo.
- Reference.
uses: org/shared-ci/.github/workflows/ci.yml@v1in the consumer's workflow file. - Inputs. Pass
with:values to override defaults (e.g.node-version: 20). - Single source of truth. Update the shared workflow once; all consumers pick up the change at the next run on the new tag.
- Permissions. Consumers must explicitly grant
permissions:for what the shared workflow needs; default is read-only.
Antipatterns
- Copy-pasted workflows across 50 repos. Drift.
- Pinning to @main. Surprise breakage.
- Reusable workflow as 100% rigid. Inputs allow flexibility.
What to do this week
Three moves. (1) Run the tutorial end-to-end on your own laptop / sandbox. (2) Apply the pattern to one production workload. (3) Document the variations you needed; share with the team.