18

I have setup on my Github repo a branch protection rule on master branch checking (activating) the following:

  • Require pull request reviews before merging
  • Required approving reviewers : 1
  • Include administrators
  • Restrict who can push to matching branches

I'm then in a situation that at least one from the team must approve a PR before someone can merge its own dev branch to master.

Apart from the above I would also want to select only some people that will have the permission to merge the reviewed and approved PR. Not everyone having access to the repo.

Is it possible to set this up?

koalaok
  • 5,075
  • 11
  • 47
  • 91
  • https://docs.github.com/en/github/administering-a-repository/enabling-branch-restrictions what is missing into the doc ? – Ôrel Jul 06 '20 at 15:53
  • I've read that and it's not that explicit...Maybe "Restrict who can push to matching branches" also meaning restrict who can merge to matching branch? And if I enable those people will they be able to push directly to master without PR? – koalaok Jul 06 '20 at 16:01
  • https://docs.github.com/en/github/administering-a-repository/enabling-required-reviews-for-pull-requests to add minimal validator and set Require pull request reviews before merging. – Ôrel Jul 06 '20 at 16:04

6 Answers6

7

No, GitHub doesn't let you restrict who can perform a merge. However, if you want to require a specific group of people to approve a PR before merging, use the CODEOWNERS file and require an approval from a code owner before merging in the branch protection settings.

For example, if you want all changes to be reviewed by the core team, you can use this in your CODEOWNERS file:

*  @my-org/core
bk2204
  • 64,793
  • 6
  • 84
  • 100
  • 3
    but this will make every new branch created after that to request a review from code owner even though the base branch is not master – Teju Amirthi Mar 23 '22 at 17:10
3

I also have requirement like you that I only want some specific people (not all collaborators) are allowed to approve changes to the main branch. And I did as follows for Github Free public repository:

  • write a Github Actions file that check the name of person who runs it. If this is name of powerful collaborator, the Actions will succeed.

name: actions_on_main_branch
on: 
  pull_request_target:
    types:
      - opened
      - synchronize
      - reopened
    branches:    
      - 'main'

jobs:
  job1:
    name: check_adminA
    runs-on: ubuntu-latest
    env:
      NAME_ADMIN: adminA
    steps:
      - name: st1
        if: ${{ github.actor != env.NAME_ADMIN }}
        run: exit 1
      - name: st2
        if: ${{ github.actor == env.NAME_ADMIN }}
        run: echo "ok"

  • in repo settings, add rule to protect 'main' branch. in that rule, select 'Require status checks to pass before merging' and select jobs that you specified previously in github actions file. (if jobs not showing, try creating pull request that trigger those github actions, after that jobs will be found on search bar) (you can also select 'Include administrators')

    enter image description here

