Skip to content

Fine-grained merge request approval policies

Description

I would like to be able to control, on a per-target-branch or per-file basis, who is allowed to approve a MR and how many approvals are needed.

Sometimes, a certain branch is reserved for a particular team (say, it's a release branch). At other companies, code has per-directory owners. Google reported does it this way, as does Twitter (the "we" in this ticket is Twitter: https://secure.phabricator.com/T10939 ). At some companies, the code author is allowed to be one of the approvers; at other companies, they're not. The point is that policies vary dramatically, and GitLab should allow a wide range of approval workflows.

Proposal

I think a webhook is probably the way to do this. The webhook could take a set of users who have approved, and enough metadata to let the hook figure out what files have been changed, and the branch to be merged to, and return either a list of users who still need to approve the review, or some user-facing text explaining the review requirements.

I prefer webhooks to hard-coding a solution, because I think we need both per-directory and per-branch rules, and I think we'll store owners data outside of the repository (say, in LDAP or some other external database).

Another option would be to add a pipeline step to handle these approvals. But I don't necessarily want to re-run my entire pipeline just because my set of approvers changed (and AIUI, GitLab doesn't do that anyway).

Documentation blurb

Sometimes, a certain branch is reserved for a particular team (say, it's a release branch). At other companies, code has per-directory owners. Merge request approval webhooks can enable arbitrarily complicated approval rules. Just install a "Merge request approval" webhook. The webhook will be called whenever the set of users who has approved a MR changes, or when a new push to the MR branch is made. To manually trigger a recheck of approvals, the review's author could push a no-op change to the branch or click the "recheck approvals" button (this is needed in the case where the webhook's underlying data source gets updated).

The webhook will take some json structure which looks like

{
  "object_kind": "merge-request-approval-information",
  "project_id": 5,
  "project":{
    [ the usual]
  },
  "repository":{
    [ the usual ]
  },
  "object_attributes": {
    "old_approvers": ["chris", "ashley"],
    "new_approvers": ["chris", "ashley", "joan"],
  },
  "merge_request": {
     [ the usual ]
  }

It will return an object of the following form: { "approvals_remaining" : ["jesse", "kee", "linda"], "message" : "Because this commit touched the file foo/bar/baz, you need approval from someone in the foo/bar hierarchy. That's either Jesse or Kee. In addition, because this commit is going to the PROD-1234 branch, you need approval from the branch owner. That's Linda." }