From 42d9b1313ea8de108fa1fd63f448d38f5792da2d Mon Sep 17 00:00:00 2001 From: admin Date: Fri, 14 Aug 2026 08:59:57 -0500 Subject: [PATCH] feat(hybrid-gate): expose docs_only so callers stop reimplementing it This workflow already computes whether a change is docs-only, and uses it to skip its own full-gate-build. It never exposed that to the caller, so an adopting repo wanting the same saving had to restate the path patterns locally -- a second copy of logic that lives here, free to diverge, and invisibly so since each side would look correct alone. thumos hit this and stopped short of building the local version for exactly that reason (thumos#775): under `strict: true` every merge invalidates every open PR, so a one-line markdown change re-ran an armv7a cross-compile and the whole QEMU witness matrix, ~324s, twice. The output carries two warnings a caller needs and cannot infer: A required check must not be gated with a job-level `if:` or a `needs:` on a preflight -- either leaves the required context never reporting and strands the PR permanently. Gate the expensive STEPS inside the job so the check still reports. A required check that can pass vacuously is worse than a slow one. And the value is EMPTY, not `false`, when check-trailer does not reach a verdict. Callers act only on the literal `'true'`, which is the same conservative direction this workflow's own docs-only step takes for an empty diff. Additive: no existing caller changes behaviour. --- .github/workflows/hybrid-gate.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/.github/workflows/hybrid-gate.yml b/.github/workflows/hybrid-gate.yml index 46f6cbd..b9d8ba1 100644 --- a/.github/workflows/hybrid-gate.yml +++ b/.github/workflows/hybrid-gate.yml @@ -24,6 +24,33 @@ name: Hybrid Gate (reusable) on: workflow_call: + # WHY expose this: under `strict: true` every merge invalidates every open + # PR, so a markdown-only change re-runs a caller's full required job. This + # workflow already computes exactly the fact that would avoid that, and a + # caller reimplementing the path patterns locally would be a second copy of + # logic that lives here -- free to diverge, and invisibly, since each side + # would look correct in isolation. (thumos#775 measured ~324s of armv7a + # cross-compile and QEMU witness matrix re-run twice for one one-line PR.) + # + # WARNING for callers: a caller must NOT gate a required check on this with + # a job-level `if:` or a `needs:` on a preflight job -- either leaves the + # required context never reporting, which strands the PR permanently. Gate + # the expensive STEPS inside the job instead, so the check still reports. + # A required check that can pass vacuously is worse than a slow one. + # + # WARNING on the empty case: this is empty rather than `false` when + # check-trailer is skipped or cancelled. Treat anything other than the + # literal `'true'` as not-docs-only -- the conservative direction, and the + # same one this workflow's own `docs-only` step takes for an empty diff. + outputs: + docs_only: + description: >- + `'true'` when every changed path matched the docs-only patterns + (`*.md`, `docs/*`, `llms.txt`) and the caller did not set + `docs_only_exemption`. Empty when check-trailer did not run to a + verdict. Callers should skip expensive steps only on the literal + string `'true'`. + value: ${{ jobs.check-trailer.outputs.docs_only }} inputs: rust_toolchain: description: >-