By doing that, changes are made to 'main' branch have to go through pull request and those checks will run and fail and prevent merging. Until the powerful collaborators (adminA, adminB) go to that pull request and re-run them, those checks succeeds and allows merging.
(The pull_request_target event makes Github-actions run on the context of base branch instead of the merging branch. So you don't have to worry github-actions file are edited to be passed easily from outside.)

irous
  • 401
  • 3
  • 8
  • Won't this allow collaborators to delete this action in their PR's? Which will make it all checks 'succeed' and allow them to merge? – MartijnvdB May 10 '23 at 09:22
  • @MartijnvdB It won't allow. the `pull_request_target` event I mentioned above will ensure github-actions file will be picked from main branch, not the merging branch. which means collaborators cannot modify actions from merging branch to make PR all passed – irous May 11 '23 at 04:52
2

Merging of pull requests respect the branch protection rule of the target branch. So add the people who should be allowed to merge into the protection rule and you are good to go.enter image description here

enter image description here

ogborstad
  • 2,309
  • 2
  • 19
  • 22
  • 2
    More information please, how is this achieved? With what rule? – kutschkem Mar 09 '23 at 12:23
  • How do you accomplish this – Dominic Farolino May 04 '23 at 14:36
  • Go to the repository in Github. Go to "Settings" -> "Branches" under "Code and automation", then check "Restrict who can push to matching branches" – ogborstad May 08 '23 at 08:59
  • This might actually do the job – Lelo Jun 15 '23 at 21:23
  • Went to Settings | Branches | Code and automation - the word "restrict" does not appear anywhere on the page. How did you do this? And screenshots would be very helpful. TIA – David Thielen Jul 20 '23 at 02:10
  • @DavidThielen On your chosen repository, go to Settings -> Branches (Under code and automation) -> Edit (on your selected branch) and then check "Restrict who can push to matching branches" – ogborstad Aug 04 '23 at 05:39
  • @ogborstad Please look at the comments to the answer by LuigiB below - that restricts who can push, not who can merge. thanks – David Thielen Aug 04 '23 at 16:12
  • In case you cannot find this in your settings, keep in mind you need either GitHub Team or GitHub Free organization ([source](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#restrict-who-can-push-to-matching-branches)) – Alexander Kucheryuk Aug 08 '23 at 20:00
1

It is posible by 'Branch protection rules':

Branch protection Rules Section

You have to select the branch you want to protect and select the people allow to merge in this option:

Section to add people who can approve pull request

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Luigi B
  • 11
  • 3
  • 1
    You can clearly see in your screen shot that that feature is to control who can push to matching branches and has nothing to do with controlling who can merge. – Sam Nov 16 '22 at 21:42
  • @Sam is pushing not an integral part of performing a merge though? You have to push the resultant merge to the remote for it to be stored there, so perhaps this is actually the answer to the original question. I will have to investigate if it works. – Harvey Adcock Aug 03 '23 at 09:26
0

I recall at least half of those features are in GitHub's settings. In your case, only approvers should be added as "collaborators", since they can push. Other users will have to open a pull request to make any change.

Ali Pardhan
  • 194
  • 1
  • 14
0

@irous I followed your answer and it work for a single user, but then trying to specify for more than one user it is then required that the two specified collaborators must pass before a PR merge. Below is the added script:

  job1:
name: check_adminA
runs-on: ubuntu-latest
env:
  NAME_ADMIN1: pracin
steps:
  - name: st1
    if: ${{ github.actor != env.NAME_ADMIN1 }}
    run: exit 1
  - name: st2
    if: ${{ github.actor == env.NAME_ADMIN1 }}
    run: echo "ok"
job2:
name: check_adminB
runs-on: ubuntu-latest
env:
  NAME_ADMIN2: stephus
steps:
  - name: st1
    if: ${{ github.actor != env.NAME_ADMIN2 }}
    run: exit 1
  - name: st2
    if: ${{ github.actor == env.NAME_ADMIN2 }}
    run: echo "ok"
Pensec
  • 21
  • 2
  • I wasn't notified by your tag. what is your issue exactly? do you want either ADMIN1 or ADMIN2 acceptance is enough? or both must accept? – irous Jan 22 '23 at 06:16
  • @irous Yes I want either ADMIN1 or ADMIN2 acceptance is enough – Pensec Feb 22 '23 at 07:29
  • you can just remove job2. In job1, st1, use '&&' to check both admins. in job1, st2, use '||' to check any of admins. [reference](https://docs.github.com/en/actions/learn-github-actions/expressions) – irous Feb 26 '23 at 10:02
  • Hello @irous I try editing the script to below, but I found out that it get passed no matter who is trying to merge, which defeat the plan, help check name: actions_on_snapshot on: pull_request_target: types: - opened - reopened branches: - 'snapshot' jobs: job1: name: merger runs-on: ubuntu-latest env: ADMIN1: user1 ADMIN2: user2 steps: - if: ${{ env.ADMIN1 != 'user1' || env.ADMIN2 != 'user2' }} run: exit - if: ${{ env.ADMIN1 == 'user1' || env.ADMIN2 == 'user2' }} run: echo "ok" – Pensec Apr 19 '23 at 08:44
  • I assume your expected result is to allow either admin 1 or 2. if so, in step1, try using '&&' instead of '||'. and 'exit 1' instead of 'exit' – irous Apr 20 '23 at 09:39