0Pricing
DevOps Bootcamp · Lesson

Reusable Workflows and Actions

Create and leverage reusable workflows and custom actions to modularize your pipelines and promote consistency across repositories.

Reusable Workflows and Actions is a free DevOps Bootcamp lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the DevOps Bootcamp learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Introduction to Workflow Reusability

In modern software development, efficiency and consistency are key. As your projects grow, so do your automation needs.

Reusable workflows and custom actions in GitHub Actions help you avoid repeating yourself, making your CI/CD pipelines more maintainable and robust.

Why Reuse Workflows?

Imagine having multiple applications that all need the same build, test, or deployment steps. Copy-pasting workflow code leads to:

  • Duplication: More code to maintain.
  • Inconsistency: Easy to miss updates across workflows.
  • Maintenance headaches: Changes require updating many files.

Reusability solves these problems!

Defining a Reusable Workflow

A reusable workflow is a complete workflow that can be called by other workflows. It's stored in your repository and acts like a template.

To make a workflow reusable, you use the workflow_call event. This tells GitHub Actions that this workflow is meant to be called, not triggered by typical events like push or pull_request.

Reusable Workflow Example

Here's a simple reusable workflow that simulates a build. Save this in .github/workflows/reusable-build.yml.

It defines an output called build_id that calling workflows can use.

name: Reusable Build Component

on:
  workflow_call:
    outputs:
      build_id:
        description: "The ID of the build operation"
        value: ${{ jobs.build.outputs.build_id }}

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      build_id: ${{ steps.generate_id.outputs.id }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Generate build ID
        id: generate_id
        run: echo "id=$(date +%s)" >> "$GITHUB_OUTPUT"
      - name: Simulate build
        run: echo "Building project with ID ${{ steps.generate_id.outputs.id }}..."

Calling a Reusable Workflow

To use a reusable workflow, another workflow (the 'caller') uses the uses keyword, similar to how you'd use a GitHub Action.

You specify the path to the reusable workflow file within your repository, or even from another repository or a specific version.

Caller Workflow Example

This workflow, saved as .github/workflows/main-app-ci.yml, calls our reusable-build.yml workflow.

Notice how it accesses the build_id output from the called workflow using jobs.call-build.outputs.build_id.

name: Main App CI

on: [push]

jobs:
  call-build:
    uses: ./.github/workflows/reusable-build.yml
    outputs:
      build_id: ${{ jobs.call-build.outputs.build_id }}
  
  deploy:
    needs: call-build
    runs-on: ubuntu-latest
    steps:
      - name: Deploy app
        run: echo "Deploying app built with ID ${{ needs.call-build.outputs.build_id }}"

Passing Inputs to Reusable Workflows

Reusable workflows aren't just static templates; they can accept inputs, making them highly flexible.

You define expected inputs in the on: workflow_call: inputs: section of the reusable workflow, specifying their type, whether they are required, and a description. The calling workflow passes these inputs using the with: keyword.

Reusable Workflow with Inputs

Here's an updated reusable-build.yml that accepts a target_env input. This allows the same build logic to be customized for different environments.

name: Reusable Build Component with Input

on:
  workflow_call:
    inputs:
      target_env:
        required: true
        type: string
        description: "The target environment for the build"
    outputs:
      build_id:
        description: "The ID of the build operation"
        value: ${{ jobs.build.outputs.build_id }}

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      build_id: ${{ steps.generate_id.outputs.id }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Generate build ID
        id: generate_id
        run: echo "id=$(date +%s)" >> "$GITHUB_OUTPUT"
      - name: Simulate build for ${{ inputs.target_env }}
        run: echo "Building project for ${{ inputs.target_env }} with ID ${{ steps.generate_id.outputs.id }}..."

Calling with Inputs Example

Now, our main CI workflow can call the reusable build component twice, once for 'staging' and once for 'production', passing different target_env values.

name: Main App CI with Input

on: [push]

jobs:
  call-build-staging:
    uses: ./.github/workflows/reusable-build-with-input.yml
    with:
      target_env: 'staging'
    outputs:
      build_id: ${{ jobs.call-build-staging.outputs.build_id }}
  
  call-build-prod:
    uses: ./.github/workflows/reusable-build-with-input.yml
    with:
      target_env: 'production'
    outputs:
      build_id: ${{ jobs.call-build-prod.outputs.build_id }}

Reusable Workflows vs. Custom Actions

While both promote reusability, they serve different purposes:

  • Reusable Workflows: Orchestrate a series of jobs. They define a complete workflow structure (e.g., build, test, deploy).
  • Custom Actions: Perform a specific, single task within a job (e.g., set up Node.js, publish a package). They are the building blocks *inside* a job's steps.

Think of workflows as recipes and actions as individual ingredients or steps.

Quick Check

Which of the following are key benefits of using reusable workflows in GitHub Actions?

Recap: Reusable Workflows & Actions

We've explored how reusable workflows help modularize your CI/CD pipelines.

  • They are defined using workflow_call.
  • They can accept inputs and provide outputs.
  • Calling workflows use the uses keyword.
  • They differ from custom actions, which are single-task building blocks within jobs.

Embracing reusability leads to more efficient, consistent, and maintainable automation across your projects.

Frequently asked questions

Is the “Reusable Workflows and Actions” lesson free?

Yes — the full text of “Reusable Workflows and Actions” is free to read here on the web, and the DevOps Bootcamp course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the DevOps Bootcamp course, upgrade to CoddyKit PRO.

What will I learn in “Reusable Workflows and Actions”?

Create and leverage reusable workflows and custom actions to modularize your pipelines and promote consistency across repositories. You practise DevOps Bootcamp with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start DevOps Bootcamp?

No prior experience is required. DevOps Bootcamp on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Reusable Workflows and Actions” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this DevOps Bootcamp lesson?

Yes. Every DevOps Bootcamp lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Matrix Builds for Multiple Environments
  2. Caching Dependencies for Speed
  3. Reusable Workflows and Actions
  4. Conditional Execution and Job Dependencies
← Back to DevOps Bootcamp