Skip to content

Repository files navigation

protector

branch protection as code!


Motivation

In larger organizations / projects, not everyone can access the configuration of a repository. Therefore, engineers are not able to see and edit the current Branch Protection Rules. This can lead to confusion. Good documentation might reduce the lack of clarity but also requires effort to keep up to date.

Keeping the protection rules as close to the source code as possible clarifies the way how the team actually works.

Versioning

protector versions are defined as vx.y.z, where x is the major version, y is the minor version, and z is the patch version, following Semantic Versioning terminology.

To support multiple versions at the same time and also to keep things simple, protector uses release branches for the most recent two major releases. Fixes (e.g. security, bugs etc.) may be backported to those branches.

VersionStatus
v1Active
v2Inactive

Getting started

  1. To use protector, a custom personal access token with the scopes repo and optionally, read:org, is required. Follow the steps described on Creating a personal access token.

  2. Next up: Creating encrypted secrets for a repository / Creating encrypted secrets for an organization to create a secret called PROTECTOR_TOKEN.

  3. Create a new workflow file (e.g. .github/workflows/enforce-protection.yml).

    name: protectoron: pushjobs:
    test:
    runs-on: ubuntu-lateststeps:
    - uses: actions/checkout@v2
    - uses: m19c/protector@v1with:
    token: ${{ secrets.PROTECTOR_TOKEN }}
  4. Generate a protector.yml file inside .github/. It is also possible to configure the location of your configuration file by passing config (with: { config: "path/to/my/config.yml" }).

    patterns:
    - dev
    - masterallowsDeletions: falseoverrides:
    dev:
    requiresLinearHistory: truemaster:
    isAdminEnforced: truereviewDismissalActors:
    - @m19c
  5. Push the changes.

  6. Profit!

Configuration

PropertyDescriptionExample
patternsList of patterns to match the actual branches.['dev', 'master']
...Any of RuleSet.-
overridesMap of RuleSet overrides to be more specific in certain cases.-

RuleSet

PropertyTypeDescription
allowsDeletionsbooleanCan this branch be deleted.
allowsForcePushesbooleanAre force pushes allowed on this branch.
dismissesStaleReviewsbooleanWill new commits pushed to matching branches dismiss pull request review approvals.
isAdminEnforcedbooleanCan admins overwrite branch protection.
requiredApprovingReviewCountbooleanNumber of approving reviews required to update matching branches.
requiresApprovingReviewsbooleanAre approving reviews required to update matching branches.
requiresCodeOwnerReviewsbooleanAre reviews from code owners required to update matching branches.
requiresCommitSignaturesbooleanAre commits required to be signed.
requiresLinearHistorybooleanAre merge commits prohibited from being pushed to this branch.
restrictsReviewDismissalsbooleanIs dismissal of pull request reviews restricted.
restrictsPushesbooleanIs pushing to matching branches restricted.
requiredStatusCheckContextsbooleanList of required status check contexts that must pass for commits to be accepted to matching branches.
requiresStatusChecksbooleanAre status checks required to update matching branches.
requiresStrictStatusChecksArray<string>Are branches required to be up to date before merging.
reviewDismissalActorsArray<string>A list of User (@<username>) and / or Team (#<team>) allowed to dismiss pull requests.
pushActorsArray<string>A list of User (@<username>) and / or Team (#<team>) allowed to push to matching branches.

Real World Example

patterns:
- dev
- staging
- masterallowsDeletions: falseallowsForcePushes: falsedismissesStaleReviews: trueisAdminEnforced: truerequiredApprovingReviewCount: 1requiresApprovingReviews: truerequiresCodeOwnerReviews: truerequiresCommitSignatures: truerequiresLinearHistory: truerestrictsReviewDismissals: falserestrictsPushes: truepushActors:
- '#developer'requiresStatusChecks: truerequiredStatusCheckContexts:
- continuous-integration/jenkins/branchrequiresStrictStatusChecks: truereviewDismissalActors:
- '#developer'overrides:
master:
requiredApprovingReviewCount: 2

Development

Workflow

protector requires both the action itself and a config file. The configuration describes whether or not a branch should be considered and how the branch should be protected.

 ┌───────────────GITHUB──────────────┐
│ │
│ ┌───────────┐ │
│ │ PROTECTOR │ │
│ │ ACTION │◄────R/W──┐ │
│ └───────────┘ │ │
│ ▲ ▼ │
│ │ ┌─────┐ │
│ │ │ API │ │
│ TRIGGER └─────┘ │
│ │ │
│ │ │
┌────────┐ │ ┌─┴──────────┐ │
│ CHANGE ├───── PUSH───────►│ REPOSITORY │ │
└────────┘ │ └────────────┘ │
│ │
└───────────────────────────────────┘

Known limitations

  • Both reviewDismissalActors as well as pushActors are limited to 100 items.
  • reviewDismissalActors and pushActors can only hold Teams / Users.
  • Some options are only available for organizations either with or without Team / Enterprise plan.
  • Strict pattern checks: GitHub offers dynamic branch matching, for example v* will match branches like v1, v2 and so on. However, protector is only able to match patterns equally.

About

github branch protection as code

Topics

Resources

Code of conduct

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages