Azure Devops : Updating Variable in VariableGroup [duplicate] - azure

Am working on Azure Devops CI&CD. Here, my release name must be in Version number using tags. Am getting this with the help of Variable Groups, by adding tags and value to it. Here am getting the tags value as constant like a static for every release like 1.1,1.2,1.3 etc.
Now am trying to increase/update my tag value dynamically for every new release triggered after completion of my Build Definition successfully which looks like 1.1,1.2,2.1,2.2,3.1,3.2 etc.It is possible with the help of statically by variable group, but manually we need to update it.
Is it possible to Increase/Update the tags value in Variable Group with the Build Definition tasks or other process.If possible, please suggest me to "How to done this?"

You can overwrite/update the value of the variables by using the logging command to set the variables again in Azure Devops Build pipleline:
Write-Host "##vso[task.setvariable variable=testvar;]testvalue"
To increase the value dynamically, you need to use the token $(Rev:.r). You can custom the variables based on the $(Build.BuildNumber) or $(Release.ReleaseName)as they will increase the value dynamically...
Just reference this thread to custom the variables:https://github.com/MicrosoftDocs/vsts-docs/issues/666#issuecomment-386769445
UPDATE:
If you just want to update the value of the variables which defined in a specific Variable Group, then you can call REST API in build pipeline to achieve that:
PUT https://{account}.visualstudio.com/{ProjectName or ID}/_apis/distributedtask/variablegroups/{Variable Group ID}?api-version=5.0-preview.1
Content-Type: application/json
Request Body:
{"id":2,"type":"Vsts","name":"VG0926","variables":{"TEST0926":{"isSecret":false,"value":"0930"}}}
UPDATE2:
You can write a PowerShell script to call the REST API, then add a PowerShell task to run the script in your build pipeline: (Use the OAuth token to access the REST API)
Below sample for your reference:
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/distributedtask/variablegroups/{Variable Group ID}?api-version=5.0-preview.1"
Write-Host $url
function CreateJsonBody
{
$value = #"
{"id":2,"type":"Vsts","name":"VG0926","variables":{"TEST0926":{"isSecret":false,"value":"0930"}}}
"#
return $value
}
$json = CreateJsonBody
$pipeline = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "New Variable Value:" $pipeline.variables.TEST0926.value
UPDATE3:
Well, tested again, below scripts works for me as well. You can try it, just replace the parameters accordingly:
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "","PAT here")))
$url = "https://dev.azure.com/xxx/Test0924/_apis/distributedtask/variablegroups/1?api-version=5.0-preview.1"
$json = '{"id":1,"type":"Vsts","name":"VG0928","variables":{"TEST0928":{"isSecret":false,"value":"0931"}}}'
$pipeline = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
Write-Host "New Variable Value:" $pipeline.variables.TEST0928.value

You can simply update any number of variables in an Azure Devops variable group using its built-in az pipelines variable-group variable update command. You can use this command in a script task in the pipeline definition as shown below.
ps: Replace all the upper case values with corresponding values except the SYSTEM_ACCESSTOKEN.
variables:
- group: VARIABLE_GROUP_NAME
jobs:
- job: UpdateVarGroup
steps:
- script: |
newValue="This is the updated value"
echo $SYSTEM_ACCESSTOKEN | az devops login
az pipelines variable-group variable update --group-id $(group_id) \
--name NAME_OF_THE_VARIABLE \
--value "${newValue}" \
--org https://dev.azure.com/YOUR_ORGANIZATION_NAME \
--project AZURE_DEVOPS_PROJECT
displayName: 'Update variable inside a variable group'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
In order for this example to work, you need to have a variable inside your variable group called group_id. The value of that needs to be set to the group id of the variable group, which can be obtained by simply looking at the url of your variable group. (The group id is the value for variableGroupId in the url of your browser when you are inside the variable group)
System.AccessToken is required for az devops login

I used this task to update the value of my variables inside my group.
Shared variable updater (preview)
Dont forget to set those settings :
Requires 'Allow scripts to access the OAuth token' in agent job additional options
Set administrator role to 'Project Collection Build Service' in the variable group.
In case of using a YAML pipeline
When using a YAML pipeline, the OAuth token is automatically added (no need for step 1 above), but requires a bit of work to make accessible for the powershell script. Use the guidance here to be able to use the token.

If you want to update a variable group's value, use the REST.API methods.
Rather than constructing the PUT request body manually, use a GET first to get the original JSON, update only what you need, then replay it as a PUT. I used to keep the variable group id also as a variable in that group to avoid hard-coding.
variables:
- group: MyVarGroup
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/distributedtask/variablegroups/$(VariableGroupId)?api-version=6.0-preview.1"
$header = #{
"Authorization" = "Bearer $(System.AccessToken)"
}
$def = Invoke-RestMethod -Uri $url -Headers $header
$def.variables.MyTestVar.value = "NewValue"
$body = #($def) | ConvertTo-Json -Depth 100 -Compress
$def = Invoke-RestMethod -Method 'Put' -Uri $url -ContentType 'application/json' -Headers $header -Body $body

