Allow a Job to run if it passes a script - github-actions

I would like to allow a job to run only if its name can be found in some file.
jobs:
job1:
if : run some script that returns true if "${{ github.job }}" is in file.txt
steps:
...
However I'm quite sure i cant run a script outside of run, which I believe can't appear before the steps section, right?
If the option above simply isn't possible, perhaps there is a way to run this script on the first step and have the next steps not run unless the said critical step passed?
Thanks!

You could for example use 2 jobs in your action, where the second job would only be executed if the first one succeed return true using an if condition and outputs.
The workflow would look like something as below:
jobs:
job1:
runs-on: ubuntu-latest
outputs:
output1: ${{ steps.script.outputs.bool }}
steps:
- name: Run the python script
id: script
run: |
value=$((your command running the script here) 2> &1) # should return true
echo "::set-output name=bool::$value" # set the value as output
job2:
runs-on: ubuntu-latest
# Wait from the job1 to be completed before starting job2
needs: job1
if ${{ ${{needs.job1.outputs.output1}} == true }} # won't execute if output of job 1 isn't true
steps:
...
If you want to know more about:
if condition + context and expression
outputs
Note: The contains expression in the if condition could also be used eventually depending on your context (what the script does). It could even be the easiest solution :)

Related

Getting empty value for output from a previous job in a new one in a GitHub Action

on: pull_request
jobs:
job1:
runs-on: [re-centos7]
# Map a step output to a job output
outputs:
output1: ${{ steps.step1.outputs.test }}
output2: ${{ steps.step2.outputs.test }}
steps:
- id: step1
run: echo "test=world1" >> $env:GITHUB_OUTPUT
- id: step2
run: echo "test=world" >> $env:GITHUB_OUTPUT
job2:
runs-on: [re-centos7]
needs: job1
steps:
- run: echo ${{needs.job1.outputs.output1}}
output
I'm trying to use the job's output in the next job. I'm trying to use github output for this but I see it's getting an empty value for the output. Can someone help? Thanks!
output is empty for ${{needs.job1.outputs.output1}}
I'm using self-hosted runners which are integrated with Kubernetes cluster
The first thing to check is the version of your self-hosted runners: The deprecation of set-output was mentioned recently (oct. 2022)
If you are using self-hosted runners make sure they are updated to version 2.297.0 or greater.
If the version is lower, that would explain the empty values.

GitHub Action assign an environment variable using a workflow_dispatch variable or job output

I have a GitHub Action workflow that can be triggered in two ways, via a pull_request and via a workflow dispatch.
During a pull_request, one of the steps generates an output that will be used in a later step.
During a workflow dispatch, the user manually inputs a custom output that will be used in a later step.
How do I use that output without running into null values? I can only use one of those outputs to assign to a variable, how can I make it accept both?
How about utilizing github.event_name context to conditionally set a variable that you can use in a later step? It requires an extra step, but is relatively straightforward.
my-workflow.yml:
name: Use input or job output
on:
workflow_dispatch:
inputs:
my_input:
description: Some workflow input
type: string
pull_request:
jobs:
job1:
runs-on: ubuntu-latest
steps:
- id: set_output
run: echo "my_output=helloworld" >> $GITHUB_OUTPUT
- name: Save job output OR workflow dispatch to Env
run: |
if [[ ${{ github.event_name == 'workflow_dispatch' }} == true ]]; then
my_variable=${{ inputs.my_input }}
else
my_variable=${{ steps.set_output.outputs.my_output }}
fi
echo "my_variable=$my_variable" >> $GITHUB_ENV
- name: Use the variable from previous step
run: echo ${{ env.my_variable }}
If you run this manually from a workflow_dispatch, env.my_variable will be whatever string you input. If not (triggered by a pull request), env.my_variable will be my_output from the set_output step.

How to throw error and stop action on condition in GH action [duplicate]

I'm developing a Github actions workflow. This workflow runs on Linux, Mac, and Windows.
As part of the workflow, I have to check whether 2 environment variables are equal. If they don't - fail the job.
As described here, Github Actions support if: condition:
steps:
- run: # How can I make a cross-platform failure here?
if: ${{ envA }} != ${{ envB }}
How can I make the job fail if the above condition is true?
In the beginning, I thought of a script, but there must be a more elegant way to fail a job.
I'd do run: exit 1. That will simply exit with an exit code of 1, on all three platforms.
Proof that it's cross-platform: https://github.com/rmunn/Testing/runs/220188838 which runs the following workflow:
name: Test exiting on failure
on: [push]
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout#v1
- name: Try to fail
run: exit 1
- name: Print message if we don't fail
run: echo Should not get here
(An earlier version of this answer recommended "/bin/false", but that would only work on Linux and macOS).
In 2021, there is perhaps a more graceful way to do this:
- name: A/B Check
if: ${{ envA }} != ${{ envB }}
uses: actions/github-script#v3
with:
script: |
core.setFailed('envA and envB are not equivalent!')
Here, we use the github-script action to provide a one liner script that will fail the job. The "A/B Check" step will only run if the condition in the if line is true, so the script will only run in that case, which is what we want.
The nice thing about this approach is that you will get nicely formatted output in the Actions UI in your repo, showing that the "A/B Check" step caused the failure, and why (i.e. "envA and envB are not equivalent").
Note that if you have additional steps in the job after this, and you do NOT want them to run if the A/B check fails, you'll want to use if: success() on them to prevent them from running in that case.
The Github workflow commands docs gives a hint on this.
Toolkit function
Equivalent workflow command
core.setFailed
Used as a shortcut for ::error and exit 1
Given that, you can do the following without using any external workflows.
steps:
- name: A/B Check
if: ${{ envA }} != ${{ envB }}
run: |
echo "::error file={name},line={line},endLine={endLine},title={title}::{message}"
exit 1

