If Else in Github action - github-actions

I am following this.
https://github.community/t/github-actions-manual-trigger-approvals/16233/83
- name: Clone Repository (Latest)
uses: actions/checkout#v2
if: github.event.inputs.git-ref == ''
- name: Clone Repository (Custom Ref)
uses: actions/checkout#v2
if: github.event.inputs.git-ref != ''
with:
ref: ${{ github.event.inputs.git-ref }}
This works fine but multiple-step makes the workflow bigger.
I was trying something more compact.
like determining the commit SHA in env.
env:
COMMIT_HASH: ${{ github.event.inputs.git-ref != '' && github.event.inputs.git-ref || github.sha }}
this works fine but looks like a ugly hack to me. any suggestions.
I am trying to avoid extra steps,tha's all.

You could 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).
Examples:
- 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 }}
or
steps:
- uses: haya14busa/action-cond#v1
id: condval
with:
cond: ${{ github.event_name == 'pull_request' }}
if_true: "value for pull request event"
if_false: "value for non pull request event"
- name: Use conditional value
run: echo "${{ steps.condval.outputs.value }}"

Related

Is it possible to access step outputs from another Github actions job?

Given the following sample workflow
name: My workflow
on:
push:
branches:
- 'main'
jobs:
job_1:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout#v3
with:
fetch-depth: 0
- name: Get next version
id: get_next_version
uses: thenativeweb/get-next-version#2.5.0
- name: Echo for new version
if: ${{ steps.get_next_version.outputs.hasNextVersion == 'true' }}
run: echo there is a new version
- name: Echo for no new version
if: ${{ steps.get_next_version.outputs.hasNextVersion != 'true' }}
run: echo there is no new version
job_2:
needs: job_1
if: needs.job_1.steps.get_next_version.outputs.hasNextVersion == 'true'
runs-on: ubuntu-latest
steps:
- name: First step
run: echo job_2 is running
The action get-next-version analyzes my commit and calculates a new version. As you can see in job_1 I can access the calculated result.
job_2 depends on job_1 and should only run if there would be a new version. I tried to access the result in the if statement of job_2 but it seems that didn't work, I might be using the wrong syntax.
I get the echo
there is a new version
but job_2 was skipped. Is there a way to get access to the data of get_next_version.outputs ( I want the fields hasNextVersion and version )?
Yes - it's possible.
Each job can define its output as an output of one of its steps.
The related documentation can be found here
name: My workflow
on:
push:
branches:
- 'main'
jobs:
job_1:
runs-on: ubuntu-latest
# define output for first job forwarding output of hasNextVersionOutput job
outputs:
hasNextVersion: ${{ steps.hasNextVersionOutput.outputs.hasNextVersion }}
steps:
- name: Checkout repository
uses: actions/checkout#v3
with:
fetch-depth: 0
- name: Get next version
id: get_next_version
uses: thenativeweb/get-next-version#2.5.0
# add a step to generate the output that will be read by the job
- name: Generate output
run: echo "hasNextVersion=${{
steps.get_next_version.outputs.hasNextVersion }}" >> $GITHUB_OUTPUT
- name: Echo for new version
if: ${{ steps.get_next_version.outputs.hasNextVersion == 'true' }}
run: echo there is a new version
- name: Echo for no new version
if: ${{ steps.get_next_version.outputs.hasNextVersion != 'true' }}
run: echo there is no new version
job_2:
needs: job_1
# read output directly from job (you cannot access its steps
if: needs.job_1.outputs.hasNextVersion == 'true'
runs-on: ubuntu-latest
steps:
- name: First step
run: echo job_2 is running

Github workflow schedule wont run?

I have a workflow which I want to run as a schedule job. But its also run based on another workflow is success or not. As now its not running as schedule but it works if the other workflow is success.
My workflow:
name: Security
on:
workflow_run:
workflows: ["My other workflow"]
types:
- completed
schedule:
- cron: '0 3 * * *'
env:
IMAGE: ghcr.io/${{ github.repository }}:${{ github.sha }}
GITHUB_USERNAME: x-access-token
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
jobs:
app-dependencies-vulnerabilities:
name: Scan for vulnerability
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v3
- name: Running snyk
uses: snyk/actions/gradle#master
with:
command: monitor
args: --org=myorg --project-name=${{ github.repository }} --remote-repo-url=https://github.com/${{ github.repository }}.git
json: true
I think this workflow is not running as excepted schedule job because I have this conditon? if: github.event.workflow_run.conclusion == 'success', am I right? How can I make it run as schedule AND based on the other workflow is success or not?
Thank you!
Your assumption is correct. To check if your workflow is being triggered via a cron job (scheduled event), you may do:
if: ${{ github.event_name == 'schedule' }}
In your case, your if condition should look:
if: ${{ (github.event.workflow_run.conclusion == 'success') || (github.event_name == 'schedule') }}

Github actions: Output from one step is only accessible in the next step and not other steps

