Backport GitHub Action

December 5, 2023 (1y 2m ago)

Introduction

Recently, our team implemented an action to synchronize the main branch with the fixes made in the release branches. You might wonder why this is important. This approach is commonly referred to as backporting.

đź“ť

Backporting is a software development practice involving the implementation of specific fixes or features from a newer version of the software and applying them to an older version or a different branch.

Traditionally, we needed to sync our main branch with fixes to prevent encountering the same issues in future releases. But sometimes, we struggled either because we missed these syncs or faced many conflicts when trying to sync after implementing multiple fixes.

One other important thing here is that if we want to merge the release branch back into the main branch after finishing the fixes, there might be some commits that we don’t want in the main branch. In such cases, we would typically need to cherry-pick commits individually. However, with the approach that I am going to explain, we can control which fixes should be applied to the main branch, eliminating the need for individual cherry-picking.

Branching Strategies

Allow me to elucidate one strategy we employ in our project to provide a clearer understanding of our approach. Let's consider having the main branch as our primary one. When a release is needed, a new branch is created from it, named with the release identifier, which for simplicity, we'll refer to as release1.

The branches graph

Note: Our development protocol restricts the development of new features from release branches. These branches are solely dedicated to releasing the project and, if any issues arise, to fixing them.

As illustrated in the above picture, Fix Number 1 has been merged into the release, and two other branches address additional issues. The requirement for these fixes in our main branch is evident. To address this, I will explain a solution involving the addition of a new action to create a new Pull Request (PR) targeting the main branch and cherry-picking the same commit previously merged into the release branch.

Our proposed diagram for this solution is as follows:

The branches graph showing backported PR

To add a new action in GitHub, we have to add it in the following path .github/workflows/<actionName>.yml. In our case, we are utilizing an action available in the marketplace called tibdex/backport@v2. The action file will appear as follows:

.github/workflows/backport.yml
name: Backport
on:
  pull_request_target:
    types:
      - closed
 
permissions:
  contents: write
  pull-requests: write
 
jobs:
  backport:
    name: Backport
    runs-on: ubuntu-latest
 
    if: >
      github.event.pull_request.merged && github.event.action == 'closed'
 
    steps:
      - uses: tibdex/backport@v2
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

The action file is self-explanatory, and you just need to follow the steps outlined to set up your repository for this action.

  1. Create a label with the instruction "backport (branch name)". In our example, we need a "backport main" label. Refer to this guide on how to create a label.

    Note: PRs can be backported to any branch by creating the respective label. For simplicity, we're only using the main branch. However, in practice, multiple branches like release-2 might require fixes. Thus, when creating a PR, assigning multiple labels will automatically generate corresponding PRs.

  2. Give actions access to your repository to create pull requests. Navigate to the repository settings, select Actions/general on the left panel, and in the Workflow permissions section, enable GitHub actions to create pull requests. Save the settings.

The workflow permission section
  1. No additional configuration is needed for the github_token as it will be automatically generated. Refer to this guide for more information.

Note: If you encounter any warnings related to the type of merging a pull request, you can modify this in the repository settings. There are three available options:

  • Merge with one additional commit alongside the commit history.
  • Combine all commit messages (based on its settings) and changes into a single commit.
  • Add all commit history directly to the base branch.

In this case, I selected the second option with the default message setting.

The Pull Request section

That's all! Now proceed to create a PR, ensuring the addition of corresponding labels. Upon merging the PR, the action will execute and generate a new PR with the main branch as its target.

The example of the backported PR

However, it's important to note that while the backporting strategy using GitHub Actions presented here is a robust and automated approach, it represents just one method among several possible ways to handle backporting. Depending on the project's complexity, team preferences, and specific version control requirements, alternative techniques or tools might also prove effective in managing code synchronization between branches.