Episode 7 β Reusable Workflows & DRY Pipelines
By now in this series, weβve built solid pipelines with:
- clean workflows
- proper triggers
- secure secrets
- fast builds using cache and artifacts
But thereβs one problem that shows up quickly as projects grow:
Too much copy-paste across workflows and repositories.
This episode is about fixing that using Reusable Workflows β a powerful feature that helps you keep pipelines DRY (Donβt Repeat Yourself).
The Problem: Copy-Paste CI/CD
Imagine you have:
- multiple frontend repos
- same CI logic everywhere
- same build + test steps repeated
Soon you face:
- inconsistent pipelines
- hard updates
- broken standards
Copy-paste worksβ¦ until it doesnβt.
1οΈβ£ What is a Reusable Workflow?
A reusable workflow is:
A complete GitHub Actions workflow that can be called by another workflow
Think of it as:
Workflow = function
Reusable workflow = shared function
Instead of repeating logic, you define it once and reuse it everywhere.
2οΈβ£ Reusable Workflow vs Composite Action (Important)
These two are often confused.
| Feature | Reusable Workflow | Composite Action |
|---|---|---|
| Reuse level | Full pipeline | Step-level |
| Can have jobs | β | β |
| Can use runners | β | β |
| Can use environments | β | β |
| Cross-repo reuse | β | β οΈ |
| Best for | CI/CD standards | Reusable steps |
π Rule of thumb:
- Steps reuse β Composite action
- Pipeline reuse β Reusable workflow
3οΈβ£ Creating a Reusable Workflow
Reusable workflows live in:
.github/workflows/
They must expose workflow_call.
Example: reusable CI workflow
name: Node CI
on:
workflow_call:
inputs:
node-version:
required: true
type: string
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
- run: npm test
This workflow:
- accepts inputs
- defines jobs
- can be reused by other repos
4οΈβ£ Calling a Reusable Workflow
From another workflow:
name: App CI
on: pull_request
jobs:
ci:
uses: my-org/shared-workflows/.github/workflows/node-ci.yml@v1
with:
node-version: 18
Key points:
-
usesis at job level - reference format:
owner/repo/path@version
5οΈβ£ Passing Secrets to Reusable Workflows
Reusable workflows donβt automatically inherit secrets.
You must pass them explicitly.
jobs:
ci:
uses: my-org/shared/.github/workflows/build.yml@v1
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
This keeps secrets:
- explicit
- controlled
- secure
6οΈβ£ Outputs from Reusable Workflows
Reusable workflows can return outputs.
Inside reusable workflow:
jobs:
build:
outputs:
artifact-name: dist
In caller workflow:
jobs:
deploy:
needs: ci
run: echo "Using artifact ${{ needs.ci.outputs.artifact-name }}"
This enables clean multi-stage pipelines.
7οΈβ£ Real-World Use Case
Common setup in teams:
org/ci-workflows
βββ frontend-ci.yml
βββ backend-ci.yml
βββ deploy.yml
Each repo:
jobs:
ci:
uses: org/ci-workflows/.github/workflows/frontend-ci.yml@v1
Benefits:
- consistent standards
- one place to update logic
- easy onboarding
- fewer mistakes
8οΈβ£ Common Mistakes π¨
β Using reusable workflows for small step reuse
β Forgetting workflow_call
β Hardcoding secrets inside reusable workflow
β Not versioning shared workflows
β Over-abstracting too early
Good abstractions:
- reduce duplication
- stay readable
- evolve gradually
Final Mental Model (Lock This In)
Composite action β reuse steps
Reusable workflow β reuse pipelines
If you understand this distinction, youβre already thinking at a senior level.
Whatβs Next?
π Episode 8:
Security, Permissions & the Fork PR Model
Weβll cover:
GITHUB_TOKEN- permissions
- why secrets are blocked in PRs
- how GitHub protects your pipelines
This episode is crucial for real-world and interview readiness π
Thanks for reading!
See you in the next episode π
Top comments (0)