GitHub Actions: NPM Version Bump using Pull Request Labels

Johnathan Miller
6 min readJun 4, 2022

--

Version bumping should be an automated step in the development process. Developers shouldn’t be expected to version bump, commit, and tag after a PR merge. Developers also should never version bump within a feature/patch branch. It can lead to messy conflicts. However, we’ll still need some indication of version incrementation before we reach our version bump workflow. For this to work we’ll be using labels.

Setup
1. Labels
2. Branch Protection
3. Secrets
Solution
GitHub Workflows Directory
PR Open Workflow
PR Label Check Workflow
PR Close Workflow
Include Workflows in Branch Protection

Setup

In our repository we have 2 main branches. Master and dev. Our feature and patch branches extend from dev and merge back into dev. Our stable dev changes merge into master. In this tutorial, we’ll be covering version bumping on merges into our dev branch.

1. Labels

We’ll be using labels to indicate our version bump. So, if you’d like to now, go ahead and add the following labels to your repository and/or organization:

  • major
  • minor
  • patch

2. Branch Protection

Under Settings > Branches we’ll add our dev branch to Branch Protection Rules.

Scroll down until you see Rules applied to everyone including administrators.

We want to check Allow force pushes, but we don’t want everyone to be able to force push on our protected branch, so let’s specify a user.

In this case I’ve specified my organization’s user account. You will need to generate a Personal Access Token under this account for the next step. This will allow the account to force push within our closing workflow.

3. Secrets

Under Settings > Secrets > Actions we will need to set our organization’s GitHub account details as secrets.

  • GH_ORG_EMAIL : account email
  • GH_ORG_NAME : account username
  • GH_ORG_PAT : this is the Personal Access Token we generated in the previous step.

Once you’ve finished adding your secrets let’s move on to setting up our workflows.

Solution

The first part of this process happens when our developers open a new PR. We’ll implement a few workflows to check when a PR has been opened, reopened, labeled, unlabeled and finally closed. These workflows will be specifically for our dev branch.

GitHub Workflows Directory

Before we start creating our workflows we’ll need to create the directory from which GitHub will read them.

In your project root create the following path with this command:
mkdir -p .github/workflows

PR Open Workflow

Our PR open workflow will serve more as a reminder to our developers who open a PR. All we want to do here is comment on the PR reminding the developer to set a label. The label will be our indication to how we want to increment the version.

Inside our .github/workflows directory, create a new file: dev-pr-open.yml

name: 'Dev - PR Open'
on:
pull_request:
branches:
- dev
types:
- opened
jobs:
add_comment:
name: 'Add Comment'
runs-on: ubuntu-latest
steps:
- uses: mshick/add-pr-comment@v1
with:
message: Please set a versioning label of either `major`, `minor`, or `patch` to the pull request.
repo-token: ${{ secrets.GITHUB_TOKEN }}

As you can see, we’re triggering the workflow on an opened pull request into our dev branch. We only check for the initial event type, opened, as we only want this comment to be posted once.

We only have one job with one step where we’re using a pre-made action from the GitHub marketplace. This action, found here, allows us to post a comment to our PR.

PR Label Check Workflow

Our next workflow will be used to check for labels and can be triggered on several different events on a pull request.

Let’s create this workflow file: dev-pr-label.yml

name: 'Dev - PR Label Checker'
on:
pull_request:
branches:
- dev
types:
- reopened
- labeled
- unlabeled
jobs:
check_labels:
name: 'Check PR Labels'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: mheap/github-action-required-labels@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
mode: exactly
count: 1
labels: 'major, minor, patch'

In this workflow, we’re using this action to help us check for EXACTLY one label. We want to avoid multiple version semantic labels.

PR Close Workflow (this is where we version bump)

Now for the workflow you really came here for. This workflow will run when a PR has been closed, but we only want it to version bump on a merge and not just any close event.

In our merge_pr job we’re checking to see that the closed PR has in fact been merged with this line:

if: github.event.pull_request.merged == true

Create new workflow file: dev-pr-close.yml

name: 'Dev - PR Close'
on:
pull_request:
branches:
- dev
types:
- closed
jobs:
merge_pr:
name: 'PR Merged'
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
token: ${{ secrets.GH_ORG_PAT }}
- uses: actions/setup-node@v2
with:
node-version: '16.x'
cache: 'npm'
- name: Git config
run: |
git config --global user.email "${{ secrets.GH_ORG_EMAIL }}"
git config --global user.name "${{ secrets.GH_ORG_NAME }}"
- name: Apply version bump (major)
if: contains(github.event.pull_request.labels.*.name, 'major')
run: npm version major
- name: Apply version bump (minor)
if: contains(github.event.pull_request.labels.*.name, 'minor')
run: npm version minor
- name: Apply version bump (patch)
if: contains(github.event.pull_request.labels.*.name, 'patch')
run: npm version patch
- name: Git push version bump
run: git push origin dev --follow-tags --force
- id: set-version
name: Output version change
run: npm pkg get version

There’s a few things happening here. We use the checkout action to access our repository and set our Personal Access Token. We then setup node and set our specifications. Next is the Git config step, where we set our git email and username using the secrets we defined earlier.

Now for the version bumping. We have a few steps here checking for a given version semantic label within our PR’s labels array. Only one of them should run since there should only be one label to indicate a version bump thanks to the action in our PR Label Check workflow.

After we’ve version bumped we want to push the commit and tag back to our repository. We do this in the Git push version bump step.

Lastly, the set-version step simply prints the version in the actions console.

Include Workflows in Branch Protection

If you haven’t done so, commit and push your workflows into your repository. Now you may not see your workflows under branch protection just yet. They will need to run at least once before you can select them. Open a PR and set a label and then come back to these settings.

You’ll want to set the PR Open and PR Label Check workflows as status checks. This will ensure the labeling requirements are met on our PR so we can correctly bump the version.

Workflows in Action

With everything in place the workflows should trigger on our defined events. The PR Open workflow should post the reminder comment. The PR Label Check workflow will run once you’ve set or unset a label. Since you’ve added the workflows as status checks it’ll prevent the PRs from being merged without version context.

When a PR has been merged the PR Close workflow will kick off.

As you can see this workflow completed successfully and our branch now has an automated version bump commit/tag.

Side Notes

If necessary, you can easily add an additional job on our PR Close workflow to deploy/publish latest changes with the bumped version.

Also, I recommend a workflow for unit testing and setting it as status check in your branch protection rules.

Share Your Solution

Post a comment if this solution helped. If you have a different solution in place please share in the comments.

--

--