Github Actions / Extract TicketID from branch name - regex

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 }}

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 }}

Problem with Github Actions IF expression syntax

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.

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

ansible parse text string from stdout

My problem is with ansible and parsing stdout. I need to capture the stdout from an ansible play and parse this output for a specific substring within stdout and save into a var. My specific use case is below
- shell: "vault.sh --keystore EAP_HOME/vault/vault.keystore |
--keystore-password vault22 --alias vault --vault-block |
vb --attribute password --sec-attr 0penS3sam3 --enc-dir |
EAP_HOME/vault/ --iteration 120 --salt 1234abcd"
register: results
become: true
This generates an output with the following line, the goal is to capture the masked key that jboss vault generates and save that in an ansible var so I can use it to configure the standalone.xml template:
vault-option name="KEYSTORE_PASSWORD" value="MASK-5dOaAVafCSd"/>
I need a way parse this string with possibly regex and save the "MASK-5dOaAVafCSd" substring into an ansible var using set_facts module or any other ansible module.
Currently my code looks like this
#example stdout
results: vault-option name=\"KEYSTORE_PASSWORD\" value=\"MASK-5dOaAVafCSd\"/>
- name: JBOSS_VAULT:define keystore password masked value variable
set_fact:
masked_value: |
"{{ results.stdout |
regex_replace('^.+(MASK-.+?)\\.+','\\\1') }}"
This code is defining masked_value as the results.stdout, not the expected capture group.
You are very close. I advice you to use regex101.com to test regular expressions.
Here is my solution:
---
- hosts: localhost
gather_facts: no
tasks:
- shell: echo 'vault-option name="KEYSTORE_PASSWORD" value="MASK-5dOaAVafCSd"'
register: results
- set_fact:
myvalue: "{{ results.stdout | regex_search(regexp,'\\1') }}"
vars:
regexp: 'value=\"([^"]+)'
- debug:
var: myvalue
result:
ok: [localhost] => {
"myvalue": [
"MASK-5dOaAVafCSd"
]
}
Update:
regex_search returns a list of found matches, so to get only first one use:
{{ results.stdout | regex_search(regexp,'\\1') | first }}
The above solution worked for me, however I had to do some extra logic to filter shell command output to get to the line which contains following
<vault-option name="KEYSTORE_PASSWORD" value="MASK-6qcNdkIprlA"/>
because vault command output has many lines in it. Once this line is captured, the solution given by Konstantin works just fine. Below is the whole thing that needs to done in one place.
- name: Creating jboss vault
shell: |
{{ baseDir }}/bin/vault.sh -e {{ vaultDir }} -k {{ keystoreURL }} -p {{ keystorePassword }} \
-s {{ keystoreSalt }} -i {{ iterationCount }} -v {{ keystoreAlias }} -b {{ vaultBlock }} \
-a {{ attributeName }} -x {{ attributeValue }}
register: vaultResult
- set_fact:
jbossKeystorePassword: "{{ item | regex_search('value=\"([^\"]+)','\\1') | first }}"
when: item | trim | match('.*KEYSTORE_PASSWORD.*')
with_items:
- "{{ vaultResult.stdout_lines }}"
- debug:
var: jbossKeystorePassword
Be sure to replace all variables with your values in above vault.sh command.

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"