Integrate CI and CD together Azure Devops - azure

we need your support on enabling continues deployment on our release pipeline .
Environment :
CI or Build Pipeline is on Azure Devops Services
CD or Release pipeline is on Azure Devops Server
We want to Integrate CI and CD together right now after Build release is not kicking automatically.(I have to manually execute the release )
[![enter image description here][1]][1]
[![enter image description here][2]][2]
[![enter image description here][3]][3]
Service connection between azure devops service and azure devops server
[![enter image description here][4]][4]
# Trigger Release pipeline
- task: PowerShell#2
displayName: 'Trigger Release pipeline'
inputs:
targetType: 'inline'
powershell: |
$url = "https://vsrm.dev.azure.com/{OrganizationName}/{ProjectName}/_apis/release/releases?api-version=6.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($env:TOKEN)"))
$JSON = #'
{
"definitionId": 38,
"variables": {
"Version": {
"value": "$(build.buildnumber)"
}
}
}
'#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -ContentType application/json -body $JSON
displayName: 'PowerShell Script'
env:
TOKEN: $(token)```
[1]: https://i.stack.imgur.com/g4J8I.png
[2]: https://i.stack.imgur.com/njsVU.png
[3]: https://i.stack.imgur.com/MIaJJ.png
[4]: https://i.stack.imgur.com/20wk9.png

We want to Integrate CI and CD together right now after Build release is not kicking automatically.
Since the azure devops service is on the cloud side and the azure devops server is local, there is no out-of-the-box feature that can Integrate CI/CD.
But you could use PowerShell task to run the Rest API in Azure Devops Service to trigger the Release on Azure Devops Server . Releases - Create
Here is an example:
You can add the Powershell Task to the end of the build, then you could add the following script in the powershell task:
$token = "PAT"
$url = "https://{instance}/{collection}/{project}/_apis/release/releases?api-version=5.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$JSON = #'
{
"definitionId": DefinitionID(e.g. 15),
"description": "Creating Sample release",
"artifacts": [],
"isDraft": false,
"reason": "none",
"manualEnvironments": null
}
'#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -ContentType application/json -body $JSON
If your CI/Build pipeline is running on self-hosted agent, you can directly add the powershell task at the same agent job.
If your build pipeline is running on Microsoft-hosted agent, you need to create a self-hosted agent and add additional agent job to run powershell script.
In this case, you also need to set the Dependencies.
Note: When running the rest api to trigger the azure devops server release, you need to ensure that they are in the same network range. So it needs self-hosted agent.
Update:
To define a stage, you could refer to the following doc and sample:
stages:
- stage: A
jobs:
- job: A1
pool:
name: Default
steps:
- script: echo
- stage: B
pool:
name: Default
jobs:
- job: B1
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
$token = "PAT"
$url = "https://{instance}/{collection}/{project}/_apis/release/releases?api-version=5.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$JSON = #'
{
"definitionId": ID,
"variables": {
"Version": {
"value": "$(Build.buildnumber)"
}
}
}
'#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -ContentType application/json -body $JSON
Update2:
In order to achieve a function similar to the system.accesstoken variable, you can try the following settings.
Step1: Create a variable in Azure Devops Service Build Pipeline and set it as variable:
Step2: PowerShell Task script:
- powershell: |
$url = "https://{instance}/{collection}/{project}/_apis/release/releases?api-version=5.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($env:TOKEN)"))
$JSON = #'
{
"definitionId": 38,
"variables": {
"Version": {
"value": "$(build.buildnumber)"
}
}
}
'#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -ContentType application/json -body $JSON
displayName: 'PowerShell Script'
env:
TOKEN: $(token)

Related

Creating bulk items with AzureBoard RESTAPI

I am creating an integration with my application using python to Azure Board. I have completed the APIs till creating a single issue. Is it possible to create multiple pr bulk issues ? I do not find any link in the documentation or in in general information.
Is there a RestAPI to create bulk issues in Azure board like we have for jira?
Please see whether the following steps could do some help.
I run the rest api https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/create?view=azure-devops-rest-6.0 in Azure devops services-pipeline. This is the code:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
$connectionToken="$(PAT)" #please add the PAT as variable in your pipeline
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$url= 'https://dev.azure.com/{org name}/{project name}/_apis/wit/workitems/$workitemtype?api-version=6.0'
for($i=1; $i -le 100 ; $i++) {
Write-Host $i
$body=#"
[
{
"op": "add",
"path": "/fields/System.Title",
"value": "TestCreateWI"
}
]
"#
Write-Host "$url"
$response= Invoke-RestMethod -Uri $url -ContentType "application/json-patch+json" -Body $body -headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST
}
And after it finishes, you will see these work items in your boards:

How to get build name on Azure?

My goal is to get the build name from Azure YAML pipeline code.
For example, here it is #20220803.9 JBS-2413 Do not approve yet, this is an experiment of automating the tra...
I looked here but no luck
https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml
I tried Build.DefinitionName it returns PR
I tried Build.BuildNumber it returns 20220803.9 only
I tried Build.SourceVersionMessage it returns Merge
No built-in predefined variables or other things to get the "build name" you want. If you intercept the network traffic analysis, you will also find that the "build name" you want is not a whole, it is a combination of two data.
You need to design your own code to get it. For example, if you are based on Azure Git Repo, below pipeline YAML can help you get the "build name" you want when creating a pull request to trigger the pipeline:
trigger:
- none
# 1
stages:
- stage: s1
displayName: Get the lastest comment
jobs:
- job: testJob
steps:
- task: PowerShell#2
name: setvar
inputs:
targetType: 'inline'
script: |
$PAT = "<Your Personal Access Token>"
$org_name = "<Organization Name>"
$project_name = "<Project Name>"
$branch_name = "<Current Branch Name>"
$def_id = "<Pipeline definition ID>"
$run_id = "$(Build.BuildId)"
Write-Host $run_id
if("$(Build.Reason)" -eq "PullRequest") {
$headers_run = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers_run.Add("Authorization", "Basic "+$PAT)
$run_url = "https://dev.azure.com/"+$org_name+"/"+$project_name+"/_apis/pipelines/"+$def_id+"/runs/"+$run_id+"?api-version=6.0-preview.1"
$response_run = Invoke-RestMethod $run_url -Method 'GET' -Headers $headers_run
$response_run | ConvertTo-Json
$pull_request_id = $response_run.variables."system.pullRequest.pullRequestId".value
$headers_pr = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers_pr.Add("Authorization", "Basic "+$PAT)
$pr_url = "https://dev.azure.com/"+$org_name+"/"+$project_name+"/_apis/git/repositories/ShowBuildName/pullrequests/"+$pull_request_id+"?api-version=6.0"
$response_pr = Invoke-RestMethod $pr_url -Method 'GET' -Headers $headers_pr
$response_pr | ConvertTo-Json
Write-Host $response_pr.title
$str = $response_pr.title
Write-Host "##vso[task.setvariable variable=outputvars;isOutput=true]$str"
}
else {
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Basic "+$PAT)
$url = "https://dev.azure.com/"+$org_name+"/"+$project_name+"/_apis/git/repositories/ShowBuildName/commits?searchCriteria.itemVersion.version="+$branch_name+"&api-version=6.0"
$response = Invoke-RestMethod $url -Method 'GET' -Headers $headers
$response | ConvertTo-Json
$str = $response.value[0].comment
Write-Host "##vso[task.setvariable variable=outputvars;isOutput=true]$str"
}
# 2
- stage: s2
displayName: Get the "build name"
dependsOn: s1
variables:
vars: $[ stageDependencies.s1.testJob.outputs['setvar.outputvars'] ]
jobs:
- job:
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
Write-Host "$(Build.BuildNumber) $(vars)"
Pipeline run:
Successfully get the "build name":

azure devops - use rest api to pass multi dimensional parameters

I have successfully been able to run the below. I would like to alter this to work with passed in params. I don't mind how I get the params in. I just want to be able to programatically pass them in.My question is what is the syntax to pass via the rest api or the gui. See my attempt script at the bottom.
pipeline
jobs:
- template: patch-template.yml
parameters:
liststuff:
- HostName: A
Prop: XXXX
- HostName: B
Prop: YYYY
being used in a template as
parameters:
- name: liststuff
type: object
default: []
jobs:
- '${{ each item in parameters.liststuff }}':
- template: patch-tasks.yml
parameters:
prop: '${{ item.Prop }}'
hostname: '${{ item.hostname }}'
and steps implemented
jobs:
- job:
displayName: 'Job_${{ parameters.prop }}'
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
Write-Host "prop '${{ parameters.prop }}'"
Write-Host "host '${{ parameters.hostname }}'"
Issue bit: changed pipeline to work with passed in params.
I don't mind how I get the params in. I just want to be able to programatically pass them in.
parameters:
- name: InstanceArgs
type: object
default: []
jobs:
- template: patch-template.yml
parameters:
liststuff: '${{ parameters.InstanceArgs }}'
and utilising api with powershell
$url="https://dev.azure.com/{comp}/{project}/_apis/pipelines/{id}/runs?api-version=5.1-preview"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$JSON = #'
{
"templateParameters": {
"listsuff": [{
"hostname": "D",
"prop": "ZZZZ"
}]
}
}
'#
Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -Body $JSON -ContentType application/json
When you using rest api to override the parameters of the yaml pipeline. The parameter's value in the request body templateParameters should be json string, which means you should convert the array object into json string in the request body.
You can define the templateParameters in request body in below format:
...
$JSON = #'
{
"templateParameters":{
"InstanceArgs":"[{\"prop\":\"aaa\",\"hostname\":\"bbb\"}]"
}
}
'#
Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -Body $JSON -ContentType application/json
Or like below:
$JSON = #{
templateParameters= #{
InstanceArgs='[{"prop":"yyyy","hostname":"xxx"}]'
}
}
Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -Body (convertto-json $JSON) -ContentType application/json

Trigger Azure DevOps pipeline from another pipeline

I was looking at the azure triggers documentation and still not able to find an appropriate solution.
How during the execution of pipeline 1 can you trigger pipeline 2, wait for it to successfully finish or fail, and based on pipeline 2 results either continue execution of pipeline 1 or fail?
How during the execution of pipeline 1 can you trigger pipeline 2, wait for it to successfully finish or fail, and based on pipeline 2 results either continue execution of pipeline 1 or fail?
Trigger one pipeline after another, it will run your pipeline upon the successful completion of the triggering pipeline. We cannot use it to trigger pipeline 1 in the execution of pipeline 1.
As a workaround:
a. We can add task power shell and add script to call the REST API to queue the build.
$connectionToken="PAT"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$PipelineUrl = "https://dev.azure.com/{Org name}/{project name}/_apis/pipelines/{Pipeline ID}/runs?api-version=6.0-preview.1"
$body ="{
`"resources`":{
`"repositories`":{
`"self`":{`"refName`":`"refs/heads/master`"
}
}
}
}"
$Pipelines = Invoke-RestMethod -Uri $PipelineUrl -ContentType "application/json" -Body $body -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST
b. Add task power shell and enter the code Start-Sleep -Seconds 1000 to sleep the pipeline 1
c. Add the task power shell in the pipeline 1 to get the pipeline 2 build result via the REST API, and set the result as env variable.
d. Configure the condition in the next task to check the env variable value. If the value is succeeded, continue run the pipeline 1
You are probably looking for something like this.
# this is being defined in app-ci pipeline
resources:
pipelines:
- pipeline: securitylib # Name of the pipeline resource
source: security-lib-ci # Name of the pipeline referenced by the pipeline resource
trigger:
branches:
- releases/*
- master
its right there in the link, you have linked, but in the sibling section of the docs. I am surprised you missed it.
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/pipeline-triggers?view=azure-devops&tabs=yaml
So here is my solution based on the suggestion above:
- task: PowerShell#2
displayName: Running second pipeline
inputs:
targetType: 'inline'
script: |
Write-Host "Triggering pipeline..."
$connectionToken= "$(PAT)"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$PipelineUrl = "https://dev.azure.com/YourOrganization/yourProject/_apis/pipelines/${{ parameters.pipelineId }}/runs?api-version=6.0-preview.1"
Write-Host "Pipeline url: $PipelineUrl"
$body ="{
`"resources`":{
`"repositories`":{
`"self`":{`"refName`":`"refs/heads/${{ parameters.branch }}`"
}
}
}
}"
$response = Invoke-RestMethod -Uri $PipelineUrl -ContentType "application/json" -Body $body -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST
Write-Host "Response: $response"
$BuildUrl = "https://dev.azure.com/YourOrganization/yourProject/_apis/build/builds/$($response.Id)?api-version=6.1-preview.6"
Write-Host $BuildUrl
$TimeoutAfter = New-TimeSpan -Minutes 15
$WaitBetweenPolling = New-TimeSpan -Seconds 10
$Timeout = (Get-Date).Add($TimeoutAfter)
do
{
$Response = Invoke-RestMethod -Uri $BuildUrl -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
Write-Host $Response.status
Start-Sleep -Seconds $WaitBetweenPolling.Seconds
}
while ((($Response.status -eq "notStarted") -or ($Response.status -eq "inProgress")) -and ((Get-Date) -lt $Timeout))
if ($Response.result -ne "succeeded")
{
Write-Host $Response.result
exit 1
}
parameter for pipeline id: pipelineId: $(resources.pipeline.resource.pipelineId)
If you're ok with using extensions, the Trigger Build Task you can get in the marketplace should support all of your requirements.
It lets you trigger another pipeline, with an option to wait for it, and options about how to treat failures of that pipeline if you do wait. So you can use that to trigger a build, wait for it, and succeed / fail based on if the build succeeds / fails.

How to promote the package with UniversalPackages#0 task in AzureDevops

Is there an option to promote universal package view with azure devops yaml task?
There is no option to promote universal package view in UniversalPackages #0 task. As a workaround, besides using extension, you can also promote universal package view through script in powershell task.
$token = "Enter your Pat here"
$url = "https://pkgs.dev.azure.com/OrgName/ProjectName/_apis/packaging/feeds/FeedID/upack/packagesbatch?api-version=5.1-preview.1"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$JSON = #'
{
"data": {
"viewId": "Release"
},
"operation": 0,
"packages": [{
"id": "YourPackageName",
"version": "PackageVersion",
"protocolType": "upack"
}]
}
'#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -ContentType application/json -body $JSON
Enter your own PAT in $token, and replace the OrgName, ProjectName, FeedID, YourPackageName, PackageVersion with your own ones, you can set PreRelease/Release in viewID to promote universal packages in Azure DevOps feed view from #local to #pre-release to #release.
Test result:
Check out this extension:
https://marketplace.visualstudio.com/items?itemName=rvo.vsts-promotepackage-task
It allows you to promote packages in a feed.

Resources