Branchprotector
branchprotector configures github branch protection according to a specified policy.
Policy configuration
Extend the primary prow config.yaml document to include a top-level
branch-protection key that looks like the following:
branch-protection:
  orgs:
    kubernetes:
      repos:
        test-infra:
          # Protect all branches in kubernetes/test-infra
          protect: true
          # Always allow the org's oncall-team to push
          restrictions:
            teams: ["oncall-team"]
          # Ensure that the extra-process-followed github status context passes.
          # In addition, adds any required prow jobs (aka always_run: true)
          required_status_checks:
            contexts: ["extra-process-followed"]
presubmits:
  kubernetes/test-infra:
  - name: fancy-job-name
    context: fancy-job-name
    always_run: true
    spec:  # podspec that runs job
This config will:
- Enable protection for every branch in the kubernetes/test-infrarepo.
- Require extra-process-followedandfancy-job-namestatus contexts to pass before allowing a merge- Although it will always allow oncall-teamto merge, even if required contexts fail.
- Note that fancy-job-nameis pulled in automatically from thepresubmitsconfig for the repo, if one exists.
 
- Although it will always allow 
Updating
- Send PR with config.yamlchanges
- Merge PR
- Done!
Make changes to the policy by modifying config.yaml in your favorite text
editor and then send out a PR. When the PR merges prow pushes the updated config
. The branchprotector applies the new policies the next time it runs (within
24hrs).
Advanced configuration
Fields
See branch_protection.go and GitHub’s protection api for a complete list of fields allowed
inside branch-protection and their meanings. The format is:
branch-protection:
  # default policy here
  orgs:
    foo:
      # this is the foo org policy
      protect: true  # enable protection
      enforce_admins: true  # rules apply to admins
      required_linear_history: true  # enforces a linear commit Git history
      allow_force_pushes: true  # permits force pushes to the protected branch
      allow_deletions: true  # allows deletion of the protected branch
      required_pull_request_reviews:
        dismiss_stale_reviews: false # automatically dismiss old reviews
        dismissal_restrictions: # allow review dismissals
          users:
          - her
          - him
          teams:
          - them
          - those
        require_code_owner_reviews: true  # require a code owner approval
        required_approving_review_count: 1 # number of approvals
      required_status_checks:
        strict: false # require pr branch to be up to date
        contexts: # checks which must be green to merge
        - foo
        - bar
      restrictions: # restrict who can push to the repo
        apps:
        - github-prow-app
        users:
        - her
        - him
        teams:
        - them
        - those
Scope
It is possible to define a policy at the
branch-protection, org, repo or branch level. For example:
branch-protection:
  # Protect unless overridden
  protect: true
  # If protected, always require the cla status context
  required_status_checks:
    contexts: ["cla"]
  orgs:
    unprotected-org:
      # Disable protection unless overridden (overrides parent setting of true)
      protect: false
      repos:
        protected-repo:
          protect: true
          # Inherit protect-by-default config from parent
          # If protected, always require the tested status context
          required_status_checks:
            contexts: ["tested"]
          branches:
            secure:
              # Protect the secure branch (overrides inhereted parent setting of false)
              protect: true
              # Require the foo status context
              required_status_checks:
                contexts: ["foo"]
    different-org:
      # Inherits protect-by-default: true setting from above
The general rule for how to compute child values is:
- If the child value is nullor missing, inherit the parent value.
- Otherwise:
- List values (like contexts), create a union of the parent and child lists.
- For bool/int values (like protect), the child value replaces the parent value.
 
- List values (like 
So in the example above:
- The securebranch inunprotected-org/protected-repo- enables protection (set a branch level)
- requires footestedclastatus contexts (the latter two are appended by ancestors)
 
- All other branches in unprotected-org/protected-repo- disable protection (inherited from org level)
 
- All branches in all other repos in unprotected-org- disable protection (set at org level)
 
- All branches in all repos in different-org- Enable protection (inherited from branch-protection level)
- Require the clacontext to be green to merge (appended by parent)
 
Developer docs
Run unit tests
go test ./cmd/branchprotector
Run locally
go run ./cmd/branchprotector --help, which will tell you about the
current flags.
Do a dry run (which will not make any changes to github) with something like the following command:
go run ./cmd/branchprotector \
  --config-path=/path/to/config.yaml \
  --github-token-path=/path/to/my-github-token
This will say how the binary will actually change github if you add a
--confirm flag.
Deploy local changes to dev cluster
Run things like the following:
# Build image locally and push it to <YOUR_REGISTRY>
make push-single-image PROW_IMAGE=cmd/branchprotector REGISTRY=<YOUR_REGISTRY>
This will build an image with your local changes, and push it to <YOUR_REGISTRY>.
Or, if you just want to build an image but not to push, run the following:
# Build image locally
make build-single-image PROW_IMAGE=cmd/branchprotector
This will build an image with your local changes, without pushing it to anywhere.
Deploy cronjob to production
branchprotector image is automatically built as part of prow, see “How to update the cluster” for more details.
Branchprotector runs as a prow periodic job, for example ci-test-infra-branchprotector.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.