Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,10 @@ jobs:
sandbox:
- 'sandbox:none'
- 'sandbox:docker'
# The suite is ~16min of wall clock on one runner, dominated by a long
# tail of sdk-typescript files. vitest assigns files to shards by path
# hash, so those spread out instead of clustering in one shard.
# Keep three-way test concurrency inside one runner so each sandbox

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R1-3: Two comments in this same job now state the opposite of what the file does, and neither is the wording the maintainer verification already asked you to change.

Collapsing the matrix to one shard retires the shard as the unit of work, but two present-tense statements inside this job still describe the old shape:

  1. :252-254 — "Mapped for integration-tests/vitest.config.ts, which caps each shared-pool shard at one fork and exempts pressure-flake unhandled errors" — sits in the very step this diff edits, two lines above the two flags that raise that cap to three. The second half of the sentence is still true; the first half is not.
  2. :305-306 — "Per-commit coordinator: one shard per host builds the image, its siblings wait here and then find it present" — with shard: ['1/1'] there is exactly one sandbox:docker job per run, so it has no siblings. The only remaining contenders are other runs of the same GITHUB_SHA, because the concurrency group at :22-24 is keyed on workflow / event name / ref, so a workflow_dispatch or schedule run of the same SHA lands in a different group and can overlap the in-flight push run.

The cost is a mis-diagnosis rather than a failure: a maintainer who finds the docker leg parked up to 30 minutes in flock --wait 1800 8 goes looking for the intra-run sibling the comment promises, finds none, and reads a cross-run collision as a stuck intra-run handoff. Nothing surfaces it — scripts/tests/e2e-workflow.test.js:131-135 pins the same sibling-shard narrative against run 33637097713 while asserting only lock ordering, which is still valid, so that test stays green.

I am deliberately not re-raising the mechanism attribution in the comment this diff adds at :130-131 ("shares setup work"): the maintainer verification already in this thread measured it (setup is 27s per job, 0.9% of the runner-time saving; the durable reason is dynamic load balancing) and asked for that sentence, so you already have it.

Witness:

vitest 3.2.7 resolveConfig on this workflow's own extracted argv, falsifying :252-254:
  RUNNER_ENVIRONMENT=self-hosted CONFIG_ONLY {"pool":"forks","forks":{"minForks":1,"maxForks":1}}
  RUNNER_ENVIRONMENT=self-hosted CONFIG+CLI  {"pool":"forks","forks":{"minForks":1,"maxForks":3}}
