Search code examples
azurepowershellazure-devopsazure-repos

Unable to copy and apply a branch policy from one repo to another repo in azure devops


Not able to copy the azure branch policy from one repo to another repo using the below PowerShell script

PowerShell script

[CmdletBinding()]

param([Parameter(Mandatory=$true)][string] $AzureDevOpsPAT,[Parameter(Mandatory=$true)][string] $OrganizationName,[Parameter(Mandatory=$true)][string] $SourceProjectName,[Parameter(Mandatory=$true)][string] $SourcerepositoryName,[Parameter(Mandatory=$true)][string] $SourceBranch,[Parameter(Mandatory=$true)][string] $TargetProjectName,[Parameter(Mandatory=$true)][string] $TargetrepositoryName,[Parameter(Mandatory=$true)][string] $TargetBranch)

$ErrorActionPreference = ‘Stop’;

$User=“”;

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes((“{0}:{1}” -f $User,$AzureDevOpsPAT)));$header = @{Authorization=(“Basic {0}” -f $base64AuthInfo)};

Get Source repository

$sourceurl = ‘https://dev.azure.com/'+ $OrganizationName + ‘/’ + $SourceProjectName + ‘/_apis/git/repositories/’ + $SourcerepositoryName +’?api-version=5.1’$sourcerepository = Invoke-RestMethod -Uri $sourceurl -Method Get -ContentType application/json -Headers $header

$sourcepolicy = 'https://dev.azure.com/'+ $OrganizationName + ‘/’ + $teamProjectName +‘/_apis/git/policy/configurations?repositoryId=’ + $sourcerepository.id + ‘&refName=refs/heads/’ + $SourceBranch + ‘&api-version=5.1-preview.1’

Get Target repository

$targeturl = ‘https://dev.azure.com/'+ $OrganizationName + ‘/’ + $TargetProjectName + ‘/_apis/git/repositories/’ + $TargetrepositoryName +’?api-version=5.1’$targetpository = Invoke-RestMethod -Uri $targeturl -Method Get -ContentType application/json -Headers $headerWrite-Output $targetpository

get policies

$Url = 'https://dev.azure.com/'+ $OrganizationName + ‘/’ + $SourceProjectName + ‘/_apis/policy/configurations?api-version=5.1’;$policies = Invoke-RestMethod -Uri $Url -Method Get -ContentType application/json -Headers $header

$policies.value | ConvertTo-Json

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/' + $TargetBranch;
}
if (($null -ne $policy.settings.searchBranches))
{
    $policy.settings.searchBranches[0] = 'refs/heads/' + $TargetBranch;
}

# 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

}

The error

Invoke-RestMethod : {"$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}

I am seeking a solution to copy a branch policy from one repository to another using either a script or an Azure pipeline. Can you please assist me with this task?


Solution

  • According to my testing, the reason you encounter the error "The update is rejected by policy" is that you are creating a branch policy on the source branch, which already has such a branch policy. $Url is your source project.

    $policyCreateResponse = Invoke-RestMethod -Uri $Url -Method Post -Body $body -ContentType application/json -Headers $header
    

    I made some modifications based on your scripts and it works fine.

    $AzureDevOpsPAT = '{PAT}'
    $OrganizationName = '{Org name}'
    $SourceProjectName = '{Source Proj}'
    $SourcerepositoryName = '{Source repo}'
    $SourceBranch = '{Source branch}'
    $SourceRefName = 'refs/heads/' + $SourceBranch
    $TargetProjectName = '{Target Proj}'
    $TargetrepositoryName = '{Target repo}'
    $TargetBranch = '{Target branch}'
    $TargetRefName = 'refs/heads/' + $TargetBranch
    
    $ErrorActionPreference = ‘Stop’;
    
    $token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($AzureDevOpsPAT)"))
    $header = @{ Authorization =" Basic $token" }
    
    #Get Source repository
    $sourceurl = ‘https://dev.azure.com/'+ $OrganizationName + ‘/’ + $SourceProjectName + ‘/_apis/git/repositories/' + $SourcerepositoryName +'?api-version=5.1’
    $sourcerepository = Invoke-RestMethod -Uri $sourceurl -Method Get -ContentType application/json -Headers $header
    $sourcerepository | ConvertTo-Json
    $sourcerepositoryid = $sourcerepository.id
    
    #Get Target repository
    $targeturl = ‘https://dev.azure.com/'+ $OrganizationName + ‘/’ + $TargetProjectName + ‘/_apis/git/repositories/’ + $TargetrepositoryName +’?api-version=5.1’
    $targetrepository = Invoke-RestMethod -Uri $targeturl -Method Get -ContentType application/json -Headers $header 
    $targetrepository| ConvertTo-Json
    $targetrepositoryid = $targetrepository.id
    
    #Get policies
    $URL1 = 'https://dev.azure.com/'+ $OrganizationName + ‘/’ + $SourceProjectName + ‘/_apis/policy/configurations?api-version=5.1’
    $policies = Invoke-RestMethod -Uri $URL1 -Method Get -ContentType application/json -Headers $header
    
    #Target project URL
    $URL2 = 'https://dev.azure.com/'+ $OrganizationName + ‘/’ + $TargetProjectName + ‘/_apis/policy/configurations?api-version=5.1’
    
    foreach($policy in $policies.value){
    
    if ($policy.settings.scope.repositoryId -eq $sourcerepositoryid -and $policy.settings.scope.refName -eq $SourceRefName )
    {
    
      if ($policy.type.id -in "fa4e907d-c16b-4a4c-9dfa-4916e5d171ab", "c6a1889d-b943-4856-b76f-9e46bb6b0df2", "40e92b44-2fe1-4dd6-b3d8-74a9c21d0c6e", "fa4e907d-c16b-4a4c-9dfa-4906e5d171dd")
      {
        $policy.settings.scope[0].repositoryId = $targetrepositoryid
        $policy.settings.scope[0].refName = $TargetRefName
        $body = $policy | ConvertTo-Json -Depth 10  
    
        Write-Host 'Create policy in the target branch'
        $policyCreateResponse = Invoke-RestMethod -Uri $URL2 -Method Post -Body $body -ContentType application/json -Headers $header
        $policyCreateResponse | ConvertTo-Json
      }
      else
      {
        Write-Host 'There is no target policy type.'
      }
    
    }
    
    }
    
    

    Based on the policy.type.id in my script if ($policy.type.id -in "fa4e907d-c16b-4a4c-9dfa-4916e5d171ab", "c6a1889d-b943-4856-b76f-9e46bb6b0df2", "40e92b44-2fe1-4dd6-b3d8-74a9c21d0c6e", "fa4e907d-c16b-4a4c-9dfa-4906e5d171dd"), it works for the following branch policies. enter image description here