GitHub Reusable Workflows: The Basics and a Quick Tutorial

What Are GitHub Actions Reusable Workflows? 

GitHub Actions is GitHub’s CI/CD platform, integrated with the GitHub repository and version control system. Reusable workflows are pre-defined, modular workflows that can be invoked within other workflows to enhance efficiency and maintainability. They eliminate repetitive code by allowing you to create components that can be utilized across multiple repositories or within different workflows in the same repository.

By encapsulating common tasks, reusable workflows enable developers to focus on the unique aspects of their projects while ensuring that standard operations are executed reliably. This approach aligns with best practices in software development, such as the DRY (Don’t Repeat Yourself) principle.

What Are the Benefits of Reusable Workflows? 

Here are a few key benefits of the reusable workflows feature in GitHub Actions:

  • Avoid redundancy: Reusable workflows can simplify maintenance. If multiple projects require a similar sequence of CI/CD steps, you can encapsulate this sequence into a reusable workflow. Instead of duplicating these steps in each project’s workflow, you reference the reusable workflow, ensuring changes are made only once.
  • Speed up workflow creation: When setting up workflows for new projects, instead of writing each step from scratch, you can call upon these reusable workflows. This also fosters an environment where workflows are iteratively improved.
  • Enhance security: Reusable workflows can be secured by implementing strict access controls, and these controls are replicated to every project that uses the workflows. By defining a set of reusable actions or workflows and limiting who can edit them, organizations can institute a controlled and secure CI/CD environment.
  • Automating compliance: Reusable workflows can encapsulate best practices and mandatory checks that ensure code and deployments meet predefined compliance criteria. For example, a reusable workflow can include steps for code quality checks, security scanning, license compliance verification, and audit logging.

Related content: Read our guide to GitHub actions workflow

Composite Action vs. Reusable Workflows: What Are the Differences?

While both composite actions and reusable workflows aim to modularize and simplify GitHub Actions, they serve different purposes and offer distinct advantages.

Composite actions bundle multiple steps into a single action. This allows you to create complex actions from simpler ones. Composite actions are stored in a repository and can be referenced just like any other GitHub Action. They are suited for packaging repeatable sequences of steps that you want to reuse across different workflows.

Reusable workflows allow entire workflows to be reused within other workflows. This feature is particularly useful for standardizing complex CI/CD pipelines across multiple projects. Reusable workflows are defined in a YAML file and can be invoked from other workflows within the same repository or even across different repositories.

While composite actions are best for creating reusable sets of steps, reusable workflows are more suited for standardizing entire CI/CD pipelines across multiple projects. Each of these features operates at a different level of the GitHub Actions architecture.

Components of a Reusable Workflow 

Triggering Event

The triggering event is a crucial component of a reusable workflow, as it determines when the workflow should be executed. Common triggering events include push events, pull requests, and scheduled intervals. By defining these triggers accurately, developers can ensure that workflows are executed at appropriate times, such as after code commits or at specific times of day.

Input definition

The input definition includes parameters that can be passed to the workflow when it is invoked, allowing for customization without changing the workflow’s internal code. These inputs can be anything from version numbers to specific feature flags that might need to be toggled during the workflow execution.

Defining inputs in a reusable workflow grants greater flexibility and control over how the workflow operates. It enables developers to tailor the workflow’s behavior based on the specific requirements of each project or scenario.

Passing Named Secrets

Passing named secrets securely within reusable workflows is crucial for maintaining the security and integrity of sensitive project information. Named secrets typically include tokens, API keys, and credentials required during the workflow execution. GitHub provides mechanisms to store these secrets securely and access them when needed in a workflow.

Using named secrets ensures that sensitive data remains confidential and is not exposed in the codebase. When setting up reusable workflows, it’s essential to define how these secrets will be passed and accessed, ensuring that they remain protected yet accessible when required, thus enhancing the security of your CI/CD processes.

Kostis Kapelonis headshot
Senior Developer Evangelist, Octopus Deploy
Kostis is a software engineer/technical-writer dual-class character. He lives and breathes automation, good testing practices, and stress-free deployments with GitOps.

TIPS FROM THE EXPERT

In my experience, here are tips that can help you make more effective use of reusable workflows:

  1. Version control your reusable workflows: Treat your reusable workflows as critical as your application code by versioning them. Use semantic versioning (semver) to track changes and ensure compatibility across projects.
  2. Optimize for reusability with parameters: Design your workflows with flexible parameters and default values. This will make them adaptable to various scenarios without extensive modifications.
  3. Implement robust logging: Ensure your reusable workflows have comprehensive logging to aid in troubleshooting and debugging. Use standardized logging formats and include logs at each step to track workflow execution progress.
  4. Enforce environment-specific configurations: Use environment variables and configuration files to manage environment-specific settings within your workflows. This will help in deploying the same codebase to different environments (development, staging, production) with appropriate configurations.
  5. Centralize secret management: Use GitHub’s secret management or integrate with external secret management tools (like HashiCorp Vault) to centralize and securely manage secrets used in your workflows. This will simplify the handling of sensitive information across multiple workflows.

