Skip to content

bug(ci): path-filtered checks marked required brick unrelated PRs (Schema Parity Gate, verify-non-root) #1228

@dolho

Description

@dolho

Summary

Two CI workflows are configured as required status checks in branch protection (org ruleset), but both filter at the workflow trigger level via on.pull_request.paths:

  • Schema Parity Gate.github/workflows/schema-parity.yml (context: schema-parity)
  • Container Security.github/workflows/container-security.yml (contexts: verify-non-root, verify-prod-frontend-uid)

When a PR changes no files matching those path globs, the workflow never runs, so the required check context is never reported. GitHub then keeps the PR in mergeStateStatus: BLOCKED"Expected — Waiting for status to be reported" — even though the PR is approved and every check that did run is green. The result: every PR that doesn’t touch db/** (schema-parity) or docker/**, docker-compose*.yml, scripts/deploy/start.sh, src/mcp-server/Dockerfile (container-security) is silently un-mergeable.

Impact

Root cause

on.pull_request.paths filters at the workflow level, not the job level:

  • Workflow not triggered (no path match) → GitHub creates no check run for that context → a required check by that name stays pending forever → merge blocked.
  • This differs from a skipped job: if the workflow runs but a job is gated off via if:, GitHub reports that job as skipped, which branch protection treats as neutral/success. The trap is assuming “skipped = pass” — that only holds when the workflow itself triggers.

The schema-parity.yml header already warns about exactly this:

"MAINTAINER NOTE: do NOT add this job to required-status-checks in branch protection until it has been green for ~1 week… any path-filter false-negative would brick PRs that don’t touch DB files. The workflow self-skips on unrelated PRs… so leaving it optional is safe."

So schema-parity should not be a required check while it is path-filtered; verify-non-root / verify-prod-frontend-uid have the same property.

Recommended fix (A) — un-require the path-filtered contexts

In the org ruleset for abilityai/trinity (the requirement is not classic branch protection — branches/dev/protection 404s — nor a repo ruleset — repos/abilityai/trinity/rulesets is empty — so it lives at orgs/abilityai/rulesets), remove these from Require status checks to pass:

  • schema-parity
  • verify-non-root
  • verify-prod-frontend-uid

They keep running (and gating) on PRs that touch their paths; they just stop blocking unrelated PRs. Requires repo/org admin (a maintain collaborator cannot edit the ruleset).

Alternative fix (B) — keep them required, make the context always report

If enforcement-on-every-PR is desired, convert each to the skip-aware gate pattern instead of un-requiring:

  1. Drop on.pull_request.paths so the workflow always triggers.
  2. Do the path discrimination inside (e.g. dorny/paths-filter, or per-job if:).
  3. Add a final always-running gate job that carries the required context name and reports success when the heavy job was not applicable.

Note: naively just deleting on.paths would make container-security boot a full docker compose stack on every PR (slow/expensive) — the gate pattern avoids that. This is a code change and can land via PR; fix A cannot (it is a Settings/ruleset toggle, not a repo file).

Acceptance criteria

  • A PR that touches neither db/** nor the container paths can reach a mergeable state (no pending phantom required check).
  • schema-parity / container-security still run and gate PRs that do touch their paths.

Evidence / references

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions