fix(data,export): collapse the STEP string escaper's two TS copies into one (#3300) #137
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This Source Code Form is subject to the terms of the Mozilla Public | |
| # License, v. 2.0. If a copy of the MPL was not distributed with this | |
| # file, You can obtain one at https://mozilla.org/MPL/2.0/. | |
| name: PR review signal | |
| # NO `paths:` FILTER, DELIBERATELY, AND FOR TWO SEPARATE REASONS. | |
| # | |
| # 1. This gate's question is "did the other lanes run at all". A path filter | |
| # would make it skip on exactly the changes whose lanes are missing. | |
| # 2. It reads scripts/pr-review-signal.config.json. #3305's gate could not fire | |
| # on the file it guarded because that file was in no path filter, so the gate | |
| # existed, was correct, and was unreachable on its own input. With no filter | |
| # here, no edit to the script or its config can dodge the job that runs them | |
| # ON THE PATH THAT MERGES IT. Asserted in | |
| # scripts/check-pr-review-signal.test.mjs. | |
| # | |
| # THE SCOPE OF THAT CLAIM, stated rather than left to be discovered: the | |
| # `branches: [main]` filter below means a PR based on a FEATURE branch does | |
| # not run this job, so both files can change on such a PR with no gate run. | |
| # That is not a hole to close by widening the filter -- the required lane set | |
| # is derived from test.yml, which carries the same `branches: [main]`, so on | |
| # a feature-targeted PR every required lane is legitimately absent and this | |
| # gate would fail every stacked PR for a reason that is not a defect. The | |
| # residue is bounded by the retarget rule the next paragraph describes: | |
| # pointing such a PR at main fires `edited`, which runs this job, and it must | |
| # then pass before the change reaches main. | |
| # | |
| # `edited` IS THE POINT OF THE TYPES LIST. GitHub's default `pull_request` | |
| # activity types are opened/synchronize/reopened. Retargeting a PR's base branch | |
| # fires `edited` and nothing else -- and it does NOT re-fire the workflows that | |
| # a `branches: [main]` filter had excluded while the PR pointed at a feature | |
| # branch. That is the deterministic, reproducible mechanism behind #3294 merging | |
| # with 8 checks and leaving main's module-size gate red. Without `edited` here, | |
| # this detector would miss the one case it was built for. | |
| # | |
| # `ready_for_review` covers the draft->ready transition for the same reason. | |
| on: | |
| pull_request: | |
| branches: [main] | |
| types: [opened, synchronize, reopened, edited, ready_for_review] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| # The two reads this gate is made of. `checks: read` for the check runs, | |
| # `statuses: read` for the commit statuses -- the reviewers publish as one or | |
| # the other, and the free-text description only exists on the raw APIs. | |
| checks: read | |
| statuses: read | |
| env: | |
| ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION: node24 | |
| jobs: | |
| review-signal: | |
| # This name is passed to the gate as `--self-name` so it can drop its own | |
| # lane from the rollup. It is `in_progress` for as long as it is asking the | |
| # question, and leaving it in would mean the rollup never reads as settled. | |
| name: PR review signal | |
| # Free runner: two API reads and a poll, not compute-bound. | |
| runs-on: ubuntu-latest | |
| # Above the poll budget below, so a run that exhausts the budget still gets | |
| # to PRINT its verdict rather than being killed mid-wait with no output. | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| lfs: false | |
| persist-credentials: false | |
| # No `pnpm install`: the gate imports only node builtins plus its own lib, | |
| # and shells out to `gh`, which is preinstalled on GitHub runners. A gate | |
| # whose job is to run when other jobs did not should depend on as little | |
| # as possible. | |
| # | |
| # THE BUDGET IS MEASURED, NOT GUESSED -- AND THE MEASUREMENT ITSELF WAS | |
| # WRONG ONCE. The first version of this comment quoted `started_at`, i.e. | |
| # when a runner picked each job up. This gate never waits for that: it | |
| # polls for PRESENCE in the rollup, which is `created_at`, and the two | |
| # diverge hard: on run 32930088375, `Lint` was CREATED 416 s into the run | |
| # and STARTED 1037 s into it. Every figure below is `created_at`, | |
| # measured from each run's own creation, over the 68 completed `test.yml` | |
| # PR runs of 2026-08-25/26 that published the aggregate. | |
| # | |
| # The fix is TWO changes, because either alone still false-fails. | |
| # 1. `excludeJobKeys: ["test"]` in the config drops the aggregate, and | |
| # this is the load-bearing half. It `needs:` twelve jobs and | |
| # publishes no check run until all finish, so requiring it ties this | |
| # budget to the SUITE's total runtime, which grows with the suite. It | |
| # appeared at min 509 / median 894 / max 2067 s -- 33 OF THE 68 PAST | |
| # 900 s. Requiring it would false-fail roughly half of every green | |
| # PR. Nothing is lost: the aggregate is one of only two contexts in | |
| # main's ruleset, so branch protection already blocks on it, and the | |
| # #3294 total-absence shape still fails under this config naming all | |
| # fifteen lanes. | |
| # 2. 900 s, not 420 s. Excluding the aggregate is not enough on its own: | |
| # the last non-aggregate lane appeared at min 161 / median 190 / | |
| # p95 522 / max 845 s, so 420 s would still have false-failed 8 of | |
| # the 68. 900 s covers all 68 -- but the tail margin is 900/845 = | |
| # 1.07x, NOT the 1.33x this comment used to claim off the `started_at` | |
| # numbers. It is thin, and measuring from run creation is the | |
| # conservative direction (this job's own deadline starts later still, | |
| # after its pickup and checkout), so the margin is worth stating | |
| # plainly rather than rounding up. | |
| # The poll normally returns in seconds via the settle rule; the budget is | |
| # the ceiling, not the expected cost. A settled-but-incomplete rollup is | |
| # confirmed across SETTLE_HOLD_SECONDS (60 s) before its absence counts, | |
| # because the fan-out boundary produces a ~1 s window in which every | |
| # published lane is terminal and more are still coming -- so the | |
| # genuine-absence path costs 60 s, not the whole budget. | |
| # THE GATE'S OWN UNIT TESTS, RUN BEFORE THE GATE. Neither | |
| # `scripts/check-pr-review-signal.test.mjs` nor | |
| # `scripts/lib/pr-review-signal.test.mjs` was reached by any workflow: the | |
| # test.yml lanes name their script files one by one and this pair was | |
| # never added, and `check-test-glob-coverage` audits package globs, not | |
| # `scripts/`. A gate whose fail-closed refusals, severity knobs and | |
| # policy scopings are asserted only on a developer's machine is a gate | |
| # nobody is checking, which is the shape this whole workflow exists to | |
| # reject. Same job, no `pnpm install` -- node builtins only, like the gate. | |
| - name: Unit-test the gate itself | |
| run: node --test scripts/check-pr-review-signal.test.mjs scripts/lib/pr-review-signal.test.mjs | |
| - name: Check required lanes ran and reviews produced a verdict | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| run: | | |
| node scripts/check-pr-review-signal.mjs \ | |
| --pr "${{ github.event.pull_request.number }}" \ | |
| --self-name 'PR review signal' \ | |
| --timeout-seconds 900 |