IF statement condition within a Azure devops pipeline - azure

EDIT
I have got a pipeline below and would want it to run an inline script based on the time of the day.
The question should have been around pipelines rather than ARM template.
schedules:
- cron: "0 10 * * *"
displayName: Test 1
branches:
include:
- master
always: true
- cron: "0 21 * * *"
displayName: Test 2
branches:
include:
- master
always: true
steps:
- ${{ if eq(schedules.cron, '0 10 ***') }}:
- task: AzureCLI#2
name: RunProcess
displayName: Run test 1
inputs:
azureSubscription: serviceConnection
scriptLocation: 'inlineScript'
scriptType: bash
failOnStandardError: true
inlineScript: |
echo 'starting process 1'
The way I was able to do this can be found below.
steps:
- task: PowerShell#02
name: taskname
displayName: task display name
inputs:
azureSubscription: $(subnamee)
scriptLocation: 'inlineScript'
failOnStandardError: true
targetType: 'inline'
script: |
$h = (Get-Date).hour
if ($h -eq 10)
{
echo 'command 1'
}
if ($h -eq 21)
{
echo 'command 2'
}

I was able to do this by changing the script type to PS.
The way I was able to do this can be found below.
steps:
- task: PowerShell#02
name: taskname
displayName: task display name
inputs:
azureSubscription: $(subnamee)
scriptLocation: 'inlineScript'
failOnStandardError: true
targetType: 'inline'
script: |
$h = (Get-Date).hour
if ($h -eq 10)
{
echo 'command 1'
}
if ($h -eq 21)
{
echo 'command 2'
}

Related

Is there a way to handle a single parameter as a build number OR source branch in an azure pipeline?

I'm trying to allow for a single variable that can specify the build id or branch to deploy from. This means I need to type coerce, and it's failing if I try to call a ge (greater than or equal) or lt (less than) on a string. It looks like I might have to use bash commands to do the type conversion for me, so I was wondering if anyone had this handy.
Here's the steps I'm using:
- ${{ each deployment in parameters.deployments }}:
- deployment: Deploy_${{deployment.serviceName}}_${{ parameters.region }}
pool:
vmImage: ${{ parameters.vmImage }}
displayName: 'Deploy ${{ deployment.serviceName }} ${{ parameters.region }}'
${{ if not(eq(parameters.kubernetesServiceEndpoint, '')) }}:
environment: ${{ parameters.kubernetesServiceEndpoint }}
${{ elseif not(and(eq(parameters.azureResourceGroup, ''), eq(parameters.kubernetesCluster, ''))) }}:
environment: ${{ parameters.environment }}
strategy:
runOnce:
deploy:
steps:
# Disable the automatic downloading of artifacts, because we will specifying exactly what we need
- download: none
- task: DownloadPipelineArtifact#2
condition: ${{ ge(0, deployment.branchBuildId) }}
inputs:
source: 'specific'
project: ${{ deployment.project }}
pipeline: ${{ deployment.pipeline }}
runVersion: 'latestFromBranch'
runBranch: ${{ deployment.branchBuildId }}
patterns: 'DeploymentData/*'
displayName: 'Download Latest Artifacts'
- task: DownloadPipelineArtifact#2
condition: ${{ lt(0, deployment.branchBuildId) }}
inputs:
source: 'specific'
project: ${{ deployment.project }}
pipeline: ${{ deployment.pipeline }}
runVersion: 'specific'
runId: ${{ deployment.branchBuildId }}
#runBranch: ${{ deployment.branch }}
patterns: 'DeploymentData/*'
displayName: 'Download Specific Artifacts (${{ deployment.buildId }})'
I want these to be mutually exclusive (run the first if pulling the latest from a specific branch, and run the second if downloading from a specific build id). By using a single parameter I can avoid another control parameter to decide which version should be used.
Two things:
1, If you use script to handle, then 'compile time usage' is unable to use.
You need to use runtime usage:
variables['xxx']
2, Variables only support passing string, you can compare them and then use logging command to output the result:
trigger:
- none
pool:
vmImage: ubuntu-latest
parameters:
- name: str1
default: 110
- name: str2
default: 130
steps:
- task: PowerShell#2
name: outputresult
inputs:
targetType: 'inline'
script: |
$str1 = "${{parameters.str1}}"
$str2 = "${{parameters.str2}}"
Write-Host $str1
Write-Host $str2
# powershell compare the strings greater than or less than
if ($str1 -gt $str2) {
$result = "greater than"
Write-Host $result
Write-Host "##vso[task.setvariable variable=result;isoutput=true]$result"
} elseif ($str1 -lt $str2) {
$result = "less than"
Write-Host $result
Write-Host "##vso[task.setvariable variable=result;isoutput=true]$result"
} else {
$result = "equal"
Write-Host $result
Write-Host "##vso[task.setvariable variable=result;isoutput=true]$result"
}
#Below is the handling logic
- task: PowerShell#2
condition: eq('greater than',variables['outputresult.result'])
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host "greater than"
- task: PowerShell#2
condition: eq('less than',variables['outputresult.result'])
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host "less than"
Result:

