How to create a new build or release using the API and YAML - azure-devops

I'm just looking for direction here as, possibly, the api already does this and I'm misunderstanding / can't find the right resource.
What I would like to do is to be able to call the azure-devops api to create a new build definition for me when I supply it with all the necessary yaml files for each stage.
I expected a create endpoint which would take in a few basic pieces of information to create the build / release definition then a collection of yaml files to create the tasks.
I've found Create your first pipeline and Api 5.0 BuildDefinition/Create however neither of these mention posting a yaml definition to the api. I was expecting far less items in the request body considering the yaml definitions contain most of the information required.
Does the api support this? Will it ever support this?

There is no docs for Rest Api with yaml, but if you try to get an existing yaml definition you`ll meet the next example:
So if you want to edit the process you have to edit existing yaml file. If you want create/clone an existing build definition you may try to create/clone yaml file and post a request (Definitions - Create) with the process member:
yamlFilename = path to yaml file in the repository
type = 2
This powershell example to clone a build definition with yaml:
$pat = '{personal access token}'
$base64AuthInfo = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$pat"))
$uri = 'https://dev.azure.com/{organization}/{team_project}/_apis/build/definitions/{buil_id}?api-version=5.0'
$result = Invoke-RestMethod -Method Get -Uri $uri -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -ErrorAction Stop
$body = $result | ConvertTo-Json -Depth 7
$existingyaml = '"yamlFilename": "{path to yaml for existing buildef}"'
$newyaml = '"yamlFilename": "{path to new yaml}"'
$buildname = '"name": "{existing build name}"'
$newbuildname = '"name": "{new build name}"'
$body = $body.Replace($existingyaml, $newyaml)
$body = $body.Replace($buildname, $newbuildname)
$Uri = "https://dev.azure.com/{organization}/{team_project}/_apis/build/definitions?api-version=5.0"
$newBuildDef = Invoke-RestMethod -Uri $Uri -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method Post -Body $body -ContentType "application/json" -ErrorAction Stop

Yes, you are right, you could do a get on a build using the api, and change the variables, it should work.
If you only need to modify variables, you could use variable group to store values, then you can get the variable group and modify the variable values using the Variablegroups api.

Related

Azure cli: clone pipeline

Looking at az pipelines documentation it seems it's not possible to clone a pipeline using cli.
I've looked at getting the yaml (az pipelines show -name=x > x_orig.yaml) and then trying to change json and create pipeline from modified yaml, but that feels like a lot of work that could break after next update.
Is there a way to clone a pipline without going the the Web UI?
Currently, there indeed is not available Azure CLI that can clone or export/import a pipeline to create a new pipeline.
I also searched and tried the Azure DevOps REST API for Pipelines, but did not find the available API.
Ideally, the Azure CLI "az pipelines create" can provide an input parameter that allows users specify an existing pipeline as a starting point for the new pipeline.
If your projects really need this feature, I recommend that you can directly report a feature request on the "Azure/azure-cli" repository to ask adding the parameter like as above mentioned. That will allow you directly interact with the appropriate engineering team, and make it more convenient for the engineering team to collect and categorize your suggestions.
As a workaround, we could clone the build definition via power shell script to call REST API.
Note: We need to change the original build definition name.
REST API
Get build definition:
GET https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=6.0
Create build definition
POST https://dev.azure.com/{organization}/{project}/_apis/build/definitions?api-version=6.0
Power shell script
$connectionToken="{pat}"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$BuildDefinitionInfoURL = "https://dev.azure.com/{org name}/{project name}/_apis/build/definitions/386"
$BuildDefinitionInfo = Invoke-RestMethod -Uri $BuildDefinitionInfoURL -Headers #{authorization = "Basic $base64AuthInfo"} -Method Get
Write-Host $BuildDefinitionInfo.name
$BuildDefinitionInfo.name = $BuildDefinitionInfo.name +" clone"
Write-Host $BuildDefinitionInfo.name
$body = $BuildDefinitionInfo | ConvertTo-Json -Depth 99
$createBuildDefinitionURL = "https://dev.azure.com/{org name}/{project name}/_apis/build/definitions?api-version=6.0"
$response = Invoke-RestMethod -Uri $createBuildDefinitionURL -ContentType "application/json" -Body $body -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST
Write-Host $response.id
Result:

How to retrieve list of projects within an organisation by running a query in Azure DevOps?

I want all the projects within a collection (organization) listed by running a query.
I searched so many resources but I hadn't got any relevant results. anybody
You can get that list if you visit Organization Page. And you cannot get that list using queries, you should REST APIs.
There is an extension in Azure DevOps Marketplace which lists projects and properties like process template etc. you can take a look at it here
You can't do ith with query.
You can do it with Rest API Projects - List, for example in PowerShell:
$pat = "YOUR-PERSONAL-ACCESS-TOKEN"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,"$pat")))
$headers = #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$azureDevOpsUrl = "https://dev.azure.com/{your-organization-name}"
$projects = Invoke-RestMethod -Uri "$azureDevOpsUrl/_apis/projects" -Method Get -Headers $headers -ContentType application/json

Azure DevOps API - Set Board Options

I'm trying to do few things with Azure DevOps projects through Rest API, but I really quickly got stuck.
For example, I want to use the method "Set Board Options", documentation is here https://learn.microsoft.com/en-us/rest/api/azure/devops/work/boards/set%20board%20options?view=azure-devops-rest-5.1
Does anyone have an idea of how to find out which options (and how exactly) I can use? Is there any way to lookup these values in the Azure DevOps portal or somewhere else?
I was trying to use the .Net library (https://github.com/microsoft/azure-devops-dotnet-samples), but the situation there is the same. Method SetBoardOptions exists but takes Dictionary of strings as the first argument and there is no documentation on how to actually fill up this dictionary, which values are possible to use etc.
This API is in preview so I guess this is the reason why the docs so poor:
After a big search and tries, I think you can change 2 options in the board settings:
1) statusBadgeIsPublic - True or False.
2) cardReordering - 0 or 1.
I success to do it with PowerShell:
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,"MY-PAT")))
$headers = #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$URI = "https://dev.azure.com/{org}/{project}/{team}/_apis/work/boards/{board}?api-version=5.1"
$params = #{
"cardReordering"="1";
} | ConvertTo-Json
Invoke-RestMethod -Method Put -Uri $URI -Headers $headers -Body $params -ContentType 'application/json'

How would you access attributes of work items (Features, User Stories, Bugs, or Tasks) associated with a build in the release pipeline?

My team and I are trying to find a way to automatically build release notes and generate them in markdown to be put into a Wiki for users to access. I found a video from Microsoft where their team uses a process where they have release notes for each feature in their Feature objects, but they have manually query those objects and build a markdown file for each release manually. I'm sure by now they must have figured this out, but can't find anything from them yet on that.
Now, I have seen a couple of market place tools (Bravo Notes for one) that do this, but I figured there must be a way we can make a task ourselves that does this for us and automatically place the markdown file in our Wiki (after an approval process of course).
If anyone has any ideas on how I can accomplish this, please let me know. I'm not afraid of getting my hands dirty with some Powershell scripts.
You can use Azure DevOps Rest API to get the work item that associated to the build, then get work item details. create from the details a Markdown file and add it to the wiki.
Example to PowerShell script that do it (get work items asscoited with the build and print the AssignedTo field):
$user = ""
$token = "MY-PAT"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$url = "https://dev.azure.com/{org}/{project}/_apis/build/builds/{buildId}/workitems?api-version=5.1"
$workItems = Invoke-RestMethod -Uri $url -Method Get -ContentType application/json -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$json = $workItems | ConvertTo-Json
$workItems.value.ForEach({
$workItem = Invoke-RestMethod -Uri $_.url -Method Get -ContentType application/json -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
Write-Host $workItem.fields.'System.AssignedTo'.displayName
})

How to modify Azure DevOps release definition variable from a release task?

What is the easiest way to get key rotation to work for azure storage accounts from a AzureDevOps relase task? The current plan is to re-generate the old key after release to invalidate it, and have a fresh key that can be used on next deployment. But to get that to work it seems like I at least need to store the name of the key to use in a release variable.
I had a look at he logging tasks (https://github.com/Microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md), but that only changes the value in the current release and does not modify the release definition.
You can use the REST API (Definitions - Update) to update the value of the release definition variable from a release task.
Go to the Agent Phase and select Allow Scripts to Access OAuth Token. See Use the OAuth token to access the REST API
Grant Project Collection Build Service (xxx) account the edit
release pipeline permission. (Select the release pipeline --> ... --> Security --> Edit release definition set to Allow)
Add a PowerShell task in your release pipeline
Run inline script: (Update the value of variable v1030 in below sample)
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0-preview.3"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
# Update an existing variable named v1030 to its new value 1035
$pipeline.variables.v1030.value = "1035"
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Varialbe 'v1030' is updated to" $updatedef.variables.v1030.value
write-host "=========================================================="
Here is a much cleaner and better solution that also allows for multiple builds being triggered simultaneously.
https://tsuyoshiushio.medium.com/how-to-pass-variables-with-pipeline-trigger-in-azure-pipeline-5771c5f18f91
Essentially your triggering build produces artifacts that your triggered build reads and turns into variables.
Still not at all great, but better than nothing and better than REST calls setting static global variable groups.
The other answer above talks about how to update Release pipelines.
If you would like to update a Build Pipeline's variables, here is how you do that:
Edit build pipeline
Go to the Agent Phase and select Allow Scripts to Access OAuth Token. See Use the OAuth token to access the REST API
Go to Manage Security -> Users -> Select Project Collection Build Service (YOUR TEAM NAME HERE)
Change "Edit Build Definitions" to Allow
Now add a powershell stage - 2.x - inline script called Update variables.
Script inline contents:
$api_version='5.0-preview.6'
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/definitions/$(System.DefinitionId)?api-version=${api_version}"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
# Update variables as desired here:
$pipeline.variables.mavenBuildVersionPatch.value = "2401"
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Variable mavenBuildVersionPatch is updated to" $updatedef.variables.mavenBuildVersionPatch.value
write-host "=========================================================="
Take note of the API version in this script is 5.0-preview.6.
If your version of Azure Devops is newer, you may need to update this in the future.
Save build pipeline.
Now when you run job, after the job completes this powershell stage, this variable will be set.
Important: If you want to update a variable then make the updated variable for other pipeline stages, then you do it with a powershell stage with the following inline script:
$mavenBuildVersionPatch = [int]"$(mavenBuildVersionPatch)"
$mavenBuildVersionPatch = $mavenBuildVersionPatch + 1
Write-Host "##vso[task.setvariable variable=mavenBuildVersionPatch;]$mavenBuildVersionPatch"
This example would take our existing patch number and increment it by 1.
This does not save the variable at the end of the job, you still need to do that with another powershell script if desired.