Reputation: 5371
Let's say I have a pull request like this.
name: Workflow
on:
pull_request:
paths:
- '**/*.h'
- '**/*.c'
I protect the master
branch by configuring GitHub Actions to require the status check to pass before the pull request is mergable.
Now I update a readme doc. I open a pull request against master
. The pull request is unmergable because the status check never returns a success nor does it return a fail.
Suggestions?
Upvotes: 12
Views: 4448
Reputation: 159
Github docs suggest using conditionals instead of path filters. Additional information here Github docs
However, I found that approach to be very cumbersome, especially for mono-repos.
An alternative would be to use something like https://github.com/upsidr/merge-gatekeeper/tree/main
Merge Gatekeeper was created to provide more control for merges. By placing Merge Gatekeeper to run for all PRs, it can check all other CI jobs that get kicked off, and ensure all the jobs are completed successfully. If there is any job that has failed, Merge Gatekeeper will fail as well. This allows merge protection based on Merge Gatekeeper, which can effectively ensure any CI failure will block merge. All you need is the Merge Gatekeeper as one of the PR based GitHub Action, and set the branch protection rule as shown below.
Upvotes: 0
Reputation: 1387
The answer provided by the docs (Vicky's answer) doesn't work correctly for me. Providing multiple values for paths-ignore isn't preventing the generic/duplicate workflow from running. Since the original and the duplicate/generic workflow both run, we're still able to merge before the check finishes unfortunately.
This commit on Github shows a viable way of handling it that isn't too complicated:
The relevant snippet (under "steps"):
- name: Check if relevant files have changed
uses: actions/[email protected]
id: service-changed
with:
result-encoding: string
script: |
const result = await github.pulls.listFiles({
owner: context.payload.repository.owner.login,
repo: context.payload.repository.name,
pull_number: context.payload.number,
per_page: 100
})
const serviceChanged = result.data.filter(f => f.filename.startsWith("app/") || f.filename.endsWith("gradle") || f.filename.startsWith(".github") || f.filename.startsWith("gradle") || f.filename.endsWith("properties")).length > 0
console.log(serviceChanged)
return serviceChanged
- name: Checkout repository
if: ${{ steps.service-changed.outputs.result == 'true' }}
uses: actions/checkout@v1
- name: Copy CI gradle.properties
if: ${{ steps.service-changed.outputs.result == 'true' }}
run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties
Here are some other options I've found that look less viable or much more complicated:
Upvotes: 2
Reputation: 145
The docs suggest creating another action with the same name, that runs when the opposite condition is met. In your case, you'd want
name: Workflow
on:
pull_request:
paths-ignore:
- '**/*.h'
- '**/*.c'
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: 'echo "No build required" '
Notice the paths-ignore
.
Upvotes: 11