Freezing your GitHub repository merges

Freezing your GitHub repository merges

Julien Danjou

Freezing your GitHub repository could mean a lot of things. In that case, I'm not talking about putting it on ice or sending it to GitHub's Artic Code Vault.

No, that's not the point here.

As controlling the merge flow becomes increasingly important, many engineering teams have encountered the need to pause the never-ending influx of pull requests being merged into a repository.

There is plenty of reasons for this. They can primarily be split into two categories:

  • Regular schedule, e.g., you know you don't want to merge on weekends;
  • Incident handling, e.g., you don't want to merge anything while your production platform is broken.

Regular Schedule

Not merging outside a regular schedule is quite common for teams that leverage continuous deployment. Exceptions aside, you probably don't want to merge code during non-working days, for example.

The best way to implement this in your development workflow is to leverage Mergify schedule condition to indicate when a merge is possible.

Here's an example

pull_request_rules:
  - name: Freeze schedule
    conditions:
      - schedule=09:00-17:00[Europe/Paris]
    actions:
      post_check:
        title: |
          {% if check_succeed %}
          Merge is allowed
          {% else %}
          Merge is forbidden 
          {% endif %}

With such a rule, every pull request will receive a check (just like a CI) that indicates if it's possible to merge it or not.

It's time to merge!

Using Mergify to realize this workflow is a must, as it's the only way to ensure every pull request will get updated in real-time. Leveraging a tool like GitHub Actions wouldn't work here, as there won't be any new event to update the check, and the merge would be always possible.

Can't merge right now.

Mergify rules system offers even more possibilities, as you could add a label that would bypass the schedule if you want. In the example above, adding the hotfix label to a pull request would ignore the schedule:

pull_request_rules:
  - name: Freeze schedule
    conditions:
      - or:
        - schedule=09:00-17:00[Europe/Paris]
        - label=hotfix
    actions:
      post_check:
        title: |
          {% if check_succeed %}
          Merge is allowed
          {% else %}
          Merge is forbidden 
          {% endif %}

You could even add an automatic merge rule using Mergify if you feel like it. Once your team has defined all its merge policies, you could fully implement them as Mergify pull request rules and let it merge the pull request based on your guidelines.

Incident Handling

When an incident happens, and especially when you're using continuous deployment, the last thing you want to do is to continue merging code. It would be best if you stopped adding more potential problems to your current issue.

The usual method for this is to yell on Slack or Teams and ask all engineering teams not to merge anything until the incident is resolved. This can work for a tiny team, but it does not scale far and is very error-prone.

My first advice on this is to leverage a merge queue. While that sounds orthogonal to the issue, it's not: merging code without a merge queue is a significant source of disruption to your continuous deployment.

Mergify merge queue dashboard

When you entrust your merges to a merge queue system, it becomes safer, and you can take control of the flow of pull requests coming to your repository.

It does not have to be complicated. If you're leveraging GitHub branch protections, install Mergify GitHub Application on your repository and use the queue command. This will put the pull request in the merge queue and ensure it's up to date and works as expected. That might avoid another incident. πŸ˜…

Using Mergify queue command

Mergify's merge queue provides a freeze feature. It makes it then easy to freeze an entire queue, stopping the merge from happening. Just click on the freeze button, and enter a reason (e.g., the incident number being handled). You can now work on resolving the root cause without worrying about adding new code (and potentially new problems).

A frozen queue

Pull requests can still enter the queue, but can't leave it until the queue is thawed. At that point, the merge will happen, and operation can be resumed normally.

As demonstrated previously, you could add any other number of conditions to queue your pull requests or get them merged using any number of pull requests or queue rules. Mergify is incredibly flexible in that regard.

You could also freeze or unfreeze the merge queue using Mergify API, allowing you do control the influx of pull requests being merged directly from your favorite tools or integration.