I have four projects. One is a common project for other three projects.
Other three project build pipeline are depend on common build pipeline. When common build pipeline is in progress, other three build pipeline should be wait until common build complete. How to achive this in on premise azure devops?
How to achive this in on premise azure devops?
You could add a PowerShell task at the beginning of the other three pipelines.
Here is Powershell script sample:
$token = "PAT"
$url="https://{instance}/{collection}/{project}/_apis/build/definitions/{definitionId}?includeLatestBuilds=true&api-version=5.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
$buildid = $response.latestBuild.id
$success = $false
do{
try{
$Buildurl2 = "https://{instance}/{collection}/{project}/_apis/build/builds/$($buildid)?api-version=5.0"
$Buildinfo2 = Invoke-RestMethod -Method Get -ContentType application/json -Uri $Buildurl2 -Headers #{Authorization=("Basic {0}" -f $token)}
$BuildStatus= $Buildinfo2.status
$result = $Buildinfo2.result
echo $result
echo $BuildStatus
if($BuildStatus -eq "completed") {
write-output "No Running Pipeline, starting Next Pipeline"
$success = $true
} else {
Write-output "Pipeline Build In Progress, Waiting for it to finish!"
Write-output "Next attempt in 30 seconds"
Start-sleep -Seconds 30
}
}
catch{
Write-output "catch - Next attempt in 30 seconds"
write-output "1"
Start-sleep -Seconds 30
# Put the start-sleep in the catch statemtnt so we
# don't sleep if the condition is true and waste time
}
$count++
}until($count -eq 2000 -or $success -eq $true )
if ($result -ne "succeeded")
{
echo "##vso[task.logissue type=error]Something went very wrong."
}
if(-not($success)){exit}
Explanation:
This powershell script runs the following two Rest APIs:
Definitions - Get
Builds - Get
The script checks the status of the pipeline(by polling) that is in process. If the pipeline is completed and the result is successful, it will run the other three pipelines. Or it will wait for the pipeline finishing the build.
Result Sample:
Related
Hi There I have been asked to modify all current CI yml pipelines to fail if the C# API or WEB app has any warning, also it needs to be in its own stage in the process.
I have been looking on the net and can't find any code please can someone help with the code needed
thanks
There are two options for your reference.
1.You could add a PowerShell task in the stage, and then run the Rest API: Timeline - Get to traverse the warning messages in the previous task. And use logging commands to control the results.
PowerShell script:
$token = "PAT"
$url="https://dev.azure.com/{OrgName}/{ProjName}/_apis/build/builds/$(build.buildid)/timeline?api-version=5.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$count = 0
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach( $issues in $response.records.issues )
{
if($issues.type -eq "warning")
{
echo $issues.Message
$count ++
}
}
echo $count
if($count -ne 0 )
{
Write-Host "##vso[task.complete result=Failed;]"
}
Pipeline Output:
2.Using Extension task: Build Quality Checks is another option.
Add this task to your target stage to check the warnings.
How can I check if I have any test cases failing within my test plan when executing my pipeline in azure devops?
How can I check if I have any test cases failing within my test plan when executing my pipeline in azure devops?
In Test Plan, the test case has no outcome state(e.g. fail pass ..). The outcome state is for Test points in Test Plan -> Execute tab.
To check if there are failed test points in Test Plan, you could use PowerShell Task to run the Rest API: Test Point - Get Points and Test Suites - Get Test Suites For Plan.
$token = "PAT"
$url1 = " https://dev.azure.com/{OrganizationName}/{ProjectName}/_apis/test/Plans/{TestPlanId}/suites?api-version=5.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response1 = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
$i = 0
ForEach ($SuitId in $response1.value.id )
{
$url="https://dev.azure.com/{OrganizationName}/{ProjectName}/_apis/testplan/Plans/{TestPlanName}/Suites/$($SuitId)/TestPoint?api-version=6.0-preview.2"
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach( $outcome in $response.value.results.outcome )
{
echo $outcome
if($outcome -eq "failed")
{
$i ++
}
}
}
echo $i
if ($i -eq 0)
{
echo "No error"
}
else
{
echo "##vso[task.logissue type=warning]the error value is $i"
}
Result:
I am trying to run a pipeline based on build completion trigger. There are 4 build completion triggers enabled. Hence, the pipeline runs 4 times.
I have enabled "Batch changes while a build is in progress".
How do I make it run a single time once all build completion is complete?
Batch changes while a build is in progress only for CI builds. You can not apply it to build completion triggers. However, you can use PowerShell to run another pipeline: How to trigger a build from another build pipeline in azure devops
Just check active pipelines to skip many triggers. Here is example:
$user = ""
$token = $env:SYSTEM_ACCESSTOKEN
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$orgUrl = "$env:SYSTEM_COLLECTIONURI"
$teamProject = "$env:SYSTEM_TEAMPROJECT"
$currentBuildDefId = "$env:SYSTEM_DEFINITIONID"
$buildBodyTemplate = "{`"definition`": {`"id`": <build_id>}}"
$restApiQueueBuild = "$orgUrl/$teamProject/_apis/build/builds?api-version=6.0"
$restApiGetBuilds = "$orgUrl/$teamProject/_apis/build/builds?definitions=$currentBuildDefId&statusFilter=inProgress,notStarted&api-version=6.0"
function InvokeGetRequest ($GetUrl)
{
return Invoke-RestMethod -Uri $GetUrl -Method Get -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
}
function InvokePostRequest ($PostUrl, $body)
{
return Invoke-RestMethod -Uri $PostUrl -Method Post -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $body
}
function RunBuild($buildId)
{
$buildBody = $buildBodyTemplate.Replace("<build_id>", $buildId)
Write-Host $buildBody
$buildresponse = InvokePostRequest $restApiQueueBuild $buildBody
Write-Host $buildresponse
}
$resBuild = InvokeGetRequest $restApiGetBuilds
if ($resBuild.count -gt 1)
{
Write-Host $resBuild.count " builds in progress, skip the second build"
return
}
RunBuild SECOND_BUILD_DEF_ID
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.
When switching slots withing azure on my application, i am trying to stop the webjobs on the "stopped" server as they seem to keep running within azure. However when i use the invoke-restmethod within my powershell script, it comes back with Error 403 - This web app is stopped, but on my azure site it is still running. Frustratingly i can use the method when using postman, but when it comes to my script with the identical request it is not stopping the webjobs.
I have tried running this particular script within powershell, but it wont run due to the stated error. The Get method works fine in powershell, bringing back the application, but the stop rest call does not.
function StopWebJob($slotToStop) {
# Get an access token to authenticate the web jobs API
Write-Verbose -Verbose "Getting an access token..."
$stopToken = Get-BasicAuthToken $slotToStop
Write-Verbose -Verbose "Got access token."
#Generate a header to start/stop the web jobs using the access token
$stopHeader = #{ 'Authorization'= $stopToken }
Write-Verbose -Verbose "Checking job status..."
$getJob = "https://$WebAppName-$slotToStop.scm.azurewebsites.net/api/continuouswebjobs/{myWebJob}/"
$getJobResult = Invoke-RestMethod -Uri $getJob -Headers $stopHeader -Method Get
If($getJobResult.status -ne "Stopped") {
Write-Verbose -Verbose "Stopping job..."
$stop = "https://$WebAppName-$slotToStop.scm.azurewebsites.net/api/continuouswebjobs/{MyWebJob}/stop"
Invoke-RestMethod -Uri $stop -Headers $stopHeader -Method Post
Write-Verbose -Verbose "Job stopped."
} else {
Write-Verbose -Verbose "Job is already stopped."
}
}
When the slot switches, I expect the Job on the "down" slot to be stopped via the rest api.
I can reproduce your issue, looks you missed the -UserAgent in the Invoke-RestMethod.
It should be like below, add the -UserAgent "powershell/1.0" to your command.
Invoke-RestMethod -Uri $stop -Headers $stopHeader -Method Post -UserAgent "powershell/1.0"
Then it will work fine, you could refer to my complete sample.
$username = "`$website"
$password = "pwd"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))
Write-Verbose -Verbose "Checking job status..."
$getJob = "https://<webappname>-slot1.scm.azurewebsites.net/api/continuouswebjobs/webjob1"
$getJobResult = Invoke-RestMethod -Uri $getJob -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method Get
If($getJobResult.status -ne "Stopped") {
Write-Verbose -Verbose "Stopping job..."
$stop = "https://<webappname>-slot1.scm.azurewebsites.net/api/continuouswebjobs/webjob1/stop"
Invoke-RestMethod -Uri $stop -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method Post -UserAgent "powershell/1.0"
Write-Verbose -Verbose "Job stopped."
} else {
Write-Verbose -Verbose "Job is already stopped."
}