-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: Option to count skipped jobs in has_successful_status #760
Comments
Thanks for the suggestion. I can think of several ways this could be added - are any of these preferable (or objectionable) for your usage?
|
From my perspective, the first 2 are equal. Server-level configuration is less good - it's possible that there are teams in our org replying on the current behaviour although I'm not aware of a specific use-case for that. Let me know if you would rather we contribute the change once you have a suggested approach. Thanks! |
The `has_successful_status` predicate currently requires predicates to be present and successful in order to pass. But workflows can be run conditionally - for example only if certain paths change - and it is currently not very convenient to write a policy which considers such skipped workflows as passing. The only feasible workaround is to duplicate the path filters in the policy, and this quickly gets unwieldy and prone to getting out-of-sync in large repositories. Here we add direct support for specifying such rules. This is done by introducing a new alernative form that `has_successful_status` predicates can take: ```yaml has_successful_status: options: skipped_is_success: true statuses: - "status 1" - "status 2" ``` In this mode, we will consider the `skipped` result as acceptable. The current form: ```yaml has_successful_status: - "status 1" - "status 2" ``` remains supported. We have done this by implementing a custom unmarshaling function to be able to handle both forms. Closes: palantir#760
We need this too at our organisation, so I had a go at implementing the second option in #789. Hope it helps! |
The `has_successful_status` predicate currently requires predicates to be present and successful in order to pass. But workflows can be run conditionally - for example only if certain paths change - and it is currently not very convenient to write a policy which considers such skipped workflows as passing. The only feasible workaround is to duplicate the path filters in the policy, and this quickly gets unwieldy and prone to getting out-of-sync in large repositories. Here we add direct support for specifying such rules. This is done by introducing a new alernative form that `has_successful_status` predicates can take: ```yaml has_successful_status: options: skipped_is_success: true statuses: - "status 1" - "status 2" ``` In this mode, we will consider the `skipped` result as acceptable. The current form: ```yaml has_successful_status: - "status 1" - "status 2" ``` remains supported. We have done this by implementing a custom unmarshaling function to be able to handle both forms. Closes: palantir#760
The `has_successful_status` predicate currently requires predicates to be present and successful in order to pass. But workflows can be run conditionally - for example only if certain paths change - and it is currently not very convenient to write a policy which considers such skipped workflows as passing. The only feasible workaround is to duplicate the path filters in the policy, and this quickly gets unwieldy and prone to getting out-of-sync in large repositories. Here we add direct support for specifying such rules. This is done by introducing a new alernative form that `has_successful_status` predicates can take: ```yaml has_successful_status: options: skipped_is_success: true statuses: - "status 1" - "status 2" ``` In this mode, we will consider the `skipped` result as acceptable. The current form: ```yaml has_successful_status: - "status 1" - "status 2" ``` remains supported. We have done this by implementing a custom unmarshaling function to be able to handle both forms. Closes: palantir#760
Just writing down our requirements since I discovered that what I thought this was was not quite correct 😁. We've got a monorepo with a whole bunch of GitHub Actions workflows that run conditionally. Imagine quite a lot of workflows like this. on:
pull_request:
branches:
- main
paths:
- foo/**
- bar/baz/*
jobs:
a:
b:
c: What I want us to be able to say is that if the workflow is run, then all jobs in it must pass. What I implemented in #789 allows that to happen at the job level. So if you have a workflow like this on:
pull_request:
branches:
- main
job:
a:
if: something
# ... You could require that But in the case of the first example that's not true. GitHub will entirely skip over the workflow and there is nothing that I've been able to find in any API which you can use to find this out directly. The approach I've been exploring, which seems to work when I test it with a fork of Policy Bot with all these PRs merged in, is a combination of things:
The config it generates looks like this: # This file is generated by generate-policy-bot.yml.
# Do not edit directly. Run "make .policy-bot.yml" to update
policy:
approval:
- and:
- .github/workflows/foo.yml succeeded
- .github/workflows/bar.yml succeeded or skipped
# This is so that the group succeeds if all the workflows have path filters. In that case we get "All rules were skipped. At least one rule must match."
- default to approval
- policy bot config is valid when modified
approval_rules:
# A workflow which doesn't have any path filter
- name: .github/workflows/foo.yml succeeded
requires:
conditions:
has_workflow_result:
workflows:
- .github/workflows/foo.yml
# A workflow which has path filters
- name: .github/workflows/bar.yml succeeded or skipped
if:
changed_files:
paths:
# This is `foo/**` as a regex!
- ^foo\/(?:(?:[^/]*(?:/|$))*)$
requires:
conditions:
has_workflow_result:
workflows:
- .github/workflows/bar.yml
- name: default to approval
# Merged from a local config so we can have generated & non-generated policies and rules
- name: policy bot config is valid when modified
if:
changed_files:
paths:
- ^\.policy\.yml
requires:
conditions:
has_successful_status:
statuses:
- Validate Policy Bot Config (feedback on this structure is appreciated; I'm still new at writing configs) |
The `has_successful_status` predicate currently requires predicates to be present and successful in order to pass. But workflows can be run conditionally - for example only if certain paths change - and it is currently not very convenient to write a policy which considers such skipped workflows as passing. The only feasible workaround is to duplicate the path filters in the policy, and this quickly gets unwieldy and prone to getting out-of-sync in large repositories. Here we add direct support for specifying such rules. This is done by introducing a new alernative form that `has_successful_status` predicates can take: ```yaml has_successful_status: options: skipped_is_success: true statuses: - "status 1" - "status 2" ``` In this mode, we will consider the `skipped` result as acceptable. The current form: ```yaml has_successful_status: - "status 1" - "status 2" ``` remains supported. We have done this by implementing a custom unmarshaling function to be able to handle both forms. Closes: palantir#760
@iainlane sorry, I missed this explanation of your goal when you posted it originally. Looking at it now, I wonder if something like this could work: policy:
approval:
- policy bot config is valid when modified
- or:
- workflow bypass authorized
- and:
- workflow foo passed
- workflow bar passed
approval_rules:
- name: workflow foo passed
if:
has_status:
conclusions: [action_required, cancelled, failure, neutral, success, skipped, stale, timed_out]
statuses:
- Workflow Foo
requires:
conditions:
has_successful_status:
statuses:
- Workflow Foo
- name: workflow bar passed
if:
has_status:
conclusions: [action_required, cancelled, failure, neutral, success, skipped, stale, timed_out]
statuses:
- Workflow Bar
requires:
conditions:
has_successful_status:
statuses:
- Workflow Bar
- name: workflow bypass authorized
requires:
count: 2
permissions: [admin]
- name: policy bot config is valid when modified
if:
changed_files:
paths:
- ^\.policy\.yml
requires:
conditions:
has_successful_status:
statuses:
- Validate Policy Bot Config Assuming you trust your workflows to have the correct paths (and based on your original goal for not duplicating paths, I think you do), the basic idea here is:
I haven't tested this, but I think it would work and save you from having to duplicate the file paths (and maybe generate the config at all, depending on the number of workflows you have.) The most important thing to keep in mind is the third point above: the fallback rule must not pass automatically, or it is very likely that the first |
GitHub branch protection rules and rulesets count skipped jobs as "success". Given GitHub's underpowered required checks config, this "feature" is commonly used with path filtering to avoid running unnecessary jobs in monorepos etc.
We also use policy-bot to ping reviewers directly when a PR is in a reviewable state (including minimum checks pass).
As
has_successful_status
only counts "success" state we have had to consider these workarounds:1. Only policy-bot as the required check
The path filtering is moved to the policies - expensive jobs run unnecessarily
2. Duplicate the conditions in policy-bot
High risk of the filtering logic getting out-of-sync
3. Additional job (chosen)
Add an additional job that is dependent on the conditional jobs and fails if any of the conditional job results is not "success" or "skipped". This job is referenced in
has_successful_status
.Small extra expense, some additional complexity and confusing PR check summary.
Thanks for your time!
The text was updated successfully, but these errors were encountered: