Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: set az devops group var #437

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/preview/03-Features/powershell/azure-devops.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ PS> Set-AzDevOpsVariable "my-variable" "my-variable-value" -AsSecret
##vso[task.setvariable variable=my-variable;issecret=true] ***
```

## Setting a variable in an Azure DevOps variable group

Assign a value to a DevOps variable group during the execution of a pipeline.

| Parameter | Mandatory | Description |
| --------------------- | --------- | ------------------------------------------------------ |
| `VariableGroupName` | yes | The name of the remote variable group on Azure DevOps |
| `VariableName` | yes | The name of the variable to set in the variable group |
| `VariableValue` | yes | The value of the variable to set in the variable group |

**Example**

```powershell
PS> Set-AzDevOpsGroupVariable -VariableGroupName "product-v1-dev" -VariableName "Product.Api.Url" -VariableValue "https://product/api/"
```

## Setting ARM outputs to Azure DevOps variable group

Stores the Azure Resource Management (ARM) outputs in a variable group on Azure DevOps.
Expand Down
Binary file modified src/Arcus.Scripting.DevOps/Arcus.Scripting.DevOps.psd1
Binary file not shown.
32 changes: 30 additions & 2 deletions src/Arcus.Scripting.DevOps/Arcus.Scripting.DevOps.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
.Description
Assign a value to a DevOps pipeline variable during the execution of this pipeline.

.Parameter VariableName
.Parameter Name
The name of the variable to set in the pipeline.

.Parameter VariableValue
.Parameter Value
The value of the variable to set in the pipeline.
#>
function Set-AzDevOpsVariable {
Expand All @@ -27,6 +27,34 @@ function Set-AzDevOpsVariable {

Export-ModuleMember -Function Set-AzDevOpsVariable

<#
.Synopsis
Set a variable in the Azure DevOps variable group.

.Description
Assign a value to a DevOps variable group during the execution of an Azure DevOps pipeline.

.Parameter VariableGroupName
The name of the Azure DevOps variable group to updat with a new variable.

.Parameter VariableName
The name of the variable to set in the variable group.

.Parameter VariableValue
The value of the variable to set in the variable group.
#>
function Set-AzDevOpsGroupVariable {
param(
[string][parameter(Mandatory = $true)]$VariableGroupName,
[string][parameter(Mandatory = $true)]$VariableName,
[string][parameter(Mandatory = $true)]$VariableValue
)

. $PSScriptRoot\Scripts\Set-AzDevOpsGroupVariable.ps1 -VariableGroupName $VariableGroupName -VariableName $VariableName -VariableValue $VariableValue
}

Export-ModuleMember -Function Set-AzDevOpsGroupVariable

<#
.Synopsis
Sets the ARM outputs as a variable group on Azure DevOps.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<Compile Include="Arcus.Scripting.DevOps.psm1" />
<Compile Include="Scripts\Set-AzDevOpsArmOutputs.ps1" />
<Compile Include="Scripts\Save-AzDevOpsBuild.ps1" />
<Compile Include="Scripts\Set-AzDevOpsGroupVariable.ps1" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Target Name="Build" />
Expand Down
55 changes: 1 addition & 54 deletions src/Arcus.Scripting.DevOps/Scripts/Set-AzDevOpsArmOutputs.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,6 @@ param(
[switch][parameter(Mandatory = $false)] $UpdateVariablesForCurrentJob = $false
)

function Add-VariableGroupVariable() {
[CmdletBinding()]
param(
[string][parameter(Mandatory = $true)]$VariableGroupName,
[string][parameter(Mandatory = $true)]$variableName,
[string][parameter(Mandatory = $true)]$variableValue
)
BEGIN {
Write-Verbose "Retrieving Azure DevOps project details for variable group '$VariableGroupName'..."
[String]$project = "$env:SYSTEM_TEAMPROJECT"
[String]$projectUri = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
[String]$apiVersion = "4.1-preview.1"
Write-Debug "Using Azure DevOps project: $project, project URI: $projectUri"


Write-Verbose "Setting authorization headers to retrieve potential existing Azure DevOps variable group '$VariableGroupName'..."
if ([string]::IsNullOrEmpty($env:SYSTEM_ACCESSTOKEN)) {
Write-Error "The SYSTEM_ACCESSTOKEN environment variable is empty. Remember to explicitly allow the build job to access the OAuth Token!"
}
$headers = @{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }


Write-Verbose "Getting Azure DevOps variable group '$VariableGroupName'..."
$getVariableGroupUrl = $projectUri + $project + "/_apis/distributedtask/variablegroups?api-version=" + $apiVersion + "&groupName=" + $VariableGroupName
$variableGroup = (Invoke-RestMethod -Uri $getVariableGroupUrl -Headers $headers -Verbose)

$releaseName = $env:RELEASE_RELEASENAME
if ([string]::IsNullOrEmpty($releaseName)) {
$releaseName = $env:BUILD_DEFINITIONNAME + " " + $env:BUILD_BUILDNUMBER
}

if ($variableGroup.value) {
Write-Host "Set properties for update of existing Azure DevOps variable group '$variableGroupName'"
$variableGroup = $variableGroup.value[0]
$variableGroup | Add-Member -Name "description" -MemberType NoteProperty -Value "Variable group that got auto-updated by release '$releaseName'." -Force
$method = "Put"
$upsertVariableGroupUrl = $projectUri + $project + "/_apis/distributedtask/variablegroups/" + $variableGroup.id + "?api-version=" + $apiVersion
} else {
Write-Host "Set properties for creation of new Azure DevOps variable group '$VariableGroupName'"
$variableGroup = @{name = $VariableGroupName; type = "Vsts"; description = "Variable group that got auto-updated by release '$releaseName'."; variables = New-Object PSObject; }
$method = "Post"
$upsertVariableGroupUrl = $projectUri + $project + "/_apis/distributedtask/variablegroups?api-version=" + $apiVersion
}

$variableGroup.variables | Add-Member -Name $variableName -MemberType NoteProperty -Value @{value = $variableValue } -Force

Write-Verbose "Upserting Azure DevOps variable group '$variableGroupName'..."
$body = $variableGroup | ConvertTo-Json -Depth 10 -Compress
Write-Debug $body
Invoke-RestMethod $upsertVariableGroupUrl -Method $method -Body $body -Headers $headers -ContentType 'application/json; charset=utf-8' -Verbose
}
}

Write-Verbose "Geting ARM outputs from '$ArmOutputsEnvironmentVariableName' environment variable..."
$json = [System.Environment]::GetEnvironmentVariable($ArmOutputsEnvironmentVariableName)
$armOutputs = ConvertFrom-Json $json
Expand All @@ -68,7 +15,7 @@ foreach ($output in $armOutputs.PSObject.Properties) {

if ($UpdateVariableGroup) {
Write-Host Adding variable $output.Name with value $variableValue to variable group $VariableGroupName
Add-VariableGroupVariable -VariableGroupName $VariableGroupName -variableName $variableName -variableValue $variableValue
. $PSScriptRoot\Set-AzDevOpsGroupVariable.ps1 -VariableGroupName $VariableGroupName -VariableName $variableName -VariableValue $variableValue
}

if ($UpdateVariablesForCurrentJob) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
param(
[string][parameter(Mandatory = $true)]$VariableGroupName,
[string][parameter(Mandatory = $true)]$VariableName,
[string][parameter(Mandatory = $true)]$VariableValue
)

Write-Verbose "Retrieving Azure DevOps project details for variable group '$VariableGroupName'..."
[String]$project = "$env:SYSTEM_TEAMPROJECT"
[String]$projectUri = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
[String]$apiVersion = "7.1"
Write-Debug "Using Azure DevOps project: $project, project URI: $projectUri"


Write-Verbose "Setting authorization headers to retrieve potential existing Azure DevOps variable group '$VariableGroupName'..."
if ([string]::IsNullOrEmpty($env:SYSTEM_ACCESSTOKEN)) {
Write-Error "The SYSTEM_ACCESSTOKEN environment variable is empty. Remember to explicitly allow the build job to access the OAuth Token!"
}
$headers = @{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }


Write-Verbose "Getting Azure DevOps variable group '$VariableGroupName'..."
$getVariableGroupUrl = $projectUri + $project + "/_apis/distributedtask/variablegroups?api-version=" + $apiVersion + "&groupName=" + $VariableGroupName
$variableGroup = (Invoke-RestMethod -Uri $getVariableGroupUrl -Headers $headers -Verbose)

$releaseName = $env:RELEASE_RELEASENAME
if ([string]::IsNullOrEmpty($releaseName)) {
$releaseName = $env:BUILD_DEFINITIONNAME + " " + $env:BUILD_BUILDNUMBER
}

if ($variableGroup.value) {
Write-Host "Set properties for update of existing Azure DevOps variable group '$variableGroupName'"
$variableGroup = $variableGroup.value[0]
$variableGroup | Add-Member -Name "description" -MemberType NoteProperty -Value "Variable group that got auto-updated by pipeline '$releaseName'." -Force
$method = "Put"
$upsertVariableGroupUrl = $projectUri + $project + "/_apis/distributedtask/variablegroups/" + $variableGroup.id + "?api-version=" + $apiVersion
} else {
Write-Host "Set properties for creation of new Azure DevOps variable group '$VariableGroupName'"
$variableGroup = @{name = $VariableGroupName; type = "Vsts"; description = "Variable group that got auto-updated by pipeline '$releaseName'."; variables = New-Object PSObject; }
$method = "Post"
$upsertVariableGroupUrl = $projectUri + $project + "/_apis/distributedtask/variablegroups?api-version=" + $apiVersion
}

$variableGroup.variables | Add-Member -Name $VariableName -MemberType NoteProperty -Value @{value = $VariableValue } -Force

Write-Verbose "Upserting Azure DevOps variable group '$variableGroupName'..."
$body = $variableGroup | ConvertTo-Json -Depth 10 -Compress
Write-Host $body

Write-Host "$method -> $upsertVariableGroupUrl"
Invoke-RestMethod $upsertVariableGroupUrl -Method $method -Body $body -Headers $headers -ContentType 'application/json; charset=utf-8' -Verbose
Original file line number Diff line number Diff line change
@@ -1,5 +1,66 @@
Import-Module -Name $PSScriptRoot\..\Arcus.Scripting.DevOps -ErrorAction Stop

function global:Get-AzDevOpsGroup {
param($VariableGroupName)

$VariableGroupName = $VariableGroupName -replace ' ', '%20'
$projectId = $env:SYSTEM_TEAMPROJECTID
$collectionUri = $env:SYSTEM_COLLECTIONURI
$getUri = "$collectionUri" + "$projectId/_apis/distributedtask/variablegroups?groupName=" + $VariableGroupName + "&api-version=7.1"
$headers = @{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }

Write-Host "GET -> $getUri"
$getResponse = Invoke-WebRequest -Uri $getUri -Method Get -Headers $headers
$json = ConvertFrom-Json $getResponse.Content

$variableGroup = $json.value[0]
Write-Host "$($getResponse.StatusCode) $variableGroup <- $getUri"

return $variableGroup
}

function global:Remove-AzDevOpsVariableGroup {
param($VariableGroupName)

$variableGroup = Get-AzDevOpsGroup -VariableGroupName $VariableGroupName

$VariableGroupName = $VariableGroupName -replace ' ', '%20'
$projectId = $env:SYSTEM_TEAMPROJECTID
$collectionUri = $env:SYSTEM_COLLECTIONURI
$deleteUri = "$collectionUri" + "$projectId/_apis/distributedtask/variablegroups/" + $variableGroup.id + "?api-version=7.1"
$headers = @{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }

Write-Host "DELETE -> $deleteUri"
$deleteResponse = Invoke-WebRequest -Uri $deleteUri -Method Delete -Headers $headers
Write-Host "$($deleteResponse.StatusCode) <- $deleteUri"
}

function global:Get-AzDevOpsGroupVariable {
param($VariableGroupName, $VariableName)

$json = Get-AzDevOpsGroup -VariableGroupName $VariableGroupName
$variable = $json.variables.PSObject.Properties | where { $_.Name -eq $VariableName }

return $variable
}

function global:Remove-AzDevOpsGroupVariable {
param($VariableGroupName, $VariableName)

$json = Get-AzDevOpsGroup -VariableGroupName $VariableGroupName
$json.variables.PSObject.Properties.Remove($VariableName)

$project = "$env:SYSTEM_TEAMPROJECT"
$projectUri = "$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"
$upsertVariableGroupUrl = $projectUri + $project + "/_apis/distributedtask/variablegroups/$($json.id)?api-version=7.1"
$headers = @{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }

$json = $json | ConvertTo-Json -Depth 10 -Compress
Write-Host "PUT $json -> $upsertVariableGroupUrl"
$putResponse = Invoke-WebRequest -Uri $upsertVariableGroupUrl -Method Put -Headers $headers -Body $json -ContentType 'application/json; charset=utf-8'
Write-Host "$($putResponse.StatusCode) <- $upsertVariableGroupUrl"
}

InModuleScope Arcus.Scripting.DevOps {
Describe "Arcus Azure DevOps integration tests" {
BeforeEach {
Expand Down Expand Up @@ -43,6 +104,7 @@ InModuleScope Arcus.Scripting.DevOps {
$collectionUri = $env:SYSTEM_COLLECTIONURI
$requestUri = "$collectionUri" + "$projectId/_apis/build/builds/" + $buildId + "/leases?api-version=7.0"
$headers = @{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }

try {
# Act
Save-AzDevOpsBuild -ProjectId $projectId -BuildId $buildId -DaysToKeep 10
Expand All @@ -66,6 +128,8 @@ InModuleScope Arcus.Scripting.DevOps {
}
}
}
}
Context "Azure DevOps variable group" {
It "Sets the DevOps variable group description with the release name" {
# Arrange
$variableGroupName = $config.Arcus.DevOps.VariableGroup.Name
Expand All @@ -86,6 +150,40 @@ InModuleScope Arcus.Scripting.DevOps {
$json = ConvertFrom-Json $getResponse.Content
$json.value[0].description | Should -BeLike "*$env:Build_DefinitionName*$env:Build_BuildNumber*"
}
It "Sets a new variable to an existing DevOps variable group" {
# Arrange
$variableGroupName = $config.Arcus.DevOps.VariableGroup.Name
$variableName = [System.Guid]::NewGuid().ToString()
$expectedValue = [System.Guid]::NewGuid().ToString()
try {
# Act
Set-AzDevOpsGroupVariable -VariableGroupName $variableGroupName -VariableName $variableName -VariableValue $expectedValue

# Assert
$actualValue = Get-AzDevOpsGroupVariable -VariableGroupName $variableGroupName -VariableName $variableName
$actualValue | Should -Be $variableValue

} finally {
Remove-AzDevOpsGroupVariable -VariableGroupName $variableGroupName -VariableName $variableName
}
}
It "Sets a new variable to a new DevOps variable group" {
# Arrange
$variableGroupName = [System.Guid]::NewGuid()
$variableName = [System.Guid]::NewGuid()
$variableValue = [System.Guid]::NewGuid()
try {
# Act
Set-AzDevOpsGroupVariable -VariableGroupName $variableGroupName -VariableName $variableName -VariableValue $variableValue

# Assert
$actualValue = Get-AzDevOpsGroupVariable -VariableGroupName $variableGroupName -VariableName $variableName
$actualValue | Should -Be $variableValue

} finally {
Remove-AzDevOpsVariableGroup -VariableGroupName $variableGroupName
}
}
}
}
}
Loading