Reusable Workflows & Composite Actions
In this tutorial, you'll learn about Reusable Workflows & Composite Actions. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Reusable workflows and Composite actions let you define automation once and use it across multiple workflows, repositories, or organizations, reducing duplication and enforcing consistency.
What You'll Learn
In this tutorial, you'll learn the difference between reusable workflows and Composite actions, how to call a reusable workflow from another workflow, how to create Composite actions, and how to pass inputs and secrets between them.
Why It Matters
Without reusability, every Repository duplicates the same CI logic. When you need to update a build step, you edit 50 workflows across 30 repositories. Reusable workflows let you define the pipeline once and call it from anywhere. Changes propagate automatically to every caller.
Real-World Use
Doda Browser maintains a reusable deployment workflow that all 12 Microservices use. The workflow handles build, test, Docker image creation, registry push, and deployment to Kubernetes. A change to the deployment Process in one place updates all 12 services.
Reusable Workflows
A reusable workflow is a workflow file in .github/workflows/ with on: workflow_call:
# .github/workflows/deploy-template.yml
name: Deploy Template
on:
workflow_call:
inputs:
environment:
required: true
type: string
secrets:
CLOUD_TOKEN:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v4
- run: echo "Deploying to ${{ inputs.environment }}"
- run: ./deploy.sh
env:
TOKEN: ${{ secrets.CLOUD_TOKEN }}
Calling a Reusable Workflow
# .github/workflows/deploy-service.yml
name: Deploy Service
on:
push:
branches: [main]
jobs:
call-deploy:
uses: ./.github/workflows/deploy-template.yml
with:
environment: staging
secrets:
CLOUD_TOKEN: ${{ secrets.CLOUD_TOKEN }}
Composite Actions
A Composite action bundles multiple steps into a reusable unit. Create it in action.yml:
# .github/actions/setup-node-cache/action.yml
name: "Setup Node with Cache"
description: "Install Node.js with npm cache"
inputs:
node-version:
description: "Node version"
required: true
default: "20"
runs:
using: "composite"
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
shell: bash
Using the Composite Action
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-node-cache
with:
node-version: 20
- run: npm test
Practice Questions
1. What is the difference between a reusable workflow and a Composite action? A reusable workflow is a complete workflow that can be called from another workflow. A Composite action bundles steps into a reusable step-level unit.
2. How do you mark a workflow as reusable?
Add on: workflow_call to the workflow event trigger.
3. Can reusable workflows call other reusable workflows? Yes, you can chain reusable workflows up to four levels deep.
4. How do you pass secrets to a reusable workflow?
Declare the secret as required in on.workflow_call.secrets and pass it when calling with the secrets keyword.
5. Challenge: Create a Composite action that installs Python dependencies and runs linting. Use it in two different workflows.
Mini Project: Standardized CI Library
Create a reusable workflow called ci-pipeline.yml that runs lint, test, and build for a Node.js project. Create a Composite action called setup-env that sets up Node.js with caching and installs dependencies. Publish both as a template for your organization. Verify a downstream project can call them.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro