skip to Main Content

I am new in azure devops and scripting. I want to auto abandon azure pull request after 2 weeks with no updates. I am able to list pull request, and do the status update. But looking for a powershell or bash script which can read the list command output, find out the date, and abandon pull request if no update for two week.

az repos pr list --repository "myrepo" --status "active"
az repos pr update --id "16729" --status "abandoned" 

2

Answers


  1. Chosen as BEST ANSWER

    @Bowman Zhu-MSFT Helped me to resolve this issue, Thanks for guidance, and as he said "As long as you have ideas about how to deal with the problem, you can write code in any language you can to achieve your requirements. "I only tweaked some of the code, Like for header I am using different code, using az cli for abandon PR.

        - task: PowerShell@2
      inputs:
        targetType: 'inline'
        script: |
                $org_name = "XXX"
                $project_name = "XXXX"
                $repo_name = "XXX"
                $PAT = $env:AZURE_DEVOPS_EXT_PAT
                
                $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "", $PAT)))
                $headers_prs = @{Authorization = ("Basic {0}" -f $base64AuthInfo) }
                
                $prs_url = "https://dev.azure.com/"+$org_name+"/"+$project_name+"/_apis/git/repositories/"+$repo_name+"/pullrequests?api-version=6.0"
                $response_prs = Invoke-RestMethod $prs_url -Method 'GET' -Headers $headers_prs
                
                $response_prs.value | foreach {
                    Write-Host 'repository name'  $repo_name
                    $pr_id = $_.pullRequestId
                    Write-Host 'pr id ='  $pr_id
                    $create_date = $_.creationDate 
                    Write-Host 'pr create date = '   $create_date # Get all of the PRs' create dates
                    $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "", $PAT)))
                    $headers_pr = @{Authorization = ("Basic {0}" -f $base64AuthInfo) }
                
                
                    $pr1_url = "https://dev.azure.com/$org_name/$project_name/_apis/git/repositories/$repo_name/pullRequests/$pr_id/threads?api-version=6.0"
                    $response_pr1 = Invoke-RestMethod $pr1_url -Method 'GET' -Headers $headers_pr
                    $count = $response_pr1.value.count
                    $last_updated_time_stamp  = $response_pr1.value[$count-1].lastUpdatedDate   
                  
                    
                    if($last_updated_time_stamp -ne $null){
                        Write-Host 'last update time stamp is not null.'
                        #Write-Host $last_updated_time_stamp
                        $last_updated_time = Get-Date -Date $last_updated_time_stamp
                        Write-Host 'last_updated_time = ' $last_updated_time
                        $now_time = Get-Date
                        Write-Host 'current time = ' $now_time
                        $diff_time = $now_time - $last_updated_time
                        Write-Host 'time difference in seconds = ' $diff_time.TotalSeconds
                        #if the diff is longer than four weeks
                        if ($diff_time.TotalSeconds -gt 60*60*24*30) {
                            Write-Host "The difference is greater than four weeks"
                            #Abandon the PR here.
                            #==========================================================
                            az devops configure --defaults organization=$org_name
                            az repos pr update --id $pr_id --status "abandoned" 
                            Write-Host 'Abandoned successfully.'
                            #==========================================================
                        } else {
                            Write-Host "The difference is less than four weeks"
                        }
                    }elseif ($last_updated_time_stamp -eq $null) {
                        #Write-Host $last_updated_time_stamp
                        $last_updated_time = Get-Date -Date $create_date
                        Write-Host 'last_updated_time = ' $last_updated_time
                        $now_time = Get-Date
                        Write-Host 'current time = ' $now_time
                        $diff_time = $now_time - $last_updated_time
                        Write-Host 'time difference in seconds = ' $diff_time.TotalSeconds
                        #if the diff is longer than four weeks
                        if ($diff_time.TotalSeconds -gt 60*60*24*30) {
                            Write-Host "The difference is greater than four weeks"
                            #Abandon the PR here.
                            #==========================================================
                            az devops configure --defaults organization=$org_name
                            az repos pr update --id $pr_id --status "abandoned"    
                            Write-Host 'Abandoned successfully.' 
                             #==========================================================          
                        } else {
                            Write-Host "The difference is less than four weeks"
                        }
                    }
                    ###
                }
      env:
        AZURE_DEVOPS_EXT_PAT: $(PAT_svc_azuresync)
    

  2. The below code can achieve your requirements.

    $org_name = "<Your Organization Name>"
    $project_name = "<Your Project Name>"
    $repo_name = "<Your Repo Name>"
    $PAT = "<Your Personal Access Token>"
    
    $headers_prs = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers_prs.Add("Authorization", "Basic "+$PAT)
    
    $prs_url = "https://dev.azure.com/"+$org_name+"/"+$project_name+"/_apis/git/repositories/"+$repo_name+"/pullrequests?api-version=6.0"
    $response_prs = Invoke-RestMethod $prs_url -Method 'GET' -Headers $headers_prs
    $response_prs | ConvertTo-Json
    
    $response_prs.value | foreach {
        $pr_id = $_.pullRequestId
        # Write-Host $pr_id
        $create_date = $_.creationDate
        # Write-Host $create_date # Get all of the PRs' create dates
        ###
        $headers_pr = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
        $headers_pr.Add("Authorization", "Basic "+$PAT)
        $headers_pr.Add("Content-Type", "application/json")
        
        $body_pr = "{
        `n    `"contributionIds`": [
        `n        `"ms.vss-code-web.pullrequests-artifact-stats-data-provider`"
        `n    ],
        `n    `"dataProviderContext`": {
        `n        `"properties`": {
        `n            `"artifactIds`": [
        `n                {
        `n                    `"artifactId`": `"vstfs:///Git/PullRequestId/c6358b04-e91a-4bd1-a894-1adb543134d6%2F044a82e2-9d12-43b2-801c-d33ac6812173%2F"+$pr_id+"`",
        `n                    `"discussionArtifactId`": `"vstfs:///CodeReview/ReviewId/c6358b04-e91a-4bd1-a894-1adb543134d6%2F"+$pr_id+"`"
        `n                }
        `n            ],
        `n            `"sourcePage`": {
        `n                `"url`": `"https://dev.azure.com/<Organization Name>/<Project Name>/_git/<Repo Name>/pullrequests?_a=mine`",
        `n                `"routeId`": `"ms.vss-code-web.lwp-prs-route`",
        `n                `"routeValues`": {
        `n                    `"project`": `"<Project Name>`",
        `n                    `"GitRepositoryName`": `"<Repo Name>`",
        `n                    `"vctype`": `"git`",
        `n                    `"controller`": `"ContributedPage`",
        `n                    `"action`": `"Execute`",
        `n                    `"serviceHost`": `"b1cc953d-b564-4eec-a222-84393e4406b1 (<some personal information>)`"
        `n                }
        `n            }
        `n        }
        `n    }
        `n}"
    
        $pr_url = "https://dev.azure.com/"+$org_name+"/_apis/Contribution/HierarchyQuery/project/"+$project_name+"?api-version=5.0-preview.1"
        $response_pr = Invoke-RestMethod $pr_url -Method 'POST' -Headers $headers_pr -Body $body_pr
        $response_pr | ConvertTo-Json
    
        $last_updated_time_stamp = $response_pr.dataProviders.'ms.vss-code-web.pullrequests-artifact-stats-data-provider'.'TFS.VersionControl.PullRequestListArtifactStatsProvider.artifactStats'.lastUpdatedDate
        if($last_updated_time_stamp -ne $null){
            Write-Host 'last update time stamp is not null.'
            Write-Host $last_updated_time_stamp
            $last_updated_time = Get-Date -Date $last_updated_time_stamp
            $now_time = Get-Date
            Write-Host $now_time
            $diff_time = $now_time - $last_updated_time
            Write-Host $diff_time.TotalSeconds
            #if the diff is longer than two weeks
            if ($diff_time.TotalSeconds -gt 60*60*24*14) {
                Write-Host "The difference is greater than two weeks"
                #Abandon the PR here.
                #==========================================================
                $headers_abpr = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
                $headers_abpr.Add("Authorization", "Basic "+$PAT)
                $headers_abpr.Add("Content-Type", "application/json")
                
                $body_abpr = "{
                `n    `"status`":`"abandoned`"
                `n}"
                $abpr_url = "https://dev.azure.com/"+$org_name+"/"+$project_name+"/_apis/git/repositories/"+$repo_name+"/pullrequests/"+$pr_id+"?api-version=6.0"
                $response_abpr = Invoke-RestMethod $abpr_url -Method 'PATCH' -Headers $headers_abpr -Body $body_abpr
                $response_abpr | ConvertTo-Json
                Write-Host 'Abandoned successfully.'
                #==========================================================
            } else {
                Write-Host "The difference is less than two weeks"
            }
        }elseif ($last_updated_time_stamp -eq $null) {
            Write-Host 'last update time stamp is null.'
            Write-Host $last_updated_time_stamp
            $last_updated_time = Get-Date -Date $create_date
            $now_time = Get-Date
            $diff_time = $now_time - $last_updated_time
            Write-Host $diff_time.TotalSeconds
            if ($diff_time.TotalSeconds -gt 60*60*24*14) {
                Write-Host "The difference is greater than two weeks"
                #Abandon the PR here.
                #==========================================================
                $headers_abpr = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
                $headers_abpr.Add("Authorization", "Basic "+$PAT)
                $headers_abpr.Add("Content-Type", "application/json")
                
                $body_abpr = "{
                `n    `"status`":`"abandoned`"
                `n}"
                $abpr_url = "https://dev.azure.com/"+$org_name+"/"+$project_name+"/_apis/git/repositories/"+$repo_name+"/pullrequests/"+$pr_id+"?api-version=6.0"
                $response_abpr = Invoke-RestMethod $abpr_url -Method 'PATCH' -Headers $headers_abpr -Body $body_abpr
                $response_abpr | ConvertTo-Json
                Write-Host 'Abandoned successfully.'
                #==========================================================
            } else {
                Write-Host "The difference is less than two weeks"
            }
        }
        ###
    }
    

    The official REST API documents don’t have such data ‘last update time’ of Pull requests. The above code is based on network traffic interception and analysis. The above code has been tested by me and works very well on my side.

    There may be a lot of code, I will share with you the ideas of how I code those here. These will help you understand the above code.

    Steps:

    1, get all of the pull requests information, especially the ‘id’.

    https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull-requests/get-pull-requests?view=azure-devops-rest-6.0&tabs=HTTP

    ID and Name in this REST API is equivalent.

    2, Go to the pull request page and analyze.

    enter image description here

    enter image description here

    enter image description here

    Please notice that if you only create pull request but do nothing, last updated time in this place will be ‘null’, you need to use pull request ‘creation time’ in this situation.

    3, calculate the difference between the last update time and the now time.

    $ago = Get-Date -Date "<Time String>"
    $now = Get-Date
    
    $diff = $now - $ago
    Write-Host $diff.TotalSeconds
    #if the diff is longer than two weeks
    if ($diff.TotalSeconds -gt 60*60*24*14) {
        Write-Host "The difference is greater than two weeks"
    } else {
        Write-Host "The difference is less than two weeks"
    }
    

    The most important is the second step, because only this place has the relevant information of last updated time of pull request.

    As long as you have ideas about how to deal with the problem, you can write code in any language you can to achieve your requirements.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search