Azure-DevOps Pull-requests: Honor previous approvals upon submitting new changes in latest iteration - azure-devops

I would like to ask for your help with steps to resolve a seemingly simple issue in regards with branch policies. We have the following requirement: Mandate at least 1 Pull-Request approval from a team member other than the code author. However, once the reviewer has added some comments for minor code changes to be made, and approved the PR, then for the next iteration on this PR we would like to retain the reviewer's previous approval vote so that the code author can complete the PR without waiting for any additional approvals for their latest code changes. We understand that if there are more critical code changes suggested by the reviewer, then they can simply vote to wait or reject the PR.
Could you please help provide steps to achieve this scenario to retain reviewer's approval votes over successive code iteration/s? Thanks.

Assuming you are using Github, do the following
Go to your repository
Click on the settings tab
Click on branches on the left
Edit the branch protection rules
Under "Require a pull request before merging" uncheck the box that says "Dismiss stale pull request approvals when new commits are pushed"
Edit: my bad, completely overlooked the azure devops tag. See if the following works for you
Under Branch Policies, set Require a minimum number of reviewers on, and uncheck the box that says when new changes are pushed.
Found documentation here.

Related

GitHub: What is the difference having these two groups of branch protection settings enabled?

Upon reviewing the branch protection settings for a GitHub repo, and reading the documentation for all of the settings, I still can't quite figure out the difference between enabling these two groups of settings:
According to the documentation, if I require approvals, it means an approval is required from someone else (I cannot approve my own PR):
If you enable required reviews, collaborators can only push changes to a protected branch via a pull request that is approved by the required number of reviewers with write permissions.
The next option seems self explanatory, but here is what the documentation has to say about it:
Optionally, you can choose to dismiss stale pull request approvals when commits are pushed. If anyone pushes a commit that modifies code to an approved pull request, the approval will be dismissed, and the pull request cannot be merged. This doesn't apply if the collaborator pushes commits that don't modify code, like merging the base branch into the pull request's branch.
However, when I look at the documentation for the branch protection setting to "require approval of the most recent push", it sounds like it does the same thing as if I had the first two enabled:
Optionally, you can require approvals from someone other than the last person to push to a branch before a pull request can be merged. This ensures more than one person sees pull requests in their final state before they are merged into a protected branch. If you enable this feature, the most recent user to push their changes will need an approval regardless of the required approvals branch protection. Users who have already reviewed a pull request can reapprove after the most recent push to meet this requirement.
It sounds like this option implies that an approval will be dismissed if a new commit is pushed to the branch for the open PR. If that's the case, then isn't enabling the first to the same as enabling the last one?
The "require approval of the most recent push" protection rule was recently introduced (oct 2022), with the express purpose to prevent someone responding to a code review request from sneaking in changes and approving them themselves or using the already supplied approval from another reviewer.
The security research that explores these topics has not been broadly published, but there are some great discussions with recommendations on how to secure your branches.
With this new policy enabled, when a reviewer applies some suggestions to the code, they can't approve and merge the code without finding another person to review their changes.
Excerpts from the article, red team, emphasis mine:
— Modify code after review
After the attacker submits a valid and good code change that is approved, the attacker abuses their existing approval to make further changes that include bad code while retaining the stale approval.
Another scenario is that the attacker could first be a good samaritan and approve the code of a fellow developer, let’s assume it’s a good code change, but it doesn’t matter. What matters is that once they have approved that pull request, they could abuse their own write access, add bad code and self-approve their own code change.
And the protections, blue team, emphasis mine:
Require a pull request before merging
Require approvals
Dismiss stale pull request approvals when new commits are pushed
Require review from Code Owners
Allow specified actors to bypass required pull requests (avoid unless you absolutely need to)
Require approval of the most recent push (this is a new setting, as of October 2022, and is really great mitigation for some of our attack scenarios)
Require status checks to pass before merging (it you have some form of CI with tests, linters, SAST, it would be great to enforce those)
Require signed commits (this is great for end-to-end accountability)
Enforce Branch Protection for administrator (i.e. “Do not allow bypassing the above settings”)
Recommended mitigations, emphasis mine:
— Modify code after review
Attacker submits good code, gets approval, then submits bad code
The mitigation is to set your Branch Protection to “Dismiss stale pull request approvals when new commits are pushed”.
Attacker approves someone else’s good code, then submits bad code and self-approves changes
The mitigation is to set your Branch Protection to “Require approval of the most recent push”.

