GitHub Actions (S2E02) - Reusable workflow

Jeason JosephJeason Joseph
4 min read

Avoid duplication when creating a workflow by reusing existing workflows. Create a common workflow and refer it in another workflow to reduce duplication.

  • The workflow referencing the reusable workflow is known as the ‘caller’ workflow

  • The reusable workflow being referenced is known as the ‘called’ workflow.

gitops-repo/
├── .github/
│   ├── workflows/
│   │   ├── main-workflow.yml         # caller workflow
│   │   ├── reusable-workflow.yml     # called workflow
├── src/
│   └── main_code.py
├── tests/
│   └── test_code.py
├── requirements.txt
└── README.md

Calling the reusable workflow

Caller workflow

Call a reusable workflow by using the uses keyword at the job level

jobs:
  workflow-in-local-repo:    #for reusable workflows in the same repository
    uses: ./.github/workflows/reusable-workflow.yml
  workflow-in-another-repo:  #for reusable workflows in public/private repositories
    uses: acme-org/another-repo/.github/workflows/reusable-workflow.yml@v1

Called workflow

For a workflow to be reusable, the values for on must include workflow_call:

on:
  workflow_call:
jobs:
  build:
    runs-on: ubuntu-latest  # Will run on an Ubuntu VM
    steps:
    - name: Welcome
      run: echo "Called workflow"

Passing secrets

Caller workflow

Use the secrets keyword to pass named secrets.

jobs:
  call-workflow-passing-data:
    uses: acme-org/g-repo/.github/workflows/reusable-workflow.yml@172239021f7ba04fe7327647b213799853a9eb89
    secrets:
      pat_token: ${{ secrets.token }}

Called workflow

Use the secrets keywords to define secrets that will be passed from a caller workflow.

Reference the secret that you defined in the on key in the previous step.

on:
  workflow_call:
    secrets:
      pat_token:
        required: true
jobs:
  build:
    runs-on: ubuntu-latest  # Will run on an Ubuntu VM
    steps:
    - uses: actions/labeler@v4
      with:
        repo-token: ${{ secrets.pat_token }}

Passing inputs

Caller workflow

To pass named inputs to a called workflow, use the with keyword in a job

jobs:
  call-workflow-passing-data:
    uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main
    with:
      config-path: .github/labeler.yml

Called workflow

Use the inputs keywords to define inputs or secrets that will be passed from a caller workflow.

Reference the input that you defined in the on key in the previous step.

For inputs, the data type of the input value must match the type specified in the called workflow (either boolean, number, or string).

on:
  workflow_call:
    inputs:
      config-path:
        required: true
        type: string
jobs:
  build:
    runs-on: ubuntu-latest  # Will run on an Ubuntu VM
    steps:
    - uses: actions/labeler@v4
      with:
        configuration-path: ${{ inputs.config-path }}

Nesting reusable workflows

You can connect a maximum of four levels of workflows - that is, the top-level caller workflow and up to three levels of reusable workflows. For example: caller-workflow.ymlcalled-workflow-1.ymlcalled-workflow-2.ymlcalled-workflow-3.yml. Loops in the workflow tree are not permitted.

Passing outputs

Called workflow

A reusable workflow may generate data that you want to use in the caller workflow. To use these outputs, you must specify them as the outputs of the reusable workflow.

name: Reusable workflow

on:
  workflow_call:
    # Map the workflow outputs to job outputs
    outputs:
      firstword:
        description: "The first output string"
        value: ${{ jobs.example_job.outputs.output1 }}
      secondword:
        description: "The second output string"
        value: ${{ jobs.example_job.outputs.output2 }}

jobs:
  example_job:
    name: Generate output
    runs-on: ubuntu-latest
    # Map the job outputs to step outputs
    outputs:
      output1: ${{ steps.step1.outputs.firstword }}
      output2: ${{ steps.step2.outputs.secondword }}
    steps:
      - id: step1
        run: echo "firstword=hello" >> $GITHUB_OUTPUT
      - id: step2
        run: echo "secondword=world" >> $GITHUB_OUTPUT

Caller workflow

Reference the outputs using the names defined at the workflow level in the reusable workflow: firstword and secondword. In this workflow, job1 calls the reusable workflow and job2 prints the outputs from the reusable workflow ("hello world") to standard output in the workflow log.

jobs:
  job1:
    uses: octo-org/example-repo/.github/workflows/called-workflow.yml@v1

  job2:
    runs-on: ubuntu-latest
    needs: job1
    steps:
      - run: echo ${{ needs.job1.outputs.firstword }} ${{ needs.job1.outputs.secondword }}

Complete workflow

Caller workflow

name: Call a reusable workflow and use its outputs, pass secrets & inputs

on:
  push:

jobs:
  job1:
    uses: octo-org/example-repo/.github/workflows/called-workflow.yml@v1
    with:
      config-path: .github/labeler.yml
    secrets:
      pat_token: ${{ secrets.token }}

  job2:
    runs-on: ubuntu-latest
    needs: job1
    steps:
      - run: echo ${{ needs.job1.outputs.firstword }} ${{ needs.job1.outputs.secondword }}

Called workflow

name: Call a reusable workflow and use its outputs

on:
  workflow_dispatch:
    inputs:
      config-path:
        required: true
        type: string
    secrets:
      pat_token:
        required: true

jobs:
  build:
    runs-on: ubuntu-latest  # Will run on an Ubuntu VM
    outputs:
      output1: ${{ steps.step1.outputs.firstword }}
      output2: ${{ steps.step2.outputs.secondword }}
    steps:
      - uses: actions/labeler@v4
        with:
          repo-token: ${{ secrets.pat_token }}
          configuration-path: ${{ inputs.config-path }}
      - id: step1
        run: echo "firstword=hello" >> $GITHUB_OUTPUT
      - id: step2
        run: echo "secondword=world" >> $GITHUB_OUTPUT
0
Subscribe to my newsletter

Read articles from Jeason Joseph directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jeason Joseph
Jeason Joseph

I am an DevOps Engineer working since 2018. Had the opportunity to provide consulting services to many IT service companies. Passionate about learning new technology.