Set variable on azure task to pass another task of Azure pipeline - azure

I am able to set a variable on powershell or bash script and pass the variable to another task by using ##vso[task.setvariable variable=abc;]xyz. But couldn't find any documentation to set variable on azure tasks like azure webapp deploy task or SqlAzureDacpacDeployment task. I want to catch the error by passing the variable value. Is there any effective way to catch the azure task error log for the next task?
- task: SqlAzureDacpacDeployment#1
displayName: 'Insertion SQL Task'
inputs:
azureSubscription: 'Org (xxxxx-xxxx-xxxx-xxxx-xxxx)'
ServerName: 'tcp:abc.database.windows.net'
DatabaseName: test_db
SqlUsername: '$(user)'
SqlPassword: $(pass)
deployType: SqlTask
SqlFile: 'SQL/test.sql'
enabled: true
- task: AzureWebApp#1
displayName: 'Azure Web App Deploy: $(AppName)'
inputs:
azureSubscription: 'Org (xxxxx-xxxx-xxxx-xxxx-xxxx)'
appType: webApp
ResourceGroupName: 'Test'
appName: '$(AppName)'
package: '$(Build.ArtifactStagingDirectory)\app/*.zip'
deploymentMethod: zipDeploy
enabled: true

You will need to set a name for the task.
For Azure SQL Database Deployment task, you can use the SqlDeploymentOutputFile output variable name.
- task: SqlAzureDacpacDeployment#1
displayName: 'Insertion SQL Task'
name: sqlInsert
inputs:
...
enabled: true
- script: echo "$(sqlInsert.SqlDeploymentOutputFile)"
The Azure Web App task does not provide the same mechanism. You could always call the Pipelines - Get Logs API to get what you need:
pool:
vmImage: ubuntu-latest
steps:
- powershell: Write-Host "Hello World"
name: 'HelloWorld'
- powershell: |
Write-Host "This is a script that could use $env:SYSTEM_ACCESSTOKEN"
# Construct the REST URL to obtain Build ID
$uri = "$(System.CollectionUri)$(System.TeamProject)/_apis/pipelines/$(System.DefinitionId)/runs/$(Build.BuildId)/logs?api-version=6.0-preview.1"
Write-Host "$uri"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "system", $env:SYSTEM_ACCESSTOKEN)))
$logs = Invoke-RestMethod -Uri $uri -Method Get -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)

Related