I have the below github actions where i am storing the release version in manager job and using it in the deployment with manager-uat and manager-production and a weird thing is happening that i get the output current_version available in manager-uat but not in manager-production whereas i am referring to the same variable. Please can somebody suggest.
manager:
runs-on: ubuntu-latest
outputs:
CURRENT_VERSION: ${{ steps.status.outputs.CURRENT_VERSION }}
NEED_RELEASE: ${{ steps.status.outputs.NEED_RELEASE }}
steps:
- uses: actions/checkout#v2
- <more steps>
- name: manager - Check the current version
working-directory: .
run: |
echo "CURRENT_VERSION=$(python tools/check_version.py manager)" >> $GITHUB_ENV
- id: status
run: |
echo "::set-output name=CURRENT_VERSION::${{ env.CURRENT_VERSION }}"
echo "::set-output name=NEED_RELEASE::${{ env.NEED_RELEASE }}"
manager_uat:
needs: [manager]
if: needs.manager.outputs.NEED_RELEASE == 'true'
uses: ./.github/workflows/cd_mlops.yml
secrets: inherit
with:
version: ${{needs.manager.outputs.CURRENT_VERSION}}
service: manager
envir: uat
manager_production:
needs: [ manager_uat ]
if: needs.manager.outputs.NEED_RELEASE == 'true'
uses: ./.github/workflows/cd_mlops.yml
secrets: inherit
with:
version: ${{needs.manager.outputs.CURRENT_VERSION}}
service: manager
envir: production
You cannot use needs.X if X is not a direct dependency of the job.
So in your case, you need to add manager as a dependency of manager_production like so:
manager_production:
needs: [ manager, manager_uat ]
if: needs.manager.outputs.NEED_RELEASE == 'true'
uses: ./.github/workflows/cd_mlops.yml
# ..etc

Github action - echo within an expression

changes:
name: Detect changes
runs-on: ubuntu-latest
outputs:
aws: ${{ steps.filter.outputs.aws }}
azure: ${{ steps.filter.outputs.azure }}
gcp: ${{ steps.filter.outputs.gcp }}
steps:
- name: Checkout source code
uses: actions/checkout#v2
- name: Check for changes
uses: dorny/paths-filter#v2
id: filter
with:
filters: |
aws:
- added|modified: 'aws/**'
azure:
- added|modified: 'azure/**'
gcp:
- added|modified: 'gcp/**'
zip_files:
runs-on: ubuntu-latest
needs: changes
steps:
- uses: actions/checkout#v2
- uses: montudor/action-zip#v1
with:
args: zip -qq -r result.zip "$(${{needs.changes.outputs.aws}} && echo aws)" "$(${{needs.changes.outputs.azure}} && echo azure)" "$(${{needs.changes.outputs.gcp}} && echo gcp)"
- uses: actions/upload-artifact#v1
with:
name: my-artifact
path: ${{ github.workspace }}/result.zip
I want to zip directories that detect changes. and then upload it to artifact.
When zipping, I get a "zip error: Nothing to do" even though aws/azure/gcp all evaluate to true. I think that the error lies within the args line.

Github action optional step execution

I am trying to execute some option steps if the previous step is failing.
I need to download the old artifacts in order to avoid that my Terraform build action is not detecting changes. Therefore I added a diff action to identify if the docker file to build the zip-layer has changed, if there is no change the old artifacts from a previous execution should be downloaded. In some cases the last execution does not contain the artifacts e.g. failure of the jobs. In that case I would like to get the latest version based on the existing docker image.
Note: The code is part of a matrix execution but for simplicity I reduced the action to the problem area.
job_prepare:
.....
job_layers:
needs: job_prepare
runs-on: ubuntu-latest
strategy:
matrix: ${{fromJson(needs.job_prepare.outputs.layer_matrix)}}
steps:
- name: Checkout
uses: actions/checkout#v2
- name: matrix name
run: |
echo $GITHUB_WORKSPACE
echo ${{ matrix.path }}
- uses: technote-space/get-diff-action#v3
id: git_diff
with:
PREFIX_FILTER: ${{ matrix.prefix }}
SUFFIX_FILTER: Dockerfile
- name: LayerDockerBuild
id: layerDocker
if: steps.git_diff.outputs.diff
run: |
docker build ...
docker push ...
- name: Layer via Artifacts
if: (steps.git_diff.outputs.diff == false)
uses: dawidd6/action-download-artifact#v2
with:
workflow: review.yml
name: ${{ matrix.name }}
- name: Layer via Docker
if: steps.git_diff.outputs.diff && ${{ failure() }}
id: layerD
run: |
....
docker pull "docker.pkg.github.com/$REPO_NAME/$IMAGE_ID:$VERSION"
docker run --rm -v $GITHUB_WORKSPACE:/data docker.pkg.github.com/$REPO_NAME/$IMAGE_ID:$VERSION cp /packages/${{ matrix.name }}.zip /data
- name: Upload layer zip
if: ${{ always() }}
uses: actions/upload-artifact#v2
with:
name: ${{ matrix.name }}
path: ${{ matrix.name }}.zip
The problem is basically the logic in the line if: steps.git_diff.outputs.diff && ${{ failure() }}
thanks for your help on any hints how to make the step option when the diff is false and the step ~Layer via Artifacts~ is not failing.
To execute your step if the previous one was not a failure you can just set failure() without brackets. With the if, no need of brackets.
if: steps.git_diff.outputs.diff && failure()
Hope it will help