A Deep Dive into GitHub Actions’ Reusable Workflows | by Wenqi Glantz | Aug, 2022

Detailed instructions on how to implement reusable workflows in CI/CD

Montana landscape. Photo by author

GitHub actions reusable workflow was released for general availability on November 29, 2021, and it’s been gaining rapid popularity since. The benefits of reusable workflows are pretty straightforward:

  • Follows DRY (Don’t Repeat Yourself) principle
  • Avoids workflow duplication
  • Easy to maintain the workflows
  • Allows us to create new workflows more quickly by building on the work of others.
  • Promotes best practices by using workflows that are well designed and have already been tested.

According to an observation from Thoughtworks’ Technology Radar,

“Reusable workflows in GitHub Actions bring modularity to pipeline design, allowing parameterized reuse even across repositories (as long as the workflow repository is public) [or internal]). They support the explicit passing of confidential values ​​as secrets and can pass outputs to the calling job.

With a few lines of YAML, GitHub Actions now gives you the type of flexibility you see with CircleCI Orbs or Azure Pipeline Templates, but without having to leave GitHub as a platform.”

In this story, we will illustrate how to implement reusable workflows in your project for CI/CD. We will start with an overview and then do a deep dive into reusable workflows. We will be using two GitHub repositories for our example:

This is a typical Spring Boot microservice with CRUD endpoints for customers. We added two workflows under its .github/workflows directory, ci.yml and cd.yml. See the diagram below for the detailed jobs and steps involved in both workflows.

If we have many microservices with similar workflows, it gets tedious to copy and paste these two workflows across all the repositories. And maintenance would become a nightmare if we need to make changes to one or multiple steps in the workflows.

Let’s look into making those two workflows reusable so changes can be made in the centralized reusable workflows and get reflected in all microservices calling these reusable workflows.

To correspond to the two workflows mentioned above, we start with two reusable workflows. You can see them below. Notice I specify the programming language (Java), build tool (Maven), and keywords (build, test, deploy, ECS) related to the specific workflow in the file naming convention for the reusable workflows. This allows easy identification of the reusable workflows in the centralized repository, especially if your organization may have multiple programming languages ​​in use. Each language can have its own set of reusable workflows identified by its naming convention.

  • java-maven-build-test.yml: for continuous integration (CI), which does code build, test, image build, and image push to AWS Elastic Container Registry (ECR). This reusable workflow will be called by ci.yml. Assume you already have your ECR and ECR repository configured for your microservice. And secrets referenced below have been configured in GitHub.
  • java-api-deploy-to-ecs.yml: for continuous deployment (CD), which pulls the image from ECR and deploys it to AWS Elastic Container Service (ECS). This reusable workflow will be called by cd.yml. Assume you already have your ECS Fargate cluster provisioned for your microservice. And secrets referenced below have been configured in GitHub.

Now let’s dive deep into these two reusable workflows:

Lives in the .github/workflows directory of a public or internal repository

As with other GitHub actions workflow files, reusable workflows live in .github/workflows directory of a public or internal repository. In our example, centralized-reusable-workflows public repository.

Note: reusable workflows cannot live in a private repository. If your organization has all private repositories, be sure to create an internal repository to host reusable workflows. Also to note, subdirectories of the workflows directory are not supported.

Add a workflow_call trigger

workflow_call trigger is the key difference between reusable workflow and normal workflows. For a workflow to be reusable, the values ​​for on must include workflow_call:

on:
workflow_call:

Add optional input parameters

Reusable workflows are templates in concept, which means they will most likely need to have parameters passed in to make them specific to the calling workflow. But parameters are not to make a workflow reusable mandatory. In most cases, reusable workflows utilize input parameters to make them reusable for various environments, different versions of a programming language, etc.

See the following snippet from java-maven-build-test.ymlnotice the comment lines above each input parameter to learn more about what those input parameters are used for.

  1. In the reusable workflow, we use the inputs keywords to define inputs that will be passed from a caller workflow.
  2. In the reusable workflow, we reference the input that was just defined in the on key in the previous step, in the form of ${{ inputs.###}}such as${{ inputs.env}}.

Since we are hosting our reusable workflows in the centralized-reusable-workflows public repository, we can reference reusable workflow files using the following syntax:

  • {owner}/{repo}/.github/workflows/{filename}@{ref}

{ref} can be a SHA, a release tag, or a branch name. For example, our customer-service-reusable-workflow-example’s ci.yml calls reusable workflow java-maven-build-test.yml to build and test the app. See line 21 below:

  • In the reusable workflow scenario, permission for a particular job is defined at the calling workflow. See lines 18–20 above.
  • To pass the input or secret from the caller workflow, we use the with keyword, line 22, in the calling workflow’s job. Workflows that call reusable workflows in the same organization can use the inherit keyword, line 24, to implicitly pass the secrets defined in GitHub.

With secrets: inherit configured at the calling workflow, we can then reference the secrets in the reusable workflows even if they are not defined in the on key. See lines 4 and 5.

similarly, cd.yml calls reusable workflow java-api-deploy-to-ecs.yml.

We explored GitHub actions reusable workflow in this story. We started with an overview of the benefits of reusable workflows. We then dived into a sample microservice’s GitHub actions workflows and extracted their jobs/steps into reusable workflows, which live in a different public repository.

We explored the detailed steps on how to make a workflow reusable, and how to call a reusable workflow, how to pass input parameters and secrets to the reusable workflow. Once you start using reusable workflows in your projects, you will never look back, as reusable workflows save so much time and effort in rolling out your apps’ CI/CD workflows and eliminating maintenance headaches.

The two GitHub repositories mentioned in this story:

Leave a Comment