Topology falsifying :305-306, read at the reviewed commit:
  e2e.yml:132-133  shard: ['1/1']  -> one sandbox:docker job per run, no siblings
  e2e.yml:22-24    concurrency group keyed on workflow / event_name / ref
                   -> a workflow_dispatch or schedule run of the same SHA is in a DIFFERENT group
  grep -n 'docker-sandbox-build-e2e' .github/workflows/*.yml -> e2e.yml:307 only

Reword both to the post-collapse shape in this same edit: at :252-254 say what the mapping is still for (the pressure-flake unhandled-error exemption, and the fork floor) and note that the ceiling is set on the two test commands below; at :305-306 say the coordinator's remaining contention is cross-run (same GITHUB_SHA, different runs or attempts on one host) rather than between sibling shards.

One constraint on the config-comment pointer the maintainer verification asked for: the consumer inventory it would be written from does not hold, and writing it as instructed would put a second false sentence exactly where this finding says the first one must be corrected. E2E is not the only self-hosted consumer of integration-tests/vitest.config.tsrelease.yml's integration_none (pool runs-on, RUNNER_ENVIRONMENT mapped at :767 and :773, running test:integration:cli:sandbox:none at :769 and :interactive at :775) and integration_docker (mapped at :819, running vitest run --root ./integration-tests at :871-872) pass no override and genuinely resolve {minForks:1, maxForks:1}. And ci.yml never maps RUNNER_ENVIRONMENT at all, so its pool legs take the non-self-hosted branch — test:integration:no-ak carries an explicit --poolOptions.forks.maxForks 2 and test:integration:cli (ci.yml:2216) carries none, resolving {minForks:2, maxForks:4} — not one fork. Keeping the override here in e2e.yml is still the right call; only the sentence describing everyone else needs to be accurate.

中文说明

同一个 job 里有两处注释现在与文件的实际行为相反,而且都不是维护者验证评论已经请你修改的那一处措辞。

把 matrix 收成单个 shard,意味着 shard 不再是工作单元,但这个 job 内仍有两处现在时的描述在讲旧形态:

  1. :252-254 —— "Mapped for integration-tests/vitest.config.ts, which caps each shared-pool shard at one fork and exempts pressure-flake unhandled errors" —— 就在本 diff 修改的这个 step 里,位于把该上限提到三的两处 flag 上方两行。这句话的后半仍然成立,前半已不成立。
  2. :305-306 —— "Per-commit coordinator: one shard per host builds the image, its siblings wait here and then find it present" —— 在 shard: ['1/1'] 下每次 run 只有一个 sandbox:docker job,因此不存在「兄弟 shard」。剩下的竞争者只可能是同一 GITHUB_SHA 的其他 run::22-24 的 concurrency group 以 workflow / event name / ref 为键,所以同一 SHA 的 workflow_dispatchschedule run 属于不同 group,可以与进行中的 push run 重叠。

代价是误诊而非失败:当维护者发现 docker leg 在 flock --wait 1800 8 上停留长达 30 分钟时,会按注释去找那个并不存在的同 run 兄弟 shard,找不到之后就把一次跨 run 的锁竞争误判为同 run 内的交接卡死。而且没有任何机制会把这一点暴露出来 —— scripts/tests/e2e-workflow.test.js:131-135 针对 run 33637097713 钉住了同样的兄弟 shard 叙事,但它断言的只是锁的顺序,而顺序仍然有效,所以该测试保持绿色。

我特意不重复提本 diff 在 :130-131 新增注释里的机制归因("shares setup work"):线程中已有的维护者验证评论已经实测过(setup 每个 job 27 秒,占 runner 时间节省的 0.9%;真正持久的原因是动态负载均衡)并请作者修改那句话,因此作者已经掌握这一点。

修复方式:在同一次编辑中把两处都改写为收拢后的形态 —— :252-254 说明该映射如今还为什么存在(pressure-flake 未处理错误豁免,以及 fork 下限),并注明上限是由下方的两条测试命令设定的;:305-306 说明该协调锁剩余的竞争是跨 run 的(同一 GITHUB_SHA、同一宿主上的不同 run 或 attempt),而不是兄弟 shard 之间的。

关于维护者建议的「在配置注释里加一行指引」,有一个前提约束:它所依据的消费者清单并不成立,若照原样书写,就会在本条发现指出需要修正的地方再放一句假话。E2E 不是 integration-tests/vitest.config.ts 唯一的 self-hosted 消费者 —— release.ymlintegration_none(pool runs-on:767:773 映射 RUNNER_ENVIRONMENT:769 运行 test:integration:cli:sandbox:none:775 运行 :interactive)与 integration_docker:819 映射,:871-872 运行 vitest run --root ./integration-tests)都没有传覆盖参数,确实解析为 {minForks:1, maxForks:1}。而 ci.yml 根本没有映射 RUNNER_ENVIRONMENT,因此它在 pool 上的 leg 走的是非 self-hosted 分支 —— test:integration:no-ak 显式带 --poolOptions.forks.maxForks 2test:integration:clici.yml:2216)不带任何覆盖,解析为 {minForks:2, maxForks:4} —— 并非单 fork。把覆盖保留在 e2e.yml 里仍然是正确选择;只是描述「其他所有人」的那句话需要写准。

— qwen3.8-max via Qwen Code /review (v0.23.0)

# shares setup work instead of occupying three pool runners.
shard:
- '1/3'
- '2/3'
- '3/3'
- '1/1'
node-version:
- '22.x'
steps:
Expand Down Expand Up @@ -362,10 +359,10 @@ jobs:
# test:integration:sandbox:docker: that script would rebuild the image
# the step above just built.
if [[ "${{ matrix.sandbox }}" == "sandbox:docker" ]]; then
npx cross-env QWEN_E2E_RENDERER=ink QWEN_SANDBOX=docker vitest run --root ./integration-tests --exclude '**/interactive/cron-interactive.test.ts' --exclude '**/channel-plugin.test.ts' --exclude '**/chat-transcript-document.test.ts' --shard='${{ matrix.shard }}' 9>&-
npx cross-env QWEN_E2E_RENDERER=ink QWEN_SANDBOX=docker vitest run --root ./integration-tests --exclude '**/interactive/cron-interactive.test.ts' --exclude '**/channel-plugin.test.ts' --exclude '**/chat-transcript-document.test.ts' --poolOptions.forks.maxForks=3 --shard='${{ matrix.shard }}' 9>&-
else
run_shard() {
QWEN_E2E_RENDERER=ink npm run test:integration:sandbox:none -- --exclude '**/interactive/cron-interactive.test.ts' --exclude '**/channel-plugin.test.ts' --exclude '**/chat-transcript-document.test.ts' --shard='${{ matrix.shard }}'
QWEN_E2E_RENDERER=ink npm run test:integration:sandbox:none -- --exclude '**/interactive/cron-interactive.test.ts' --exclude '**/channel-plugin.test.ts' --exclude '**/chat-transcript-document.test.ts' --poolOptions.forks.maxForks=3 --shard='${{ matrix.shard }}'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] R1-6: [fails-closed] [regression] Three Vitest forks now share one scratch root, and two files in the suite ask for that root by the same name — so one fork rm -rfs the other's live test directory mid-test.

