Reusable workflows and matrix strategies

Make a workflow reusable, call it in another workflow, and use a matrix strategy to run multiple versions

Welcome

Reusable workflows offer a simple and powerful way to avoid copying and pasting workflows across your repositories, and adding a matrix strategy lets you use variables in a single job definition to automatically create multiple job runs.

  • Who is this for: Developers, DevOps engineers, students, managers, teams, GitHub users.
  • What you'll learn: How to create and use reusable workflows, create a matrix strategy, trigger workflows, and find workflow logs.
  • What you'll build: An Actions workflow with a matrix strategy that calls a reusable workflow to output multiple verisions of node.
  • Prerequisites: In this course you will work with pull requests and YAML workflow files. We recommend you take the Introduction to GitHub course first or be familiar with GitHub basics, and the Hello GitHub Actions course for an introduction to GitHub Actions and workflow files.
  • How long: This course is five steps long and can be finished in less than one hour.
  • Attribution: This Skills course was inspired by a demo video created by Mickey Gousset (@mickeygousset).

How to start this course

  1. Right-click Start course and open the link in a new tab.
    start-course
  2. In the new tab, follow the prompts to create a new repository.
    • For owner, choose your personal account or an organization to host the repository.
    • We recommend creating a public repository—private repositories will use Actions minutes. Create a new repository
  3. After your new repository is created, wait about 20 seconds, then refresh the page. Follow the step-by-step instructions in the new repository's README.

Step 1: Make a workflow reusable

Welcome to "Reusable Workflows and Matrix Strategies"! 👋

You can do a lot with GitHub Actions! You can automate repetitive tasks, build continuous integration and continuous deployment pipelines, and customize essentially any part of your software development workflow. It doesn't matter if you're just learning about workflows and GitHub Actions for the first time or you're well exerpienced with the process, you'll quickly find yourself repeating automation jobs and steps within the same workflow, and even using the dreaded copy and paste method for workflows across multiple repositories.

Is there a solution to reduce these repetitive tasks? Yes, I'm glad you asked 😉 Enter reusable workflows, a simple and powerful way to avoid copying and pasting workflows across your repositories.

What are the benefits of using reusable workflows?: Reusable workflows are … reusable. Reusable workflows let you DRY (don’t repeat yourself) your Actions configurations, so you don’t need to copy and paste your workflows from one repository to another.

  • Case in point: if you have three different Node applications and you’re building them all the same way, you can use one reusable workflow instead of copying and pasting your workflows again and again.

I have a workflow, how do I make it reusable?: A reusable workflow is just like any GitHub Actions workflow with one key difference: it includes a workflow_call event trigger, similar to event triggers like push, issues, and workflow_dispatch. This means that all you need to do to make a workflow reusable is to use the workflow call trigger.

Let's get started with our first step to see how this would work!