Why can't I approve my own PR in GitHub, even when I have disabled the setting for "Require approval from someone other than the last pusher"?

GitHub says I can disable protections that prevent the last pusher from approving the PR, but I am not able to even when I have that setting turned on. Is there some other setting I need to disable in my branch protections?
I can still merge the pull request by bypassing the requirements (since I'm the administrator of the repository), but that's not what I want to do. I want to be able (and want other pushers to be able) to approve my own pull requests, as long as they are considered Code Owners (which I am, in this case).
I have tried enabling the setting and disabling it again. It does not seem to make a difference.
I created this PR before I even had branch protections turned on, and I turned off branch protections off altogether to confirm that the branch protection settings are indeed being updated.
I also tried requiring a PR but unchecking "require approvals" and leaving "require review from Code Owners" checked, and this did not work either.
I have found the solution works for me; I am the only one working in the repository, so it may not be appropriate for other situations.
On the settings page, select "Branches". Select "Edit" in the Branch Protection Rule.
Make sure that these two checkboxes are unchecked:
Require approvals
When enabled, pull requests targeting a matching branch require a number of approvals and no changes requested before they can be merged.
Require approval from someone other than the last pusher
Require review approval from someone other than the last pusher to the pull request branch.
As TTT pointed out,
GitHub does not allow one to approve their own PRs that they created, ever.
The setting for "Require approval from someone other than the last pusher" is most likely an additional check on top of that, for if someone pushed to a PR that they did not create/own.
So it seems there is no way to enable the functionality that I wanted.

Azure Devops Pull Request - Prevent a user approving request if they have worked on the branch

I'm trying to find a way to stop users who have worked on a branch (who have committed changes on a branch) form being able to approve in a pull request on that branch. The idea that a dev can't approve their own work.
I haven't been able to find anything in the devops documentation and was hoping someone might have found a way that I've missed.
Anyone come across a solution?
Out of the box, you can prevent the creator of the pull request and the most recent pusher from approving their own changes, but you can't prevent every user who's committed to the branch from approving their changes. You likely won't want to prevent every developer who's committed to a branch from approving, because eventually, that will be nearly the entire development team.
You'll want to head to Project Settings > Repositories > Policies and update your branch policy to adjust the following settings:
Unchecked: Allow requestors to approve their own changes
Checked: Prohibit the most recent pusher from approving their own changes
Here's Microsoft's documentation on how to enable approval restrictions:
https://learn.microsoft.com/en-us/azure/devops/repos/git/branch-policies?view=azure-devops#require-a-minimum-number-of-reviewers
The feature Prohibit the most recent pusher from approving their own changes just prohibit the pull request creator from approving their own changes.
For example, user A create branch and push commit, then user B create the pull request.
The user B can vote Approve but the vote will not count toward the Minimum number of reviewers. And user A vote approve the pull request and the vote will count toward the Minimum number of reviewers
Prevent a user approving request if they have worked on the branch
You could add your request for this feature on our UserVoice site, which is our main forum for product suggestions. Thank you for helping us build a better Azure DevOps.
In addition, as a workaround, we could configure the branch policy and enable the feature Automatically included reviewers-> add admin as request reviewer and set the option Policy requirement to Required. Then after the administrator checks and approves the pull request, then developers can complete the pull request.
Also, If there are fewer developers, we can let each developer create his own branch, they can only work on their own branch and create pull request for their own branch, then enable the branch policy Prohibit the most recent pusher from approving their own changes to do this.

On GitHub, what's the difference between reviewer and assignee?

A feature added on Dec, 7, 2016, announced on GitHub blog, introduced the option to add reviewers to a Pull Request
You can now request a review explicitly from collaborators, making it easier to specify who you'd like to review your pull request.
You can also see a list of people who you are awaiting review from in the pull request page sidebar, as well as the status of reviews from those who have already left them.
However, explicit setting a reviewer for a PR was already done by assigning people (assignees option).
With both options now available, what's the role of each option since they both share the same end goal?
EDIT:
After discussing with several OSS maintainers, reviewers is defined as what the word supposed to be: to review (someone's code) and "assignee" has a looser definiton explained below.
For "reviewer": someone you want to review the code. Not necessarily the person responsible for that area or responsible for merging the commit. Can be someone who worked on that chunk of code before, as GitHub auto-suggests.
For "assignee": up to the project's team/maintainer what it means and there's no strict definition. It can be the PR opener, or someone responsible for that area (who is going to accept the PR after the review is done or just close it). It's not up to GitHub to define what it is leaving it open for project maintainers what fits best for their project.
Previous answer:
Ok I'll go ahead and answer my own question.
For PR of users with write-access: the Assignee would be the same person who opened the PR, and reviewer would replace the old assignee function (reviewing code), being this one someone of assignee choice.
For PR of users without write-access (outside contributors): Someone with write-access would assign herself (or other write-priviledge member), to review the PR (Reviewer). Assignee is blank.
For unfinished PR from outside contributors: the write-access member would take the unfinished work and assign for her. She will be responsible for finishing the task, being the Assignee. Since the main reason of PRs is reviewing changes, she would select some other people to review the changes.
In GitHub a reviewer is a person who reviews the pull request. A project owner can request review from any of the maintainers, They can even set an option so that the pull request can be merged only if it is reviewed by one of the maintainer with write access.
According to official github documentation, Assignee is a person who is working on specific issues and pull requests. It is sometimes confused as a reviewer. It is actually meant to be used with issues rather than pull request so that when we receive a issue we can assign someone to fix it. In a pull request, an assignee refers to a person who's in charge of merging that pull request after getting comments and change requests from other maintainers.
As per accepted answer. Yes, "assignee" has a looser definition and can be used differently to suit a teams need.
In our team of 8 devs, in most PRs we have 1 reviewer, who suggests changes and ultimately approves the PR. During review phase, "assignee" is the person who opened the PR; later on if PR is picked up by other developer, a new "assignee" is added. Once PR is approved and ready for QA or direct merge, a new QA "assignee" is added. This way "assignee" list grows.
We use "assignee" to designate following people collectively:
Pull Request Author
Author working on PR change suggestions (usually same as 1)
QA person involved
Person responsible to merge (usually same as 2 or 3)
Using "assignee" helps locating the PR in future easily. One of my project has >3000 PRs.
is:open is:pr author:raya-dumas
is:closed is:pr assignee:raya-dumas
Or just author:raya-dumas to find all items author created (issues, PRs)
and other similar queries to ease the search process. "milestones" are quite helpful to use as well to ease PR search.
The biggest difference between "reviewers" and "assignees" is that reviewers actually have a tracked state according to GitHub -- did they review the PR yet or not?
When you add a reviewer, what it actually does is create a "review request":
The reviewer gets notified (like an "assignee" would) but now they actually have a task they can complete, which is to provide a "review" on a pull request:
After the reviewer leaves a review (approving or requesting changes), that information is tracked in the GitHub API and interface:
With assignees, you can associate people with a PR but beyond that GitHub doesn't really care what that means or what those people need to do. With reviewers, you can use new search queries, "protect" branches, assign reviewers with CODEOWNERS, and build deeper API integrations around review assignment and workflows manually or through tools like PullApprove.
Before GitHub only had an assignee field and no reviewer field. There was no distinction back then so the assignee field was most commonly used as a reviewer field.
But use them whatever way suits your project.
Another difference: the person who created the PR can assign himself/herself as the assignee, however cannot request himself/herself as one of the reviewers.

Automatically merge verified and tested GitHub Pull Requests

I'd like to automatically (i.e. from Jenkins) merge a GitHub pull request that has been approved by a person and has been tested successfully; in other words, when all THREE of these checkmarks are green:
Is this possible? I haven't found any documentation on an API for GitHub's new "changes approved" code review functionality.
There is a new PullRequestReviewEvent webhook that is triggered when a review is submitted in a non-pending state. The body of the webhook contains the ["review"]["state"] field, which will be approved when all reviewers have approved the changes (i.e. when you get the green "changes approved" tick in the UI).
Combine this with the StatusEvent for the head SHA of your pull request to get the status checks from CI and so on, then finally check the "merge-ability" of the pull by requesting the pull request from the API:
GET /repos/:owner/:repo/pulls/:number
Once you have all three things, you can merge the pull request with:
PUT /repos/:owner/:repo/pulls/:number/merge
and appropriate payload parameters. Note you'll need the Accept: application/vnd.github.polaris-preview+json for some of the payload parameters as they are in a preview period.
Official documentation: "Managing auto-merge for pull requests in your repository".
That is now (Dec. 2020, 4 years later) available:
Pull request auto-merge public beta
Pull request auto-merge is now rolling out as a public beta!
With auto-merge, pull requests can be automatically merged when all requirements for merging are met. No more waiting for long checks to finish just so you can press the merge button!
To use auto-merge, a repository maintainer or admin must first toggle on the repository setting to allow auto-merge (see steps).
Then any user with write permission can enable or disable auto-merge by navigating to the pull request page.
Keep in mind that auto-merge is only available for pull requests targeting a branch with required reviews or required status checks, and therefore is only available on public repositories and private repositories on Team and GitHub Enterprise Cloud plans.
Learn more about pull request auto-merge.
Update Feb. 2021:
Pull request auto-merge is now generally available
With auto-merge, pull requests can be set to merge automatically when all merge requirements are met.
No more waiting on slow CI jobs or tests to finish just so you can click the merge button!
To use auto-merge, first have an administrator allow auto-merge in the repository settings.
Then to enable auto-merge, navigate to the pull request on GitHub.com or GitHub Mobile and tap the button to enable.
Note that auto-merge can only be enabled by users with permission to merge and when there are unsatisfied merge requirements, like missing approvals or failing required status checks.
GraphQL APIs will be rolling out later this week. The pull request webhook event also now includes actions that indicate when auto-merge is enabled or disabled.
Learn more about pull request auto-merge
However, as The Godfather mentions in the comments:
The problem with this is that it doesn't do auto-update.
So as soon as your repo has "branches must be up-to-date" and some other PR got merged, this "auto-merge" doesn't work any more.
It should have been called the same way as Gitlab: "merge when pipeline succeeds", at least it's not as confusing... –
Update Aug. 2021:
Maintainers can now manage the availability of auto-merge in a repository
Maintainers can now manage the repository-level "Allow auto-merge" setting.
This setting, which is off by default, controls whether auto-merge is available on pull requests in the repository.
Previously, only admins could manage this setting.
Additionally, this setting can now by controlled using the "Create a repository" and "Update a repository" REST APIs.
I wrote an app that does this. It responds to the review, labelled, and commit status/checks events, and merges when the merge button is green.
The fact that it merges when the merge button is green means that you can configure the requirements for a mergeable PR in the GitHub settings, there's no need to write separate configuration for the app.
Mergery is:
Free, including for private repositories.
Fast. It's event-driven, it doesn't run on a schedule.
Simple. No configuration required. Just label your PRs with automerge.
You can use Mergify to do exactly this, since this is what it has been created for. Just set up a minimal .mergify.yml file in your repository:
rules:
default:
protection:
required_status_checks:
context:
- continuous-integration/travis/pr
required_pull_request_reviews:
required_approving_review_count: 1
And you'll be good to go.
(disclaimer: I'm one of the Mergify founders)
Using github actions which is one of the new ways, this can be done. I have written a blog about auto approving and auto merging PRs using github actions. However, if the intent is to just merge the PRs only, then then the second job in this work flow would be enough to do it.
https://github.com/bobvanderlinden/probot-auto-merge is a free GitHub app that does the job. It's configurable in .github/auto-merge.yml.