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".
Related
I was trying with following code but it is not taking care of all 3 conditions due to following reason:
base_ref will only work on pull_request/push event not on pull_request_review
action dorny/paths-filter#v2.2.1 only works with pull_request/push event
on:
pull_request_review:
types: [submitted]
branches:
- main
jobs:
myJob:
name: myJob
if: github.event.review.state == 'approved' && startsWith(github.base_ref, 'main/')
runs-on: [self-hosted, prd]
steps:
- name: Checkout repository
uses: actions/checkout#v2.2.0
- name: Check if *.csv is modified
uses: dorny/paths-filter#v2.2.1
id: changes
with:
filters: |
csv:
- 'data/*.csv'
- name: Run process bmv script
if: ${{ steps.changes.outputs.csv == 'true' }}
run: |
echo "-Started running script-"
Can any one suggest how can i handle all 3 conditions : PR approval, base branch as main and only csv is modified.
Finally I got the answer by doing Matteo's way and also tweaking existing code.
Tweaks: Updated dorny/paths-filter#v2.2.1 to dorny/paths-filter#v2.10.2 as this version support it to work on other than pull/pill_request events.
on:
pull_request_review:
types: [submitted]
jobs:
myJob:
name: myJob
if: startsWith(github.event.pull_request.base.ref, 'main') && (github.event.review.state == 'approved')
runs-on: [self-hosted, prd]
steps:
- name: Checkout repository
uses: actions/checkout#v2.2.0
- name: Check if *.csv is modified
uses: dorny/paths-filter#v2.10.2
id: changes
with:
filters: |
csv:
- 'data/*.csv'
- name: Run process bmv script
if: ${{ steps.changes.outputs.csv == 'true' }}
run: |
echo "-Started running script-"
Thanks for all the help, above is the complete working solution which check for all 3 conditions i.e run workflow only when PR is approved and PR has base branch as main and only csv file inside data folder is modified.
I have two reusable workflows to deploy and destroy GCP resources, which I call from one workflow based on different conditions.
One workflow creates infra and is triggered when the label preview is added to a PR:
on:
pull_request:
types: [opened, reopened, labeled]
jobs:
create-infrastructure:
if: ${{ contains( github.event.pull_request.labels.*.name, 'preview') }}
# Call to a reusable workflow here
The second workflow I need to trigger when the PR is closed or when a specific label is removed; I tried this:
on:
pull_request:
types: [ closed, unlabeled ]
jobs:
destroy_preview:
if: ${{ contains( github.event.pull_request.labels.*.name, 'preview') }}
uses: myrepo/.github/workflows/preview-app-destroy.yml#v0.3.6
with:
project_id: xxx
I don't know how to define unlabeled for a specific label. It would be great if someone has any idea.
The pull request webhook payload doesn't contain the removed label, as far as I can tell, but you can fetch the list of issue events (which work for pull requests, too), filter by unlabeled events, and then look at the label name of the last one.
Using the GitHub CLI in a run step, that might look something like this:
name: Preview removed workflow
on:
pull_request:
types:
- unlabeled
jobs:
destroy_preview:
runs-on: ubuntu-20.04
steps:
- name: Check if "preview" was removed
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
pr=${{ github.event.number }}
label=$(gh api "repos/$GITHUB_REPOSITORY/issues/$pr/events" \
--jq 'map(select(.event == "unlabeled"))[-1].label.name')
if [[ $label == 'preview' ]]; then
echo "The 'preview' label has been removed"
fi
where you'd replace the echo with your infrastructure commands.
Now, if you want to call a reusable workflow when that specific label is removed, you have to somehow find a way to add a condition to the job where the reusable workflow is called.
One option is to make two jobs, one to check the condition and setting the result as a job output. The other job is set up as depending on the first one, and its if condition checks if the output was set to true.
This would look something like this (omitting the name and trigger, as they are identical to above):
jobs:
checklabel:
runs-on: ubuntu-20.04
outputs:
waspreview: ${{ steps.check.outputs.preview }}
steps:
- name: Check if "preview" was removed
id: check
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
pr=${{ github.event.number }}
label=$(gh api "repos/$GITHUB_REPOSITORY/issues/$pr/events" \
--jq 'map(select(.event == "unlabeled"))[-1].label.name')
if [[ $label == 'preview' ]]; then
echo "::set-output name=preview::true"
fi
destroy_preview:
needs: checklabel
if: needs.checklabel.outputs.waspreview
uses: myrepo/.github/workflows/preview-app-destroy.yml#v0.3.6
with:
project_id: xxx
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.
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
In gitlab we have support for CI_COMMIT_BEFORE_SHA and CI_COMMIT_SHA
Whereas in github we only have support for GITHUB_REF which holds SHA of current commit that triggered this action.
My requirement is to find if a particular file changed since last Action execution
Found a way to solve this using event payload - see push event payload:
in .github/workflows/release.yaml
name: release
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: deploy
run: sh deploy.sh
env:
CI_COMMIT_BEFORE_SHA: ${{ github.event.before }}
CI_COMMIT_SHA: ${{ github.event.after }}
in bin/deploy.sh
HAS_DESIRED_CHANGES=`git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA | grep -E 'path/to/file1|path/to/dir2'`
echo $HAS_DESIRED_CHANGES
HAS_DESIRED_CHANGES=`echo ${#HAS_DESIRED_CHANGES}`
if ! [ $HAS_DESIRED_CHANGES -eq 0 ]
then
echo "Has desired changes, proceed performing necessary actions"
else
echo "No desired changes. Skipping...."
fi