Skip to content

Reusable Workflows

GitHub Actions enables teams to build complex CI/CD pipelines by leveraging reusable workflows, which allow modular composition of tasks across repositories. Reusable workflows reduce duplication, improve maintainability, and enable consistent processes across projects. This section explains how to design and compose reusable workflows for scalable, maintainable pipelines.


Understanding Reusable Workflows

Reusable workflows are defined in .github/workflows/ directories and can be referenced by other workflows using the uses keyword. They encapsulate common tasks (e.g., testing, linting, deployment) into self-contained units, which can be versioned and shared.

Key benefits:
- Modularity: Break down monolithic workflows into focused, reusable components.
- Consistency: Ensure standardized processes across repositories.
- Collaboration: Enable cross-team reuse of workflows without duplicating logic.

Reusable workflows can accept inputs (parameters), produce outputs, and expose secrets for secure data passing.


Creating Reusable Workflows

To create a reusable workflow, define it in a separate YAML file (e.g., test-workflow.yml) and reference it in other workflows.

Example: Reusable Testing Workflow

# .github/workflows/test-workflow.yml
name: Run Tests
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install dependencies
        run: npm install
      - name: Run tests
        run: npm test

Example: Referencing the Reusable Workflow

# .github/workflows/main-workflow.yml
name: Main Pipeline
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        uses: .github/workflows/test-workflow.yml@main

Composing Workflows with Reusability

Reusable workflows can be combined with other workflows or nested within jobs. Use jobs to orchestrate multiple reusable components.

Example: Multi-Stage Pipeline with Reusables

# .github/workflows/full-pipeline.yml
name: Full CI/CD Pipeline
on: [push]
jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build project
        run: npm run build
      - uses: .github/workflows/test-workflow.yml@main
  deploy:
    runs-on: ubuntu-latest
    needs: build-and-test
    steps:
      - name: Deploy to staging
        run: ./deploy.sh staging

Best Practices for Reusability

  1. Parameterize Inputs: Use inputs to make workflows flexible.
    inputs:
      env: { type: string, default: 'dev' }
    
  2. Version Control: Tag reusable workflows with semantic versions (e.g., v1.0.0) for dependency management.
  3. Avoid Hardcoding: Use outputs to pass dynamic values between workflows.
  4. Security: Restrict secret exposure by using secrets and avoiding hardcoded credentials.
  5. Namespace Workflows: Organize reusable workflows into dedicated directories (e.g., ./workflows/).

Key takeaways

  • Reusable workflows modularize CI/CD pipelines, reducing duplication and improving maintainability.
  • Use uses to reference reusable workflows and inputs/outputs for dynamic interaction.
  • Version and namespace reusable workflows to ensure consistency across projects.
  • Prioritize security by avoiding hardcoded secrets and leveraging workflow parameters.
  • Combine reusable workflows with jobs to create complex, orchestrated pipelines.