Problem with Github Actions IF expression syntax - if-statement

I need to check if steps.get_acc.outputs.acc < 1 but right now the steps.get_acc.outputs.acc is a string how to make it an integer?
cml.yaml
name: MOPS
on: [push]
jobs:
run:
runs-on: [ubuntu-latest]
steps:
- uses: actions/checkout#v2
- uses: iterative/setup-cml#v1
- uses: actions/setup-python#v2
with:
python-version: '3.x'
- name: cml
id: get_acc
shell: pwsh
env:
repo_token: ${{ secrets.GITHUB_TOKEN }}
run: |
pip3 install -r requirements.txt
python train.py
$firstLine = Get-Content -Path 'metrics.txt' -TotalCount 1
$digits = $firstline.Split(':')[-1]
$acc = [int]$digits
Write-Output "::set-output name=acc::$acc"
- name: Check acc
if: ${{steps.get_acc.outputs.acc <1 }}
uses: actions/github-script#v3
with:
script: |
core.setFailed('Accuracy dropped')

The Github Documentation for output explained that:
The value that the output parameter will be mapped to can be set to a string or an expression with context. For example, you can use the steps context to set the value of an output to the output value of a step.
Taking a look at the Literals Github documentation, we can note that:
As part of an expression, we can use boolean, null, number, or string data types. Boolean literals are not case sensitive, so we can use true or True.
Therefore, it all depends on the way you set the output variable.
Example to set a number as output:
outputs:
random-number:
description: "Random number"
value: ${{ steps.random-number-generator.outputs.random-id }}
runs:
using: "composite"
steps:
- id: random-number-generator
run: echo "::set-output name=random-id::$(echo $RANDOM)"
shell: bash
EDIT:
Moreover the syntax you used for the if condition isn't correct, you need to remove the ${{ }} to make it work.
Example with if condition:
job:
runs-on: ubuntu-latest
steps:
- name: step-1
id: xyz
run: echo "::set-output name=acc::$(echo $RANDOM)"
- name: step-2
if: steps.xyz.outputs.acc < 1
run: |
echo "Number lower than 1"
echo "${{ steps.xyz.outputs.acc }}"
- name: step-3
if: steps.xyz.outputs.acc > 1
run: |
echo "Number higher than 1"
echo "${{ steps.xyz.outputs.acc }}"

It looks like you have been given an answer on how to handle it as an integer, but given that you are setting the output via code. Why not just evaluate the integer in your code and then set a true/false boolean value or a Y/N string? If all you need to do is use the value as an If condition why bother to set the integer value? You could just evaluate it and set the condition at the source.

Related

Unexpected symbol: 'are' for if then else condition check

