how to run Github Actions Jobs in parallel using matrix? - github-actions

I've really struggled here doing this for the first time and having no background in development.
We have an action that checks the status of several services running on different envs (DEV, TEST, PROD) and sends notifications to Microsoft Teams Channel.
At the moment there is a dedicated action for each env and the goal is to combine them in one.
the action itself:
name: Services Health Check
on:
workflow_dispatch:
schedule:
- cron: '*/30 * * * *'
env:
DEV: https://app.dev.contoso.com
TEST: https://app.test.contoso.com
PROD: https://app.contoso.com
TEAMS_TOKEN_DEV: ${{ secrets.HEALTH_CHECK_TEAMS_WEB_HOOK_URL_DEV }}
TEAMS_TOKEN_TEST: ${{ secrets.HEALTH_CHECK_TEAMS_WEB_HOOK_URL_TEST }}
TEAMS_TOKEN_PROD: ${{ secrets.HEALTH_CHECK_TEAMS_WEB_HOOK_URL_PROD }}
jobs:
#here I want to create a matrix as a JSON array to look like this, but Im not sure if I do it right (I am also not sure if I correctly escape the characters and which one should I escape):
#[
# { dev : https://app.dev.contoso.com, webhook : ${{ secrets.WEB_HOOK_URL_DEV }} },
# {test : https://app.test.contoso.com, webhook : ${{ secrets.WEB_HOOK_URL_TEST }} },
# {prod : https://app.contoso.com, webhook : ${{ secrets.WEB_HOOK_URL_TEST }} }
#]
env-matrix:
name: Setup ENV Matrix
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.env }}
steps:
- id: matrix-env
run: |
echo '::set-output name=env::[\{\"env\"\:\"$DEV\", \"webhook\"\:\"$TEAMS_TOKEN_DEV\"\}, \{\"env\"\:\"$DEMO\", \"webhook\"\:\"$TEAMS_TOKEN_DEMO\"\}, \{\"env\"\:\"$TEST\", \"webhook\"\:\"$TEAMS_TOKEN_TEST\"\}, \{\"env\"\:\"$POC\", \"webhook\"\:\"$TEAMS_TOKEN_POC\"\}, \{\"env\"\:\"$PRE\", \"webhook\"\:\"$TEAMS_TOKEN_PRE\"\}, \{\"env\"\:\"$PROD\", \"webhook\"\:\"$TEAMS_TOKEN_PROD\"\}]'
#and the healthcheck job itself
healthcheck:
needs: env-matrix
name: Health Check
runs-on: ubuntu-18.04
strategy:
matrix:
value: ${{ fromJson(needs.env-matrix.outputs.matrix-env)}}
steps:
- name: service1
uses: repo/action
continue-on-error: true
with:
url: '${{ matrix.value.env }}/service1/q/health/ready'
teamsWebHookURL: '${{ matrix.value.webhook }}'
- name: service2
uses: repo/action
continue-on-error: true
with:
url: '${{ matrix.value.env }}/service2/q/health/ready'
teamsWebHookURL: '${{ matrix.value.webhook }}'
so the job must run on DEV with TEAMS_TOKEN_DEV, on TEST with TEAMS_TOKEN_TEST, but I don't know the way to access an array item, so the steps are incorrect.
Any help will be appreciated. If you know a simpler solution pls share.
Thanks for your time and help

Another way of rewriting your workflow is to define the name of the secrets in the matrix and then using Array notation to fetch the actual value of the secrets. Below is a way of doing this and it is not a clone of your workflow. But this should give you an idea.
name: Services Health Check
on:
workflow_dispatch:
jobs:
healthcheck:
name: Health Check
runs-on: ubuntu-18.04
strategy:
matrix:
environment: [dev, test, prod]
include:
- environment: dev
url: https://app.dev.contoso.com
webhook: HEALTH_CHECK_TEAMS_WEB_HOOK_URL_DEV
- environment: test
url: https://app.test.contoso.com
webhook: HEALTH_CHECK_TEAMS_WEB_HOOK_URL_TEST
- environment: prod
url: https://app.prod.contoso.com
webhook: HEALTH_CHECK_TEAMS_WEB_HOOK_URL_PROD
steps:
- name: test_1
run: |
echo ${{ format('{0}{1}', matrix.url, '/service1/q/health/ready') }}
echo ${{secrets[matrix.webhook]}}
- name: test_2
run: |
echo ${{ format('{0}{1}', matrix.url, '/service2/q/health/ready') }}
echo ${{secrets[matrix.webhook]}}