Azure Devops Pipeline task (Azure CLI#2) failing

I have the below step in the Azure pipeline
- task: AzureCLI#2
displayName: get Logic App SAS Token
name: getLogicAppSASToken1
inputs:
azureSubscription: ${{ parameters.serviceAccount }}
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
$workflowDetails1 = az rest --method post --uri https://management.azure.com/subscriptions/$(SUBSCRIPTION_ID)/resourceGroups/$(RG_LOGIC_APP)/providers/Microsoft.Web/sites/$(LOGIC_APP_NAME)/hostruntime/runtime/webhooks/workflow/api/management/workflows/$(WORKFLOW_NAME1)/triggers/manual/listCallbackUrl?api-version=2018-11-01
$workflowResponse1 = $workflowDetails1 | ConvertFrom-Json
$nameValueBody1 = '{"Name":"Workflow1","value":"' + $workflowResponse1.queries.sig + '"}'
echo $nameValueBody1
$workflowDetails2 = az rest --method post --uri https://management.azure.com/subscriptions/$(SUBSCRIPTION_ID)/resourceGroups/$(RG_LOGIC_APP)/providers/Microsoft.Web/sites/$(LOGIC_APP_NAME)/hostruntime/runtime/webhooks/workflow/api/management/workflows/$(WORKFLOW_NAME2)/triggers/manual/listCallbackUrl?api-version=2018-11-01
$workflowResponse2 = $workflowDetails2 | ConvertFrom-Json
$nameValueBody2 = '{"Name":"Workflow2","value":"' + $workflowResponse2.queries.sig + '"}'
echo $nameValueBody2
Below is what I see in the logs
/usr/bin/az account set --subscription 4xxxxxxxxxxxxxxxxxxxxxxxx0313
/usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command . '/myagent/_work/_temp/azureclitaskscript1674363859719.ps1'
{"Name":"Workflow1","value":"oxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxA"}
ERROR: Bad Request({"Code":"BadRequest","Message":"Encountered an error (ServiceUnavailable) from host runtime.","Target":null,"Details":[{"Message":"Encountered an error (ServiceUnavailable) from host runtime."},{"Code":"BadRequest"},{"ErrorEntity":{"Code":"BadRequest","Message":"Encountered an error (ServiceUnavailable) from host runtime."}}],"Innererror":null})
{"Name":"Workflow2","value":""}
##[error]Script failed with exit code: 1
/usr/bin/az account clear
If you see the logs, the first API call works fine and I get the SAS Token of the Logic App Workflow. However, the second call is failing with an error as seen in the logs below. The thing that stumps me is how come the first call works and the second fails. So I assume it's not because of any configuration as if that's the case, I believe all calls should fail.
Any pointers please? Thank you!
Not sure of the exact reason why it worked. But introducing a delay of 10 seconds between the 2 API calls did the trick! Refer below.
- task: AzureCLI#2
displayName: get Logic App SAS Token
name: getLASASToken1
inputs:
azureSubscription: ${{ parameters.serviceAccount }}
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
$workflowDetails1 = az rest --method post --uri https://management.azure.com/subscriptions/$(SUBSCRIPTION_ID)/resourceGroups/$(RG_LOGIC_APP)/providers/Microsoft.Web/sites/$(LOGIC_APP_NAME)/hostruntime/runtime/webhooks/workflow/api/management/workflows/$(WORKFLOW_NAME)/triggers/manual/listCallbackUrl?api-version=2018-11-01 --debug
$workflowResponse1 = $workflowDetails1 | ConvertFrom-Json
$nameValueBody1 = '{"Name":"Workflow1-SASToken","value":"' + $workflowResponse1.queries.sig + '"}'
echo $nameValueBody1
- task: PowerShell#2
inputs:
displayName: 'Delay'
targetType: 'inline'
script: |
Start-Sleep -Seconds 10
pwsh: true
- task: AzureCLI#2
displayName: get Logic App SAS Token 2
name: getLASASToken2
inputs:
azureSubscription: ${{ parameters.serviceAccount }}
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
$workflowDetails2 = az rest --method post --uri https://management.azure.com/subscriptions/$(SUBSCRIPTION_ID)/resourceGroups/$(RG_LOGIC_APP)/providers/Microsoft.Web/sites/$(LOGIC_APP_NAME)/hostruntime/runtime/webhooks/workflow/api/management/workflows/$(WORKFLOW_NAME)/triggers/manual/listCallbackUrl?api-version=2018-11-01 --debug
$workflowResponse2 = $workflowDetails2 | ConvertFrom-Json
$nameValueBody2 = '{"Name":"Workflow2-SASToken","value":"' + $workflowResponse2.queries.sig + '"}'
echo $nameValueBody2

Azure Devops : Set a variable for future stages and Job not working

I am trying to generate a random string of length 32 characters in Build Stage, then I want to pass the same to the next job/deployment And Also to the next Stage.
I referred to https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-variables-scripts?view=azure-devops&tabs=powershell to pass a variable from one job to another job and stage. But it is not working, Here is my pipeline code YAML file.
trigger: none
pool:
name: agentpool-myproj
stages:
- stage: 'BuildStage'
variables:
- group: myproj-vargrp-common-dp-poc
displayName: 'BuildStage'
jobs:
- deployment: BuildStageSecretProducerjobs # deployment is equal to job
environment: dev
displayName: 'BuildStageSecretProducerjobs'
strategy:
runOnce:
deploy:
steps:
- checkout: none
- download: none
- task: AzurePowerShell#5
name: mastertask
inputs:
azureSubscription: 'con-myproj-dev'
ScriptType: 'InlineScript'
Inline: |
$Random32Key = -join (((48..57)+(65..90)+(97..122)) |Get-Random -Count 32 |%{[char]$_})
Write-Host "##vso[task.setvariable variable=supersecret;isoutput=true;issecret=false]$Random32Key"
FailOnStandardError: true
azurePowerShellVersion: LatestVersion
- deployment: BuildStageSecretConsumerjobs
dependsOn: BuildStageSecretProducerjobs
variables:
thissupersecret: $[ dependencies.BuildStageSecretProducerjobs.outputs['masterjob.supersecret'] ]
environment: dev
displayName: 'BuildStageSecretConsumer'
strategy:
runOnce:
deploy:
steps:
- checkout: none
- download: none
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host $(thissupersecret)
- stage: 'DeployStage'
dependsOn: 'BuildStage'
condition: succeeded('BuildStage')
displayName: 'DeployStage'
jobs:
- deployment: DeployStageSecretconsumerjobs # deployment is equal to job
variables:
thissupersecret: $[stageDependencies.BuildStage.BuildStageSecretProducerjobs.outputs['mastertask.supersecret']]
environment: dev
displayName: 'DeployStageSecretconsumerjobs'
strategy:
runOnce:
deploy:
steps:
- checkout: none
- download: none
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host $(thissupersecret)
$releaseurl = ('{0}{1}/_apis/release/releases/{2}?api-version=5.0' -f $($env:SYSTEM_TEAMFOUNDATIONSERVERURI), $($env:SYSTEM_TEAMPROJECTID), $($env:RELEASE_RELEASEID) )
$Release = Invoke-RestMethod -Uri $releaseurl -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
$variableName = '<HERE_VARIABLE_NAME>'
$release.variables.($variableName).value = "<YOUR VALUE HERE IN STRING OR REFERNCE TO A VARIABLE E.G. $(OTHER_VARIABLE)>"
$json = #($release) | ConvertTo-Json -Depth 99
Invoke-RestMethod -Uri $releaseurl -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }
$Release = Invoke-RestMethod -Uri $releaseurl -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
Above is 100% working for Releases in ADO. Try to dig for URLs referencing Builds and you should be fine. Of course is you opt to Powershell.

