I wrote a Github action workflow of which will be triggered only when some specific files were updated:
name: CI
on:
push:
paths:
### If a push was applied on one of these files, the CI workflow is triggered.###
### I want to know which file triggered the CI workflow and save it to a variable s I can use later in the CI steps ###
- 'dwh/helm/values-versions.yaml'
- 'ai/helm/values-versions.yaml'
- 'platform/helm/values-versions.yaml'
jobs:
copy-values-template-to-fluent-bit:
runs-on: self-hosted
container:
image: ghcr.io/***/myImage
credentials:
username: ${{ secrets.GHCR_USER }}
password: ${{ secrets.GHCR_PASS }}
steps:
- uses: actions/checkout#v2
- name: show repo files
run: |
pwd
ls -l
I need a way to figure out which file triggered the CI workflow and save it to a variable.
You can use this action Get All Changed Files:
- id: files
uses: jitterbit/get-changed-files#v1
- run: |
for changed_file in ${{ steps.files.outputs.all }}; do
echo "Do something with this ${changed_file} to check if this is you file and set variable."
done
Related
I'd like to create a workflow in GitHub that triggers when all the changed files are .csv. I've been looking at GitHub's workflow syntax and I can only find instances where workflows are triggered when at least 1 certain file/directory is excluded or included.
My initial approach was
on:
push:
paths:
- '**.csv'
But this workflow will trigger as long as 1 file ends in .csv
What I ended up doing was running a workflow that tirggers when .csv files are added in the PR. Then a job starts that collects all the names of the files changed. Last it loops through the files changed and returns 'false' if any file doesn't end in .csv.
You can then add another job that uses the value of needs.compare.outputs.compare
name: csv-check
on:
pull_request:
branches:
- '**'
paths:
- '**.csv'
jobs:
changed_files:
runs-on: ubuntu-latest
outputs:
all: ${{ steps.changes.outputs.all }}
steps:
- name: Checkout repository
uses: actions/checkout#v2
with:
fetch-depth: 2
- name: Get changed files
id: changes
run: |
echo "::set-output name=all::$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | xargs)"
compare:
runs-on: ubuntu-latest
needs: changed_files
outputs:
compare: ${{ steps.all_csv.outputs.compare }}
if: ${{ needs.changed_files.outputs.all }}
steps:
- name: echo changed files
id: all_csv
run: |
echo "::set-output name=compare::true"
for file in ${{ needs.changed_files.outputs.all }}; do
if [[ $file != *.csv ]]; then
echo "::set-output name=compare::false"
fi
done
I suggest to review https://github.com/dorny/paths-filter - "GitHub Action that enables conditional execution of workflow steps and jobs, based on the files modified by pull request, on a feature branch, or by the recently pushed commits".
Building a GitHub action based on the commit message I'm trying to base a step on whether the commit message contains a particular string, set it to a variable and then in the next step check with a condition.
My current implementation of my action works:
name: Smoke Test
on:
push:
branches:
- main
permissions:
contents: read
issues: write
jobs:
smoking:
runs-on: [ubuntu-latest]
steps:
- name: Run smoke tests
if: ${{ !contains(github.event.head_commit.message, 'smoke_test') }}
run: |
echo 'Smoke Test not requested'
exit 1
stuff:
needs: smoking
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: JasonEtco/create-an-issue#v2
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
with:
filename: .github/ISSUE_TEMPLATE/smoke-test.md
id: create-issue
- run: 'echo Created issue number ${{ steps.create-issue.outputs.number }}'
- run: 'echo Created ${{ steps.create-issue.outputs.url }}'
but with the implementation of:
exit 1
causes the action to indicate it error'ed out in the action panel and while that works that isn't technically accurate because I don't need it to error I just don't want the remaining steps to run.
I've tried setting a variable:
if: ${{ contains(github.event.head_commit.message, 'smoke_test') }}
with:
run-smoke-test: true
run: |
echo 'Smoke Test requested'
but it's not passing to the next step.
Research
Use environment variable in github action if
How to pass variable between two successive GitHub Actions jobs?
github-action: does the IF have an ELSE?
How to fail a job in GitHub Actions?
GitHub Actions - trigger another action after one action is completed
Without relying on another GitHub action is there a way in step smoking to set an env variable that step stuff would need to validate for before running the step?
Edit
After reading the answer and implementing job outputs I've written:
name: Smoke Test
on:
push:
branches:
- main
permissions:
contents: read
issues: write
jobs:
commitMessage:
runs-on: ubuntu-latest
outputs:
output1: ${{ steps.isSmoke.outputs.test }}
steps:
- id: isSmoke
if: ${{ contains(github.event.head_commit.message, 'smoke_test') }}
run: echo "::set-output name=test::true"
smokeTest:
runs-on: ubuntu-latest
needs: commitMessage
steps:
- uses: actions/checkout#v2
- uses: JasonEtco/create-an-issue#v2
if: steps.isSmoke.output.test == true
env:
GITHUB_TOKEN: ${{ secrets.DEV_TOKEN }}
with:
filename: .github/ISSUE_TEMPLATE/smoke-test.md
but when the commit message of smoke_test is used it bypasses create-an-issue:
and I'm basing my condition after reading "Run github actions step based on output condition" and reading:
Contexts
Expressions
Using conditions to control job execution
Can a condition come before a step and/or what is the correct way to run a step based off the previous step?
You are looking for job outputs, which allow you to send data to the following jobs.
so I have this code:
name: run-script
on: push
jobs:
run_tests:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout#v2
- name: Run script file
run: |
echo {here should be the secret} > ~/id_rsa
shell: bash
On my git action, where {here should be the secret} I want to put the variable, which is a secret token saved as a repo secret.
How can this be done?
Thank you for your help.
Assuming you have a secret named TOKEN, you can use it like so:
name: run-script
on: push
jobs:
run_tests:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout#v3
- name: Run script file
run: |
echo ${{ secrets.TOKEN }} > ~/id_rsa
shell: bash
Unrelated to how to use secrets, please note that > will override the contents of ~/id_rsa.
Secondly, if you want to do something with your private key (which is my guess based on the filename), the correct file would be in ~/.ssh/id_rsa.
And lastly, note that I have changed the checkout action to v3 as that's the latest available version.
I have one workflow (that I want to be triggered by any commit with no path filter)
name: workflow1
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
...
that triggers another workflow
name: workflow2
on:
workflow_run:
workflows: ["workflow1"]
types:
- completed
jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
...
which is working fine with the workflow_run event. Now is it possible somehow to restrict workflow2 from being triggered even further (like with a path filter)? E.g. I make a commit to folder folder1 -> workflow1 triggered -> workflow2 triggered and if it's not a commit to the folder folder1, e.g. folder2 -> workflow1 triggered -> workflow2 not triggered. Is there something like the following I can add to workflow2?
name: workflow2
on:
paths:
- 'folder1/**'
workflow_run:
workflows: ["workflow1"]
types:
- completed
jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
...
Or another way to achieve that?
Thanks in advance for any help.
First option: Did you consider using the action verify-changed-files in your workflow run to execute the jobs only if specific files are updated?
Second option: It's more verbose, but you could save the path from the first workflow in an artifact to download in the second workflow.
Using the variable GITHUB_EVENT_PATH that returns the path of the file with the complete webhook event payload. For example, /github/workflow/event.json
It would look like this
In the FIRST workflow, you extract the path, then you save that number into a file and upload it as an artifact.
- name: Save the PATH in an artifact
shell: bash
env:
- PATH: {{ github.event.path}} ## If it's not specific enough, you can extract the $PATH variable on a previous step using the shell.
run: echo $PATH > path.txt
- name: Upload the PATH
uses: actions/upload-artifact#v2
with:
name: path
path: ./path.txt
In the SECOND workflow, you get the artifact and the path from the FIRST workflow, using the following GitHub Apps:
- name: Download workflow artifact
uses: dawidd6/action-download-artifact#v2.11.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: <first_workflow_name>.yml
run_id: ${{ github.event.workflow_run.id }}
- name: Read the path.txt file
id: path_reader
uses: juliangruber/read-file-action#v1.0.0
with:
path: ./path/path.txt
- name: Step to check the path output from the step above with an if condition to perform an operation (or not)
[...]
This link can also help to understand how to extract the PATH depending on the event.
I have a workflow build whose output is store in a docker registry,
depending on its outcome, then, I would like to run a e2e test.
I know I can use workflow_run but it's not clear how to pass outputs to the dependant workflow.
on:
workflow_run:
workflows: ["Build"]
types: [completed]
I should be able to grab the IMAGE_URL output and run tests on that specific artefact.
how can I set a workflow output
how can I read a workflow output
Current workaround is using workflow_dispatch, but it has the drawback of not being listed as PR check.
You can write your variables and values, which you want to pass, to a file and upload it as an artifact in the triggering workflow.
In the triggered workflow, download the artifact of the triggering workflow run. Then parse the file to get your variables.
Triggering workflow
[...]
name: Build
jobs:
aJob:
name: A job
runs-on: ubuntu-latest
steps:
- run: echo "aVariable,aValue" > vars.csv
- uses: actions/upload-artifact#v2
with:
name: variables
path: vars.csv
Triggered workflow
(artifacts from other workflows can't be downloaded with the action download-artifact)
on:
workflow_run:
workflows: ["Build"]
types: [completed]
jobs:
aJob:
name: A job
runs-on: ubuntu-latest
steps:
- uses: actions/github-script#v4
id: get-artifact-id
with:
result-encoding: string
script: |
const result = await octokit.request('GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts', {
owner: '${{github.repository_owner}}',
repo: '${{github.event.repository.name}}',
run_id: ${{github.event.workflow_run.id}}
})
# assumes the variables artifact is the only one in this workflow
return result.data.artifacts[0].artifact_id
- name: Get result
run: |
echo "${{steps.get-artifact-id.outputs.result}}"
curl -L -H "Authorization: token ${{github.token}}" \
-H "Accept: application/vnd.github.v3+json" \
-O variables.zip \
https://api.github.com/repos/${{github.repository}}/actions/artifacts/${{steps.get-artifact-id.outputs.result}}/zip
unzip variables.zip
# parse variables from variables.csv and set them
You can declaratively access artifacts from the workflow_run event this way:
- name: Download BuildMetadata
if: github.event_name == 'workflow_run'
uses: dawidd6/action-download-artifact#v2
with:
workflow: 'Build'
workflow_conclusion: success
github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ github.event.workflow_run.id }}
run_number: ${{ github.event.workflow_run.run_number }}
name: build.meta.json
Also checkout github.event.workflow_run.artifacts_url
https://github.com/dawidd6/action-download-artifact