Skip to content

Instantly share code, notes, and snippets.

@MarcusFelling
Last active June 5, 2019 15:55
Show Gist options
  • Save MarcusFelling/3a0d9387495c0be3ee664dea541b4fc4 to your computer and use it in GitHub Desktop.
Save MarcusFelling/3a0d9387495c0be3ee664dea541b4fc4 to your computer and use it in GitHub Desktop.
<#
.DESCRIPTION
Creates a new release for the specified release definition name, using the latest artifact versions available
.Parameter PAT
Personal Access token. It's recommended to use a service account and pass via encrypted build definition variable.
https://docs.microsoft.com/en-us/vsts/organizations/accounts/use-personal-access-tokens-to-authenticate?view=vsts
.Parameter ReleaseDefinitionName
Name of release definition to create a release for
.Notes
-Parameters are outside of functions in order to be passed by TFS build definition variables
#>
[CmdletBinding()]
Param
(
[String] [Parameter(Mandatory = $true)]
$PAT,
[String] [Parameter(Mandatory = $true)]
$ReleaseDefinitionName
)
# Base64-encodes the Personal Access Token (PAT) appropriately
# This is required to pass PAT through HTTP header
$script:User = "" # Not needed when using PAT, can be set to anything
$script:Base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User, $PAT)))
Function Find-ReleaseDefinition {
Param([Parameter(Mandatory = $true)] $TfsUri)
$url = [string]::Format("{0}{1}/_apis/release/definitions?`$expand=artifacts&api-version=3.0-preview.1", $TfsUri, $TeamProject)
"url= $url"
$result = $null
Try
{
$result = Invoke-RestMethod -Uri $url -Method GET -ContentType "application/json" -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo)}
}
Catch
{
Write-Verbose $_.Exception.ToString()
$response = $_.Exception.Response
$responseStream = $response.GetResponseStream()
$streamReader = New-Object System.IO.StreamReader($responseStream)
$streamReader.BaseStream.Position = 0
$streamReader.DiscardBufferedData()
$responseBody = $streamReader.ReadToEnd()
$streamReader.Close()
Write-Error $responseBody
}
return $result.value | Where-Object {$_.name -eq $ReleaseDefinitionName}
}
Function Get-ArtifactsVersions {
Param
(
[Parameter(Mandatory = $true)] $TfsUri,
[Parameter(Mandatory = $true)] $Artifacts
)
"Get artifacts versions"
$url = [string]::Format("{0}{1}/_apis/release/artifacts/versions?releaseDefinitionId={2}&api-version=3.0-preview.1", $TfsUri, $TeamProject, $definition.id)
"url= $url"
$result = $null
Try
{
$result = Invoke-RestMethod -Uri $url -Method Get -Body $body -ContentType "application/json" -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo)}
}
Catch
{
Write-Verbose $_.Exception.ToString()
$response = $_.Exception.Response
$responseStream = $response.GetResponseStream()
$streamReader = New-Object System.IO.StreamReader($responseStream)
$streamReader.BaseStream.Position = 0
$streamReader.DiscardBufferedData()
$responseBody = $streamReader.ReadToEnd()
$streamReader.Close()
Write-Error $responseBody
}
return $result
}
Function Get-Artifacts {
Param
(
[Parameter(Mandatory = $true)] $TfsUri,
[Parameter(Mandatory = $true)] $ReleaseDefinition
)
$artifacts = @()
$defArtifacts = $ReleaseDefinition.artifacts
If ($null -eq $defArtifacts)
{
Write-Error "Cannot find artifacts for the Release Definition."
}
$versions = Get-ArtifactsVersions -TfsUri $TfsUri -Artifacts $defArtifacts
If ($null -eq $versions)
{
Write-Error "Cannot find artifacts versions."
}
foreach ($artifact in $defArtifacts)
{
$latestVersion = $versions.artifactVersions | Where-Object -Property alias -eq -Value $artifact.alias
$latestVersion = $latestVersion.versions[0]
$artifacts += @{
alias = $artifact.alias
instanceReference = @{
name = $latestVersion.name
id = $latestVersion.id
}
}
}
return $artifacts
}
Function CreateRelease {
Param
(
[Parameter(Mandatory = $true)] $TfsUri,
[Parameter(Mandatory = $true)] $ReleaseDefinition,
[Parameter(Mandatory = $true)] $Artifacts
)
"Create release"
$url = [string]::Format("{0}{1}/_apis/release/releases?api-version=3.0-preview.1", $TfsUri, $TeamProject)
"url= $url"
$body = @{
definitionId = $ReleaseDefinition.id
description = ""
artifacts = $Artifacts
isDraft = $false
manualEnvironments = @()
} | ConvertTo-Json -Depth 4
"body= $body"
$result = $null
# Create release
Try
{
$result = Invoke-RestMethod -Uri $url -Method POST -Body $body -ContentType "application/json" -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo)}
}
Catch
{
Write-Verbose $_.Exception.ToString()
$response = $_.Exception.Response
$responseStream = $response.GetResponseStream()
$streamReader = New-Object System.IO.StreamReader($responseStream)
$streamReader.BaseStream.Position = 0
$streamReader.DiscardBufferedData()
$responseBody = $streamReader.ReadToEnd()
$streamReader.Close()
Write-Error $responseBody
}
# Get release ID from release that was created above
$releaseID = $result.id
# Wait for deployment to complete
Do
{
"Deployment of $ReleaseDefinitionName in progress..."
# Wait 10 seconds before checking status of release
Start-Sleep -s 10
# Use release ID to get status of deployment
$url = [string]::Format("{0}{1}/_apis/release/releases/{2}?api-version=3.0-preview.1", $TfsUri, $TeamProject, $releaseID)
Try
{
$CheckDeployStatusResult = Invoke-RestMethod -Uri $url -Method Get -ContentType "application/json" -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo)}
}
Catch
{
Write-Verbose $_.Exception.ToString()
$response = $_.Exception.Response
$responseStream = $response.GetResponseStream()
$streamReader = New-Object System.IO.StreamReader($responseStream)
$streamReader.BaseStream.Position = 0
$streamReader.DiscardBufferedData()
$responseBody = $streamReader.ReadToEnd()
$streamReader.Close()
Write-Error $responseBody
}
$deploymentstatus = $CheckDeployStatusResult.environments.status
}
Until($deploymentstatus -ne "notStarted" -and $deploymentstatus -ne "inProgress")
# https://docs.microsoft.com/en-us/rest/api/vsts/release/releases/get%20release?view=vsts-rest-4.1#deployphasestatus
Switch($deploymentstatus)
{
"canceled"
{
Write-Error "Deployment canceled"
}
"cancelling"
{
Write-Error "Deployment cancelling"
}
"failed"
{
Write-Error "Deployment failed"
}
"partiallySucceeded"
{
Write-Error "Deployment partiallySucceeded"
}
"skipped"
{
Write-Error "Deployment skipped"
}
"succeeded"
{
"Deployment succeeded"
}
"undefined"
{
Write-Error "Deployment undefined"
}
default
{
Write-Error "Deployment did not succeed"
}
}
}
$ErrorActionPreference = 'Stop'
"ReleaseDefinitionName= $ReleaseDefinitionName"
$TeamProject= "$env:SYSTEM_TEAMPROJECT"
"TeamPreojct= $TeamProject"
$tfsUri = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
"TfsUri= $tfsUri"
$definition = Find-ReleaseDefinition -TfsUri $tfsUri
If ($null -eq $definition -or $definition.Count -gt 2)
{
Write-Error "Cannot find Release Definition or there are more than one Release Definition with the name."
}
$artifacts = @(Get-Artifacts -TfsUri $tfsUri -ReleaseDefinition $definition)
CreateRelease -TfsUri $tfsUri -ReleaseDefinition $definition -Artifacts $artifacts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment