paths-filter icon indicating copy to clipboard operation
paths-filter copied to clipboard

workflow_run always evaluates to true

Open gmyrianthous opened this issue 2 years ago • 6 comments

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?

gmyrianthous avatar Aug 08 '22 16:08 gmyrianthous

@dorny Any thoughts?

gmyrianthous avatar Aug 09 '22 09:08 gmyrianthous

Same behaviour with workflow_dispatch 🤔

DpoBoceka avatar Aug 10 '22 16:08 DpoBoceka

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.

henrycpainter avatar Aug 16 '22 15:08 henrycpainter

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 avatar Aug 17 '22 09:08 DpoBoceka

@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

ghost avatar Oct 14 '22 08:10 ghost

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.

スクリーンショット 2022-10-22 22 50 20

スクリーンショット 2022-10-22 22 44 39

To check full yml, see my trial repo: https://github.com/gki/paths-filter-workflow-run-workaround

gki avatar Oct 22 '22 13:10 gki