Azure DevOps Repos Limit or Block PR by Number of Commits

I am working in Azure DevOps and have junior developers creating PRs with massive code changes and over 100 commits. I have looked at the default policies in Azure DevOps Repos, but did not see anything that limits the number of commits in a PR.

Is there any way to limit the number of commits in a single PR, so it promotes positive development behavior?

Thanks in advance for the help.


Addendum:

I am not looking to make any universal judgements on coding practices. I am simply looking for advice to determine if there is a way to limit number of commits or commit sizes per PR.

I believe there can be legitimate situations to have many large commits per PR. One example of this would be a rigid, strictly regulated systems that do not allow simpler components without error.

From my leadership perspective with my teams’ context, it does not constitute one of these valid reasons.

4

There is no documented limit for the max count of commits on a PR, and also no built-in option to set a custom limit for this.

As a workaround, you can try like as below:

  1. In Azure DevOps project, go to Project Settings > Teams to create a team (e.g., Developers).

    • Add all the developers in the project as members of this team.
    • Go to Project Settings > Repositories > “Security“, set and ensure the permission “Remove others' locks” is “Deny” for this team.
  2. Go to Project Settings > Repositories > “Security“, set and ensure the following permissions are “Allow” for the identities “Project Collection Build Service ({Organization Name})” and “{Project Name} Build Service ({Organization Name})“:

    • Contribute
    • Contribute to pull requests
    • Edit policies
    • Remove others' locks
  3. Go to Project Settings > Service connections to create a Generic service connection.

    • Server URL: https://dev.azure.com/{organization}/{project}, replace {organization} and {project} with the actual names of your Azure DevOps organization and project.
    • Service connection name: A custom name of the service connection.
  4. In the Azure DevOps project, create a YAML pipeline (e.g., LockPR) with the configurations like as below.

  • The pipeline main YAML. Replace {organization} with the actual name of your Azure DevOps organization.

    # pipeline-lock-PR.yml
    
     trigger: none
    
     jobs:
     - job: lock
       pool: server
       variables:
         repoName: $[variables['Build.Repository.Name']]
         branchName: $[replace(variables['System.PullRequest.SourceBranch'], 'refs/', '')]
       steps:
       - task: InvokeRESTAPI@1
         displayName: 'Lock source branch of PR'
         inputs:
           connectionType: 'connectedServiceName'
           serviceConnection: 'ForGitAPI'
           method: 'PATCH'
           headers: |
             {
               "Content-Type":"application/json",
               "Authorization": "Bearer $(system.AccessToken)"
             }
           body: |
             {
               "isLocked": true
             }
           urlSuffix: '/_apis/git/repositories/$(repoName)/refs?filter=$(branchName)&api-version=7.0'
           waitForCompletion: 'false'
    
     - job: check
       dependsOn: lock
       steps:
       - task: PowerShell@2
         displayName: 'Check PR Commits Count'
         inputs:
           filePath: 'scripts/Check-PR-Commits-Count.ps1'
           arguments: '-o "{organization}" -p "$(System.TeamProject)" -r "$(Build.Repository.Name)" -pr $(System.PullRequest.PullRequestId)'
           pwsh: true
         env:
           SYSTEM_ACCESSTOKEN: $(System.AccessToken)
    
  • The content of the PowerShell script “scripts/Check-PR-Commits-Count.ps1“.

    In this example script, I set the default value of $maxCommitCount be to 5 for testing. You can change it to be a different value in the script, or pass a different value to overwrite it using the parameter ‘maxCount‘ or ‘max‘ when calling the script.

# Check-PR-Commits-Count.ps1

param (
    [Alias("org", "o")]
    [string] $organization,

    [Alias("proj", "p")]
    [string] $project,

    [Alias("repo", "r")]
    [string] $repository,

    [Alias("prId", "pr")]
    [int] $pullRequestId,

    [Alias("maxCount", "max")]
    [int] $maxCommitCount = 5,

    [Alias("sGenre", "sg")]
    [string] $statusGenre = "PR-Status",

    [Alias("sName", "sn")]
    [string] $statusName = "Lock-SourceBranch"
)

$headers = @{
    Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
    "Content-Type" = "application/json"
}

# Get the count of commits on PR.
$uri_list_commits = "https://dev.azure.com/${organization}/${project}/_apis/git/repositories/${repository}/pullRequests/${pullRequestId}/commits?api-version=7.0" 
$commit_count = (Invoke-RestMethod -Method GET -Uri $uri_list_commits -Headers $headers).count

# Check whether to unlock the source branch of PR.
$statusDescription = "Allowed max commits count: $maxCommitCount; Current commits count: $commit_count;"

if ($commit_count -lt $maxCommitCount) {
    # Unlock the source branch of PR.
    $branchName = $env:SYSTEM_PULLREQUEST_SOURCEBRANCH -replace "refs/", ""
    $uri_unlock_branch = "https://dev.azure.com/${organization}/${project}/_apis/git/repositories/${repository}/refs?filter=${branchName}&api-version=7.0"
    $body_unlock_branch = @{isLocked = $false} | ConvertTo-Json -Depth 5
    Invoke-RestMethod -Method PATCH -Uri $uri_unlock_branch -Headers $headers -Body $body_unlock_branch

    $statusDescription += " Unlock source branch, allow subsequent new commits."    
}
else {
    $statusDescription += " Lock source branch, disallow subsequent new commits."
}

# Get the ID of latest iteration for PR.
$uri_list_iterations = "https://dev.azure.com/${organization}/${project}/_apis/git/repositories/${repository}/pullRequests/${pullRequestId}/iterations?api-version=7.0"
$iterationId = (Invoke-RestMethod -Method GET -Uri $uri_list_iterations -Headers $headers).count

# Create a status for the latest iteration of PR.
$uri_create_status = "https://dev.azure.com/${organization}/${project}/_apis/git/repositories/${repository}/pullRequests/${pullRequestId}/statuses?api-version=7.0"

$body_create_status = @{
    iterationId = $iterationId
    state = "succeeded"
    description = $statusDescription
    context = @{
        genre = $statusGenre
        name = $statusName
    }
} | ConvertTo-Json -Depth 5

Invoke-RestMethod -Method POST -Uri $uri_create_status -Headers $headers -Body $body_create_status

  1. Go to Project Settings > Repositories > “Policies” to create the Cross-Repository Branch Policies within the project.

    • Protect the default branch of each repository: If select this option, the policies will be applied to the default branch of all repositories within the project.
    • Protect current and future branches matching a specified pattern: If select this option, you can set a pattern. The policies will be applied to the branches that the names can match the pattern.
    • Add the YAML pipeline (LockPR) as a required Build Validation on the Branch Policies.

With above configuration, if the target branch of PR has the Branch Policies applied, when opening a new PR or have new commits to an active PR, the pipeline (LockPR) automatically gets triggered by the PR:

  • If the count of commits on the PR is equal or more than the value of $maxCommitCount, the source branch of the PR gets locked, and the developers cannot push new commits. They need to wait for the the current PR is completed, and the source branch gets unlocked by admin. Then they can create a new PR for the subsequent commits.

    When the branch is locked, the developers still can clone the repository to their local machines and make changes on the local repository. But they cannot push the changes from the local repository to the locked branch in remote repository.

  • If the count of commits on the PR is less than the value of $maxCommitCount, the source branch of the PR gets unlocked, and the developers can continue pushing new commits.


Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật