Implementing cascading merges in GitHub Actions (Part 2)
Zohar Zilberman
- November 2022

In Part 1 we implemented cascading merges in GitHub Actions. The implementation used release branches named release/YEAR.MONTH (for example release/2022.10).
In this part we’ll add another workflow that creates new release branches automatically every month.
Why create release branches automatically
The first release branch naming we looked at resembled Semantic Versioning, which is simple and intuitive: release/1.0, release/2.0, etc.
However, this means that when a version’s development is about to end and we want to enter code freeze, the next release branch has to be created manually.
Nothing wrong with that, but here we’ll try a different approach: Instead of creating release branches manually, we’ll create them automatically every month.
What we’ll implement
The workflow we’ll add will create a new release branch every month on the 22nd at midnight UTC.
Once the new release branch is created, we also set it as the default branch for the repo.
The idea is to have at least a week between the time the workflow runs and when a version would be released, assuming it’s at the end of the month. This gives us time to stabilize the release while new changes are pushed to the next release.
We might still want to push changes to the current release branch, such as be fixes and small changes to help stabilize the release.
The workflow
Let’s see the new workflow and walk through each step below. We’ll create the new workflow in .github/workflows/create-next-release.yml:
name: ✨ Create Next Release on: schedule: - cron: "0 0 22 * *" jobs: create_next_release: name: ✨ Create Next Release runs-on: ubuntu-latest steps: - name: 🛎 Checkout uses: actions/checkout@v3 with: token: ${{ secrets.CI_PAT }} fetch-depth: "0" - name: 🔍 Find next release branch id: branches run: | current_branch="release/`date +%Y.%m`" git checkout "${current_branch}" ./.github/scripts/next-release-branch.sh - name: 🏗 Create next branch run: | current_branch="${{ steps.branches.outputs.current }}" next_branch="${{ steps.branches.outputs.next }}" if git branch -r --format "%(refname:short)" | grep "^origin/${next_branch}$" then echo "Next branch already exists" else echo "Creating next branch" git checkout -b "${next_branch}" git push origin --set-upstream "${next_branch}" fi - name: 🛠 Set default branch env: GITHUB_TOKEN: ${{ secrets.CI_PAT }} run: | gh repo edit "${{ github.repository }}" \ --default-branch "${{ steps.branches.outputs.next }}"
1. On… schedule… cron
This is when the workflow would be executed.
2. Checkout step
Like in the previous workflow, we’re checking out the code using a custom PAT (personal access token) so that we can push branches to the origin repo.
3. Find next release branch
Since the workflow starts on a schedule, we can’t assume which branch we’d start running from.
This step only assumes the release branch for the current month already exists and checks it out.
Then, we run the same next-release-branch.sh script from Part 1 to find the next release branch.
4. Create next branch
This step tests if the next release branch already exists, as we may still be creating it manually sometimes. For example, this might happen if we needed to create several release branches in advance.
If the next release branch doesn’t exist, we simply create it from the current branch, which is assumed to be the latest as the next branch doesn’t exist yet.
5. Set default branch
The last step uses GitHub’s CLI gh to set the default branch of the repo as the next branch.
Note that we always do this, regardless of whether we had to create the next release branch or not.
Setting the default branch will make all new PRs open against the next release branch by default, encouraging everyone to only push critical changes to the current release branch.
Up next
In Part 3 we’ll add Slack notifications to both workflows so everyone can get notified whenever a cascading merged happens, when it failed and requires manual fixing and when a new release branch is created.