2 environment variables need to do a equally check before carry on the next sep in my workflow
- name: version check
env:
version_in_code : "v$(poetry version -s)"
version_in_tag : $(git describe --exact-match --tags $(git log -n1 --pretty='%h'))
version_is_equal: ${{ env.version_in_code != env.version_in_tag }}
run: |
if [ ${{ env.version_is_equal }} ]; #here comes the error
then
echo " ${{ env.version_in_tag }} will be released"
else
git push -d origin ${{ env.version_in_tag }}
echo "⛔️ Tag-version: ${{ env.version_in_tag }} and Code-version: ${{ env.version_in_code are NOT equivalent"
exit 1
fi
Using $env.version_is_equal is not allowed inside the if condition check, and the error message is very confusing: Unexpected symbol: 'are' how can I solve this issue?
There is the syntax issue pointed out by Gui, but there is also a Bash problem: this
[ ${{ env.version_is_equal }} ]
is either [ true ] or [ false ]. This will always evaluate to true, because the construct checks if it contains a non-empty string; it doesn't care if the string is true or false.
Then, you can replace ${{ env.version_is_equal }} with $version_is_equal; doesn't make much of a difference, but it's more convenient.
To fix the comparison, you either have to compare to a string:
if [ "$version_is_equal" = 'true' ]; then
or run it as a command (without the [ ... ]), which is shorter, but a bit more magic:
if "$version_is_equal"; then
This works because true and false are commands returning a success/failure exit status.
Notice that this
version_in_tag : $(git describe --exact-match --tags $(git log -n1 --pretty='%h'))
is evaluated only when it is used, and not when it is assigned. Until it is used, it's just a string. This may or may not be the intention, but it's in my opinion more clear to make the assignment part of the script itself:
version_in_tag=$(git describe --exact-match --tags $(git log -n1 --pretty='%h'))
It seems there is an error in the syntax.
You didn't close the env variable on the error message implementation:
echo "⛔️ Tag-version: ${{ env.version_in_tag }} and Code-version: ${{ env.version_in_code are NOT equivalent"
You used ${{ env.version_in_code instead of ${{ env.version_in_code }}

Convert Ansible variable to integer for arithmetic

I would like to execute a command to obtain the current AWS EC2 launch template version in an integer format so I can do basic arithmetic on it to use in subsequent queries / deletes.
For example:
tasks:
- name: Lookup current default version of EC2 launch template
command: aws ec2 describe-launch-template-versions --launch-template-id lt-xxx --filters Name=is-default-version,Value=true --query 'LaunchTemplateVersions[*].[VersionNumber]'
delegate_to: localhost
register: result
- name: Show results
debug:
msg: '{{ result.stdout }}'
delegate_to: localhost
If this output is '5' I would like to subtract 1 from it so I can execute an additional command to do the following:
aws ec2 delete-launch-template-versions --launch-template-id lt-xxx --versions {{result - 1}}
I realize this will not work as written, but this is the premise I'm going for.
Convert the string to an integer. For example
- command: echo 5
register: result
- command: "echo {{ result.stdout|int - 1 }}"
register: result
- debug:
var: result.stdout
gives
result.stdout: '4'
The type of the command return values' attribute stdout is string. See the results below
- command: echo 5
register: result
- debug:
msg: |-
result.stdout: {{ result.stdout }}
result.stdout|type_debug: {{ result.stdout|type_debug }}
result.stdout|int|type_debug: {{ result.stdout|int|type_debug }}
msg: |-
result.stdout: 5
result.stdout|type_debug: AnsibleUnsafeText
result.stdout|int|type_debug: int

Github Actions / Extract TicketID from branch name

You can currently set env vars via:
- name: Configure Environment Variables
uses: allenevans/set-env#v1.0.0
with:
CDN_PATH: app-foo/${{ github.run_id }}
CDN_URL: 'https://cdn.mycompany.com'
JIRA_TICKET_ID: ${{ match(github.ref, ...) }} # How can I extract a string from a branch name?
https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#functions
https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions
How can I extract a string from the branch name?
JIRA_TICKET_ID: ${{ match(github.ref, ...) }}
I don't believe there is a build in function in github actions to do that. But you can run a step before your action that gets the jira ticket for you.
NOTE: You will need to modify the sed regex to the one to get your ticket. Right now it only gets the branch name from the ref
- id: getjiraticket
run: echo "::set-output name=jiraticketid::`echo "${{ github.ref }}" | sed 's/.*\///'`"
- name: Configure Environment Variables
uses: allenevans/set-env#v1.0.0
with:
CDN_PATH: app-foo/${{ github.run_id }}
CDN_URL: 'https://cdn.mycompany.com'
JIRA_TICKET_ID: ${{ steps.getjiraticket.outputs.jiraticketid }}

Conditions in yaml pipeline like "eq" and "ne" is not working

I have created a pipeline build variable "svctag" and assigned its value to blank (empty string). Now trying to execute below script inside a job in yaml file. Every time it prints "svctag is not blank". Not sure what I am doing wrong.
Please help.
- ${{ if eq('$(svctag)', '') }}:
- script: echo 'svctag is blank'
- ${{ if ne('$(svctag)', '') }}:
- script: echo 'svctag is not blank'
As I know, this format is only applied in YAML template. Now, the issue is the variable called method you are using is not correct.
You should use the format variables['svctag'] instead of $(svctag) to access the variable which declared previously while you using YAML.
So, you should change your script as
- ${{ if eq(variables['svctag'], '') }}:
- script: echo it is true
- ${{ if ne(variables['svctag'], '') }}:
- script: echo it is false
Here is the output on my side.
Another solution is define svctag under parameters:
parameters:
svctag: ''
Then use parameters with step:
steps:
- ${{ if eq(parameters.svctag, '') }}:
- script: echo it is true
- ${{ if ne(parameters.svctag, '') }}:
- script: echo it is false
Note: Please use parameters.svctag.
So, you should change your script as
- ${{ if eq(variables['svctag'], '') }}:
- script: echo it is true
- ${{ if ne(variables['svctag'], '') }}:
- script: echo it is false

adding an fstab option using Ansible

I am trying to add nodev to my /etc/fstab file. I am using the Ansible command below but with no luck. My issue lies with the regular expression, I'm not a pro at regex.
- name: Add nodev to /etc/fstab
lineinfile:
dest=/etc/fstab
backup=yes
backrefs=yes
state=present
regexp='(^/dev[\w/_-]+(\s+(?!nodev)[\w,]+)*)'
line='\1,nodev'
One of the lines from /etc/fstab that I am trying to add nodev is:
/dev/mapper/ex_sys-ex_home /home /ext4 rw,exec,auto,nouser,sync 1 2
While this may not be the most elegant answer, it worked for me.
- name: Ensure fstab uses nodev
mount:
name: "{{ item.mount }}"
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
opts: "{{ item.options }},nodev"
state: present
with_items: ansible_mounts
when: item.options.find(",") >= 0 and item.options.find("nodev") == -1
Inspired by Joe's answer I made this version which will add a single option to a specific line in /etc/fstab if it isn't there already. This will also keep any other options the line already had.
main.yml
- import_tasks: fstab-opt-present.yml point=/home opt=nodev
fstab-opt-present.yml
- name: '/etc/fstab: Set opt "{{ opt }}" for mount point {{ point }}'
lineinfile:
path: /etc/fstab
backup: yes
backrefs: yes
regexp: '^(\S+\s+{{ point }}\s+\S+\s+)(?!(?:\S*,)?{{ opt }}(?:,\S*)?\s+)(\S+)(\s+.+)$'
line: '\1{{ opt }},\2\3'
register: fstab
- name: 'If {{ point }} changed, remount'
command: 'mount {{ point }} -o remount'
when: fstab.changed
https://regex101.com/ is a really helpful tool for building and testing these kind of regexps. Just enable the "multiline" option there and open the "Substitution" panel and you can even paste in your /etc/fstab and see which lines your regex will match and what it will do to them. Just remember to use real values instead of the Ansible variables {{ point }} etc. when testing there
We've developed a 3rd-party ansible module to add, set or remove mount options. Check it out!
- mountopts:
name: /
option: nodev
https://github.com/Uberspace/ansible-mountopts
I wanted to state that there seems to be a new ansible module which covers all this much more easily:
https://docs.ansible.com/ansible/latest/modules/mount_module.html
Tested & works fine
- name: Set nodev option
replace:
path: /etc/fstab
backup: yes
regexp: '^(\S+\s+)(\/\S+)(\s+)((?:ext4|xfs)\s+)(?!(?:\S*,)?nodev(?:,\S*)?\s+)(\S+)(\s+.+)$'
replace: '\1\2 \4 \5,nodev \6'
It excludes adding nodev to /(root), sets only to ext4 and xfs filesystem. doesn't add to temp filesystems.
Note: while you test regexp101, make sure to select python
Landed here looking for an answer, wound up rolling my own for my use case:
main.yml
- include: fstab-opts.yml point=/tmp opts=noexec,nodev,nosuid,noatime
- include: fstab-opts.yml point=/backup opts=noatime
fstab-opts.yml
---
- name: 'Ensure {{ point }} flags'
lineinfile:
path: /etc/fstab
# uses "(not-spaces spaces /tmp spaces )(not-spaces)(the rest)" pattern to match column content and capture args
regexp: '^([^ ]+[ ]+\{{ point }}[ ]+[^ ]+[ ]+)([^ ]+)(.*)'
line: '\1{{ opts }}\3'
backrefs: yes
register: fstab
- name: 'If {{ point }} changed, remount'
command: mount -o remount {{ point }}
when: fstab.changed
i have added the noexec,nodev,nosuid option in /etc/fstab for the /var/tmp mount point.
Requirement is:
Ensure noexec option set on /var/tmp partition
Ensure nodev option set on /var/tmp partition
Ensure nosuid option set on /var/tmp partition
if required install ansible.posix.mount module using below command .
# ansible-galaxy collection install ansible.posix
Playbook:
---
- name: "STEP 1: Get /var/tmp mounted SRC device"
shell: mount | grep -E '\s/var/tmp\s' | awk '{print $1}'
register: "vartmpsrc"
- debug:
msg: "Validated the /var/tmp mount output: {{ vartmpsrc.stdout }}"
- name: "Add mount noexec,nodev,nosuid options for /var/tmp"
mount:
path: "/var/tmp"
src: "{{ vartmpsrc.stdout }}"
fstype: "tmpfs"
opts: "nosuid,nodev,noexec"
state: "present"
when: vartmpsrc.stdout == "/var/tmp"
- name: Remount /var/tmp mounted volume with mount options noexec,nodev,nosuid
ansible.posix.mount:
path: /var/tmp
state: remounted
when: vartmpsrc.stdout == "/var/tmp"
- name: 'STEP 2: Validate noexec,nodev,nosuid option set on /var/tmp partition'
shell: mount | grep -E '\s/var/tmp\s' | grep -v {{ item }}
loop:
- noexec
- nodev
- nosuid
register: vartmp_exists
ignore_errors: yes
when: vartmpsrc.stdout == "/var/tmp"