Related

GitHub Actions - How to use environment variable at job level?

I want to use environment variables at the job level. Is there a way to do it?
env:
stageEnv: UAT
jobs:
name: Upload Build
if: ${{ env.stageEnv == 'UAT' }}
steps:
....
I get unrecognized named-value: 'env' error. Tried $stageEnv and ${{ env.stageEnv }}
Note: It works when I access within 'steps', but would like this to be accessible at 'jobs' level.
I'm afraid not, but you can do like this:
env:
stageEnv: UAT
jobs:
build:
name: Build
runs-on: ubuntu-latest
outputs:
stageEnv: ${{ steps.init.outputs.stageEnv }}
steps:
- name: Make environment variables global
id: init
run: |
echo "stageEnv=${{ env.stageEnv }}" >> $GITHUB_OUTPUT
And use it in another job:
upload:
name: Upload build
needs: build
if: ${{ needs.build.outputs.stageEnv == 'UAT' }}
Note this is just an example, and I personally prefer environment variables uppercase and output variables lowercase

Github Actions workflow_dispatch choice not working

So, i have tried different versions of this, but i still cannot get it right.
I have a github actions pipeline where i would like to insert a choice so people don't have to look for it in documentation:
name: Echo message
on:
workflow_dispatch:
inputs:
hubAddressGroupObject:
type: choice
description: 'Enter the name of the hub where the entry is added'
required: true
default: 'AZURE-EUW-XXXXX'
options:
- 'AZURE-EUW-XXXXX'
- 'AZURE-FRC-XXXXX'
- 'AZURE-USE-XXXXX'
- 'AZURE-FRC-XXXXX'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: WriteMessage
shell: pwsh
run: |
Test-script.ps1 -message "${{ github.event.inputs.hubAddressGroupObject }}"
The 'Test-script.p1' can look like this:
param (
[string] $message
)
Write-Host ('{0}' -f $message)
The output is still a normal workflow_dispatch with no choice.
What am i doing wrong?
Also, i have merged the current branch into main (default).
your code seems to be correct, you have space issue's with "jobs",
shift-tab it and it should work:
name: Echo message
on:
workflow_dispatch:
inputs:
hubAddressGroupObject:
type: choice
description: 'Enter the name of the hub where the entry is added'
required: true
default: 'AZURE-EUW-XXXXX'
options:
- 'AZURE-EUW-XXXXX'
- 'AZURE-FRC-XXXXX'
- 'AZURE-USE-XXXXX'
- 'AZURE-FRC-XXXXX'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: WriteMessage
run: |
echo "${{ github.event.inputs.hubAddressGroupObject }}"

Can I define a global across jobs

I have a workflow with 2 jobs:
on: [push]
jobs:
ssql:
runs-on: ubuntu-latest
### bunch of steps in between ###
- name: Upload data as artifact
uses: actions/upload-artifact#v2
with:
name: ${{ env.GAME }} + "-" + "data"
path: output_data/training-data.csv
env:
GAME: "FunGame"
Rtrain:
runs-on: ubuntu-latest
name: Train model
needs: ssql
steps:
- name: checkout current repo
uses: actions/checkout#v2
- name: Retreive data from ssql job
uses: actions/download-artifact#v2
with:
name: ${{ env.GAME }} + "-" + "data"
env:
GAME: "FunGame"
I had to set env variable $GAME twice, once in each job. Is there any syntax where I can e.g. add this at the top to make it truly global across jobs, e.g. something like:
on: [push]
env:
GAME: "FunGame"
jobs: ...
You can set an env variable exactly as you described at the workflow level.
Just note that it can conflict with env variables set at the job level, or at the step level, if they have the same name. In that case, the variable used is the most specific one: STEP over JOB over WORKFLOW.
Reference 1 + Reference 2
Here is an example of how to use env variables at different levels (without conflict):
name: Environment Workflow
on:
workflow_dispatch:
env:
WORKFLOW_VARIABLE: WORKFLOW
jobs:
job1:
runs-on: ubuntu-latest
env:
JOB_VARIABLE: JOB
steps:
- name: Run Commands with various variables
if: ${{ env.WORKFLOW_VARIABLE == 'WORKFLOW' }}
env:
STEP_VARIABLE: STEP
run: |
echo "Hello World"
echo "This is the $WORKFLOW_VARIABLE environment variable"
echo "This is the $JOB_VARIABLE environment variable"
echo "This is the $STEP_VARIABLE environment variable"
Full workflow implementation (if you want to reproduce)
Previous workflow run display

