Skip to content

Instantly share code, notes, and snippets.

@akuryan
Last active January 13, 2023 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akuryan/f1218dda7e4741c4acfe1a740a3c79c2 to your computer and use it in GitHub Desktop.
Save akuryan/f1218dda7e4741c4acfe1a740a3c79c2 to your computer and use it in GitHub Desktop.
###############################################################################
<#
.SYNOPSIS
GetTicketsInBuld
.DESCRIPTION
GetTicketsInBuld collects Jira tickets in build, basing on last successful build in target environment
.PARAMETER authHeaderValue
Added for OutputDebugDetails purpose to allow one to specify Basic auth by passing string like "Basic ..."
For running in Azure DevOps - leave blank
Do not forget to allow your project build services to access environments, at least as Reader (go to Pipeline -> Environments -> Security (on top left) and add ther Project Collection Build Service (your-collection-name) as Reader)
.PARAMETER baseDoApiUri
Base URL for reaching API in Azure DO. When executing in scope of build - set to $env:SYSTEM_TEAMFOUNDATIONSERVERURI$env:SYSTEM_TEAMPROJECT
Locally: https://dev.azure.com/$(AzureDoProject)/$(AzureDoTeam)
.PARAMETER envNamePrefix
Azure DevOps environment name prefix to filter out only required project environments. Also I am using it to have short hand of my environment, like team-cms-env to store only env name in output variable for tickets
.PARAMETER OutputOutputDebugDetailsDetails
In Azure DO - pass the value of system.debug: -OutputDebugDetails $(system.debug)
.NOTES
.EXAMPLE
#>
# ' char inc as Notepad++ language recognition does not like get-help contents
##############################################################################
[CmdletBinding()]
param (
[string] $authHeaderValue,
[string] $baseDoApiUri,
[string] $envNamePrefix = "team-cms-",
[bool] $OutputDebugDetails = $false
)
if ([string]::IsNullOrWhiteSpace($env:SYSTEM_ACCESSTOKEN)) {
$headers = @{ Authorization = "Basic $authHeaderValue" };
}
else {
$headers = @{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" };
}
$allEnvironmentsUri = "$baseDoApiUri/_apis/distributedtask/environments";
$allEnvsJson = Invoke-RestMethod -Method Get -Headers $headers -Uri $allEnvironmentsUri -Verbose:$OutputDebugDetails;
$ids = @();
$allEnvsJson.value | ForEach-Object { if ($_.name -like "$envNamePrefix*") { $ids += "$($_.id)|$($_.name)"; } };
if ($OutputDebugDetails) {
Write-Host "Auth header: $($headers.Authorization)";
Write-Host "All environments URI: $allEnvironmentsUri";
Write-Host "allEnvsJson: $allEnvsJson";
Write-Host "Env's ID's: $ids";
}
foreach ($envInfoRecord in $ids) {
$envId = $envInfoRecord.Split('|')[0];
$envName = $envInfoRecord.Split('|')[1] -replace $envNamePrefix, '';
$deploymentRecordsUri = "$baseDoApiUri/_apis/distributedtask/environments/$envId/environmentdeploymentrecords";
$envDeploymentRecord = Invoke-RestMethod -Method Get -Headers $headers -Uri $deploymentRecordsUri -Verbose:$OutputDebugDetails;
if ($OutputDebugDetails) {
Write-Host "envId = $envId; envName = $envName; deploymentRecordsUri = $deploymentRecordsUri";
Write-Host $envDeploymentRecord;
}
$jobNameToFilter = "some-job-name";
# deployment at each environment consists of several stages - so, I wish to get successful stage, which is last in pipeline, to be sure that I am collecting correct commits
$build = $envDeploymentRecord.value | Where-Object { $_.jobName -eq $jobNameToFilter -and $_.result -eq "succeeded" } | Select-Object -First 1;
$changesInBetween = @();
$result = @();
if ($null -ne $build) {
# set the build from which we are grabbing our changes
$targetBuildId = $build.owner.id;
$uri = "$baseDoApiUri/_apis/build/builds/$targetBuildId/?api-version=7.0";
$json = Invoke-RestMethod -Method Get -Headers $headers -Uri $uri -Verbose:$OutputDebugDetails;
if ($json.count -gt 0) {
$commit_id_after = $json.sourceVersion;
$changesInBetween = git log HEAD...$commit_id_after --no-merges --pretty='format:%s';
if ($OutputDebugDetails) {
Write-Host "Changes commit id: $commit_id_after";
}
}
else {
Write-Warning "No commits found in related build $targetBuildId"
}
}
# now to check, if $changesInBetween in between have something inside
if ($changesInBetween.Count -eq 0) {
# we was not able to grab last successful build from environment - so, we will use current build changes as source of changes
Write-Host "No successful builds have been found for environment $envName identified by id $envId, so we will grab changes for current build";
$uri = "$baseDoApiUri/_apis/build/builds/$($env:BUILD_BUILDID)/changes?api-version=7.0" + '&$top=10000';
$json = Invoke-RestMethod -Method Get -Headers $headers -Uri $uri -Verbose:$OutputDebugDetails;
if ($json.count -gt 0) {
$changesInBetween = $json.value | Select-Object -ExpandProperty message;
}
else {
Write-Warning "No commits found in current build $buildId"
}
}
else {
}
# we have strict rule, which requires each developer to mention ticket number prefixed by US or BUG in commit, so I could grab ticket numbers for JIRA from those commit messages
$numbers = $changesInBetween | Select-String -Pattern 'US\d+|BUG\d+'
# here I want to be sure that I have only unique tickets in report
$result = $numbers.Matches | Select-Object -ExpandProperty Value | ForEach-Object { [int]($_ -replace "US|BUG", "") } | Select-Object -Unique | Sort-Object
$tickets = "NO"
if ($result.Count -gt 0) {
$result = $result | ForEach-Object { "$jiraShortProjectName-" + $_ };
$tickets = $result -join ",";
}
if ($OutputDebugDetails) {
Write-Host "changesInBetween: ";
$changesInBetween | ForEach-Object { Write-Host $_ };
Write-Host "Result: ";
$result | ForEach-Object { Write-Host $_ };
Write-Host "Current build uri: $uri";
Write-Host "Build uri JSON: $json";
}
# finally, I am writing to output variable postfixed with _environmentName to be able to consume this data later
Write-Host "##vso[task.setvariable variable=TICKETS_$envName;isOutput=true]$tickets"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment