github.com/abayer/test-infra@v0.0.5/prow/cmd/branchprotector/README.md (about) 1 # Branch Protection Documentation 2 3 branchprotector configures [github branch protection] according to a specified 4 policy. 5 6 ## Policy configuration 7 8 Extend the primary prow [`config.yaml`] document to include a top-level 9 `branch-protection` key that looks like the following: 10 11 ```yaml 12 13 branch-protection: 14 orgs: 15 kubernetes: 16 repos: 17 test-infra: 18 # Protect all branches in kubernetes/test-infra 19 protect: true 20 # Always allow the org's oncall-team to push 21 restrictions: 22 teams: ["oncall-team"] 23 # Ensure that the extra-process-followed github status context passes. 24 # In addition, adds any required prow jobs (aka always_run: true) 25 required_status_checks: 26 contexts: ["extra-process-followed"] 27 28 presubmits: 29 kubernetes/test-infra: 30 - name: fancy-job-name 31 context: fancy-job-name 32 always_run: true 33 spec: # podspec that runs job 34 ``` 35 36 This config will: 37 * Enable protection for every branch in the `kubernetes/test-infra` 38 repo. 39 * Require `extra-process-followed` and `fancy-job-name` [status contexts] to pass 40 before allowing a merge 41 - Although it will always allow `oncall-team` to merge, even if required 42 contexts fail. 43 - Note that `fancy-job-name` is pulled in automatically from the 44 `presubmits` config for the repo, if one exists. 45 46 ### Updating 47 48 * Send PR with `config.yaml` changes 49 * Merge PR 50 * Done! 51 52 Make changes to the policy by modifying [`config.yaml`] in your favorite text 53 editor and then send out a PR. When the PR merges prow pushes the updated config 54 . The branchprotector applies the new policies the next time it runs (within 55 24hrs). 56 57 ### Advanced configuration 58 59 60 #### Fields 61 62 See [`branch_protection.go`] and Github's [protection api] for a complete list of fields allowed 63 inside `branch-protection` and their meanings. The format is: 64 65 ```yaml 66 branch-protection: 67 # default policy here 68 orgs: 69 foo: 70 # this is the foo org policy 71 protect: true # enable protection 72 enforce_admins: true # rules apply to admins 73 required_pull_request_reviews: 74 dismiss_stale_reviews: false # automatically dismiss old reviews 75 dismissal_restrictions: # allow review dismissals 76 users: 77 - her 78 - him 79 teams: 80 - them 81 - those 82 require_code_owner_reviews: true # require a code owner approval 83 required_approving_review_count: 1 # number of approvals 84 required_status_checks: 85 strict: false # require pr branch to be up to date 86 contexts: # checks which must be green to merge 87 - foo 88 - bar 89 restrictions: # restrict who can push to the repo 90 users: 91 - her 92 - him 93 teams: 94 - them 95 - those 96 ``` 97 98 99 100 #### Scope 101 102 103 It is possible to define a policy at the 104 `branch-protection`, `org`, `repo` or `branch` level. For example: 105 106 ```yaml 107 branch-protection: 108 # Protect unless overridden 109 protect: true 110 # If protected, always require the cla status context 111 required_status_checks: 112 contexts: ["cla"] 113 orgs: 114 unprotected-org: 115 # Disable protection unless overridden (overrides parent setting of true) 116 protect: false 117 repos: 118 protected-repo: 119 # Inherit protect-by-default config from parent 120 # If protected, always require the tested status context 121 required_status_checks: 122 contexts: ["tested"] 123 branches: 124 secure: 125 # Protect the secure branch (overrides inhereted parent setting of false) 126 protect: true 127 # Require the foo status context 128 required_status_checks: 129 contexts: ["foo"] 130 different-org: 131 # Inherits protect-by-default: true setting from above 132 ``` 133 134 The general rule for how to compute child values is: 135 * If the child value is `null` or missing, inherit the parent value. 136 * Otherwise: 137 - List values (like `contexts`), create a union of the parent and child lists. 138 - For bool/int values (like `protect`), the child value replaces the parent value. 139 140 So in the example above: 141 * The `secure` branch in `unprotected-org/protected-repo` 142 - enables protection (set a branch level) 143 - requires `foo` `tested` `cla` [status contexts] 144 (the latter two are appended by ancestors) 145 * All other branches in `unprotected-org/protected-repo` 146 - disable protection (inherited from org level) 147 * All branches in all other repos in `unprotected-org` 148 - disable protection (set at org level) 149 * All branches in all repos in `different-org` 150 - Enable protection (inherited from branch-protection level) 151 - Require the `cla` context to be green to merge (appended by parent) 152 153 ## Developer docs 154 155 Use [`planter.sh`] if [`bazel`] is not already installed on the machine. 156 157 ### Run unit tests 158 159 `bazel test //prow/cmd/branchprotection:all` 160 161 ### Run locally 162 163 `bazel run //prow/cmd/branchprotection -- --help`, which will tell you about the 164 current flags. 165 166 Do a dry run (which will not make any changes to github) with 167 something like the following command: 168 169 ```sh 170 bazel run //prow/cmd/branchprotection -- \ 171 --config-path=/path/to/config.yaml \ 172 --github-token-path=/path/to/my-github-token 173 ``` 174 175 This will say how the binary will actually change github if you add a 176 `--confirm` flag. 177 178 ### Deploy local changes to dev cluster 179 180 Run things like the following: 181 ```sh 182 # Build and push image, create job 183 bazel run //prow/cmd/branchprotection:oneshot.create 184 # Delete finished job 185 bazel run //prow/cmd/branchprotection:oneshot.delete 186 # Describe current state of job 187 bazel run //prow/cmd/branchprotection:oneshot.describe 188 ``` 189 190 This will build an image with your local changes, push it to 191 `STABLE_DOCKER_REPO` and then deploy to `STABLE_PROW_CLUSTER`. 192 193 See [`print-workspace-status.sh`] for the definition of these variables. 194 See [`oneshot-job.yaml`] for details on the deployed job resource. 195 196 ### Deploy cronjob to production 197 198 Follow the standard prow deployment process: 199 200 ```sh 201 # build and push image, update tag used in production 202 prow/bump.sh branchprotector 203 # apply changes to production 204 bazel run //prow/cluster:branchprotector.apply 205 ``` 206 207 See [`prow/bump.sh`] for details on this script. 208 See [`prow/cluster/branchprotector_cronjob.yaml`] for details on the deployed 209 job resource. 210 211 212 [`bazel`]: https://bazel.build 213 [`branch_protection.go`]: /prow/config/branch_protection.go 214 [`config.yaml`]: /prow/config.yaml 215 [github branch protection]: https://help.github.com/articles/about-protected-branches/ 216 [`oneshot-job.yaml`]: oneshot-job.yaml 217 [`planter.sh`]: /planter 218 [`print-workspace-status.sh`]: ../../../hack/print-workspace-status.sh 219 [`prow/bump.sh`]: /prow/bump.sh 220 [`prow/cluster/branchprotector_cronjob.yaml`]: /prow/cluster/branchprotector_cronjob.yaml 221 [status contexts]: https://developer.github.com/v3/repos/statuses/#create-a-status 222 [protection api]: https://developer.github.com/v3/repos/branches/#update-branch-protection