How can I use a Github action's output in a workflow?

Let's take this example composite action found on Github's documentation:
name: 'Hello World'
description: 'Greet someone'
inputs:
who-to-greet: # id of input
description: 'Who to greet'
required: true
default: 'World'
outputs:
random-number:
description: "Random number"
value: ${{ steps.random-number-generator.outputs.random-id }}
runs:
using: "composite"
steps:
- run: echo Hello ${{ inputs.who-to-greet }}.
shell: bash
- id: random-number-generator
run: echo "::set-output name=random-id::$(echo $RANDOM)"
shell: bash
- run: ${{ github.action_path }}/goodbye.sh
shell: bash
How can we use that specific output random-number in an external workflow that calls this action? I tried the following snippet but currently it seems the workflow cannot read the output variable from the action as it just comes out empty - 'Output - '
jobs:
test-job:
runs-on: self-hosted
steps:
- name: Call Hello World
id: hello-world
uses: actions/hello-world-action#v1
- name: Comment
if: ${{ github.event_name == 'pull_request' }}
uses: actions/github-script#v3
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Output - ${{ steps.hello-world.outputs.random-number.value }}'
})
It seems my attempt was correct with the exception of one detail:
Instead of:
${{ steps.hello-world.outputs.random-number.value }}
It should be referenced without the .value:
${{ steps.hello-world.outputs.random-number}}
Now it works.

Options to have variables in GitHub Actions

I know that I can use Runner's Linux environment variables in GitHub Actions.
Do I have any other options to have variables and use them in workflow steps?
This is how variables are designed to work in GitHub Actions. I mean declared variables are mapped to env variables, like here:
name: Show env
on:
push:
branches:
- '*'
env:
somevar: 'lastvar'
jobs:
show:
runs-on: ubuntu-latest
steps:
- name: Is variable exported?
run: |
echo "${{ env.somevar }}"
However, you can't use them everywhere - please check this topic:
env:
pluginId: 'plugin-fn-xml-node'
on:
push:
paths:
- ${{env.pluginId}}/**
- .github/workflows/**
pull_request:
paths:
- ${{env.pluginId}}/**
- '.github/workflows/**'
jobs:
build:
env:
working-directory: ${{env.pluginId}}
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [8.x, 10.x, 12.x]
steps:
This will not work because you can't use workflow variable at job level.
So if you define variable at workflow level you should be able to use it across steps.
I added also dynamically set variable based on documentation
env:
somevar: 'lastvar'
jobs:
show:
runs-on: ubuntu-latest
steps:
- name: Is variable exported?
run: |
echo "${{ env.somevar }}"
echo "action_state=yellow" >> $GITHUB_ENV
- name: PowerShell script
# You may pin to the exact commit or the version.
# uses: Amadevus/pwsh-script#25a636480c7bc678a60bbf4e3e5ac03aca6cf2cd
uses: Amadevus/pwsh-script#v2.0.0
continue-on-error: true
with:
# PowerShell script to execute in Actions-hydrated context
script: |
Write-Host $env:somevar
Write-Host $env:action_state
- name: Read exported variable
run: |
echo "$action_state"
echo "${{ env.action_state }}"