Github workflow job not triggered while dependent on other job

I'm trying to achieve a flow with a job dependency tree based on needs and if
This is the workflow file, and my problem is that the job4 is not being triggered even when the job3 is being executed successfully.
I can't find any documentation explaining what is happening, but it seems that the needs tree that is being built behind the scenes is not matching the job4, because the needs on the job3 is not completed (is forced by the if)
I have a workaround to solve this flow using job outputs, but I was wondering why the simple example is not working. Can anyone explain me why?
Thanks
name: Test Workflow
on:
push:
jobs:
job1:
runs-on: ubuntu-latest
steps:
- run: echo Job1
job2:
if: cancelled()
runs-on: ubuntu-latest
steps:
- run: echo Job2
job3:
if: always()
needs: [job1, job2]
runs-on: ubuntu-latest
steps:
- run: echo Job3
job4:
needs: job3
runs-on: ubuntu-latest
steps:
- run: echo Job4
All dependent jobs must succeed. So jon your job 4 depdends on the job 3 it must that job 3 and all it's need must be succeded.
Please check this GitHub issue - Job-level "if" condition not evaluated correctly if job in "needs" property is skipped.
I assume that in your case even if you forced job 3 to run the result is not success but something different. Thus job 4 is not run.
You probably need sth like this on job 4.
if: |
always() &&
(needs.job3.result == 'success' || needs.job3.result == 'skipped')

github-action: does the IF have an ELSE?

in github action
I have an if, but I still need to run someother thing if I'm in the else case. Is there a clean way to do it or do I have to do another step with the same condition at false?
- if: contains(['SNAPSHOT'],env.BUILD_VERSION)
name:IF
run: echo ":)"
- if: false == contains(['SNAPSHOT'], env.BUILD_VERSION)
name: Else
run: echo ":("
GitHub Actions doesn't have else statement to run a different command/action/code. But you're right, all what you need to do is to create another step with reversed if condition. BTW, you can just use ! instead of false ==, if you surround your statement with ${{ }}.
Here are some links: if statement, operators
You can do the following which would only run the script where the condition passes:
job_name:
runs-on: windows-latest
if: "!contains(github.event.head_commit.message, 'SKIP SCRIPTS')" <--- skips everything in this job if head commit message does not contain 'SKIP SCRIPTS'
steps:
- uses: ....
- name: condition 1
if: "contains(github.event.head_commit.message, 'CONDITION 1 MSG')"
run: script for condition 1
- name: condition 2
if: "contains(github.event.head_commit.message, 'CONDITION 2 MSG')"
run: script for condition 2
and so on. Of course you would use your own condition here.
You may consider using the haya14busa/action-cond action. It is useful when the if-else operation is needed to set dynamic configuration of other steps (don't need to duplicate the whole step to set different values in a few parameters).
Example:
- name: Determine Checkout Depth
uses: haya14busa/action-cond#v1
id: fetchDepth
with:
cond: ${{ condition }}
if_true: '0' # string value
if_false: '1' # string value
- name: Checkout
uses: actions/checkout#v2
with:
fetch-depth: ${{ steps.fetchDepth.outputs.value }}
Alternative solution to github actions based commands, is to use shell script commands for if else statement.
On Ubuntu machine,example workflow to check if commit has a tag or not,
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- run: |
ls
echo ${{ github.ref }}
ref='refs/tags/v'
if [[ ${{ github.ref }} == *${ref}* ]]; then
v=$(echo ${{ github.ref }} | cut -d'/' -f3)
echo "version tag is ${v}"
else
echo "There is no github tag reference, skipping"
fi
You can also do something like this if you want to check for some data type value without using built in functions
- name: Notify Team on Slack
if: ${{github.repository == 'calebcadainoo/cascade-img'}}
run: |
# some command
Over here, I'm triggering event on each push.
I'm pushing to two repos at the same time but I only want to run my command once.
Read More on Expressions Here:
https://docs.github.com/en/actions/learn-github-actions/expressions