--poolOptions.forks.maxForks=3 raises the self-hosted pool lane from one child process to three. integration-tests/globalSetup.ts computes one runDir per vitest process and assigns it to INTEGRATION_TEST_FILE_DIR, so every fork inherits the identical value. integration-tests/test-helper.ts:228 then derives testDir from the case name alone — no file, fork or pid component — and the next two lines rm -rf it and recreate it. cli/file-system.test.ts:52 and cli/write_file.test.ts:18 both call rig.setup('should be able to write a file'), which sanitizeTestName folds to the same path. When vitest co-schedules those two files across two of the three forks, the second fork's setup() wipes the first fork's live directory: its test.txt, its .qwen/settings.json and its telemetry.log. The spawned CLI runs with cwd: testDir and the assertions read join(testDir, 'telemetry.log'), so the victim throws ENOENT on rig.readFile('test.txt') or loses its cwd. On the docker leg the container mounts the test directory at the same host path, so two sandboxes mount one directory.

This is not a pre-existing hazard the diff merely exposes. At the merge base the self-hosted branch of integration-tests/vitest.config.ts held the pool lane to one child process, and vitest's own shard rule put the pair in different shards (1/3 vs 3/3) — therefore different jobs, workspaces and runDirs. The macOS lane splits them too (1/2 vs 2/2). shard: '1/1' is what puts them in one job, so no lane in this repository could co-schedule that pair before this change. What lands is a nondeterministic red on the lane that runs on every push to main, with a signature (ENOENT, cross-test telemetry) that reads as a product bug rather than a harness collision, and the bounded retry absorbs it by re-running the whole suite.

Witness:

Real TestRig driven in two vitest forks, replaying both files' real openings (reviewed commit, unmodified tree):
  file-system.probe pid 2000511 after-setup testDir <runDir>/should-be-able-to-write-a-file markerExists=true
  write_file.probe  pid 2000510 after-setup testDir <runDir>/should-be-able-to-write-a-file
  file-system.probe after-run samples: [{"dirExists":true,"testTxt":false,"settings":true,"telemetry":false}, ... x10]
  file-system.probe readFileError=Error: ENOENT: no such file or directory, open '<runDir>/should-be-able-to-write-a-file/test.txt'
Two pids, one identical testDir. Over 5 repetitions per arm:
  second setup() landing while the first is mid-run -> 5/5 ENOENT
  both setup() calls in the same millisecond        -> 0/5
Population sweep (76 executed files, 128 setup() call sites): cross-file duplicate directory names: 1
Vitest's own shard rule (read from its dist, validated against real vitest) on the real population:
  count=3 (Linux, BASE)      -> file-system=1/3 write_file=3/3 sameShard=false
  count=2 (macOS, unchanged) -> file-system=1/2 write_file=2/2 sameShard=false
  count=1 (Linux, THIS DIFF) -> file-system=1/1 write_file=1/1 sameShard=true