⌨️ Activity: Add a workflow_call trigger to a workflow

  1. Open a new browser tab, and navigate to this same repository. Then, work on the steps in your second tab while you read the instructions in this tab.

  2. Navigate to the Code tab.

  3. From the main branch dropdown, click on the reusable-workflow branch.

  4. Navigate to the .github/workflows/ folder, then select the reusable-workflow.yml file.

  5. Replace the workflow_dispatch event trigger with the workflow_call event trigger. It should look like the following:

       name: Reusable Workflow
    
       on:
         workflow_call:
           inputs:
             node:
               required: true
               type: string
  6. To commit your changes, click Start commit, and then Commit changes.

  7. (optional) Create a pull request to view all the changes you'll make throughout this course. Click the Pull Requests tab, click New pull request, set base: main and compare: reusable-workflow.

  8. Wait about 20 seconds for actions to run, then refresh this page (the one you're following instructions from) and an action will automatically close this step and open the next one.

Step 2: Add a job to call the reusable workflow

Nice work! 🎉 You made a workflow reusable!

Now that you have a reusable workflow, you can call it in another workflow within a new or existing job. But before we do that, let's take a minute to understand what our reusable workflow is doing by looking at the content of the file.

Understanding the file contents of your reusable workflow

name: Reusable Workflow

on:
  workflow_call:
    inputs:
      node:
        required: true
        type: string
        
jobs: 

  build:
  
    runs-on: ubuntu-latest
    
    steps:
    
      - uses: actions/checkout@v3
      
      - name: Output the input value
        run: |
         echo "The node version to use is: ${{ inputs.node }}"

The resuable workflow requires an input of node in order for the workflow to work. You need to make sure that the other workflow you are using to call this reusable workflow outputs a node version. If a node input is detected, the workflow will kick off a job called build that runs on ubuntu-latest.

The step within the build job uses an action called checkout@v3 to checkout the code and then a step to output the input value by running an echo command to print to the Actions log console the following message, The node version to use is: ${{ inputs.node }}. The node input here is the output node value you need to have in your other workflow.

Okay, now that we know what the reusable workflow is doing, let's now add a new job to another workflow called my-starter-workflow to call our reusable workflow. We can do this by using the uses: command and then setting the path to the workflow we want to use. We also need to make sure we define that node input or the reusable workflow won't work.

⌨️ Activity: Add a job to your workflow to call the reusable workflow

  1. Navigate to the .github/workflows/ folder and open the my-starter-workflow.yml file.

  2. Add a new job to the workflow called call-reusable-workflow.

  3. Add a uses command and path the command to the reusable-workflow.yml file.

  4. Add a with command to pass in a node paramater and set the value to 14.

    call-reusable-workflow:
      uses: ./.github/workflows/reusable-workflow.yml
      with:
        node: 14   
  5. To commit your changes, click Start commit, and then Commit changes.

  6. Wait about 20 seconds for actions to run, then refresh this page (the one you're following instructions from) and an action will automatically close this step and open the next one.

Step 3: Add a matrix strategy to your workflow

Well done! ✨

Your My Starter Workflow now has a job that outputs the node version of 14 and calls the reusable workflow called Reusable Workflow. It then prints a message to the Actions logs of the node version for the build. Now, we haven't checked the Actions logs at the point to see the message, but don't worry, we'll get there after this next step. Let's improve our My Starter Workflow a little more but adding a matrix strategy.

What is a matrix strategy: A matrix strategy lets you use variables in a single job definition to automatically create multiple job runs that are based on the combinations of the variables. For example, you can use a matrix strategy to test your code in multiple versions of a language or on multiple operating systems. Below is an example:

jobs:
  example_matrix:
    strategy:
      matrix:
        version: [10, 12, 14]
        os: [ubuntu-latest, windows-latest]

To define a matrix strategy inside a job, you first need to define the matrix with the keyword strategy followed by the nested keyword matrix. You can then define variables for the matrix. In the above example, the variables are version with the values of 10, 12, and 14, and another variable called os with the values of ubuntu-latest and windows latest.

The example_matrix job will run for each possible combination of the variables. So, in the above example, the workflow will run six jobs, one for each combination of the os and version variables. If you want to run a job for multiple versions, using a matrix strategy is a great solution over writing out 6 different jobs.

Let's add a matrix strategy to the My Starter Workflow so we can run our job on different versions of node instead of the hard-coded single verison of 14.

⌨️ Activity: Use a matrix strategy to run multiple versions

  1. In the same my-starter-workflow.yml file, add a strategy keyword under the call-reusable-workflow job.

  2. Under strategy, add a matrix keyword.

  3. Define the nodeversion variable to run over the following versions of node [14, 16, 18, 20].

  4. Replace the hard-coded node paramter of 14 used in the with command, and call the nodeversion in the matrix by using the following syntax ${{ matrix.nodeversion }}. Below is that your job should look like:

    call-reusable-workflow:
      strategy:
        matrix:
          nodeversion: [14, 16, 18, 20]
      uses: ./.github/workflows/reusable-workflow.yml
      with:
        node: ${{ matrix.nodeversion }}   
  5. To commit your changes, click Start commit, and then Commit changes.

  6. Wait about 20 seconds for actions to run, then refresh this page (the one you're following instructions from) and an action will automatically close this step and open the next one.

Step 4: Merge your changes

Nicely done! 🥳

You've added a matrix strategy to your workflow file that is now running on four different versions of node [14, 16, 18, 20] instead of the single hard-coded version of only 14.

We'll now merge your changes so that your workflow file changes will be part of the main branch.

⌨️ Activity: Create and merge your pull request

  1. Merge your changes from reusable-workflow into main. If you created the pull request in step 1, open that PR and click on Merge pull request. If you did not create the pull request earlier, you can do it now by following the instructions in step 1.
  2. Optionally, click Delete branch to delete your reusable-workflow branch.
  3. Wait about 20 seconds for actions to run, then refresh this page (the one you're following instructions from) and an action will automatically close this step and open the next one.

Step 5: Trigger your workflow and view the Actions logs

You're almost done. Last step! ❤️

Now that the changes have been merged into the main branch, let's trigger the My Starter Workflow workflow to see everyting in action! But before we do, let's recall what we should expect to see before we run the workflow.

  • We should expect to see five jobs running from our My Starter Workflow*. Do you remember which ones? We have the build job and then the call-reusable-workflow job that has the matrix strategy. Screen Shot 2022-09-08 at 9 53 52 AM
  • We should also expect to see the echo message printed as an output from the reusable workflow with the node version for each of the matrix version jobs. Screen Shot 2022-09-08 at 9 52 41 AM

⌨️ Activity: Run the My Starter Workflow and view the Actions logs

  1. Navigate to the Actions tab in your repo.
  2. Choose the My Starter Workflow workflow from the left, and select the Run workflow button and run the workflow on the Main branch.
  3. Wait a few seconds for the workflow run to appear in the queue. Once it shows, select the My Starter Workflow from the workflow runs queue.

Notice the list of build jobs on the left. One for the build job and four for the different node versions (14, 16, 18, 20) that you are running from your matrix. When one of the node version jobs complete, you can select that job and view the Actions logs for the Output the input value. This will print out the message from the reusable workflow file.

When you're done reviewing the Actions logs, return here and refresh the page to finish the course! 🎉

Finish

Congratulations friend, you've completed this course! 🎉

celebrate

Here's a recap of all the tasks you've accomplished in your repository:

  • You made a workflow reusable by using the workflow_call event trigger
  • You created a new job in a separate workflow to call the reusable workflow
  • You added a matrix strategy to run a job on multiple node versions
  • You navigated through the Actions logs to view the workflow runs and results from specific jobs

What's next?


Get help: Post in our discussion boardReview the GitHub status page

© 2022 GitHub • Code of ConductMIT License