Branch Protection Examples

This public content is an excerpt from Flutter staff GitHub docs. It is published as a reference to show how GitHub is used for inner source at Flutter.

You know why branching protection is necessary and the recommended options. This page explores the detail of some specific examples.

Service

A service repository uses a simple Reviewed Source workflow.

  • The repository contains critical code as the service handles sensitive data and/or directly process customer transactions.
  • At least 1 other user must review all changes before release.
  • The Reviewed Source branching strategy means that all production deployments run the code from the main branch.

You need branch protection on the main branch configured using Codebase Governor with:

branch-protections:
  - patterns:
      - "main"
    parameters:
      required-reviews-count: 1
      requires-codeowner-reviews: true
      required-status-check-jobs:
        - context: validation
          app: github-actions
  • Ensure contributors use pull requests with at least 1 approving review (required-reviews-count: 1).
  • Require a Codeowner approval rather than any other user with write permissions (requires-codeowner-reviews: true).
  • The selected pull request validation checks should pass to merge the PR (required-status-check-jobs).

Testing Tool

Not all repositories contain critical production service code – to reduce effort more relaxed protection is OK. For example for a testing tool repository using Reviewed Source relaxes the review requirements: allowing stale reviews and administrator override.

With Codebase Governor:

branch-protections:
  - patterns:
      - "main"
    parameters:
      required-reviews-count: 1
      requires-codeowner-reviews: true
      allow-admin-bypass: true
      allow-stale-reviews: true
      allow-stale-branch-merge: true

These settings encourage review and optimise for development speed:

  • maintainers and any other repository admins can push directly to main due to enabling allow-admin-bypass. This allows them to perform maintenance directly without waiting for review.
  • Approving reviews remain valid for a pull request after a contributor makes minor feedback fixes (allow-stale-reviews: true). This means the author spends less time chasing re-reviews after minor edits.
  • A branch not up-to-date can still merge (allow-stale-branch-merge: true). This reduces the time an author spends updating their branch.

Long Release Process

For a service with a long release process, a more complex branching strategy like GitFlow helps by batching a number of small changes into a larger release. For this service the complexity of Multiple Team Source is worthwhile to allow engineers to iterate on a develop branch while a isolated release can be tested separately.

With Codebase Governor:

branch-protections:
  - patterns:
      - "main"
      - "support/*"
    parameters:
      required-reviews-count: 2
      requires-codeowner-reviews: true
  - patterns:
      - "*/develop"
      - "*/release/*"
    parameters:
      required-reviews-count: 1
      requires-codeowner-reviews: true
      allow-admin-bypass: true
      allow-stale-reviews: true
      allow-stale-branch-merge: true
      allows-deletions: true

In this case stricter protection applies to critical production branches, and settings optimised for development speed used for branches which need review but won’t be directly released to production without further review.

Docs

A docs repository can permit any user with write access to commit and change the docs directly without review. If the author would like a review they can of course choose one, but it isn’t required. In this case, branch protection for main is still valuable to protect it from force pushes or deletions that would destroy its history. If you preserve history you can always revert any change which you retrospectively want to reject.

With Codebase Governor this is simply:

branch-protections:
  - patterns: ["main"]

Bot Commits

Some repositories require automated commits: for example a commit to update a release version from a build script. You need to use some GitHub credentials to automate this. Branch protection makes this use-case more complicated – avoid it if you can! If not:

  • There is an option in the GitHub user interface to configure users or apps that can “bypass branch protection”. Configuring this manually is the best approach.
  • When using a service account, you can allow repository admins to override the protection (allow-admin-bypass: true) and configure the service account as an admin. This isn’t recommended because the service account has a higher level of access to the repository than is necessary.
  • If you are using a deploy key for your automated access this counts as an admin user when it pushes, so the (allow-admin-bypass: true) can be a good setup in this case.