Is there a way to loop over all outputs from stageDependencies in Azure DevOps?

I want to loop over all the outputs of dependent stages and check if any of them are set to a specific value which would indicate there was a problem. Is this possible, and if so, how?
I'm having trouble finding any relevant documentation on stageDependencies outside of using them in job conditions. I know the code below doesn't work, but I've tried a few variations on this and I'm not even seeing the stageDependencies object.
- task: PowerShell#2
displayName: Check for Failures
inputs:
targetType: inline
script: |
foreach ($dependency in $[stageDependencies]) {
foreach ($job in $dependency) {
foreach ($output in $job.outputs) {
if ("$output" -eq "Started") {
write-host "##vso[task.logissue type=error]Task failed in a previous step"
}
}
}
}
The pipeline can output variables through the logging command, but the variables can only be strings:
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#set-variables-in-scripts
All variables set by this method are treated as strings.
It is not difficult to parse a string and put it into an array, just use the function(split()) that comes with the string type to split and restore.
Here is an example:
trigger:
- none
# 1
stages:
- stage: s1
displayName: setvars
jobs:
- job: testJob
steps:
- task: PowerShell#2
name: setvar
inputs:
targetType: 'inline'
script: |
# logic here. For example you get the vars and put it into this format:
$testvars = "testvar1,testvar2,testvar3"
Write-Host "##vso[task.setvariable variable=outputvars;isOutput=true]$testvars"
# 2
- stage: s2
displayName: getvars
dependsOn: s1
variables:
vars: $[ stageDependencies.s1.testJob.outputs['setvar.outputvars'] ]
jobs:
- job:
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
$varsArr = "$(vars)".Split(',')
foreach ($var in $varsArr)
{
Write-Host "$var`r`n"
if($var -eq 'testvar1')
{
Write-Host 'The value is correct.'
}
}
Result:

Publish file content to service bus from CI pipeline

