Reusable Workflows vs. Composite Actions: DRY Your CI/CD

Reusable Workflows vs. Composite Actions: DRY Your CI/CD
If you find yourself copying and pasting the same 50 lines of YAML into ten different repositories, you are violating a core engineering principle: DRY (Don't Repeat Yourself). GitHub Actions provides two distinct ways to share code across your organization. Reusable Workflows allow you to "call" entire multi-job files, while Composite Actions let you bundle multiple shell steps into a single reusable unit.
Table of Contents
- The Maintenance Nightmare of Copy-Paste
- What are Composite Actions?
- What are Reusable Workflows?
- Key Differences in Execution
- When to Use Which?
- Frequently Asked Questions
- Key Takeaway
The Maintenance Nightmare of Copy-Paste
Imagine your company has 50 microservices. Each one needs to run a specialized security scan before deploying. If you copy that 50-line YAML block into every repo, and the security team suddenly updates the scan's requirements, you now have to manually edit 50 different files.
By centralizing that logic in a single reusable unit, you can update it once, and every repository in your organization instantly inherits the fix.
What are Composite Actions?
A Composite Action is a way to bundle multiple steps into one single "step."
Instead of writing npm install, npm test, and npm lint in every workflow, you can create a action.yml file that groups them together and calls them like a standard community action.
Pros of Composite Actions:
- Simplify Workflows: Instead of 10 steps in your main YAML, you have 1.
- Access to Shell: You can run raw bash, Python, or node scripts.
- Repository Agnostic: You can even host these in a central repository and call them from any private repo in your organization.
What are Reusable Workflows?
While Composite Actions share steps, Reusable Workflows share entire jobs.
A reusable workflow is a complete, standalone YAML file stored in .github/workflows. It becomes "callable" when you define the trigger on: workflow_call.
Pros of Reusable Workflows:
- Complete Jobs: They can contain multiple parallel jobs, matrix strategies, and secrets.
- Native Logging: In the GitHub UI, a reusable workflow shows up as its own distinct job, making it much easier to debug than a hidden composite step.
- Strict Input/Output: You can define mandatory inputs (like
environmentorversion-number) that the calling workflow must provide.
Key Differences in Execution
| Feature | Composite Actions | Reusable Workflows |
|---|---|---|
| Level of abstraction | Steps (runs inside a job) | Jobs (replaces a job) |
| Multi-Job support? | No | Yes |
| Secrets Support? | Indirect (via inputs) | Direct (via secrets: inherit) |
| UI Visibility | Bunched into one step | Appears as a distinct job |
When to Use Which?
The rule of thumb is simple:
- Use Composite Actions when you want to simplify the Steps list inside an existing job. Use this for things like "Setup my specialized dev environment" or "Clean up temporary files".
- Use Reusable Workflows when you want to standardize an entire process. Use this for "The Standard Production Deployment" or "The Universal Security Scan".
Frequently Asked Questions
Can a reusable workflow call another reusable workflow? GitHub supports nesting up to 4 levels deep. You can have a "Production Workflow" that calls a "Security Workflow" which calls a "Logging Workflow".
Do I have to make my repo public to share actions? No. If your organization is on a GitHub Pro or Team account, you can share actions and reusable workflows across all your private repositories as long as they belong to the same GitHub Organization.
Key Takeaway
Scaling automation across a company requires modularity. By moving repetitive shell logic into Composite Actions and standardizing entire delivery pipelines with Reusable Workflows, you create a centralized "DevOps Toolkit" that makes your organization faster, more secure, and significantly easier to maintain.
Read next: Continuous Integration (CI): Building a Bulletproof Pipeline →
