azure devops yaml 'if' not evaluating as expected - azure-pipelines-yaml

Oh man, I'm having a really time with the yaml learning curve. Something that seems so simple, I just can't get to work.
I have this nested parameter group (not sure if that's the correct term) -
build: {
configuration: '',
nugetSource: '',
dotnetVersion: '',
projectsToPublish: '',
releaseCandidate: 'False',
tag: ''
}
I'm trying to then use an 'if' to set a variable for pool, dependent on the parameters.build.dotnetVersion passed in.
- job: build
displayName: Build & test
variables:
- ${{ if eq(parameters.build.dotnetVersion,6.0.200) }}:
- name: buildpool
value: build-dotnet6
- ${{ if ne(parameters.build.dotnetVersion,6.0.200) }}:
- name: buildpool
value: build-default
pool: $(buildpool)
So even though I have confirmed with an echo command that the value of parameters.build.dotnetVersion is 6.0.200, buildpool is always getting set to build-default.
I also tried wrapping 6.0.200 in single quotes, but didn't work as expected.

Related

GitHub Actions: Use variables in matrix definition?

I have the following code in a GitHub Action config:
name: Build & Tests
on:
pull_request:
env:
CARGO_TERM_COLOR: always
ZEROCOPY_MSRV: 1.61.0
ZEROCOPY_CURRENT_STABLE: 1.64.0
ZEROCOPY_CURRENT_NIGHTLY: nightly-2022-09-26
jobs:
build_test:
runs-on: ubuntu-latest
strategy:
matrix:
# See `INTERNAL.md` for an explanation of these pinned toolchain
# versions.
channel: [ ${{ env.ZEROCOPY_MSRV }}, ${{ env.ZEROCOPY_CURRENT_STABLE }}, ${{ env.ZEROCOPY_CURRENT_NIGHTLY }} ]
target: [ "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "arm-unknown-linux-gnueabi", "aarch64-unknown-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc64-unknown-linux-gnu", "wasm32-wasi" ]
features: [ "" , "alloc,simd", "alloc,simd,simd-nightly" ]
exclude:
# Exclude any combination which uses a non-nightly toolchain but
# enables nightly features.
- channel: ${{ env.ZEROCOPY_MSRV }}
features: "alloc,simd,simd-nightly"
- channel: ${{ env.ZEROCOPY_CURRENT_STABLE }}
features: "alloc,simd,simd-nightly"
I'm getting the following parsing error on this file:
Invalid workflow file: .github/workflows/ci.yml#L19
You have an error in your yaml syntax on line 19
It appears to be referring to this line (it's actually one off, but maybe it's zero-indexing its line numbers?):
channel: [ ${{ env.ZEROCOPY_MSRV }}, ${{ env.ZEROCOPY_CURRENT_STABLE }}, ${{ env.ZEROCOPY_CURRENT_NIGHTLY }} ]
Is there any way to use variables in the matrix definition like this? Or do I just need to hard-code everything?
According to the documentation (reference 1 and reference 2)
Environment variables (at the workflow level) are available to the steps of all jobs in the workflow.
In your example, the environment variables are used at the job level (inside the job strategy / matrix definition), not inside the job steps.
At that level, environment variables aren't interpolated by the GitHub interpreter.
First alternative
Hardcode the values inside the channel field inside your matrix strategy:
Example:
channel: [ "1.61.0", "1.64.0", "nightly-2022-09-26" ]
However, you'll have to do this for each job (bad for maintenance as duplicated code).
Second alternative
Use inputs (with reusable workflow workflow_call trigger, or with workflow_dispatch trigger.
Example:
on:
workflow_dispatch: # or workflow_call
inputs:
test1:
description: "Test1"
required: false
default: "test1"
test2:
description: "Test2"
required: false
default: "test2"
test3:
description: "Test3"
required: false
default: "test3"
jobs:
build_test:
runs-on: ubuntu-latest
strategy:
matrix:
channel: [ "${{ inputs.test1 }}", "${{ inputs.test2 }}", "${{ inputs.test3 }}" ]
In that case, inputs will be interpolated by the GitHub interpreter.
However, you'll need to trigger the workflow from another workflow, or through the GitHub API to send the inputs (in some way, it gives you more flexibility with the values, but increase the complexity).

Passing variable between jobs in Azure Pipeline with empty result

I am writing an azure pipeline yml requesting to pass variables between jobs but the variables are not passing through. however, it wasn't successful and it returns an empty variable.
here is my pipeline:
jobs:
- job: UpdateVersion
variables:
terraformRepo: ${{ parameters.terraformRepo }}
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
persistCredentials: true
- checkout: ${{ parameters.terraformRepo }}
- task: AzureCLI#2
displayName: PerformVerUpdate
inputs:
azureSubscription: ${{ parameters.azureSubscriptionName }}
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
echo Step 3 result
echo "Reponame $Reponame"
echo "notify $notify"
echo "pullRequestId $pullRequestId"
echo "##vso[task.setvariable variable=pullRequestId;isOutput=true;]$pullRequestId"
echo "##vso[task.setvariable variable=Reponame;isOutput=true;]$Reponame"
echo "##vso[task.setvariable variable=notify;isOutput=true;]true"
Name: PerformVerUpdate
- job: SlackSuccessNotification
dependsOn: UpdateVersion
condition: and(succeeded(), eq(dependencies.UpdateVersion.outputs['PerformVerUpdate.notify'], 'true'))
pool:
vmImage: 'ubuntu-latest'
variables:
- group: platform-alerts-webhooks
- name: notify_J1
value: $[ dependencies.UpdateVersion.outputs['PerformVerUpdate.notify'] ]
- name: pullRequestId_J1
value: $[ dependencies.UpdateVersion.outputs['PerformVerUpdate.pullRequestId'] ]
- name: Reponame_J1
value: $[ dependencies.UpdateVersion.outputs['PerformVerUpdate.Reponame'] ]
steps:
- task: AzurePowerShell#5
displayName: Slack Notification
inputs:
pwsh: true
azureSubscription: ${{ parameters.azureSubscriptionName }}
ScriptType: 'InlineScript'
TargetAzurePs: LatestVersion
inline: |
write-host "Reponame $(Reponame_J1)"
write-host "pullRequest $(pullRequestId_J1)"
I've tried so many different syntax for it but the variables are still not able to pass through between both jobs - e.g. The condition is passing Null result to second job "(Expanded: and(True, eq(Null, 'true'))". Could anyone help with this?
Firstly 'Name' should be 'name' in lowercase
Name: PerformVerUpdate
The rest of syntax seems fine(I have tested it on Bash task because I do not have Azure subscription).
If renaming 'Name' does not help I suppose the problem may be that your Bash task is running within AzureCLI#2 task.
Maybe as workaround you could add new Bash task right after AzureCLI#2 and try to set there output variable for next job?

Ansible replace a string in a variable with a variable

debug:
msg: "{{backup_facts | replace(',world',',{{custom}}')}}"
register: replace_csv
in the above code, I am trying to replace a string/word in a variable with a variable.
so in this case these are the vars:
backup_facts = "hello,world"
custom = "prab"
so the end results I would like is: "hello, prab" after the replace. But everytime I run the playbook, I get the following:
"replace_csv": {
"changed": false,
"failed": false,
"msg": "hello,{{custom}}"
}
I have attempted different variation such as putting a quotation around the curly brackets or not putting the curly brackets at all but no results.
Q: "The result is: hello,prab after the replace."
Keep it simple. Put the parameters into variables. This will simplify the code. For example,
- hosts: localhost
vars:
backup_facts: "hello,world"
custom: "prab"
tasks:
- debug:
msg: "{{ backup_facts|replace(old, new) }}"
vars:
old: ",world"
new: ",{{ custom }}"
gives (abridged)
ok: [localhost] =>
msg: hello,prab

How to pass variable as parameter, object type, to Azure DevOps template

To reduce duplicates I want to rewrite our Azure DevOps pipelines. The main pipelines looks like:
parameters:
- name: MODULE_Foo
type: boolean
default: false
- name: MODULE_Bar
type: boolean
default: false
...
- name: MODULE_X
type: boolean
default: false
...rest of parameters
- name: BRANCH_NAME
type: string
- name: CHECKOUT_TAG
type: boolean
default: false
extends:
template: template1.yml
parameters:
MODULES: ${{paramaters}}
BRANCH_NAME: ${{parameters.BRANCH_NAME}}
...rest of parameters
The template template1.yml:
parameters:
- name: MODULES
type: object
default: {}
...rest of parameters
stages:
- stage: Build
jobs:
- job: BuildAndDeploy
steps:
- bash: |
MODULES=$(echo "${{ convertToJson(parameters.MODULES) }}" \
| sed -E 's/^([[:space:]]+)/\1"/;s/(:[[:space:]]+)/"\1"/;s/,$/",/;s/([^{},])$/\1"/' \
| jq 'with_entries( select(.key | startswith("MODULE_") ) )' \
)
echo "##vso[task.setvariable variable=MODULES;]$MODULES"
- template: template2.yml
parameters:
MODULES: $(MODULES)
...rest of parameters
And finally template2.yml:
parameters:
- name: MODULES
type: object
default: {}
...rest of parameters
- ${{ each module in parameters.MODULES }}:
- ${{ if and(startsWith(module.Key, 'module'), eq(module.Value, true)) }}:
- bash: |
echo "Module to build: ${{module.key}}, Value: ${{module.value}}"
Now I'm stuck.
How to pass a variable as parameter to a template?
To the template is passed empty string '' for ${{variables.MODULES}} or '$(MODULES)' for $(MODULES). But never generated string. I think that $(MODULES) is valid for this situation.
How to create a valid object, which can be iterated inside each loop in template?
I think that my construction with convertToJson, sed, and jq is not correct.
My goal is to eliminate the MODULE_ parameter group from the templates. Currently, every template contains a duplicate of this parameter section.

Condition (if, else, else if) in YAML

I use hautelook/AliceBundle to create faker data in YAML, but I would for more consistency of data.
I would like that:
gender: <randomElement(['Homme', 'Femme'])>
if $gender == 'Homme'
title: 'Monsieur'
else if $gender == 'Femme'
title: 'Madame'
I know it's not directly possible in YAML, but I do not know which plugin to use... And how to.
My tools/languages used in my project (Symfony, hautelook/AliceBundle, PHP, YAML)
You cannot do that. YAML is data serialization language, not a programming language.
- task: TerraformTaskV1#0
${{ if eq(parameters.destroy, false) }}:
displayName: Terraform Apply
${{ if eq(parameters.destroy, true) }}:
displayName: Terraform Destroy
inputs:
provider: 'azurerm'
${{ if eq(parameters.destroy, false) }}:
command: 'apply'
${{ if eq(parameters.destroy, true) }}:
command: 'destroy'
workingDirectory: "$(System.ArtifactsDirectory)/${{ parameters.environment_name }}${{ parameters.root_directory }}"
${{ if eq(parameters.destroy, false) }}:
commandOptions: "$(System.ArtifactsDirectory)/${{ parameters.environment_name }}${{ parameters.root_directory }}/plan.tfplan"
${{ if eq(parameters.destroy, true) }}:
commandOptions: "--var-file=$(System.ArtifactsDirectory)/${{ parameters.environment_name }}${{ parameters.tfvarFile }}"
environmentServiceNameAzureRM: ${{ parameters.service_connection_name }}
yaml files won't include any conditional logic. YAML is a data serialisation language, so it's not contain if/else style executable statements.