From 84282d0d38f08112d9b56d8aa14ef721319e8bfb Mon Sep 17 00:00:00 2001 From: Chidozie Ononiwu Date: Fri, 30 Oct 2020 21:12:32 -0700 Subject: [PATCH] Add Invoke-DevOpsAPI.ps1, Add functions for Canceling and Listing Builds --- eng/common/scripts/Get-PullRequestCreator.ps1 | 8 +- eng/common/scripts/Invoke-DevOpsAPI.ps1 | 92 ++++++++ eng/common/scripts/Invoke-GitHubAPI.ps1 | 200 ++++++------------ eng/common/scripts/Queue-Pipeline.ps1 | 36 ++-- eng/common/scripts/Submit-PullRequest.ps1 | 8 +- 5 files changed, 189 insertions(+), 155 deletions(-) create mode 100644 eng/common/scripts/Invoke-DevOpsAPI.ps1 diff --git a/eng/common/scripts/Get-PullRequestCreator.ps1 b/eng/common/scripts/Get-PullRequestCreator.ps1 index 1b531ad5ee..e9ed824c91 100644 --- a/eng/common/scripts/Get-PullRequestCreator.ps1 +++ b/eng/common/scripts/Get-PullRequestCreator.ps1 @@ -6,14 +6,18 @@ param ( [string]$RepoName, [Parameter(Mandatory = $true)] - $PullRequestNumber + $PullRequestNumber, + + [Parameter(Mandatory = $true)] + [string]$AuthToken ) . "${PSScriptRoot}\common.ps1" try { - $pullRequest = Get-GithubPullRequest -RepoOwner $RepoOwner -RepoName $RepoName -PullRequestNumber $PullRequestNumber + $pullRequest = Get-GithubPullRequest -RepoOwner $RepoOwner -RepoName $RepoName ` + -PullRequestNumber $PullRequestNumber -AuthToken $AuthToken Write-Host "##vso[task.setvariable variable=System.PullRequest.Creator;]$($pullRequest.user.login)" } catch diff --git a/eng/common/scripts/Invoke-DevOpsAPI.ps1 b/eng/common/scripts/Invoke-DevOpsAPI.ps1 new file mode 100644 index 0000000000..024594785a --- /dev/null +++ b/eng/common/scripts/Invoke-DevOpsAPI.ps1 @@ -0,0 +1,92 @@ +. "${PSScriptRoot}\logging.ps1" + +$DevOpsAPIBaseURI = "https://dev.azure.com/{0}/{1}/_apis/{2}/{3}?{4}api-version=6.0" + +function Get-DevOpsApiHeaders ($Base64EncodedToken) { + $headers = @{ + Authorization = "Basic $Base64EncodedToken" + } + return $headers +} + +function Start-DevOpsBuild { + param ( + $Organization="azure-sdk", + $Project="internal", + [Parameter(Mandatory = $true)] + $SourceBranch, + [Parameter(Mandatory = $true)] + $DefinitionId, + [ValidateNotNullOrEmpty()] + [Parameter(Mandatory = $true)] + $Base64EncodedAuthToken + ) + + $uri = "$DevOpsAPIBaseURI" -F $Organization, $Project , "build" , "builds", "" + + $parameters = @{ + sourceBranch = $SourceBranch + definition = @{ id = $DefinitionId } + } + + return Invoke-RestMethod ` + -Method POST ` + -Body ($parameters | ConvertTo-Json) ` + -Uri $uri ` + -Headers (Get-DevOpsApiHeaders -Base64EncodedToken $Base64EncodedAuthToken) ` + -MaximumRetryCount 3 ` + -ContentType "application/json" +} + +function Update-DevOpsBuild { + param ( + $Organization="azure-sdk", + $Project="internal", + [ValidateNotNullOrEmpty()] + [Parameter(Mandatory = $true)] + $BuildId, + $Status, # pass canceling to cancel build + [ValidateNotNullOrEmpty()] + [Parameter(Mandatory = $true)] + $Base64EncodedAuthToken + ) + + $uri = "$DevOpsAPIBaseURI" -F $Organization, $Project, "build", "builds/$BuildId", "" + $parameters = @{} + + if ($Status) { $parameters["status"] = $Status} + + return Invoke-RestMethod ` + -Method PATCH ` + -Body ($parameters | ConvertTo-Json) ` + -Uri $uri ` + -Headers (Get-DevOpsApiHeaders -Base64EncodedToken $Base64EncodedAuthToken) ` + -MaximumRetryCount 3 ` + -ContentType "application/json" +} + +function Get-DevOpsBuilds { + param ( + $Organization="azure-sdk", + $Project="internal", + $BranchName, #Should start with 'refs/heads/' + $Definitions, # Comma seperated string of definition IDs + $StatusFilter, # Comma seperated string 'cancelling, completed, inProgress, notStarted' + [ValidateNotNullOrEmpty()] + [Parameter(Mandatory = $true)] + $Base64EncodedAuthToken + ) + + $query = "" + + if ($BranchName) { $query += "branchName=$BranchName&" } + if ($Definitions) { $query += "definitions=$Definitions&" } + if ($StatusFilter) { $query += "statusFilter=$StatusFilter&" } + $uri = "$DevOpsAPIBaseURI" -F $Organization, $Project , "build" , "builds", $query + + return Invoke-RestMethod ` + -Method GET ` + -Uri $uri ` + -Headers (Get-DevOpsApiHeaders -Base64EncodedToken $Base64EncodedAuthToken) ` + -MaximumRetryCount 3 +} diff --git a/eng/common/scripts/Invoke-GitHubAPI.ps1 b/eng/common/scripts/Invoke-GitHubAPI.ps1 index b4a3d89715..46a76251c5 100644 --- a/eng/common/scripts/Invoke-GitHubAPI.ps1 +++ b/eng/common/scripts/Invoke-GitHubAPI.ps1 @@ -1,140 +1,14 @@ -if ((Get-ChildItem -Path Function: | ? { $_.Name -eq "LogWarning" }).Count -eq 0) { - . "${PSScriptRoot}\logging.ps1" -} +. "${PSScriptRoot}\logging.ps1" $GithubAPIBaseURI = "https://api.github.com/repos" -function Get-GitHubHeaders ($token) { +function Get-GitHubApiHeaders ($token) { $headers = @{ Authorization = "bearer $token" } return $headers } -function Invoke-GitHubAPIPost { - param ( - [Parameter(Mandatory = $true)] - $apiURI, - [Parameter(Mandatory = $true)] - $body, - [Parameter(Mandatory = $true)] - $token - ) - - try { - if ($body.Count -gt 0) { - $resp = Invoke-RestMethod ` - -Method POST ` - -Body ($body | ConvertTo-Json) ` - -Uri $apiURI ` - -Headers (Get-GitHubHeaders -token $token) ` - -MaximumRetryCount 3 - - return $resp - } - else { - $warning = "{0} with Uri [ $apiURI ] did not fire request because of empty body." -f (Get-PSCallStack)[1].FunctionName - LogWarning $warning - return $null - } - } - catch { - $warning = "{0} with Uri [ $apiURI ] failed. `nBody: [ {1} ]" -f (Get-PSCallStack)[1].FunctionName , ($body | Out-String) - LogWarning $warning - throw - } -} - -function Invoke-GitHubAPIPatch { - param ( - [Parameter(Mandatory = $true)] - $apiURI, - [Parameter(Mandatory = $true)] - $body, - [Parameter(Mandatory = $true)] - $token - ) - - try { - if ($body.Count -gt 0) { - $resp = Invoke-RestMethod ` - -Method PATCH ` - -Body ($body | ConvertTo-Json) ` - -Uri $apiURI ` - -Headers (Get-GitHubHeaders -token $token) ` - -MaximumRetryCount 3 - - return $resp - } - else { - $warning = "{0} with Uri [ $apiURI ] did not fire request because of empty body." -f (Get-PSCallStack)[1].FunctionName - LogWarning $warning - return $null - } - } - catch { - $warning = "{0} with Uri [ $apiURI ] failed. `nBody: [ {1} ]" -f (Get-PSCallStack)[1].FunctionName , ($body | Out-String) - LogWarning $warning - throw - } -} - -function Invoke-GitHubAPIDelete { - param ( - [Parameter(Mandatory = $true)] - $apiURI, - [Parameter(Mandatory = $true)] - $token - ) - - try { - $resp = Invoke-RestMethod ` - -Method DELETE ` - -Uri $apiURI ` - -Headers (Get-GitHubHeaders -token $token) ` - -MaximumRetryCount 3 - - return $resp - } - catch { - $warning = "{0} with Uri [ $apiURI ] failed." -f (Get-PSCallStack)[1].FunctionName - LogWarning $warning - throw - } -} - - -function Invoke-GitHubAPIGet { - param ( - [Parameter(Mandatory = $true)] - $apiURI, - $token - ) - - try { - if ($token) - { - $resp = Invoke-RestMethod ` - -Method GET ` - -Uri $apiURI ` - -Headers (Get-GitHubHeaders -token $token) ` - -MaximumRetryCount 3 - } - else { - $resp = Invoke-RestMethod ` - -Method GET ` - -Uri $apiURI ` - -MaximumRetryCount 3 - } - return $resp - } - catch { - $warning = "{0} with Uri [ $apiURI ] failed." -f (Get-PSCallStack)[1].FunctionName - LogWarning $warning - throw - } -} - function Set-GitHubAPIParameters ($members, $parameterName, $parameters, $allowEmptyMembers=$false) { if ($null -ne $members) { if ($members -is [array]) @@ -166,6 +40,7 @@ function Get-GitHubPullRequests { $Sort, [ValidateSet("asc","desc")] $Direction, + [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] $AuthToken ) @@ -178,7 +53,11 @@ function Get-GitHubPullRequests { if ($Sort) { $uri += "sort=$Sort&" } if ($Direction){ $uri += "direction=$Direction&" } - return Invoke-GitHubAPIGet -apiURI $uri -token $AuthToken + return Invoke-RestMethod ` + -Method GET ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } # @@ -195,13 +74,18 @@ function Get-GitHubSourceReferences { $RepoName, $Ref, [ValidateNotNullOrEmpty()] + [Parameter(Mandatory = $true)] $AuthToken ) $uri = "$GithubAPIBaseURI/$RepoOwner/$RepoName/git/matching-refs/" if ($Ref) { $uri += "$Ref" } - return Invoke-GitHubAPIGet -apiURI $uri -token $AuthToken + return Invoke-RestMethod ` + -Method GET ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } function Get-GitHubPullRequest { @@ -213,11 +97,17 @@ function Get-GitHubPullRequest { [Parameter(Mandatory = $true)] $PullRequestNumber, [ValidateNotNullOrEmpty()] + [Parameter(Mandatory = $true)] $AuthToken ) $uri = "$GithubAPIBaseURI/$RepoOwner/$RepoName/pulls/$PullRequestNumber" - return Invoke-GitHubAPIGet -apiURI $uri -token $AuthToken + + return Invoke-RestMethod ` + -Method GET ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } function New-GitHubPullRequest { @@ -250,7 +140,12 @@ function New-GitHubPullRequest { } $uri = "$GithubAPIBaseURI/$RepoOwner/$RepoName/pulls" - return Invoke-GitHubAPIPost -apiURI $uri -body $parameters -token $AuthToken + return Invoke-RestMethod ` + -Method POST ` + -Body ($parameters | ConvertTo-Json) ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } function Add-GitHubIssueComment { @@ -274,7 +169,12 @@ function Add-GitHubIssueComment { body = $Comment } - return Invoke-GitHubAPIPost -apiURI $uri -body $parameters -token $AuthToken + return Invoke-RestMethod ` + -Method POST ` + -Body ($parameters | ConvertTo-Json) ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } # Will add labels to existing labels on the issue @@ -305,7 +205,12 @@ function Add-GitHubIssueLabels { $parameters = Set-GitHubAPIParameters -members $Labels -parameterName "labels" ` -parameters $parameters - return Invoke-GitHubAPIPost -apiURI $uri -body $parameters -token $AuthToken + return Invoke-RestMethod ` + -Method POST ` + -Body ($parameters | ConvertTo-Json) ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } # Will add assignees to existing assignees on the issue @@ -336,7 +241,12 @@ function Add-GitHubIssueAssignees { $parameters = Set-GitHubAPIParameters -members $Assignees -parameterName "assignees" ` -parameters $parameters - return Invoke-GitHubAPIPost -apiURI $uri -body $parameters -token $AuthToken + return Invoke-RestMethod ` + -Method POST ` + -Body ($parameters | ConvertTo-Json) ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } function Add-GitHubPullRequestReviewers { @@ -363,7 +273,12 @@ function Add-GitHubPullRequestReviewers { $parameters = Set-GitHubAPIParameters -members $Teams -parameterName "team_reviewers" ` -parameters $parameters - return Invoke-GitHubAPIPost -apiURI $uri -body $parameters -token $AuthToken + return Invoke-RestMethod ` + -Method POST ` + -Body ($parameters | ConvertTo-Json) ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } # For labels and assignee pass comma delimited string, to replace existing labels or assignees. @@ -401,7 +316,12 @@ function Update-GitHubIssue { $parameters = Set-GitHubAPIParameters -members $Assignees -parameterName "assignees" ` -parameters $parameters -allowEmptyMembers $true - return Invoke-GitHubAPIPatch -apiURI $uri -body $parameters -token $AuthToken + return Invoke-RestMethod ` + -Method PATCH ` + -Body ($parameters | ConvertTo-Json) ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } function Remove-GitHubSourceReferences { @@ -425,5 +345,9 @@ function Remove-GitHubSourceReferences { $uri = "$GithubAPIBaseURI/$RepoOwner/$RepoName/git/refs/$Ref" - return Invoke-GitHubAPIDelete -apiURI $uri -token $AuthToken + return Invoke-RestMethod ` + -Method DELETE ` + -Uri $uri ` + -Headers (Get-GitHubApiHeaders -token $AuthToken) ` + -MaximumRetryCount 3 } \ No newline at end of file diff --git a/eng/common/scripts/Queue-Pipeline.ps1 b/eng/common/scripts/Queue-Pipeline.ps1 index 4e0122ca92..d3c135e7ba 100644 --- a/eng/common/scripts/Queue-Pipeline.ps1 +++ b/eng/common/scripts/Queue-Pipeline.ps1 @@ -12,33 +12,45 @@ param( [Parameter(Mandatory = $true)] [int]$DefinitionId, + [boolean]$CancelPreviousBuilds=$false, + [Parameter(Mandatory = $false)] [string]$VsoQueuedPipelines, [Parameter(Mandatory = $true)] - [string]$AuthToken + [string]$Base64EncodedAuthToken ) . "${PSScriptRoot}\logging.ps1" +. "${PSScriptRoot}\Invoke-DevOpsAPI.ps1" -$headers = @{ - Authorization = "Basic $AuthToken" -} +if ($CancelPreviousBuilds) +{ + try { + $queuedBuilds = Get-DevOpsBuilds -BranchName "refs/heads/$SourceBranch" -Definitions $DefinitionId ` + -StatusFilter "inProgress, notStarted" -Base64EncodedAuthToken $Base64EncodedAuthToken -$apiUrl = "https://dev.azure.com/$Organization/$Project/_apis/build/builds?api-version=6.0" + if ($queuedBuilds.count -eq 0) { + LogDebug "There is no previous build still inprogress or about to start." + } -$body = @{ - sourceBranch = $SourceBranch - definition = @{ id = $DefinitionId } + foreach ($build in $queuedBuilds.Value) { + $buildID = $build.id + LogDebug "Canceling build [ $($build._links.web.href) ]" + Update-DevOpsBuild -BuildId $buildID -Status "cancelling" -Base64EncodedAuthToken $Base64EncodedAuthToken + } + } + catch { + LogError "Call to DevOps API failed with exception:`n$_" + exit 1 + } } -Write-Verbose ($body | ConvertTo-Json) - try { - $resp = Invoke-RestMethod -Method POST -Headers $headers $apiUrl -Body ($body | ConvertTo-Json) -ContentType application/json + $resp = Start-DevOpsBuild -SourceBranch $SourceBranch -DefinitionId $DefinitionId -Base64EncodedAuthToken $Base64EncodedAuthToken } catch { - LogError "Invoke-RestMethod [ $apiUrl ] failed with exception:`n$_" + LogError "Start-DevOpsBuild failed with exception:`n$_" exit 1 } diff --git a/eng/common/scripts/Submit-PullRequest.ps1 b/eng/common/scripts/Submit-PullRequest.ps1 index bbb9c2e8ac..32422e7f51 100644 --- a/eng/common/scripts/Submit-PullRequest.ps1 +++ b/eng/common/scripts/Submit-PullRequest.ps1 @@ -63,7 +63,7 @@ param( try { $resp = Get-GitHubPullRequests -RepoOwner $RepoOwner -RepoName $RepoName ` - -Head "${PROwner}:${PRBranch}" -Base $BaseBranch + -Head "${PROwner}:${PRBranch}" -Base $BaseBranch -AuthToken $AuthToken } catch { LogError "Get-GitHubPullRequests failed with exception:`n$_" @@ -89,8 +89,10 @@ else { # setting variable to reference the pull request by number Write-Host "##vso[task.setvariable variable=Submitted.PullRequest.Number]$($resp.number)" - Add-GitHubPullRequestReviewers -RepoOwner $RepoOwner -RepoName $RepoName -PrNumber $resp.number ` - -Users $UserReviewers -Teams $TeamReviewers -AuthToken $AuthToken + if ($UserReviewers -or $TeamReviewers) { + Add-GitHubPullRequestReviewers -RepoOwner $RepoOwner -RepoName $RepoName -PrNumber $resp.number ` + -Users $UserReviewers -Teams $TeamReviewers -AuthToken $AuthToken + } if ($CloseAfterOpenForTesting) { $prState = "closed"