You can overwrite variables using the REST API with a PowerShell task without needing to create a PAT.
You'll need to first going into the agent job and set "Allow scripts to access OAuth token".
You'll need too go to your variable group and add the 'Project Collection Build Service' as an administrator.
Now you can call the Rest API using the OAuth Bearer token. Code for reference:
$id = <variable group id>
# This is using some environment variables provided by the pipeline to build the URL
$url = ("$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/distributedtask/variablegroups/{0}?api-version=5.0-preview" -f $id)
# You might find it useful to us a GET method to grab the variable group, update it and then convert it to this json string rather than doing this here
$json = '{"id":$id,"type":"Vsts","name":"<Variable Group Name>","<Variable Name":{"ThisIsMyVariable":{"isSecret":false,"value":"20"}}}'
$pipeline = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}

I made this task to manage variable groups from Pipelines:
ManageVariableGroupTask
Using this you can Create/Update/Delete variable groups and do the same operations on variables contained in them.
Hope that's helpfull!

Related

Update Release Description in Release Pipeline [duplicate]

In Azure DevOps I'm trying to set the release description via PowerShell / CMD in order to have a dynamic description of my releases based on the input of the artifacts from the build step.
I've tried setting the release variables via powershell like:
Write-Host "##vso[task.setvariable variable=release.releasedescription;]bar"
Write-Host "##vso[task.setvariable variable=RELEASE_RELEASEDESCRIPTION;]bar"
But that didn't work and the description field remains always empty.
Is there any tweak / setting that would help achieve this behavior?
What you tried to do is just to set the environment variable that contains the release description data and not set the "real" release description, so after the release finished the description not changed.
If you want to set the release description during the release you can try to do it with Azure DevOps Rest API - Update Release.
So add a PowerShell task that executes the Rest API with Invoke-RestMethod, get the current release with GET method and then update the release with PUT, in the body change the description to the new one.
You could do this too:
- bash: |
echo "Updating pipeline job Run description"
echo "##vso[build.updatebuildnumber]$(Build.BuildNumber) $(App_Name)"
displayName: "Set pipeline job Run description for Azure DevOps console"
For anyone who simply wants to set the name of an Azure Pipelines run, you can find the description here.
TLDR: Set the top-level name: attribute.
Here is the PowerShell script to set release description in DevOps. Before the stage that need approval, add a PowerShell task to invoke REST API to change the release description. Please use your own orgName, projectName, PAT and modify the release description.
$url = https://vsrm.dev.azure.com/<orgName>/<ProjectName>/_apis/release/releases/$(Release.ReleaseId)?api-version=6.0
$token="PAT"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$head = #{ Authorization =" Basic $base64AuthInfo" }
$pipeline = Invoke-RestMethod -Uri $url -Headers $head -Method Get
$Pipeline.description = "<Modify the release description>"
$body = $Pipeline | ConvertTo-Json -Depth 100
$url2=https://vsrm.dev.azure.com/<orgName>/<ProjectName>/_apis/release/releases/$(Release.ReleaseId)?api-version=6.0
$resp = Invoke-RestMethod -Uri $url2 -Method Put -Headers $head -Body $body -ContentType application/json

Is there any azure DevOps rest API that will fetch the list if releases along with their environment status by providing the build-id?

I have a problem where if I provide a build id and use 'LIST Release Azure DevOps API' it is fetching all the releases present in that build. But here the problem is that the 'LIST API' is not providing details of the environments present in the list of releases. I need to make another request with the release id to fetch the environment details for every release. Is there any option that will combine both these operations?
You can provide the $expand=environments parameter in the List release API to include the details of environments in the response result. See here.
https://vsrm.dev.azure.com/{org}/{proj}/_apis/release/releases?sourceId={projectGuid}:{BuildDefinitionId}&$expand=environments&api-version=6.1-preview.8
See below example in powershell scripts:
$url = "https://vsrm.dev.azure.com/{org}/{proj}/_apis/release/releases?sourceId={projectGuid}:{BuildDefinitionId}&`$expand=environments&api-version=6.1-preview.8"
$PAT = "Personal access token"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
Invoke-RestMethod -Uri $reurl -Headers #{authorization = "Basic $base64AuthInfo"} -Method get

Is it possible to search a package from all Artifact Feeds in Azure DevOps?

