Skip to content

Instantly share code, notes, and snippets.

@chamindac
Created April 7, 2020 06:02
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chamindac/771a2a4ce124ddc99a2abf2ee28379f3 to your computer and use it in GitHub Desktop.
Save chamindac/771a2a4ce124ddc99a2abf2ee28379f3 to your computer and use it in GitHub Desktop.
Copy Branch policies from a Azure DevOps Git branch to another branch
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string] $AzureDevOpsPAT,
[Parameter(Mandatory=$true)]
[string] $OrganizationName,
[Parameter(Mandatory=$true)]
[string] $teamProjectName,
[Parameter(Mandatory=$true)]
[string] $repositoryName,
[Parameter(Mandatory=$true)]
[string] $fromBranch,
[Parameter(Mandatory=$true)]
[string] $toBranch
)
$ErrorActionPreference = 'Stop';
$User="";
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User,$AzureDevOpsPAT)));
$header = @{Authorization=("Basic {0}" -f $base64AuthInfo)};
# Get repository
$Url = 'https://dev.azure.com/'+ $OrganizationName + '/' + $teamProjectName + '/_apis/git/repositories/' + $repositoryName +'?api-version=5.1'
$repository = Invoke-RestMethod -Uri $Url -Method Get -ContentType application/json -Headers $header
$Url = 'https://dev.azure.com/'+ $OrganizationName + '/' + $teamProjectName +
'/_apis/git/policy/configurations?repositoryId=' + $repository.id + '&refName=refs/heads/' + $fromBranch + '&api-version=5.1-preview.1'
# get policies
$policies = Invoke-RestMethod -Uri $Url -Method Get -ContentType application/json -Headers $header
$Url = 'https://dev.azure.com/'+ $OrganizationName + '/' + $teamProjectName + '/_apis/policy/configurations?api-version=5.1';
foreach($policy in $policies.value)
{
if ($policy.type.id -eq '0517f88d-4ec5-4343-9d26-9930ebd53069')
{
continue; # skipping GitRepositorySettingsPolicyName
}
# remove properties from policy so it can be applied to target branch
$props = $policy.PSObject.Properties
$props.remove('createdBy');
$props.remove('createdDate');
$props.remove('revision');
$props.remove('id');
$props.remove('url');
$policy._links.PSObject.Properties.Remove('self')
# set target branch
if (($null -ne $policy.settings.scope[0].refname))
{
$policy.settings.scope[0].refName = 'refs/heads/' + $toBranch;
}
if (($null -ne $policy.settings.searchBranches))
{
$policy.settings.searchBranches[0] = 'refs/heads/' + $toBranch;
}
# create policy in target branch
$body = $policy | ConvertTo-Json -Depth 10
$policyCreateResponse = Invoke-RestMethod -Uri $Url -Method Post -Body $body -ContentType application/json -Headers $header
$policyCreateResponse
}
@MisinformedDNA
Copy link

Thanks for this. But what is GitRepositorySettingsPolicyName and why do you skip it?

@chamindac
Copy link
Author

There is top level policy name returned comprising of common policy settings as header but such cannot be applied. That is the reason it needs to be skipped.

@tomaustin700
Copy link

This is awesome! Just what I was looking for.

@Slohrsh
Copy link

Slohrsh commented Mar 11, 2021

You could also connect it to your build pipeline:

trigger:
  branches:
    include:
      - 'Release*'

steps:
  - task: PowerShell@2
    inputs:
      targetType: 'filePath'
      filePath: $(System.DefaultWorkingDirectory)/pipeline/scripts/BranchPolicyCopy.ps1
      arguments: >
        -AzureDevOpsPAT foo
        -OrganizationName bar
        -teamProjectName foo
        -repositoryName bar
        -fromBranch foo
        -toBranch $(Build.SourceBranchName)
        -accessToken $(System.AccessToken)
    displayName: 'Copy Branch Policies'

In addition you need to add
[Parameter(Mandatory=$true)] [string] $accessToken
to the script above and replace the authorization with that snippet:
-Headers @{Authorization = "Bearer $accessToken"}

@brucewilkins
Copy link

Is there a way to include the reviewers ('Automatically included reviewers') as well?

@swonge
Copy link

swonge commented May 20, 2021

Hi @chamindac,
Thanks for sharing your great work.
Noticed that after I ran the code, entries under policy (i.e. "Automatically included reviewers", "Build Validation", etc.) will be duplicated from original branch policy. Is there a way to eliminate the duplication?

Thanks in advance

from branch policy
image

to branch policy
image

@mdailey77
Copy link

mdailey77 commented Aug 10, 2022

I tried out the above code and kept getting this error:

{"$id":"1","innerException":null,"message":"The update is rejected by
     | policy.","typeName":"Microsoft.TeamFoundation.Policy.Server.PolicyChangeRejectedByPolicyException,
     | Microsoft.TeamFoundation.Policy.Server","typeKey":"PolicyChangeRejectedByPolicyException","errorCode":0,"eventId":3000}

For those who came across this via a google search, you're probably better off using the Azure DevOps CLI to add branch policies like 'minimum number of reviewers' and 'require linked work items'. See https://docs.microsoft.com/en-us/azure/devops/repos/git/branch-policies?view=azure-devops&tabs=azure-devops-cli

@sahithiazure
Copy link

iam getting this error while using this script.please help me

{"$id":"1","innerException":null,"message":"The update is rejected by
| policy.","typeName":"Microsoft.TeamFoundation.Policy.Server.PolicyChangeRejectedByPolicyException,
| Microsoft.TeamFoundation.Policy.Server","typeKey":"PolicyChangeRejectedByPolicyException","errorCode":0,"eventId":3000}

@MisinformedDNA
Copy link

@sahithiazure You don't have the necessary permissions.

@devops4all77
Copy link

I tried out the above code and kept getting this error:

{"$id":"1","innerException":null,"message":"The update is rejected by
     | policy.","typeName":"Microsoft.TeamFoundation.Policy.Server.PolicyChangeRejectedByPolicyException,
     | Microsoft.TeamFoundation.Policy.Server","typeKey":"PolicyChangeRejectedByPolicyException","errorCode":0,"eventId":3000}

For those who came across this via a google search, you're probably better off using the Azure DevOps CLI to add branch policies like 'minimum number of reviewers' and 'require linked work items'. See https://docs.microsoft.com/en-us/azure/devops/repos/git/branch-policies?view=azure-devops&tabs=azure-devops-cli

Any mitigation you did found for this error, even I am getting same error. is it due to org policy conflict?

@mdailey77
Copy link

@devops4all77 I came up with a way to use the Azure CLI to add branch policies using a pipeline. Also I had to give 'Project Collection Build Service' service account in my DevOps instance certain permissions like Create a branch, and Contribute. Here's the pipeline YAML that creates the branch and adds the policies: https://github.com/mdailey77/sprint-branch-create

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment