Write the pipeline once and reuse it everywhere: reusable workflows (workflow_call) for whole jobs, composite actions for shared steps. One source of truth for all repos.
| Reusable workflow | Composite action | |
|---|---|---|
| Reuses | Whole jobs (own runners, env, secrets) | A sequence of steps inside a job |
| File | .github/workflows/x.yml with on: workflow_call | action.yml with runs: using: composite |
| Called with | jobs.<id>.uses: | steps[].uses: |
| Secrets | secrets: inherit or explicit | Pass as inputs |
| Best for | Org-wide CI/CD templates | "setup java + cache + login" snippets |
Put shared ones in a central repo (e.g. my-org/.github or my-org/ci-templates) and version it with tags.
Reusable workflows can be nested up to 10 levels deep in total, and a caller can use a limited number of them per run. Keep the chain shallow: one template layer is usually enough.