107 lines
5 KiB
Markdown
107 lines
5 KiB
Markdown
|
---
|
||
|
title: Enforcing a "Do Not Merge" label with Github Actions
|
||
|
date: 2023-02-18T12:33:32-05:00
|
||
|
toc: false
|
||
|
images:
|
||
|
tags:
|
||
|
- dev
|
||
|
---
|
||
|
|
||
|
At my workplace, we sometimes find ourselves in situations where a PR passes all
|
||
|
tests, and has been reviewed and approved, but still shouldn't be merged.
|
||
|
Sometimes this is because that PR needs some other work in another repository to
|
||
|
be merged and deployed first. Sometimes it's because merging the PR will
|
||
|
kickstart some process like sending out emails, and we are waiting to start that
|
||
|
process at a certain time.
|
||
|
|
||
|
Whatever the reason, our convention is that we add a "Do Not Merge" label to the
|
||
|
PR. But we recently had a case where someone didn't see the label and clicked
|
||
|
the merge button anyway. I can tell you that it's not fun scrambling to hit the
|
||
|
"cancel action" button on Github before the code gets deployed! So we started
|
||
|
looking into a way to prevent such issues.
|
||
|
|
||
|
Now, you might ask why we don't just leave these PRs as drafts. While that would
|
||
|
stop them from being merged on an accidental click, there is still some risk
|
||
|
that someone might just mark it ready for review and merge it without checking
|
||
|
the label. We also have some automation set up, like automatically changing card
|
||
|
state when a PR is marked as ready, which would not work if we leave PRs in
|
||
|
draft. Luckily, I found a better solution.
|
||
|
|
||
|
After coming across this [post from Jesse Squires](https://www.jessesquires.com/blog/2021/08/24/useful-label-based-github-actions-workflows/),
|
||
|
I decided to try the improved version of a "Do Not Merge" check he suggests.
|
||
|
|
||
|
```yml
|
||
|
name: Do Not Merge
|
||
|
|
||
|
on:
|
||
|
pull_request:
|
||
|
types: [synchronize, opened, reopened, labeled, unlabeled]
|
||
|
|
||
|
jobs:
|
||
|
do-not-merge:
|
||
|
if: ${{ contains(github.event.*.labels.*.name, 'do not merge') }}
|
||
|
name: Prevent Merging
|
||
|
runs-on: ubuntu-latest
|
||
|
steps:
|
||
|
- name: Check for label
|
||
|
run: |
|
||
|
echo "Pull request is labeled as 'do not merge'"
|
||
|
echo "This workflow fails so that the pull request cannot be merged"
|
||
|
exit 1
|
||
|
```
|
||
|
|
||
|
Our first attempt was dropping this into the repository, which worked, but we
|
||
|
have a lot of repositories and we sometimes create new ones too. Having to copy
|
||
|
this check to all repositories seems like a lot of work! But thanks to a
|
||
|
coworker discovering that you can set repository-wide workflows, we were able to
|
||
|
set up all of this organization-wide.
|
||
|
|
||
|
To do that, you first add this workflow file in some repository. It doesn't need
|
||
|
to be (and probably shouldn't be) in your `.github/workflows` folder. You might
|
||
|
even want to create a new repository to contain just this workflow file.
|
||
|
|
||
|
![A github repository, with a single file named do-not-merge.yml at the root of the repository. The file contains the code listed earlier in this page.](/img/gh-do-not-merge-action.png)
|
||
|
|
||
|
Next, go to your organization settings and select "Actions > General" on the
|
||
|
side menu.
|
||
|
|
||
|
![Github side bar menu, with heading Action expanded, and General selected inside that section.](/img/gh-menu-actions-general.png)
|
||
|
|
||
|
Scroll to the bottom, where you'll find "Required workflows". Click
|
||
|
to add a workflow.
|
||
|
|
||
|
![The required workflows section in Github organization settings. An "Add workflow" button is present.](/img/gh-required-workflows.png)
|
||
|
|
||
|
Then select the repository where you added your action, and
|
||
|
write the path to the workflow file within that repository.
|
||
|
|
||
|
![Add required workflow page. The previously mentioned repository is selected, and the path do-not-merge.yml is written next to that. A selection below has picked 'All repositories'.](/img/gh-required-workflows-config.png)
|
||
|
|
||
|
|
||
|
You're now done! All PRs in all repositories will run the do not merge label
|
||
|
check, and will prevent you from merging any PR with the label.
|
||
|
|
||
|
![The checks section on a PR page. A check named "Do Not Merge" has failed, and the merge button is disabled. Github warns that all checks must pass before merging.](/img/gh-do-not-merge-fail.png)
|
||
|
|
||
|
One caveat is
|
||
|
that there seems to be a bug on Github's end of things where for any PR that was
|
||
|
open at the time you added this check, the check gets stuck with the message
|
||
|
"Expected - Waiting for status to be reported". If that happens, add the "do not
|
||
|
merge" label then remove it. This will remind Github to actually run the check.
|
||
|
|
||
|
To make the experience a bit smoother for new repositories, you can also add "do
|
||
|
not merge" as a default PR label. To do so, go to the "Repository > Repository
|
||
|
defaults" section on the side bar.
|
||
|
|
||
|
![Github side bar menu, with heading Repository expanded, and Repository defaults selected inside that section.](/img/gh-repository-defaults.png)
|
||
|
|
||
|
Click "New label", and create a label named
|
||
|
"do not merge".
|
||
|
|
||
|
![The repository labels section in Github organization settings. A new label is being added, with the name do not merge.](/img/gh-repository-defaults-labels.png)
|
||
|
|
||
|
This will only apply to new repositories, so you may need to add
|
||
|
the label to your existing repositories. But even if you don't add the label to
|
||
|
the repository, the check should not block you so you don't have to worry about
|
||
|
going through all your repositories to add this label.
|