GitAction: Trigger workflow on PR approval AND when base branch is main AND .csv file is updated - github

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.

Related

How to trigger workflow when all files in PR are .csv

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".

In a GitHub Action how to conditionalize a step based off the previous step's output?

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.

Github action test if a commit containing a specific word was previously made

I need to make sure to test with github action, if a commit has previously been made that contains the word build.
If the commit does not contain the word build then tests with github action should not be run.
Can you give me some advice?
Test:
name: "Testing"
on:
push:
branches:
- master
jobs:
test_the_action:
name: Test the action
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout#v2
- uses: suisei-cn/actions-download-file#master
id: downloadfile
name: Download a file
with:
url: "[API Endpoint](https://api.github.com/repos/suisei-cn/actions-download-file)"
target: public/
auto-match: true
- name: Display the file
run: head -n8 public/actions-download-file
From a push event, it's possible to extract the commit message by using github.event.commit.message
Here is an example of the github context for a push event.
Note that if there are several commit messages:
commit[0] contains the oldest commit
${{ github.event.commits[0].message }}
head_commit contains the youngest commit
${{ github.event.head_commit.message }}
Then, you can check in your job if the commit message contains or not the word you want, for example by using:
if: "!contains(github.event.head_commit.message, 'build')"
Therefore, your workflow could look like this if you don't want the job to be run if the commit message contains the 'build' word:
name: "Testing"
on:
push:
branches:
- master
jobs:
test_the_action:
if: "!contains(github.event.head_commit.message, 'build')"
name: Test the action
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout#v2
- uses: suisei-cn/actions-download-file#master
id: downloadfile
name: Download a file
with:
url: "[API Endpoint](https://api.github.com/repos/suisei-cn/actions-download-file)"
target: public/
auto-match: true
- name: Display the file
run: head -n8 public/actions-download-file
Finally, you now also have the option to skip ci workflows with key words in the commit messages.

How to trigger a new workflow from another workflow based on a path filter?

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.

git actions save workflow trigger to variable

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