Photo by Dayne Topkin

Reuse your workflows across multiple projects with GitHub Actions

Create a bank of composite actions!

Posted by Damien Aicheh on 10/07/2021 · 7 mins

When you implement continuous integration and continuous delivery in your projects, if you are using the same technology, you probably noticed that the workflows are similar or identical, and as you know duplicate is not a good thing at all!

Why are we trying to mutualize workflows?

  • Avoid duplication
  • Simplify the maintenance
  • Fix potential script errors only once
  • Unify the syntax and the approach between your projects
  • Save time for the next projects
  • Share scripts with other teams of your company

So the question is, how to reuse your workflows and be more efficient between your projects instead of duplicate your workflows?

Basic workflow

Let’s suppose you have a workflow to build a dotnet project called DemoReusableTemplates. This project needs a specific version of dotnet to build. So the workflow will looks like this:

name: Main

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build_dotnet:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout the code
        uses: actions/checkout@v2

      - name: Setup dotnet
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: '5.0.x'

      - run: dotnet restore src/DemoReusableTemplates.csproj   

      - run: dotnet build src/DemoReusableTemplates.csproj 

This kind of workflow can be easily reused between your dotnet projects, if you can pass these inputs as parameters:

  • the project path to build
  • the dotnet version to use

This is where the composite actions come in!

Transform the workflow into a composite action

Let’s create a reusable action using the composite actions to build our dotnet application.
In a new GitHub repository let’s create a folder called dotnet-build and let’s add in it a file called action.yml. The name of the file must be action.yml or action.yaml. If your file does not respect this convention, your GitHub Action will not work.


name: "Build dotnet"
description: "Build dotnet..."
inputs:
  dotnet-version:
    description: 'The dotnet version to use'
    default: '2.1.x'
    required: false
  project-path:
    description: 'The path to the project'
    required: true

runs:
  using: "composite"
  steps: 
    - name: Setup dotnet
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: ${{ inputs.dotnet-version }}

    - run: dotnet restore ${{ inputs.project-path }}
      shell: bash

    - run: dotnet build ${{ inputs.project-path }} 
      shell: bash

As you can see above we have the project path and the dotnet version defined as input parameters. We pass them using $ and $. Then we use the composite keyword to be able to reuse this action and we add the list of all previous commands afterwards.

Because it’s a composite action we don’t specify a runner so we need to add the shell parameter to each run action. If you don’t do it you will have this kind of error message: Required property is missing: shell.

As you have probably already noticed, the dotnet-version has a default value set to 2.1.x so it’s not required.

Create a dedicated repository

To reference a composite in your different workflows and projects, it must be save in a specific repository. This common repository will contain different composites with different versions of it:

Composite actions repository

You can have one project referencing the composite action in the version v0.0.1 and another referencing the version v0.0.2.

With that in mind, let’s commit and push this composite action in a dedicated repository. Then add a tag for instance: v0.0.1.

Reference your composite action in your workflow

The idea now is to update our first workflow with our new action:

name: Main

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build_dotnet:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout the code
        uses: actions/checkout@v2

      - name: Build dotnet
        uses: damienaicheh/demo-action-composite/dotnet-build@v0.0.1
        with:
          dotnet-version: 5.0.x
          project-path: src/DemoReusableTemplates.csproj

As you can see above we reference the dotnet-build action using the name of the repository with the entire path to the folder that contain the action.yml. Also, to specify the version of this composite action we want to use, we add the number of the tag at the end. Here it’s @v0.0.1.

Final touch

As you saw it’s really easy to reuse your workflows between your projects and avoid duplication. Feel free to create your own repositories of composite action! You will find the two GitHub repository for this article available here:

Happy coding!

Do not hesitate to follow me on to not miss my next tutorial!