In my CI pipeline I am trying to publish message to service bus and its working when its just some hardcoded text or variables, here Using "PublishToAzureServiceBus" task .
But problem is when trying to a read file from repository and then publish that to service bus.
I have tried using read file using scripting language and put to variable but its not able to work as variable is not storing big json file.
Is there any way to read file directly when publishing message to service bus.
Below is sample code snippet for debugging
trigger:
- none
pool:
vmImage: ubuntu-latest
parameters:
- name: ProjectName
displayName: Project Name
type: string
default: DevOpsDemo
- name: repoName
displayName: repo Name
type: string
default: ProjectCode
- name: branchRef
displayName: Branch Name
type: string
default: main
variables:
- name: jobStatus
value: "Failed"
- name: projectFile
value: ""
stages:
- stage: Stage1
displayName: Stage 1
jobs:
- job: CheckOutRepo
displayName: CheckOut-Repo Display
steps:
- script: |
echo "Checkout for " ${{ parameters.ProjectName}} : ${{ parameters.repoName}} : ${{ parameters.branchRef}}
name: PrintMessage
- checkout: git://${{ parameters.ProjectName}}/${{ parameters.repoName}}#refs/heads/${{ parameters.branchRef}}
name: Checkout
- task: PythonScript#0
inputs:
scriptSource: 'inline'
script: |
import json
import requests
f = open('project-release.json')
projectFile = json.load(f)
print(projectFile)
f.close()
print("Afterclosing")
print(projectFile)
- script: |
echo "Project release file" $(cat project-release.json)
name: TestPrint
- task: CopyFiles#2
inputs:
SourceFolder: 'services'
Contents: '**'
TargetFolder: $(Build.ArtifactStagingDirectory)
name: CopyFiles
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)
ArtifactName: 'drop'
publishLocation: 'Container'
name: PublishArtifacts
- bash: |
echo "##vso[task.setvariable variable=jobStatus]Success"
name: setVar
- bash: |
echo "##vso[task.setvariable variable=jobStatus;isOutput=true]$(jobStatus)"
echo "##vso[task.setvariable variable=projectFile;isOutput=true]$(cat project-release.json)"
name: SetStatus
condition: always()
- stage: Stage2
displayName: Stage 2
condition: always()
jobs:
- job: Publish
pool: server
variables:
jobStatus: $[ stageDependencies.Stage1.CheckOutRepo.outputs['SetStatus.jobStatus'] ]
projectFile: $[ stageDependencies.Stage1.CheckOutRepo.outputs['SetStatus.projectFile'] ]
steps:
- task: PublishToAzureServiceBus#1
inputs:
azureSubscription: 'SBConnection'
messageBody: |
{
"Status": "$(jobStatus)",
"BuildID": "$(build.buildid)",
"BuildNumber":"$(build.buildnumber)",
"projectFile":$(cat project-release.json)
}
signPayload: false
waitForCompletion: false
condition: always()
I am able to solve this by using setvariable in bash script as below
pool:
vmImage: ubuntu-latest
stages:
- stage: Stage1
displayName: Stage 1
jobs:
- job: CheckOutRepo
displayName: CheckOut-Repo Display
steps:
- checkout: git://${{ parameters.ProjectName}}/${{ parameters.repoName}}#refs/heads/${{ parameters.branchRef}}
name: Checkout
- bash: |
data=$(cat project-release.json)
echo "##vso[task.setvariable variable=jobStatus;isOutput=true]$(jobStatus)"
echo "##vso[task.setvariable variable=data;isOutput=true]"$data
name: SetStatus
condition: always()
- stage: Stage2
displayName: Stage 2
condition: always()
jobs:
- job: Publish
pool: server
variables:
jobStatus: $[ stageDependencies.Stage1.CheckOutRepo.outputs['SetStatus.jobStatus'] ]
projectFile: $[ stageDependencies.Stage1.CheckOutRepo.outputs['SetStatus.data'] ]
steps:
- task: PublishToAzureServiceBus#1
inputs:
azureSubscription: 'SBConnection'
messageBody: |
{
"Status": "$(jobStatus)",
"BuildID": "$(build.buildid)",
"BuildNumber":"$(build.buildnumber)",
"projectFile":$(projectFile)
}
signPayload: false
waitForCompletion: false
condition: always()

azurepipelines template task condition not evaluating as expected

When I remove the task condition from the deploy_data_factory_steps.yaml template the parameter displays with the expected value:
parameter is DEV2
But when I run with the condition it fails to evaluate as True:
Evaluating: and(succeeded(), eq('$(env)', 'DEV2'))
Expanded: and(True, eq('$(env)', 'DEV2'))
Result: False
azurepipelines.yaml:
- stage: DataFactoryDEV2
condition: and(succeeded(), eq('${{ parameters.runEnv }}', 'dev2'))
dependsOn: DeployDEV2
variables:
- group: xxx_DEV2
pool:
name: 'yyyDev'
jobs:
- deployment: deploy
environment: xxx-dev2
strategy:
runOnce:
deploy:
steps:
- template: templates/deploy_data_factory_steps.yml
parameters:
environ: $(env)
artifact: 'publish-factory'
azureSubscription: 'yyy - xxx'
deploy_data_factory_steps.yaml
steps:
...
- task: AzureCLI#2
condition: and(succeeded(), eq('${{ parameters.environ }}', 'DEV2'))
displayName: 'Blah blah blah'
inputs:
azureSubscription: ${{ parameters.azureSubscription }}
scriptLocation: inlineScript
scriptType: bash
inlineScript: |
echo parameter is ${{ parameters.environ }}

Microsoft Dev Ops yaml variables between deployments

