Skip to content

Commit 842a0ae

Browse files
ci: assert the Turbo remote cache is on after Build Core, the Test Core closure and the three Type Check builds (#25419)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} --> _Requested by **Elon** · [project thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DY934Zuxuxy6J1RxTkCS2QV)_ Fixes #25374 Clause-②: no Metadata-protocol: none Claim: comment 6364174741 on the card (session `session_01QPa866zGYAuVVnv8kKLnKg`, branch `claude/project-thread-hr4due`). Tier H: `.github/workflows/ci.yml` and `.github/workflows/lint.yml` are on the governed register, so this PR stays draft until a GOVERNED_APPROVERS approval. ## 维护者速读(草稿) **改了什么**:CI 里五处走 Vercel Turbo 远程缓存的构建(Build Core、Test Core 每个分片的依赖闭包构建、lint 的三条 Type Check 车道)后面各加一步「远程缓存是否开着」的断言。它读 turbo 自己打印的那一句 `Remote caching enabled / disabled / unavailable (…)`,并把本次构建的远程命中、本地命中、未命中个数写进该 job 的 Step Summary。新脚本一个:`scripts/ci/assert-turbo-remote-cache.mjs`;另把门禁 `check-ci-filter-parity` 的识别放宽到「`pnpm build` 后只跟这两个报告类参数」,其余写法照旧拒绝。 **为什么改**:远程缓存的 token 只在签名密钥非空时才传,任何一个密钥或变量缺失、轮换,缓存就静默关掉,构建照样绿,只在日志里留一句没人读的话。每个 PR 十条并行构建可能长期在冷跑而无人察觉。 **风险与代价(含回滚)**:合并队列与 main 推送(会写远程缓存的运行)在缓存关闭时会变红,直到有人补好密钥;PR 与定时运行只出黄色警告(fork PR 拿不到密钥)。Vercel 连不上或服务端报错只警告,不红队列。新增步骤耗时为毫秒级;两个新增的 turbo 参数不改变任何任务哈希(83/83 相同)。回滚:还原本 PR 即可,无数据或产物迁移。 **席位意见**: **你要做的**:批准本 PR(受管面)。 ## What changed - **`scripts/ci/assert-turbo-remote-cache.mjs`** (new, `--self-test` with a battery floor and the handshake). It reads the build step's turbo **structured log** for the prelude line, and the run summary (`--summarize`) for each build task's `cache.source`. The summary does not record whether the remote cache was on, which is why both are read. Verdict table (header is the authority): - `enabled`: green. - `disabled` (any reason), or `unavailable` for an account state (auth failed, disabled for the team, usage limit, spending paused, the mid-run 403): **red on a writing run, a warning otherwise**. A writing run is `merge_group`, or `push` / `workflow_dispatch` on `refs/heads/main`: the `remote:rw` branch of the TURBO_CACHE expression. - `unavailable` for a transient reason (`Could not connect`, `Unexpected server error`): a warning on every run, so a Vercel outage does not block the merge queue. - no prelude line, no log, or no summary: exit 3 PREREQUISITE NOT MET on every run. - Remote hits are reported, never judged. - **The five carriers** pass `--summarize --log-file=.turbo/remote-cache/SITE.json` to their existing `turbo run build`. The assertion step runs straight after each: - Build Core: `The Turbo remote cache was on for the build`. Build Core also runs the script's `--self-test` once, beside `check-dts-emitted self-test`. - Test Core closure: `The Turbo remote cache was on for this shard's closure build`, with `--if-ran` (an empty shard runs no turbo) and `--move-summary-to "$RUNNER_TEMP/turbo-remote-cache"`, so `.turbo/runs/` is still the test step's alone for the drift check and the timings capture. The closure comment that said "No `--summarize`" now says why it is there. - lint.yml `Type Check · workspace`, `· debt ledger` and `· consumer gates`: `The Turbo remote cache was on for the workspace build`, `id: turbo-remote-cache-was-on` + `continue-on-error: true`, so it is a lane gate and `lane-verdict.mjs` carries its red while the lane's other gates still run. - Build Core's "Turbo remote cache (#21186)" comment gains an ASSERTED paragraph. The other carriers point back to it. - **`scripts/check-ci-filter-parity.mjs`** (one file beyond the dispatched surface; see Deviations). Its Build Core subject required a step whose `run:` is exactly `pnpm build`, so Build Core's new `pnpm build --summarize --log-file=…` was refused. The recognizer (`isBuildCommand`) now accepts `pnpm build` followed ONLY by the closed list `--summarize` and `--log-file=PATH`. These flags change what turbo reports, never the task set. Anything else still refuses. 9 new battery-(9) cases, floor 33 → 42: - pass: both flags, and `--summarize` alone; - refuse: `--filter=…` beside them, `--affected`, an unknown flag (`--force`), an empty `--log-file=`, a `--` passthrough, the same flags on `pnpm test`, and a second command after the build. - The fixture now quotes `run:` so a multi-line value stays one YAML scalar. - Ablations: making the flag check always true reds 6 of the 7 refusal cases (the `pnpm test` one is held by the prefix check). Dropping the prefix check reds the `pnpm test` case. - The new script gets its Build Core guard row in ci.yml's `core:` filter (`check-ci-filter-parity` derives it: Build Core runs the script's self-test and assertion). ## Measured - **Flags do not move a hash.** `turbo run build --filter=!@objectstack/docs --dry=json`, with and without `--summarize --log-file=.turbo/remote-cache/x.json`: 83 of 83 tasks, 0 differing hashes (turbo 2.11.5). - **`--log-file` must be repo-relative.** An absolute path outside the repo prints `Structured log path '…' escapes the repository root, using default location` and writes `.turbo/logs/EPOCH.json` instead. A repo-relative path creates its directory. - **The structured log is not valid JSON as a whole.** turbo 2.11.5 leaves some separating commas out, so it is read line by line. - **The three states, from a real run** (turbo 2.11.5, `--filter=@objectstack/formula`): - no token: `Remote caching disabled (remote cache requested — set TURBO_TOKEN and TURBO_TEAM, or run "turbo login" and "turbo link"), using shared worktree cache`; - token without team: `Remote caching disabled (TURBO_TOKEN set without TURBO_TEAM)`; - token and team, no route to Vercel: `Remote caching unavailable (Could not connect to "https://vercel.com/api")`, at level `warn`. - `enabled` cannot be produced from a seat container, which has no route to Vercel. The prelude wording is read from the turbo binary's strings, and the full set of `disabled` / `unavailable` reasons comes from the same place. - **Token withheld, writing run: the simulation.** This is the acceptance's PR-side simulation. A real `turbo run build --filter=@objectstack/formula --summarize --log-file=.turbo/remote-cache/sim.json` was run with `TURBO_TOKEN=` (what the carriers' expression yields with the signing key empty). The script was then run on its log: - `GITHUB_EVENT_NAME=merge_group`: exit **1**, with `::error title=Turbo remote cache disabled (…)::Remote caching disabled (remote cache requested — set TURBO_TOKEN and TURBO_TEAM, …) -- this run writes the remote cache, so it must be on. …`; - `GITHUB_EVENT_NAME=pull_request`: exit 0, with the same sentence as a `::warning`; - the summary was moved out of `.turbo/runs/` (now empty); - `--if-ran` with no log: exit 0, "the build step ran no turbo". - **Before (the card's item 3).** Merge-queue run 39939612132 (`830a63a`): Build Core `Build packages (excluding docs)` 4m21s, `Cached: 38 cached, 76 total`. The six closure builds took 2m14s to 3m28s. The prelude line itself is outside the 5,000 lines a seat container can read from that log, so whether the remote cache was on before this change is read from **this PR's first run**: the new step summary on Build Core and on each closure shard. The seat records that reading on the card. ## Not changed, on purpose - No new job, workflow or check context: every new step sits inside a job that is already required (`check:required-contexts`). - The `test` / `test:repo` / `typecheck` steps stay off the remote, as Build Core's PINS require. The assertion steps run no turbo. - Only the first build of each lint lane asserts: the lane's second build carries the same four TURBO_* lines, so it would print the same state. ## Deviations - **One file beyond the dispatched surface, approved by the seat on 2026-10-23.** That file is `scripts/check-ci-filter-parity.mjs`; the seat's conditions were the closed allowlist, cases both ways, and the 83/83 measurement stated here. On its own it reads NOT governed; this PR is Tier H because of the two workflows. ## Acceptance notes - Two more remote-cache carriers exist and are **not** asserted here, because the card names five places. They are Temporal Conformance (four build steps, ci.yml `temporal-conformance`) and the dogfood closure build (ci.yml `dogfood`). Each needs the same two flags and one step. Leaving them is a scope choice for the seat; the script needs no change for them. ## Gates At head `ef582fff` (this branch merged with `origin/main` `f0fdd45b`), after a full `pnpm build`: - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derives 71 commands for the 4 paths. All 71 ran and all 71 exited 0. `--ran` over the record: 71 derived, 71 run, 0 NOT-MEASURED. - Of those, `node scripts/check-ci-filter-parity.mjs` and its `--self-test` (140 assertions) were red in the first round, before the gate change, and are green now. - `node scripts/ci/assert-turbo-remote-cache.mjs --self-test`: 32 cases across 6 batteries, OK. - `eslint --no-inline-config` over both scripts: exit 0. - `node scripts/pm/check-governed-merges.mjs --branch HEAD`: governed (Tier H) through `.github/workflows/ci.yml` and `lint.yml`; the two scripts are not on the register; 526 changed lines (+514 / −12). --- _Generated by [Claude Code](https://claude.ai/code/session_01QPa866zGYAuVVnv8kKLnKg)_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QPa866zGYAuVVnv8kKLnKg --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent e207b97 commit 842a0ae

4 files changed

Lines changed: 514 additions & 12 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ jobs:
275275
- 'scripts/check-dual-build-cjs-loads.mjs'
276276
- 'scripts/check-lean-entry-closure.mjs'
277277
- 'scripts/check-sourcemap-no-sources-content.mjs'
278+
- 'scripts/ci/assert-turbo-remote-cache.mjs'
278279
- 'scripts/population-floor.mjs'
279280
# Build inputs of the vendored Console SPA — see the Console Pin Gate
280281
# job at the bottom of this file. `.objectui-sha` is a ROOT DOTFILE, so
@@ -736,9 +737,11 @@ jobs:
736737
# builds it there.
737738
#
738739
# Its own guarded step, for the reason the slice step below gives: a
739-
# guarded SITE is (file, job, step). No `--summarize`: `.turbo/runs/`
740-
# stays the test step's alone, and that is what the drift check and the
741-
# timings capture read. The four TURBO_* lines are Build Core's,
740+
# guarded SITE is (file, job, step). `.turbo/runs/` stays the test step's
741+
# alone, because that is what the drift check and the timings capture
742+
# read: the `--summarize` here is for the remote-cache assertion after
743+
# this step (#25374), which moves the summary it read out to
744+
# $RUNNER_TEMP before the tests run. The four TURBO_* lines are Build Core's,
742745
# verbatim; its "Turbo remote cache (#21186)" comment holds the write
743746
# rule, the signing and the PINS. ⛔ An empty FILTERS must exit here:
744747
# `turbo run build` with no filter builds the whole workspace.
@@ -764,7 +767,16 @@ jobs:
764767
mkdir -p "$RUNNER_TEMP/stall-reports"
765768
node scripts/run-with-stall-guard.mjs --log "$RUNNER_TEMP/test-core-closure-build.log" --stall-minutes 10 \
766769
--report-dir "$RUNNER_TEMP/stall-reports" -- \
767-
pnpm turbo run build $FILTERS --concurrency=4 --log-order=stream
770+
pnpm turbo run build $FILTERS --concurrency=4 --log-order=stream \
771+
--summarize --log-file=.turbo/remote-cache/test-core-closure.json
772+
773+
# Build Core's "Turbo remote cache (#21186)" comment, ASSERTED paragraph.
774+
# `--if-ran`: an empty shard exits the step above before turbo runs.
775+
- name: The Turbo remote cache was on for this shard's closure build
776+
run: |
777+
node scripts/ci/assert-turbo-remote-cache.mjs --site 'Test Core (${{ matrix.shard }}/6) closure' \
778+
--log .turbo/remote-cache/test-core-closure.json --if-ran \
779+
--move-summary-to "$RUNNER_TEMP/turbo-remote-cache"
768780
769781
# ⛔ A FILE-LEVEL SLICE BUILDS ITS DEPENDENCY CLOSURE HERE, IN ITS OWN
770782
# GUARDED STEP, so the slice leg in the next step REPLAYS it. Since #19278
@@ -2544,6 +2556,12 @@ jobs:
25442556
- name: check-dts-emitted self-test
25452557
run: node scripts/check-dts-emitted.mjs --self-test
25462558

2559+
# The remote-cache assertion after the build below, and after every
2560+
# carrier that runs it (Test Core's closure, lint.yml's three Type Check
2561+
# lanes), is one script; its self-test runs here, once.
2562+
- name: assert-turbo-remote-cache self-test
2563+
run: node scripts/ci/assert-turbo-remote-cache.mjs --self-test
2564+
25472565
# ── Turbo remote cache (#21186) ─────────────────────────────────────
25482566
# Vercel's managed Turborepo remote cache. objectstack-ai/cloud's
25492567
# test.yml builds this repo at its pinned SHA with the same command and
@@ -2579,6 +2597,16 @@ jobs:
25792597
# unset: remote caching is off and the build is unchanged; the summary
25802598
# then reads `Remote caching disabled (remote cache requested — …)`.
25812599
#
2600+
# ASSERTED (#25374). The step after this one reads that prelude line
2601+
# from turbo's structured log (`--log-file`, repo-relative or turbo
2602+
# ignores it) and the hit counts from `--summarize`, prints both into the
2603+
# job's step summary, and reds a run that WRITES the remote (the
2604+
# `remote:rw` branch above) when the cache is off; a read-only run only
2605+
# warns. Neither flag enters a task hash (83 of 83 identical with and
2606+
# without, `--dry=json`, turbo 2.11.5). The carriers that assert are this
2607+
# step, Test Core's closure and lint.yml's three Type Check lanes; the
2608+
# verdict table is the script header's.
2609+
#
25822610
# PINS, for every step that carries these four lines (#22077). Each
25832611
# carrier points back here.
25842612
# - BUILD TASKS ONLY. #19086's lesson: a step that writes artifacts from
@@ -2608,7 +2636,10 @@ jobs:
26082636
TURBO_TOKEN: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY != '' && secrets.TURBO_TOKEN || '' }}
26092637
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
26102638
TURBO_REMOTE_CACHE_SIGNATURE_KEY: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }}
2611-
run: pnpm build
2639+
run: pnpm build --summarize --log-file=.turbo/remote-cache/build-core.json
2640+
2641+
- name: The Turbo remote cache was on for the build
2642+
run: node scripts/ci/assert-turbo-remote-cache.mjs --site 'Build Core' --log .turbo/remote-cache/build-core.json
26122643