Nested loops in azure pipeline yml

I have two parameter list and i want to pass these parameter values in sql task and webapp deploy task on azure pipeline yml.
parameters:
- name: db
type: object
default: [db1, db2, db3.......]
- name: apps
type: object
default: [app1, app2, app3......]
steps:
- ${{ each dblist in parameters.db && each applist in parameters.apps}}:
- task: SqlAzureDacpacDeployment#1
displayName: 'Azure SQL SqlTask ${{ db }}'
inputs:
azureSubscription: '$(Parameters.connectedServiceName)'
ServerName: xxxx.xxxx.windows.net
DatabaseName: ${{ dblist }}
SqlUsername: xxxxx
SqlPassword: xxxxx
deployType: SqlTask
SqlFile: 'Table.sql'
- task: AzureWebApp#1
displayName: 'Azure Web App Deploy ${{ applist }}'
continueOnError: true
inputs:
azureSubscription: '$(Parameters.connectedServiceName)'
appType: webApp
ResourceGroupName: $(group)
appName: ${{ applist }}
package: '$(build.artifactstagingdirectory)/**/*.zip'
When i run this pipeline, i got error and sequence that i want to run might not be right.
How can i run tasks like this loop:
db1
app1
db2
app2
db3
app3...... and so on
How the issue can be solved?
So you have an array of app + db that you would like to deploy in sequence if i understand.
Array are just objects so you should be able to do something like that
parameters:
- name: configurations
type: object
default:
- app: app1
db: db1
- app: app2
db: db2
steps:
- ${{ each configuration in parameters.configurations }}:
- pwsh: Write-Host Hello ${{ configuration.db }}
displayName: Deploy database
- pwsh: Write-Host Hello ${{ configuration.app }}
displayName: Deploy webapp

Return an object variable from a script - Azure YAML pipelines

Consider the following simplified pipeline:
### template.yml ###
parameters:
- name: "tables"
type: object
default: {}
steps:
- ${{ each table in parameters.tables }}:
- task: BackupTask#0
displayName: "Backup ${{ table }}"
### pipeline.yml ###
- template: template.yml
parameters:
tables:
- "table1"
- "table2"
- "table3"
- "table4"
- "table5"
What I would like is that the list of tables are generated with a bash script instead of having to write them by hand. So every time a new table is created it gets automatically backed up by the pipeline.
As a workaround, we can create another pipeline. In this pipeline, we add two powershell tasks. In the first task, we set a variable with tables as the value.
- task: PowerShell#2
inputs:
targetType: 'inline'
script: 'Write-Host "##vso[task.setvariable variable=list]table1,table2,table3"'
In the second task, we use rest api to trigger the pipeline.yml pipeline. In the request body, we use the variable set in the first task as the value of the template parameter.
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
$token = "PAT"
$url="https://dev.azure.com/{org}/{pro}/_apis/pipelines/{pipelineId}/runs?api-version=5.1-preview"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$JSON = #'
{
"templateParameters": {
"tab":"[$(list)]"
},
}
'#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -Body $JSON -ContentType application/json
Below is my test sample:
### pipeline.yml ###
parameters:
- name: tab
type: object
default: {}
pool:
vmImage: 'ubuntu-latest'
steps:
- template: template1.yml
parameters:
tables: ${{ parameters.tab }}
template.yml:
### template1.yml ###
parameters:
- name: "tables"
type: object
default: {}
steps:
- ${{ each table in parameters.tables }}:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: echo "${{ table }}"
Then we run the newly created pipeline to trigger the pipeline.yml pipeline, get the result:

Referencing SQL Username and Password from KeyVault in YAML

Below I have an Azure CI pipeline written in YAML, I already created a KV with 2 secrets (Username and Password) and their respective values (admin and password). Now, I have been trying to refer the secrets in variables into task: SqlAzureDacpacDeployment#1 but it doesnt work.
If I put $Username and $Password in SqlUsername and SqlPassword, I'd get this error Cannot validate argument on parameter 'Username'.
If I put '$(Username)'and '$(Password)' in SqlUsername and SqlPassword, I'd get this error Login failed for user '***'.
What should I put there or how do I refer them properly? Thanks!
trigger:
- master
pool:
vmImage: 'windows-latest'
variables:
$Username: ""
$Password: ""
steps:
- task: AzureKeyVault#1
displayName: 'Get credentials from Key-Vault'
inputs:
azureSubscription: 'Test-SC'
KeyVaultName: 'Test-KV'
SecretsFilter: '*'
RunAsPreJob: false
- task: SqlAzureDacpacDeployment#1
displayName: 'Reg Database DDL Script'
inputs:
SqlUsername: $Username
SqlPassword: $Password
enabled: true
Found the answer, so set RunAsPreJob: true and SqlUsername: '$(Username)' SqlPassword: '$(Password)' make sure you have access policies added and the name of the KV and azureSubscription are both correct

Resources