Candidate fix (sanitizedName + '-' + process.pid): rounds 1-5 readFileError=none (was 5/5 ENOENT)

Make the rig directory fork-unique in this same change rather than after it — in integration-tests/test-helper.ts:228, key the directory on the worker as well as the case name, or on the test file basename, or mkdtemp under the name:

// integration-tests/test-helper.ts:228
this.testDir = join(env['INTEGRATION_TEST_FILE_DIR']!, `${sanitizedName}-${process.pid}`);

Renaming the rig.setup() argument in one of the two files fixes today's pair but leaves the class open for the next duplicate name; keying the shared root is what closes it.

The reset itself has to stay: test-helper.ts:229-232 records that two cases setting up under the same name share the directory, that cleanup() keeps it whenever KEEP_OUTPUT is set (which CI always sets), and that the rm exists so a case never inherits the previous one's files — so make the directory fork-unique rather than dropping the reset, and keep test-helper.test.ts's reused-directory, cleanup and keep-output cases green (measured 7/7 green both before and after the candidate fix). Please add a case to integration-tests/test-helper.test.ts asserting that two rigs created with the same case name but different worker identity resolve to different directories and that neither setup() removes the other's, then prove it by taking the pid component back out and confirming that case goes red.

中文说明

三个 Vitest fork 现在共用同一个临时根目录,而测试集中有两个文件用同一个名字去申请该目录 —— 于是一个 fork 会在测试进行中途 rm -rf 掉另一个 fork 正在使用的测试目录。

--poolOptions.forks.maxForks=3 把 self-hosted pool 通道从单个子进程提升到三个。integration-tests/globalSetup.ts 每个 vitest 进程只计算一个 runDir 并赋给 INTEGRATION_TEST_FILE_DIR,因此所有 fork 继承到完全相同的值。integration-tests/test-helper.ts:228 随后仅凭用例名推导 testDir —— 不含文件、fork 或 pid 分量 —— 紧接着两行先 rm -rf 再重建。cli/file-system.test.ts:52cli/write_file.test.ts:18 都调用 rig.setup('should be able to write a file'),经 sanitizeTestName 归一后落到同一路径。当 vitest 把这两个文件调度到三个 fork 中的两个上并发执行时,后一个 fork 的 setup() 会清掉前一个 fork 正在使用的目录:它的 test.txt.qwen/settings.jsontelemetry.log。被拉起的 CLI 以 cwd: testDir 运行,断言又读取 join(testDir, 'telemetry.log'),因此受害方要么在 rig.readFile('test.txt') 上抛出 ENOENT,要么丢失自己的 cwd。docker 一侧更严重:容器把测试目录挂载到同一宿主路径,等于两个 sandbox 挂载同一个目录。

这并不是本 diff 仅仅「暴露」出来的既有隐患。在 merge base 上,integration-tests/vitest.config.ts 的 self-hosted 分支把 pool 通道限制为单个子进程,而 vitest 自身的分片规则会把这一对文件分到不同 shard(1/33/3),因而落在不同 job、不同 workspace、不同 runDir。macOS 通道同样会把它们分开(1/22/2)。正是 shard: '1/1' 把它们放进了同一个 job,所以在本次改动之前,仓库里没有任何通道能让这一对文件并发。落地后的表现是:在每次 push 到 main 都会跑的通道上出现非确定性红灯,其特征(ENOENT、跨用例 telemetry)看起来像产品缺陷而非测试框架冲突,而有界重试只能通过重跑整套用例来吸收它。

修复方式:在同一次改动里就让 rig 目录具备 fork 唯一性,而不是事后再补 —— 在 integration-tests/test-helper.ts:228 让目录同时以 worker 和用例名为键(或加上测试文件基名,或在名字下 mkdtemp)。只重命名两个文件之一的 rig.setup() 参数能解决当前这一对,但下一次出现重名时同类问题仍会复现;对共享根目录做键化才是真正封口。