26132644
# [#15042] The closure-wide declaration re-check. `check-dts-emitted` runs
26142645
# per package, immediately after that package's `tsup`, and is the LAST

‎.github/workflows/lint.yml‎

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5785,7 +5785,14 @@ jobs:
57855785
TURBO_TOKEN: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY != '' && secrets.TURBO_TOKEN || '' }}
57865786
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
57875787
TURBO_REMOTE_CACHE_SIGNATURE_KEY: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }}
5788-
run: pnpm exec turbo run build --filter='./packages/*' --filter='./examples/*^...'
5788+
run: pnpm exec turbo run build --filter='./packages/*' --filter='./examples/*^...' --summarize --log-file=.turbo/remote-cache/typecheck-workspace.json
5789+
5790+
# ci.yml Build Core's "Turbo remote cache (#21186)" comment, ASSERTED
5791+
# paragraph (#25374). A gate of this lane, so the lane verdict carries its red.
5792+
- name: The Turbo remote cache was on for the workspace build
5793+
id: turbo-remote-cache-was-on
5794+
continue-on-error: true
5795+
run: node scripts/ci/assert-turbo-remote-cache.mjs --site 'Type Check · workspace' --log .turbo/remote-cache/typecheck-workspace.json
57895796

57905797
# CLI transcripts in content/docs are bound to the registries they quote
57915798
# (#15373). `content/docs` teaches with pasted CLI output, and some of those
@@ -6041,7 +6048,14 @@ jobs:
60416048
TURBO_TOKEN: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY != '' && secrets.TURBO_TOKEN || '' }}
60426049
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
60436050
TURBO_REMOTE_CACHE_SIGNATURE_KEY: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }}
6044-
run: pnpm exec turbo run build --filter='./packages/*' --filter='./examples/*^...'
6051+
run: pnpm exec turbo run build --filter='./packages/*' --filter='./examples/*^...' --summarize --log-file=.turbo/remote-cache/typecheck-debt.json
6052+
6053+
# ci.yml Build Core's "Turbo remote cache (#21186)" comment, ASSERTED
6054+
# paragraph (#25374). A gate of this lane, so the lane verdict carries its red.
6055+
- name: The Turbo remote cache was on for the workspace build
6056+
id: turbo-remote-cache-was-on
6057+
continue-on-error: true
6058+
run: node scripts/ci/assert-turbo-remote-cache.mjs --site 'Type Check · debt ledger' --log .turbo/remote-cache/typecheck-debt.json
60456059