I know it's possible to get all packages contained in a single Artifact Feed using the link below:
https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/packages?api-version=6.0-preview.1
I noticed in Azure DevOps that the search bar has the ability to look into ALL feeds inside a project. Thus, my question is: Is it possible to achieve the same functionality through the API, and get all packages from all feeds instead of one.
Is it possible to achieve the same functionality through the API, and get all packages from all feeds instead of one.
As far as I know, this is achievable.
You could use the Rest API -Feed Management - Get Feeds to get All feeds in Project level.
Then you could use the Rest API to get the packages. You can execute these two apis simultaneously through powershell.
Here is the Powershell sample:
$token = "PAT"
$url="https://feeds.dev.azure.com/{Organization Name}/{Project Name}/_apis/packaging/feeds?api-version=6.0-preview.1"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach( $feedid in $response.value.id )
{
echo $feedid
$url1="https://feeds.dev.azure.com/{Organization Name}/{Project Name}/_apis/packaging/Feeds/$($feedid)/packages?api-version=6.0-preview.1"
$response1 = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
Write-Host "Package = $($response1 | ConvertTo-Json -Depth 100)"
}
In this case, you can get alls feeds of project scope in a project, and then get all the packages in it.
By the way, if you want to get all organization scope feeds, you only need to delete the project parameter in the URL.

Handling multiple azure devops pipelines

I have several azure devops pipeline files in one project. The files are all in a subdirectory and called azure-pipelines.yml.
Renaming: I can rename the pipelines in the UI to distinguish them... but I would like to skip that manual step and perform that in the yml. Is there a parameter for that - I cannot find it in the docs.
Workdirs: the pipelines start in the main directory. I can adjust the working directory of the script steps with workingDirectory thanks to the answer here. But can we also adjust that for the entire pipeline?
There is not a parameter for renaming the pipelines. There are two ways to rename the pipelines. One is to manually rename them from the UI. Another way is through build definition update rest api.
Below is an example in powershell scripts to rename the pipeline through rest api.
the scripts first get the build definition by build definition get api. Then assign a new name for the build definition, and update the definition with the new name.
$create = "https://dev.azure.com/{ORG}/{PROJ}/_apis/build/definitions/{DefinitionId}?api-version=5.1"
$PAT="{Person access token}"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
$result = Invoke-RestMethod -Uri $create -Headers #{authorization = "Basic $base64AuthInfo"} -Method get
$result.name = "YamlPipeline-newName"
$updateBody= $result | ConvertTo-Json -Depth 100
$result7 = Invoke-RestMethod -Uri $create -Headers #{authorization = "Basic $base64AuthInfo"} -Method put -ContentType application/json -Body $updateBody
You cannot change the workingdirectory for the entire pipeline. You can change the workingdirectory inside the tasks.
And there are predefined variables you can use to refer to the places in the agents.
For below example:
$(Agent.BuildDirectory) is mapped to c:\agent_work\1
%(Build.ArtifactStagingDirectory) is mapped to c:\agent_work\1\a
$(Build.BinariesDirectory) is mapped to c:\agent_work\1\b
$(Build.SourcesDirectory) is mapped to c:\agent_work\1\s
You can also submit a feature request for above renaming pipeline and adjust workingdirectory for the entire pipeline(click Suggest a feature and choose Azure Devops) to Microsoft Development team. Hope they will consider supporting these feature in the future.

Adding index creation/configuration in a Azure search ARM Template

There is ways to create a Azure Search Service via ARM template (Example: https://raw.githubusercontent.com/azure/azure-quickstart-templates/master/101-azure-search-create/azuredeploy.json).
What I want to know is there a way to define a specific index within the ARM template (fields, data sources, indexers etc)?
I know that there are REST services that you can use in order to create and modify indexes but I do not want a separate script/application to handle that after my resource group and Azure Search Service is created.
+1 to Don's comment. You will need to create the index either using the REST API or the .NET SDK. If you happen to be using PowerShell to create the service, you might find the following code helpful which calls the REST API using Invoke-RestMethod and a set of .JSON files that contain the schema for the index and some documents.
#------------------------#
# Setting up search index#
#------------------------#
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", 'application/json')
$headers.Add("api-key", $searchApiKey)
Write-Host
Write-Host "Creating Index..."
$schemaFile = "$(Split-Path $MyInvocation.MyCommand.Path)\zipcodes.schema"
$response = Invoke-RestMethod -TimeoutSec 10000 $searchServiceUrl"/indexes/zipcodes2?api-version=2015-02-28-Preview" -Method Put -Headers $headers -Body "$(get-content $schemaFile)"
Write-Host $response
$jsonFile = "$(Split-Path $MyInvocation.MyCommand.Path)\zipcodes1.json"
Write-Host
Write-Host "Adding Documents from $jsonFile..."
$response = Invoke-RestMethod -TimeoutSec 10000 $searchServiceUrl"/indexes/zipcodes2/docs/index?api-version=2015-02-28-Preview" -Method Post -Headers $headers -Body "$(get-content $jsonFile)"
Write-Host $response
No, you cannot create an index within an ARM template. The terminology I've read before is that ARM is for managing the Azure control plane.
Azure Search does not support managing indexes via ARM templates today. If this capability is important to you, please add an item on User Voice to help us prioritize it.

Resources