重置逻辑本身必须保留:test-helper.ts:229-232 记录了同名用例共享该目录、cleanup() 在设置了 KEEP_OUTPUT 时(CI always 设置)会保留它、以及这个 rm 的存在是为了让用例不会继承上一个用例的文件 —— 所以应让目录具备 fork 唯一性,而不是去掉重置,并保持 test-helper.test.ts 中「重用目录」「清理目录」「KEEP_OUTPUT 时保留目录」三个用例为绿(实测在候选修复前后均为 7/7 通过)。请在 integration-tests/test-helper.test.ts 中补一个用例,断言两个用例名相同但 worker 身份不同的 rig 会解析到不同目录、且任一 setup() 都不会删除对方的目录;然后把 pid 分量去掉,确认该用例变红,以此证明它确实有效。

— qwen3.8-max via Qwen Code /review (v0.23.0)

}
# One bounded retry: pool runners' sandbox:none shards die under
# shared-host pressure with every test green and no vitest FAIL
Expand Down
14 changes: 13 additions & 1 deletion scripts/tests/e2e-workflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ describe('e2e workflow', () => {
expect(group).toContain('github.head_ref || github.ref_name');
});

it('runs three Vitest forks on one Linux runner per sandbox', () => {
const linuxJob = yml.jobs['e2e-test-linux'];
const runStep = linuxJob.steps.find(
(step) => step.name === 'Run E2E tests',
);

expect(linuxJob.strategy.matrix.shard).toEqual(['1/1']);
expect(runStep.run.match(/--poolOptions\.forks\.maxForks=3/g)).toHaveLength(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R1-7: This count does not pin the docker leg — the flag can leave the docker command and the whole suite stays green.

runStep.run is the entire ~120-line step script, comments included, and /--poolOptions\.forks\.maxForks=3/g is anchored to nothing, so any two occurrences anywhere in it satisfy toHaveLength(2). The sandbox:none leg is positionally pinned at :208, which asserts the full command; the docker leg is not — its only positional pin is :159's toContain("--shard='${{ matrix.shard }}' 9>&-"), which stops before the flag.

So delete --poolOptions.forks.maxForks=3 from the docker command at .github/workflows/e2e.yml:362 and keep the string twice in the step by mentioning it in the adjacent comment: the count still reads 2, :159 still matches, :208 still matches, this file's new case still prints green — and the docker leg silently reverts to integration-tests/vitest.config.ts:38's maxForks: isSelfHostedRunner ? 1 : 4, one fork on the ECS pool that is this workflow's normal lane. Against the paired measurement this PR's own rationale rests on (aggregate test-step minutes 120.9 → 31.6, 3.8×), that is roughly a tripling of the docker job's wall clock against an unchanged timeout-minutes: 60, with no red test to say so. This file already states the rule the new assertion falls short of, for exactly this reason: "Structure, not just count" (:235).

Worth knowing because it corrects a claim already on the PR: the reported "5/5 mutants killed, including dropping the flag from only the docker leg (the toHaveLength(2) assertion is what catches that)" covers the uncompensated deletion, which drops the count to 1 and is indeed killed. The compensated deletion above survives every assertion in the repository.

Witness:

Mutation run in a scratch tree at the reviewed commit, then reverted:
  BASELINE (unmodified): e2e-workflow.test.js (30 tests) 30 passed
  MUTATION A (flag deleted from the docker command at e2e.yml:362, string kept twice
              in the step by mentioning it in the adjacent comment):
    grep -c -- "--poolOptions.forks.maxForks=3" .github/workflows/e2e.yml -> 2
    e2e-workflow.test.js (30 tests) 30 passed   <- the new case still green
    e2e-shard-retry.test.js (6) + no-ak-integration-ci.test.js (14) -> 50 passed
  (These are all three test files in the repo that read .github/workflows/e2e.yml.)
  CANDIDATE FIX, then re-run:
    fix + mutation A   -> FAIL 'closes the lock descriptors in every child process'  (mutant killed)
    fix + real e2e.yml -> e2e-workflow.test.js (30 tests) 30 passed

Pin each leg's command rather than counting the string — extend the existing descriptor-close assertion at :159 to carry the flag:

expect(runStep.run).toContain(
  "--poolOptions.forks.maxForks=3 --shard='${{ matrix.shard }}' 9>&-",
);

and keep :208's full-command pin for the sandbox:none leg. The toHaveLength(2) count can then go, or stay as redundancy on top of two positional pins.

Keep the 9>&- suffix in that extended pin: :159's existing toContain is the witness for the descriptor close (:151-153, "closes the lock descriptors in every child process"), and dropping the suffix would unpin the fd-9 close that stops the three forks and their sandbox containers from inheriting the daemon read lock. Any edit must also keep :208 byte-identical to the run_shard() body at .github/workflows/e2e.yml:365. Please prove the new pin by removing the flag from the docker command and confirming that assertion goes red — today nothing in the repository does.

中文说明

这个计数并没有钉住 docker 一侧 —— 该 flag 可以从 docker 命令中消失,而整个测试套件仍然是绿的。

runStep.run 是整段约 120 行的 step 脚本,注释也包含在内,而 /--poolOptions\.forks\.maxForks=3/g 没有任何位置锚定,因此脚本中任意位置出现两次就能满足 toHaveLength(2)sandbox:none 一侧在 :208 有位置性钉住(断言完整命令);docker 一侧没有 —— 它唯一的位置性钉住是 :159toContain("--shard='${{ matrix.shard }}' 9>&-"),而该断言在 flag 之前就截止了。

于是:把 --poolOptions.forks.maxForks=3.github/workflows/e2e.yml:362 的 docker 命令里删掉,并在相邻注释中提一句、让这个字符串在 step 中仍出现两次 —— 计数依然是 2,:159 依然匹配,:208 依然匹配,本文件新增用例依然为绿 —— 而 docker 一侧会静默退回到 integration-tests/vitest.config.ts:38maxForks: isSelfHostedRunner ? 1 : 4,也就是在这个 workflow 的常规通道(ECS pool)上只跑一个 fork。以本 PR 立论所依据的配对实测为参照(各 job 测试阶段耗时合计 120.9 分钟 → 31.6 分钟,3.8 倍),这大致等于 docker job 墙钟时间变为三倍,而 timeout-minutes: 60 未变,却没有任何红灯提示。本文件其实已经写明了这条新断言未达到的标准,且理由正是如此:"Structure, not just count"(:235)。

有一点值得说明,因为它更正了 PR 上已有的一处结论:已报告的「5/5 变异体全部被杀,包括只从 docker 一侧删掉该 flag(正是 toHaveLength(2) 断言抓住了它)」针对的是未做补偿的删除 —— 那会把计数降到 1,确实会被杀掉。而上面这种带补偿的删除能躲过仓库中的每一条断言。

修复方式:钉住每一侧的命令,而不是数字符串出现次数 —— 把 :159 已有的描述符关闭断言扩展为同时包含该 flag,并保留 :208sandbox:none 一侧的完整命令钉住。此后 toHaveLength(2) 计数可以删除,也可以作为两条位置性钉住之上的冗余保留。

扩展后的钉住必须保留 9>&- 后缀::159 现有的 toContain 正是描述符关闭的见证(:151-153,"closes the lock descriptors in every child process"),去掉该后缀就会失去对 fd-9 关闭的钉住 —— 而正是它阻止三个 fork 及其 sandbox 容器继承 daemon 读锁。任何修改还必须让 :208.github/workflows/e2e.yml:365run_shard() 函数体保持逐字节一致。请通过从 docker 命令中删除该 flag、并确认该断言变红来证明新的钉住确实有效 —— 目前仓库中没有任何断言能做到这一点。

— qwen3.8-max via Qwen Code /review (v0.23.0)

2,
);
});

describe('sandbox image preparation', () => {
const steps = yml.jobs['e2e-test-linux'].steps;
const setupStep = steps.find((step) => step.name === 'Set up Docker');
Expand Down Expand Up @@ -193,7 +205,7 @@ describe('e2e workflow', () => {
// shard and exclude coverage lives only in this argument list. The
// excludes are shared verbatim with the docker leg above.
expect(runStep.run).toContain(
"npm run test:integration:sandbox:none -- --exclude '**/interactive/cron-interactive.test.ts' --exclude '**/channel-plugin.test.ts' --exclude '**/chat-transcript-document.test.ts' --shard='${{ matrix.shard }}'",
"npm run test:integration:sandbox:none -- --exclude '**/interactive/cron-interactive.test.ts' --exclude '**/channel-plugin.test.ts' --exclude '**/chat-transcript-document.test.ts' --poolOptions.forks.maxForks=3 --shard='${{ matrix.shard }}'",
);
});

Expand Down
Loading