60466060
# The MEASURED half of the coverage gate (#5278). The cheap structural
60476061
# check near the top of this job asserts that a package without a
@@ -6242,7 +6256,14 @@ jobs:
62426256
TURBO_TOKEN: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY != '' && secrets.TURBO_TOKEN || '' }}
62436257
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
62446258
TURBO_REMOTE_CACHE_SIGNATURE_KEY: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }}
6245-
run: pnpm exec turbo run build --filter='./packages/*' --filter='./examples/*^...'
6259+
run: pnpm exec turbo run build --filter='./packages/*' --filter='./examples/*^...' --summarize --log-file=.turbo/remote-cache/typecheck-consumers.json
6260+
6261+
# ci.yml Build Core's "Turbo remote cache (#21186)" comment, ASSERTED
6262+
# paragraph (#25374). A gate of this lane, so the lane verdict carries its red.
6263+
- name: The Turbo remote cache was on for the workspace build
6264+
id: turbo-remote-cache-was-on
6265+
continue-on-error: true
6266+
run: node scripts/ci/assert-turbo-remote-cache.mjs --site 'Type Check · consumer gates' --log .turbo/remote-cache/typecheck-consumers.json
62466267

62476268
# The nested-package build. ⚠️ NOT redundant with "Build workspace
62486269
# packages" above, and the reason is the glob: the bare `./packages/*`