Tutorial: Creating and Calling Reusable Workflows 

These instructions are adapted from the GitHub documentation.

Using Inputs and Secrets in a Reusable Workflow

To define and use inputs and secrets in a reusable workflow, follow these steps:
1. Define inputs and secrets
In the reusable workflow file, specify the inputs and secrets that will be passed from the calling workflow:

on:
  workflow_call:
    inputs:
      log-level:
        required: false
        type: string
        default: 'info'
    secrets:
      DB_HOST:
        required: true
      DB_USER: 
        required: true
      DB_PASSWORD: 
        required: true

2. Reference inputs and secrets
Use the defined inputs and secrets within the jobs of the reusable workflow:

jobs:
  trigger-reusable-workflow:
    uses: ./.github/workflows/reusable-workflow.yml
    with:
      api-key: ${{ secrets.API_KEY }}
      config-path: '.github/reusable-config.yml'

3. Pass inputs and Secrets from the caller workflow
In the calling workflow, use the with keyword for inputs and secrets keyword for secrets to pass values to the reusable workflow:

jobs:
  call-workflow-passing-data:
    uses: my-company/data-science-team/ml-repo/.github/workflows/app-build-workflow.yml@dev
    with:
      config-path: .github/config-values.yaml
    secrets:
      api_session_token: ${{ secrets.SESSION_TOKEN }}

Calling a Reusable Workflow

The uses keyword allows you to reference the reusable workflow file in a job within the calling workflow. You can reference workflows in the same repository or in different repositories:

jobs:
  call-workflow-passing-data:
    uses: my-company/data-science-team/ml-repo/.github/workflows/app-build-workflow.yml@dev

For workflows in the same repository, you can use a relative path:

jobs:
  my--workflow:
    uses: ./.github/workflows/data-model-workflow.yml

Passing Inputs and secrets to a reusable workflow

To pass named inputs and secrets to a reusable workflow, use the with and secrets keywords:
1. Passing named inputs
Ensure that the data type of the input value matches the type specified in the reusable workflow:

	jobs:
  deploy-app:
    uses: my-org/deploy-repo/.github/workflows/deploy-workflow.yml@v1
    with:
      deploy-config: configs/deploy-settings.yml
    secrets:
      apiToken: ${{ secrets.apiToken }}

2. Inheriting secretsWorkflows within the same organization or enterprise can inherit secrets:

jobs:
  call-perform-data-cleaning:
    uses: my-org/deploy-repo/.github/workflows/deploy-workflow.yml@v1
    with:
      config-path: .github/v1/cleaner.yml
    secrets: inherit

Using a Matrix Strategy with a Reusable Workflow

A matrix strategy allows for running multiple jobs with different configurations. This is useful for testing across different environments or configurations.
Here is how to use the matrix context to define variables and pass them to the reusable workflow:

jobs:
  QA-StagingArea-Deployment:
    strategy:
      matrix:
        target: [qa, staging-area]
    uses: my-org/deploy-repo/.github/workflows/deploy-workflow.yml@v1
    with:
      target: ${{ matrix.target }}

This example runs two jobs, one for each value in the target variable, effectively deploying to qa, and staging-area environments using the reusable workflow.

Combine GitHub Actions with Codefresh to Support GitOps and Kubernetes Deployments

GitHub actions is a very powerful platform but it is focused mostly on CI and does not support GitOps and native Kubernetes deployments. Codefresh is created specifically for GitOps and Cloud native applications and includes native support for using GitHub Actions for the CI part of the Software lifecycle.

This means that you can get the best of both worlds by keeping all your CI workflows in GitHub Actions, while using Codefresh for advanced features such as:

  • Application dashboards
  • Git source managements
  • Configuration drift management
  • Kubernetes environment dashboards
  • Topology views

In case you are new to Codefresh – we have made it our mission since 2014 to help teams accelerate their pace of innovation. Codefresh recently released a completely rebuilt GitOps CI/CD toolset. Powered by Argo, Codefresh now combines the best of open source with an enterprise-grade runtime allowing you to fully tap the power of Argo Workflows, Events, CD, and Rollouts. It provides teams with a unified GitOps experience to build, test, deploy, and scale their applications.

The World’s Most Modern CI/CD Platform

A next generation CI/CD platform designed for cloud-native applications, offering dynamic builds, progressive delivery, and much more.

Check It Out