Required actions workflows from branch protections should only be required if run #13690
Replies: 39 comments 43 replies
-
Thanks @daltonv. I agree that this is not the ideal solution. I'll talk with the team that owns branch protection to give them your feedback. I'll also talk to the docs team to suggest some improvements for this article in the meantime. Thanks again for taking the time to leave feedback. |
Beta Was this translation helpful? Give feedback.
-
This should be a generalized change as it affects users who don't use GitHub Actions, but instead have third party CI/CD integrations triggered via webhooks. The option should simply be |
Beta Was this translation helpful? Give feedback.
-
See also the most active discussion in ye olde GitHub Community Forum on this topic: https://gh.neting.ccmunity/t/feature-request-conditional-required-checks/16761 |
Beta Was this translation helpful? Give feedback.
-
See also https://gh.neting.ccmunity/t/feature-request-required-checks-conditioned-on-path/2042 |
Beta Was this translation helpful? Give feedback.
-
Ran into it as well. Having something like this would also let us implement more straightforward skipping. For instance, I don't need to to spend the time running all our test, visual regressions, etc. on a PR from an internal bot that edits changelogs, but I absolutely want those to be required checks for us humans so we can use really helpful things like auto-merging, etc. |
Beta Was this translation helpful? Give feedback.
-
Very much want this, we spend piles of cash on GitHub because of this shortcoming. |
Beta Was this translation helpful? Give feedback.
-
+1. We have the same problem over at Keycloak: Multiple workflows / jobs are running for e.g. a simple typo in our documentation, or a bump in npm dependencies. Would be very nice to have better support than the dummy workflow approach. |
Beta Was this translation helpful? Give feedback.
-
Running into similar problem when using conditional workflow via circle-ci. It should not be waiting infinitely if the workflow doesn't run at all |
Beta Was this translation helpful? Give feedback.
-
+1, it's surprising that GitHub and disappointing that GitHub doesn't fully support a code first approach for the definition of requirements. The dummy workaround is hacky to say the least. |
Beta Was this translation helpful? Give feedback.
-
+1 |
Beta Was this translation helpful? Give feedback.
-
+1 |
Beta Was this translation helpful? Give feedback.
-
this is a real pain. any update on this? @ethomson |
Beta Was this translation helpful? Give feedback.
-
Hard not to see this as a cash grab, we've been asking for it for 3 years now, the only way to safely protect branches in this scenario is to run all checks always. |
Beta Was this translation helpful? Give feedback.
-
Came here to add to the chorus of programmers asking for help with this sad trombone UX. |
Beta Was this translation helpful? Give feedback.
-
I got the "dummy workflow workaround" working but it broke after about a week. I don't know if it was some internal Github change or if my setup is just fragile, but the whole situation is pretty disappointing nonetheless. |
Beta Was this translation helpful? Give feedback.
-
I hate to be that guy, but: any official update on this? Maybe this made sense in some convoluted archaic GitFlow with 6 long-lived branches that each have their own branch protection rules, but the world is doing much less of that these days. I looked into the new Repository Rules (in beta as of this writing) thinking GitHub might have been focusing their efforts there, but it seems (so far) that required checks work the same way there. |
Beta Was this translation helpful? Give feedback.
-
+1 for |
Beta Was this translation helpful? Give feedback.
-
I really still can't get my head around how this is being implemented. Where is the |
Beta Was this translation helpful? Give feedback.
-
+1 is there any plan in place for this? |
Beta Was this translation helpful? Give feedback.
-
I ended up having to write a GitHub Action to add a status check that polls other GitHub check runs (but not from 3rd parties). Then marking name: summary
on:
pull_request:
jobs:
enforce-all-checks:
runs-on: ubuntu-latest
permissions:
checks: read
steps:
- name: GitHub Checks
uses: poseidon/wait-for-status-checks@v0.1.0
with:
token: ${{ secrets.GITHUB_TOKEN }} It works, but writing actions is fundamentally limited compared to native GitHub support. First, we have to poll GitHub which is wasteful. Next, it's possible (though unlikely) to race if no other GitHub Checks start for a whle. And finally, when a triggered check fails, developers naturally re-run it, but that can't reasonably re-trigger a job like |
Beta Was this translation helpful? Give feedback.
-
My approach for this has been a reusable workflow named "ready to merge" that parses the |
Beta Was this translation helpful? Give feedback.
-
👋 First thanks for the feedback and discussions on work arounds. This behavior is a long standing one that exists for reasons (no need to bore y'all with history on things we should fix.) We've working on the successor to branch protections in Repository Rules and are making strides to have those interoperate with Actions with Required Workflows. This will help us close gaps between "branch protections" and actions, but not this one yet. That said we do have an internal issue tracking this request. A question for y'all to help us build internal context, what are the typical path filters y'all are using? Is there a specific path/file type etc? Is this limited to only actions workflows or are there areas where path filtering would be useful? |
Beta Was this translation helpful? Give feedback.
-
The most typical use-case is monorepo with frontend/backend/packages, where the only subset of flows that we want to run is what was affected by the PR. Hence paths are something like |
Beta Was this translation helpful? Give feedback.
-
We got an AMAZING workaround by Paul from GitHub enterprise support. Unfortunately he hasn't posted it here himself even though he promised to, roughly two weeks ago. He understands it better and wanted to package it nicer, but this is it: It is a standalone workflow that polls the github API every minute for other workflows running for the same merge request and first completes once none is in progress anymore. How to:
name: Confirm that all checks have passed or skipped
on:
pull_request:
types: [opened, synchronize, reopened]
branches:
- main
jobs:
check_commit_status:
runs-on: ubuntu-latest
steps:
- name: Confirm Check Runs
uses: actions/github-script@v7
with:
script: |
console.log("Sleeping 10s to give other runs a chance to start");
await sleep(10000);
const { owner, repo } = context.repo;
const commit_sha = context.payload.pull_request.head.sha; // Get the SHA of the head commit of the PR
const maxRetries = 15; // Maximum number of retries
const excludedCheckRunName = 'check_commit_status' // important you don't define name key for the job
let retryCount = 0;
async function fetchCheckRuns() {
const response = await github.rest.checks.listForRef({
owner,
repo,
ref: commit_sha,
per_page: 100
});
return response.data.check_runs;
}
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
let checkRuns = await fetchCheckRuns();
let inProgressFound = false;
let failureFound = false;
do {
inProgressFound = false;
failureFound = false;
for (const checkRun of checkRuns) {
// exclude this job from the evaluation
if (checkRun.name === excludedCheckRunName) {
console.log(`Skipping excluded check run: ${checkRun.name}`);
continue;
}
if (checkRun.status === 'in_progress') {
inProgressFound = true;
console.log(`Check run in progress: ${checkRun.name}`);
}
if (checkRun.conclusion === 'failure') {
failureFound = true;
console.log(`Check run failed: ${checkRun.name}`);
}
}
if (inProgressFound) {
if (retryCount >= maxRetries) {
core.setFailed('Maximum retries reached with check runs still in progress.');
break;
}
console.log('Waiting for 1 minute before rechecking...');
await sleep(60000);
checkRuns = await fetchCheckRuns();
retryCount++;
}
} while (inProgressFound);
if (failureFound) {
core.setFailed('There are failed check runs.');
}
Edit: if you want to save github actions minutes by first starting the workaround workflow after some minutes, you can add
|
Beta Was this translation helpful? Give feedback.
-
I've created a GitHub Action that wraps the logic of what @danieltroger described in a nicer package. Check it out at https://github.com/wechuli/allcheckspassed. It provides some additional options such as excluding certain checks from the evaluation and choosing what exactly constitutes a passing check (e.g. skipped, neutral). The action also creates a summary of the checks that were evaluated. Additional documentation is on the README. Ultimately this is only a workaround for a missing feature, the main downside it has is that you need to configure it on its own workflow and it will consume your Actions minutes, I have tried to document this under limitations section. Let me know what you think, if you want some features it doesn't have, please open an issue (or a pr 😉 ). |
Beta Was this translation helpful? Give feedback.
-
Just a note that https://github.com/palantir/policy-bot is a great option until github support this. Only real downside is the duplication of conditions between the policies and the conditional jobs imo. |
Beta Was this translation helpful? Give feedback.
-
the way I solved this issue is by adding a job like the following to all the workflows.
and a dummy workflow that with the same job name that runs exit 0. and marked check-for-successful-tests as required. this way i'm sure that the job runs 100 percent of the time and also if a required check is failing it blocks the merge. |
Beta Was this translation helpful? Give feedback.
-
We've actually used https://github.com/dorny/paths-filter to create conditional actions, based on paths, that still succeed in the end. Workflow runs, it decides if it needs to do the work, and then passes/fails based on the work. If it doesn't need to do the work, it skips the conditional job, and passes. |
Beta Was this translation helpful? Give feedback.
-
I tried the path filter action approach, and it’s been incredibly frustrating. The configuration goes like this:
Initially, this seemed like a reasonable solution, but it completely breaks down when you have even a slightly complex setup with job dependencies. For example, my CI has a build phase and a test phase, where the test phase has a matrix of runtime arguments. All these test jobs with different matrix values are marked as "required checks to pass." The issue arises when the file changes aren’t related to this CI. In such cases, I need to skip the build and test phases. If I use To hack around this, you can’t rely on path filtering in the workflow or job scope. Instead, you have to move the path filtering logic into steps. You check the output of the path filter job as a global variable, and in every job, the first step checks this variable. If the job needs to be skipped, you force a pass in the step itself, not in the job’s This approach is far more complicated than it should be. Something as basic as skipping jobs based on file changes shouldn’t require this level of convoluted hacking. It’s frustrating and feels like an overengineered solution for what should be a straightforward problem. |
Beta Was this translation helpful? Give feedback.
-
If you have branch protections set so that a GitHub Action workflow must be run and pass before you can merge, and this workflow has path filtering in the
on:
clause then you sometimes can't ever merge because the workflow doesn't run.This GitHub docs talk about this issue here: https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks
There is a workaround suggested in the doc article, but it involves making a "dummy" workflow of the same name of the required workflow. This dummy workflow always passes and is triggered by the inverse path filtering of the required workflow.
This isn't the best solution in my mind because:
Instead it should be changed so local workflows are only required if they run in the first place.
Beta Was this translation helpful? Give feedback.
All reactions