paths-filter
paths-filter copied to clipboard
workflow_run always evaluates to true
So I've tired paths-filter
with the following triggers:
on:
push:
branches:
- my-feature-branch
....
- name: Capture changes
uses: dorny/[email protected]
id: changes
with:
filters: |
my_first_path:
- 'path/to/my_first_path**'
my_second_path:
- 'path/to/my_second_path/**'
my_third_path:
- 'path/to/my_third_path/**'
and the changes are identified correctly (say I made a change under path my_first_path
:
Filter my_first_path = true
Filter my_second_path = false
Filter my_third_path = false
However, once I make the execution of this Worfklow dependent on the successful execution of another workflow
on:
workflow_run:
workflows: ["another workflow"]
types: [completed]
branches:
- master
the filters applied with dorny/[email protected]
always evaluate to true
.
Note that this workflow gets executed once a Pull Requests gets merged to master (this is going to trigger a workflow whose successful completion will trigger the workflow I shared above).
Run dorny/[email protected]
Get current git ref
/usr/bin/git branch --show-current
master
Warning: 'before' field is missing in event payload - changes will be detected from last commit
Change detection in last commit
Detected 821 changed files
Results:
Filter my_first_path = true
Filter my_second_path = true
Filter my_third_path = true
Changes output set to ["my_first_path","my_second_path","my_third_path"]
Any thoughts what am I missing here?
@dorny Any thoughts?
Same behaviour with workflow_dispatch
🤔
Events triggered by workflow_dispatch or workflows_run essentially don't have any context in them that can sensibly be assumed to be referred to as a "state before this change".
You can explicitly pass the paths filter base and ref which allows you to tell paths_filter what things to compare. To make that meaningful you'd probably want an input into the workflow_dispatch, or perhaps you can always generate the change base from say a known branch you want to compare.
I find this extremely useful: https://docs.github.com/en/actions/learn-github-actions/contexts#example-printing-context-information-to-the-log
To help find out what is in the event context that you might be able to pass as base and ref to the paths filter.
I personally ended up with a workaround:
- uses: dorny/paths-filter@v2
id: paths-filter-init
with:
filters: |
service1: services/service1/**
service2: services/service2/**
- name: Hack-1
# when event_name is workflow_dispatch or workflow_call, all the packages are set to true
# so we want to return an empty json array instead as no files were changed
id: hack-1
env:
GH_EVENT_NAME: ${{ github.event_name }}
run: |
case $GH_EVENT_NAME in
workflow_dispatch)
echo "::set-output name=paths-filter-final::'[]'"
;;
workflow_call)
echo "::set-output name=paths-filter-final::'[]'"
;;
*)
echo "::set-output name=paths-filter-final::'${{ toJSON(steps.paths-filter-init.outputs.changes) }}'"
;;
esac
And declared paths-filter-final
output so downstream jobs and steps could use that. If you skip paths-filter
step entirely, you wouldn't have a valid json output
@DpoBoceka
Thanks for the workaround. However I doesn't work for me. I wasn't able to figure it out. When event_name
is workflow_run
all the packages are always set to true
anyway. How do you declare paths-filter-final
so it's true
only if files are really changed ? A full example might be useful.
name: Deploy Test Second
on:
workflow_run:
workflows: ["Deploy Test First"]
branches: [main]
types: [completed]
jobs:
changes-detection:
runs-on: ubuntu-20.04
outputs:
changes: ${{ steps.paths-filter-workaround.outputs.paths-filter-final }}
steps:
- uses: actions/checkout@v3
- uses: dorny/paths-filter@v2
id: paths-filter-init
with:
filters: |
test1:
- "./testonefiledir1/testonefile1.yml"
- "./testmultiplefilesdir1/**"
test2:
- "./testonefiledir2/testonefile2.yml"
- "./testmultiplefilesdir2/**"
- name: paths-filter-workaround
id: workaround-1
env:
GH_EVENT_NAME: ${{ github.event_name }}
run: |
case $GH_EVENT_NAME in
workflow_run)
echo "::set-output name=paths-filter-final::'[]'"
;;
*)
echo "::set-output name=paths-filter-final::'${{ toJSON(steps.paths-filter-init.outputs.changes) }}'"
;;
esac
dorny/paths-filter@v2 step log:
Run dorny/paths-filter@v2
Get current git ref
Warning: 'before' field is missing in event payload - changes will be detected from last commit
Change detection in last commit
Detected 9 changed files
Results:
Filter test1 = true
Filter test2 = true
Changes output set to ["test1","test2"]
paths-filter-workaround step log:
Run case $GH_EVENT_NAME in
case $GH_EVENT_NAME in
workflow_run)
echo "::set-output name=paths-filter-final::'[]'"
;;
*)
echo "::set-output name=paths-filter-final::'"[\"test1\",\"test2\"]"'"
;;
esac
shell: /usr/bin/bash -e {0}
env:
GH_EVENT_NAME: workflow_run
Hi. I faced the same issue and found a workaround. (It's not smart though... )
First of all, my workaround is passing Artifact between workflows.
To do so, you must use action-download-artifact
instead of the official actions/download-artifact
, because the original one doesn't support download artifacts from another workflow.
Step 1. Save refs as artifact.
first-action.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
(...omit...)
- name: Save base ref info
run: |
if [[ '${{ github.event_name }}' == 'push' ]]; then
BASE=${{ github.event.before }}
CURRENT_BRANCH=${{ github.ref }}
elif [[ '${{ github.event_name }}' == 'pull_request' ]]; then
BASE=${{ github.base_ref }}
CURRENT_BRANCH=${{ github.head_ref }}
fi
echo $BASE > base.txt
echo $CURRENT_BRANCH > current-branch.txt
- name: Upload base ref info
uses: actions/upload-artifact@v3
with:
name: original-refs
path: |
base.txt
current-branch.txt
retention-days: 1
Step 2. Download them and set to base and ref.
second-aciton.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Download a single artifact
uses: dawidd6/action-download-artifact@v2
with:
workflow: first-action.yml
name: original-refs
workflow_conclusion: success
- name: set REF_BASE to env
run: |
echo "BASE=$(cat base.txt)" >> $GITHUB_ENV
echo "CURRENT_BRANCH=$(cat current-branch.txt)" >> $GITHUB_ENV
- uses: actions/checkout@v3
with:
ref: ${{ env.CURRENT_BRANCH }}
- uses: dorny/paths-filter@v2
id: filter
with:
base: ${{ env.BASE }}
ref: ${{ env.CURRENT_BRANCH }}
filters: |
src:
- src/**
lib:
- lib/**
The result is here, I've confirmed the output of workflow_run action is same with its first action.
This workflow should work push
and pull_request
event. But you might need to adjust the contents of the artifact (BASE
, CURRENT_BRANCH
), if they are not suitable for your situation.
To check full yml, see my trial repo: https://github.com/gki/paths-filter-workflow-run-workaround