So at it's core what I'm essentially trying to do is this:
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/deployment-jobs?view=azure-devops&preserve-view=true#support-for-output-variables
Which breaks down to the fact that I have a single deployment template that produces an output variable that I want to map back to a variable in my main template so that I can use it in subsequent deployment templates.
I have created a github project with all of my yaml templates here
https://github.com/MCKRUZ/azure-pipelines
but the crux of the problem lies in these few lines. First I'm calling a template deployment in my main "development.yaml" file.
# Deploy
# ------
- stage: Deploy
displayName: Deploy - Development
jobs:
- template: jobs/jobs-deploy-spa-arm-template.yaml
parameters:
environment: '$(environment)'
serviceConnection: '$(serviceConnection)'
subscriptionId: '$(subscriptionId)'
resourceGroup: '$(resourceGroup)'
storageAccountName: '$(storageAccountName)'
cdnEndpointName: '$(cdnEndpointName)'
cdnProfileName: '$(cdnProfileName)'
deploymentLocation: '$(deploymentLocation)'
armTemplateArtifactName: ${{ variables['armTemplateArtifactName'] }}
storageAccountCSMFilePath: '$(storageAccountCSMFilePath)'
storageAccountCSMParametersFile: '$(storageAccountCSMParametersFile)'
deployCDN: '${{ variables.isProduction }}'
cdnCSMFilePath: '$(cdnCSMFilePath)'
cdnCSMParametersFile: '$(cdnCSMParametersFile)'
That template looks like this:
# Parameters
# ---------
parameters:
- name: environment
type: string
- name: serviceConnection
type: string
- name: subscriptionId
type: string
- name: resourceGroup
type: string
- name: storageAccountName
type: string
- name: cdnEndpointName
type: string
- name: cdnProfileName
type: string
- name: deploymentLocation
type: string
- name: armTemplateArtifactName
type: string
- name: storageAccountCSMFilePath
type: string
- name: storageAccountCSMParametersFile
type: string
- name: deployCDN
type: boolean
default: false
- name: cdnCSMFilePath
type: string
- name: cdnCSMParametersFile
type: string
- name: overrideParameterFile
type: boolean
default: true
# Jobs
# ---------
jobs:
# Job - Deploy SPA ARM Template
# ---------
- #deployment: '${{ parameters.armTemplateArtifactName }}'
deployment: armTemplates
variables:
storageAccountNameCalculated: ''
cdnEndpointNameCalculated: ''
displayName: Deploy SPA ARM Template
environment: ${{ parameters.environment }}
workspace:
clean: all
strategy:
runOnce:
deploy:
steps:
# Bash - Show Input Parameter Variables
# ---------
- bash: |
echo ''
echo '===== Deploy SPA ARM Template Input Variables ====='
echo ''
echo ' ===== Parameters ====='
echo ' environment: ${{ parameters.environment }}'
echo ' serviceConnection: ${{ parameters.serviceConnection }}'
echo ' subscriptionId: ${{ parameters.subscriptionId }}'
echo ' resourceGroup: ${{ parameters.resourceGroup }}'
echo ' storageAccountName: ${{ parameters.storageAccountName }}'
echo ' cdnEndpointName: ${{ parameters.cdnEndpointName }}'
echo ' cdnProfileName: ${{ parameters.cdnProfileName }}'
echo ' deploymentLocation: ${{ parameters.deploymentLocation }}'
echo ' armTemplateArtifactName: ${{ parameters.armTemplateArtifactName }}'
echo ' storageAccountCSMFilePath: ${{ parameters.storageAccountCSMFilePath }}'
echo ' storageAccountCSMParametersFile: ${{ parameters.storageAccountCSMParametersFile }}'
echo ' deployCDN: ${{ parameters.deployCDN }}'
echo ' cdnCSMFilePath: ${{ parameters.cdnCSMFilePath }}'
echo ' cdnCSMParametersFile: ${{ parameters.cdnCSMParametersFile }}'
echo ''
displayName: Debug - Input Parameters
# Task - Deploy Storage Account ARM Template
# ---------
- task: AzureResourceManagerTemplateDeployment#3
displayName: Deploy Storage Account ARM Template
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: '${{ parameters.serviceConnection }}'
subscriptionId: '${{ parameters.subscriptionId }}'
action: 'Create Or Update Resource Group'
resourceGroupName: '${{ parameters.resourceGroup }}'
location: '${{ parameters.deploymentLocation }}'
templateLocation: 'Linked artifact'
csmFile: '$(Pipeline.Workspace)\${{ parameters.armTemplateArtifactName }}\${{ parameters.storageAccountCSMFilePath }}'
csmParametersFile: '$(Pipeline.Workspace)\${{ parameters.armTemplateArtifactName }}\${{ parameters.storageAccountCSMParametersFile }}'
deploymentMode: 'Incremental'
deploymentName: 'storageAccountDeployment'
deploymentOutputs: 'storageAccountDeploymentOutput'
${{ if eq(parameters.overrideParameterFile, 'true') }}:
overrideParameters: '-formatNames true -environment ${{ parameters.environment }} -storageAccountName ${{ parameters.storageAccountName }}'
# Task - Retrieve Output Variable
#----------
- task: AzurePowerShell#5
displayName: Retrieve Output Variables
name: retrieveStorageAccountDeploymentOutput
condition: succeeded()
inputs:
azureSubscription: '${{ parameters.serviceConnection }}'
scriptType: 'inlineScript'
azurePowerShellVersion: 'LatestVersion'
inline: |
$armOutput = '$(storageAccountDeploymentOutput)' | ConvertFrom-Json
Write-Output "##vso[task.setvariable variable=storageAccountNameCalculated;]$($armOutput.storageAccountName.value)"
- script: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the deployment variable value"
name: setvarStep
- script: echo $(setvarStep.myOutputVar)
name: echovar
# Task - Add Static Hosting to Storage Account
# ---------
- task: AzurePowerShell#5
displayName: Add Static Hosting to Storage Account
condition: succeeded()
inputs:
azureSubscription: '${{ parameters.serviceConnection }}'
scriptType: 'inlineScript'
azurePowerShellVersion: latestVersion
inline: |
$StorageAccount = Get-AzStorageAccount -Name $(storageAccountNameCalculated) -ResourceGroupName '${{ parameters.resourceGroup }}'
Enable-AzStorageStaticWebsite -Context $StorageAccount.Context -IndexDocument index.html -ErrorDocument404Path index.html
# Task - Deploy CDN ARM Template
# ---------
- task: AzureResourceManagerTemplateDeployment#3
displayName: Deploy CDN ARM Template
condition: and(succeeded(), eq(${{ parameters.deployCDN }}, 'true'))
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: '${{ parameters.serviceConnection }}'
subscriptionId: '${{ parameters.subscriptionId }}'
action: 'Create Or Update Resource Group'
resourceGroupName: '${{ parameters.resourceGroup }}'
location: '${{ parameters.deploymentLocation }}'
templateLocation: 'Linked artifact'
csmFile: '$(Pipeline.Workspace)\${{ parameters.armTemplateArtifactName }}\${{ parameters.cdnCSMFilePath }}'
csmParametersFile: '$(Pipeline.Workspace)\${{ parameters.armTemplateArtifactName }}\${{ parameters.cdnCSMParametersFile }}'
deploymentMode: 'Incremental'
deploymentName: 'cdnDeployment'
deploymentOutputs: 'CDNDeployOutput'
${{ if eq(parameters.overrideParameterFile, 'true') }}:
overrideParameters: '-formatNames true -environment ${{ parameters.environment }} -cdnEndpointName ${{ parameters.cdnEndpointName }} -cdnProfileName ${{ parameters.cdnProfileName }} -storageAccountPrimaryEndpoint -storageAccountPrimaryEndpoint $storageAccountNameCalculated.z13.web.core.windows.net'
# Task - Retrieve Output Variable
#----------
- task: AzurePowerShell#5
displayName: Retrieve Output Variables
condition: and(succeeded(), eq(${{ parameters.deployCDN }}, 'true'))
inputs:
azureSubscription: '${{ parameters.serviceConnection }}'
scriptType: 'inlineScript'
azurePowerShellVersion: 'LatestVersion'
inline: |
$armOutput = '$(CDNDeployOutput)' | ConvertFrom-Json
Write-Output "##vso[task.setvariable variable=cdnEndpointNameCalculated;isOutput=true]$($armOutput.cdnEndpointName)"
# Bash - Show Output Parameter Variables
# ---------
- bash: |
echo ''
echo '===== Deploy SPA ARM Template Output Variables ====='
echo ''
echo ' ===== Parameters ====='
echo ' storageAccountNameCalculated: $(storageAccountNameCalculated)'
echo ' cdnEndpointName: $(cdnEndpointNameCalculated)'
echo ''
displayName: Debug - Output Parameters
Where I'm using these two lines
- script: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the deployment variable value"
name: setvarStep
- script: echo $(setvarStep.myOutputVar)
name: echovar
To try and isolate a way that I can create a variable that will be able to be used back in my main yaml file. When I look at the logs, the second echo successfully echos out the variable so I know that part works at least. Once this runs, back in my main yaml file I call this.
- job: job_deploy_code
displayName: Deploy Some Code
dependsOn: armTemplates
variables:
myVarFromDeploymentJob: $[ dependencies.armTemplates.outputs['deploy_Development.setvarStep.myOutputVar'] ]
steps:
- script: "echo $(myVarFromDeploymentJob)"
name: echovar
Which is just supposed to echo back what is in my variable. Right now it's blank. I know it's some stupid syntax that I'm not seeing but I can't for the life of me figure out what it is.
I solved this with the correct syntax
- job: job_deploy_code
displayName: Deploy Some Code
dependsOn: armTemplates
variables:
myVarFromDeploymentJob: $[ dependencies.armTemplates.outputs['armTemplates.setvarStep.myOutputVar'] ]

Resources