‎scripts/check-ci-filter-parity.mjs‎

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@
161161
* build-task inputs and `globalDependencies` come out of turbo.json, and the
162162
* builds Build Core does not run come out of the root manifest's `build`
163163
* script (`--filter=!<package>`), which is what the job's `run: pnpm build`
164-
* expands to. Every misreading of that script can only drop an exclusion,
164+
* expands to (followed, at most, by the closed BUILD_COMMAND_FLAGS list:
165+
* reporting flags that change no task, #25374). Every misreading of that script can only drop an exclusion,
165166
* which REQUIRES more of `core` -- a loud red, never a silent gap. The only
166167
* constant is turbo.json itself, which is the config being read.
167168
*
@@ -276,7 +277,7 @@ const SELF_TEST_BATTERIES = Object.freeze({
276277
'(6) the real tree': 10,
277278
'(7) WIRING: the gate and its self-test really run in CI': 2,
278279
'(8) the `console` selection and the dist key it must move': 20,
279-
'(9) Build Core and the build inputs turbo.json declares': 33,
280+
'(9) Build Core and the build inputs turbo.json declares': 42,
280281
'(10) Build Core and the scripts its own steps run': 30,
281282
});
282283

@@ -644,6 +645,23 @@ export const TURBO_CONFIG = 'turbo.json';
644645
export const ROOT_MANIFEST = 'package.json';
645646
/** The step Build Core runs, verbatim; the manifest's `build` script is what it expands to. */
646647
const BUILD_COMMAND = 'pnpm build';
648+
/**
649+
* The CLOSED list of words that may follow BUILD_COMMAND in that step. Each
650+
* changes what turbo REPORTS, never which tasks it runs or how they hash
651+
* (measured: 83 of 83 hashes identical with and without, `--dry=json`, turbo
652+
* 2.11.5), and the remote-cache assertion after the step reads both
653+
* (#25374). ⛔ No pattern over "any flag": a `--filter` or `--affected` here
654+
* changes the task set the manifest's script says, and must refuse.
655+
*/
656+
const BUILD_COMMAND_FLAGS = Object.freeze([/^--summarize$/, /^--log-file=\S+$/]);
657+
658+
/** Whether a `run:` is BUILD_COMMAND followed only by BUILD_COMMAND_FLAGS. */
659+
export function isBuildCommand(run) {
660+
if (typeof run !== 'string') return false;
661+
const words = run.trim().split(/\s+/);
662+
if (words.slice(0, 2).join(' ') !== BUILD_COMMAND) return false;
663+
return words.slice(2).every((w) => BUILD_COMMAND_FLAGS.some((re) => re.test(w)));
664+
}
647665
/** The prefix turbo.json spells a repo-root-relative input with. */
648666
const TURBO_ROOT = '$TURBO_ROOT$/';
649667

@@ -794,7 +812,7 @@ export function judgeBuildInputs(source, turboSource, manifestSource, closureOf
794812
};
795813
}
796814
const steps = Array.isArray(job.steps) ? job.steps : [];
797-
if (!steps.some((s) => typeof s?.run === 'string' && s.run.trim() === BUILD_COMMAND)) {
815+
if (!steps.some((s) => isBuildCommand(s?.run))) {
798816
return {
799817
refusal:
800818
`${CI_WORKFLOW}'s \`${BUILD_JOB}\` job has no \`run: ${BUILD_COMMAND}\` step, so ${ROOT_MANIFEST}'s \`build\` ` +
@@ -1574,7 +1592,8 @@ export async function selfTest() {
15741592
' build-core:',
15751593
` if: ${JSON.stringify(condition)}`,
15761594
' steps:',
1577-
` - run: ${run}`,
1595+
// Quoted, so a multi-line `run` stays one YAML scalar.
1596+
` - run: ${JSON.stringify(run)}`,
15781597
].join('\n');
15791598
};
15801599
const turboFixture = ({ globalDependencies = ['tsconfig.json', 'tsup.config.ts'], tasks } = {}) =>
@@ -1653,6 +1672,21 @@ export async function selfTest() {
16531672
assert(/no \`build-core\` job/.test(judgeBuildInputs(fixtureWorkflow(), turboFixture(), manifestFixture()).refusal ?? ''), 'no Build Core job => REFUSAL');
16541673
assert(/no longer names \`core\`/.test(buildRefusal({ workflow: buildWorkflow({ condition: '${{ !cancelled() }}' }) })), 'Build Core dropping `core` from its `if:` => REFUSAL');
16551674
assert(/no \`run: pnpm build\` step/.test(buildRefusal({ workflow: buildWorkflow({ run: 'pnpm turbo run build' }) })), 'Build Core no longer running `pnpm build` => REFUSAL');
1675+
// The closed flag list (#25374): reporting flags pass, anything that could
1676+
// change the task set refuses, and so do the same flags on another command.
1677+
assert(!buildRefusal({ workflow: buildWorkflow({ run: 'pnpm build --summarize --log-file=.turbo/remote-cache/build-core.json' }) }), '`pnpm build --summarize --log-file=PATH` is still Build Core running `pnpm build`');
1678+
assert(!buildRefusal({ workflow: buildWorkflow({ run: 'pnpm build --summarize' }) }), '-- and so is `pnpm build --summarize` alone');
1679+
for (const [run, why] of [
1680+
['pnpm build --summarize --filter=@objectstack/spec', 'a `--filter` beside the allowed flags'],
1681+
['pnpm build --affected', '`--affected`'],
1682+
['pnpm build --summarize --force', 'an unknown flag'],
1683+
['pnpm build --log-file=', 'a `--log-file=` with no path'],
1684+
['pnpm build -- --summarize', 'a `--` passthrough'],
1685+
['pnpm test --summarize --log-file=x.json', 'the allowed flags on a different command'],
1686+
['pnpm build --summarize\nnode scripts/x.mjs', 'a second command after the build'],
1687+
]) {
1688+
assert(/no \`run: pnpm build\` step/.test(buildRefusal({ workflow: buildWorkflow({ run }) })), `${why} => REFUSAL`);
1689+
}
16561690
assert(/turbo.json could not be read\./.test(buildRefusal({ turbo: null })), 'an unreadable turbo.json => REFUSAL');
16571691
assert(/could not be read as JSON/.test(buildRefusal({ turbo: '{ tasks: ' })), 'a turbo.json that is not JSON => REFUSAL');
16581692
assert(/no \`tasks\` map/.test(buildRefusal({ turbo: '{}' })), 'a turbo.json with no tasks map => REFUSAL');

0 commit comments

Comments
 (0)