Skip to content

ci: keep the nightly gate inside its job and name each running phase - #7070

Merged
moq-bot[bot] merged 1 commit into
mainfrom
quest/m0/nightly/gate-hang
Oct 30, 2026
Merged

moq-bot[bot] merged 1 commit into
mainfrom
quest/m0/nightly/gate-hang

Conversation

@kixelated

@kixelated kixelated commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Nightly's Tests (gate) job has timed out at 60 minutes every day since 10-27: run 40506938673, 10-28, 10-29.

It was not a hung test. The gate's Rust lane outgrew the 4-vCPU hosted job.

  • moq-dev/moq#6703 (10-25) added feature shapes to the gate. On 10-26 the gate passed in 53 of its 60 minutes. The rs lane took 2874s of that (check rs 2122s, test rs 752s), and 1023s of it was the two unified feature-shape passes.
  • moq-dev/moq#6830 (10-26) moved those shapes to cargo hack, which runs one clippy pass per package at each extreme. Since then the rs lane has not finished inside the job. On 10-29 every other lane finished 24 minutes in, and rs was still running at the 60-minute timeout. dart, which runs alone, never started.

Visibility: concurrent lanes buffer their output until the lane ends, and GitHub's timeout signals only the step's top process. So neither the lane log nor the dispatcher's timing report was ever printed.

Decisions

  1. How to bring the gate back inside its job. Settled by the maintainer in a /quest-complete session, replacing option A, which this PR first implemented.

    • A: the gate skips isolated shapes on whole-workspace selections, and Features sweeps every package.
    • ✅ B: keep the isolated feature-shape sweep in the gate, and split Nightly's gate across several hosted jobs, adding the module filter the dispatcher needs.
    • C: run Nightly's gate on a bigger runner (the self-hosted queue runner or a paid larger hosted runner).

    Reason: the queue keeps isolated shapes for every selection, including lockfile, toolchain, and .cargo/ changes, instead of leaving them to Nightly.

Changes

  • rs_shapes dispatcher module: the isolated feature-shape sweep (rs feature-shapes) moves out of check rs into a module of its own. It has the same impact pattern, sits in the same lane, and runs after test rs. So the queue and just check still run it for every Rust selection, in the same lane, just as before. Only the lint path of sh/rs/select.sh, which the dispatcher calls, drops it. The rs check-changed and rs check-test-changed recipes still run it.
  • CHECK_MODULES filter: it runs only the modules it names, or skips each one named with a leading -. An unknown name fails with the valid list. just gate [MODULE|-MODULE]... passes it through.
  • Nightly split: Nightly's Tests job runs gate -rs_shapes, and Features runs gate rs_shapes. Features runs on Nightly and on every release PR.
  • Release-PR Check: Check now runs only on release PRs, over --all, on the same 60-minute hosted job, so it sets CHECK_MODULES=-rs_shapes. Their Features job runs the sweep. It passes today only because release has no feature shapes yet (moq-dev/moq#7202: 20 minutes). The next release cut would have brought the same timeout.
  • Live phase lines (kept from the first revision): buffered dispatcher lanes announce each phase as it starts and ends (ci: test rs started, ci: check rs passed in 2122s) on the run's stderr. A run killed mid-phase now names the phase it stopped in, and each phase's time is logged even when the final report never prints. These lines replace the per-lane ci: started <modules> line.
  • Tests: dispatch-query.test.py checks the rs_shapes order in its lane, both halves of the CHECK_MODULES split, and the error for an unknown name. The cancellation test also checks that the running phase's start line reaches stderr while the phase is still blocked. select.test.py checks that lint leaves the shapes to the new feature-shapes action. sh/gh/queue.test.ts pins the split: release-PR Check skips rs_shapes, Features runs gate rs_shapes, and Nightly's Tests runs gate -rs_shapes instead of gate.
  • Docs: README.md and doc/setup/dev.md describe the filter and the split.

Public API: none. Wire: none.

Choices made without asking

  • The release-PR fix reuses B's split. Release PRs already run Features, so moving rs_shapes there costs one env line and no new job. The alternative, splitting Check itself, would rename the required Check context or need an aggregator job.
  • Two jobs, no cargo hack --partition. The 10-26 numbers put the gate without shapes at about 31 minutes for rs. I have no hosted measurement of the shapes alone. The live phase lines will log it on the first Nightly, and --partition M/N across Features entries is the next step if it runs long.
  • rs_shapes shares the rs lane. Both compile into one target/ and would only queue on Cargo's build-directory lock in separate lanes. This keeps queue behavior unchanged.

Checks

  • Ran: sh/dispatch-query.test.py (28 OK), sh/rs/select.test.py (17 OK), sh/gh/queue.test.ts, shellcheck, shfmt, actionlint, just --fmt --check on both justfiles, and quest check --base origin/main.
  • just ci origin/main passed every module except check flake. That one failed because this host forbids unshare while building the github-runner VM image, a derivation this PR does not touch. Locally check rs_shapes took 386s beside check rs 339s and test rs 184s.
  • CHECK_MODULES=-rs_shapes python3 sh/dispatch-query.test.py: 28 OK, after the fixture fix in 6fa5bb9.
  • After merging main (647f500): bun test sh/gh/ (19 pass), bun sh/gh/queue.test.ts, actionlint, sh/dispatch-query.test.py, and sh/rs/select.test.py pass. just check origin/main passed every Rust/JS module including check rs_shapes (516s); c, cpp, obs_compile, kt, go, and dart failed because this host's mbx cargo shim rejects the cargo build-ffi alias (unexpected argument 'build', reproduced standalone), and flake was skipped for the unshare restriction. None touch this PR's files.

Review

  • Harness quest review, reviewer Codex gpt-6.1-sol, effort medium.
  • Round 1 at head 647f500 (merge of origin/main bdc4785 with hand-resolved conflicts): 0 findings.
  • Merge resolution: main's batched gate (moq-dev/moq#7024) dropped merge_group and runs Check only on release PRs with CI_BASE: --all, so Check now sets CHECK_MODULES: -rs_shapes unconditionally and sh/gh/queue.test.ts pins it as a plain value. Nightly keeps main's new test resume-model recipe beside gate -rs_shapes. doc/setup/dev.md keeps main's wording plus the split.
  • Earlier: Codex's online P1 at c5485bf (thread) was fixed in 6fa5bb9.

Suggested follow-ups

  • Narrow the queue's feature shapes to changed crates. select.sh isolates seeds plus every dependent, so a moq-net change costs about 26 minutes of isolated clippy on the queue runner (run 40624404802). The 2026-10-24 decision says the gate checks shapes for "the crates a branch changes".
  • cargo-hack's log groups break the dispatcher's group. In CI, cargo-hack emits its own ##[group] for each package, and GitHub does not nest groups. --log-group none in rs feature-shapes would keep the dispatcher's grouping.
  • Measure lane concurrency on hosted runners. Rust lanes share target/ and wait on Cargo's build-directory lock, so CHECK_JOBS=3 on a 4-vCPU runner mostly queues them.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

@kixelated kixelated changed the title Nightly's gate stops hanging ci: keep the nightly gate inside its job and name each running phase Oct 28, 2026
@kixelated

Copy link
Copy Markdown
Collaborator Author

Design change: replacing option A with option B, as the maintainer chose in a /quest-complete session.

  • Rejected (A, the first revision): the gate skipped isolated feature shapes on whole-workspace selections, and a separate rs feature-sweep Features job covered them. That left lockfile, toolchain, and .cargo/ queue entries without isolated shapes until Nightly.
  • Now (B): the isolated feature-shape sweep stays in the gate for every selection. It becomes its own dispatcher module, rs_shapes, in the rs lane. A new CHECK_MODULES filter (just gate [MODULE|-MODULE]...) splits Nightly's gate across two hosted jobs: Tests runs gate -rs_shapes, and Features runs gate rs_shapes.
  • Release-PR Check: it runs --all on the same 60-minute job, so it sets CHECK_MODULES=-rs_shapes on release PRs. Release PRs always run Features through the Release gate, which carries the sweep. This avoids splitting the required Check context.
  • Kept: the live per-phase lines (ci: test rs started, ci: check rs passed in …s), so a job killed mid-phase names the phase it stopped in.

(Written by Claude Opus 5.5)

@kixelated
kixelated marked this pull request as ready for review October 30, 2026 02:58
@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 641d6734-151a-47d7-bc15-0030d6ca77fe
Commits

Reviewing files that changed from the base of the PR and between 8d7a8e5 and 647f500.

Files selected for processing: 14
  • .github/workflows/check.yml
  • .github/workflows/features.yml
  • .github/workflows/nightly.yml
  • README.md
  • doc/setup/dev.md
  • justfile
  • quest/m0/nightly/README.md
  • quest/m0/nightly/gate-hang.md
  • rs/justfile
  • sh/dispatch-query.test.py
  • sh/dispatch.sh
  • sh/gh/queue.test.ts
  • sh/rs/select.sh
  • sh/rs/select.test.py
Files with no reviewable changes: 2
  • quest/m0/nightly/gate-hang.md
  • quest/m0/nightly/README.md

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 0 remain after this review.

Walkthrough

The dispatcher adds an rs_shapes check module and supports selecting or excluding modules through CHECK_MODULES. Rust selection scripts add a feature-shapes action. The Check, Features, and Nightly workflows split feature-shape checks across jobs. The dispatcher also emits phase start and result messages on file descriptor 3. Documentation and workflow tests are updated, and the nightly gate-hang quest item and document are removed.

Priority: Normal

Merge Risk: Minimal · up to 647f5

The gate splits Rust feature-shape checks into a separate job. No merge-blocking issue was found.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title accurately summarizes the main changes: keeping the Nightly gate within its job and reporting each running phase.
Description check Passed The description directly explains the timeout problem, the dispatcher changes, the Nightly and release-PR split, live phase reporting, tests, and validation results.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 9 functions across 5 files. (7 skipped: 7 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
⚔️ Resolve merge conflicts: 💡
  • Resolve merge conflict in branch quest/m0/nightly/gate-hang
✨ Simplify code
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-30T09:05:38.808192Z 647f500 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5485bf097

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sh/dispatch-query.test.py Resolved

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Automated review by review (OpenAI)

Reviewed commit: c5485bf0979e42f798047f3aee1ca90f82923b2a.

One actionable blocker, already reported independently: P1: clear inherited CHECK_MODULES in dispatcher test fixtures. I confirmed the code path: both new split callers export CHECK_MODULES=-rs_shapes, gh test runs this suite, and QueryTests.setUp preserves that variable. The new unconditional three-call assertion then excludes its expected feature-shapes-changed call. Clear the variable in the fixture and cover running the suite under the actual split environment; no duplicate inline comment added.

Overall direction is sound: separating the expensive sweep preserves the same crate selection and queue coverage rather than weakening it or raising timeouts. Release gate depends on Features, and the live phase logging retains the original stderr correctly. No additional actionable bugs found in the independent static pass.

Verification limits: no tests or hosted jobs run. The split's ability to finish within 60 minutes still needs a hosted measurement; reported local timings and test results were not independently verified.

(Written by OpenAI)

@kixelated
kixelated added this pull request to the merge queue Oct 30, 2026

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Automated review by review (OpenAI)

Reviewed commit: 6fa5bb98cc618410226f5b463a946c321f86a8dd, compared with my last review at c5485bf0979e42f798047f3aee1ca90f82923b2a.

The prior P1 inherited CHECK_MODULES finding is fixed: QueryTests.setUp now clears the caller's filter before fixture subprocesses run, while explicit filter tests still supply their own values. No new actionable bugs found in this delta.

Direction: this narrow fixture-isolation fix preserves the split-gate design and its filter coverage without changing production selection. Verification was static GitHub inspection with an independent check; I did not run tests or hosted jobs. Hosted completion within the timeout remains unverified here.

(Written by OpenAI)

@kixelated
kixelated enabled auto-merge (squash) October 30, 2026 06:29
@github-actions
github-actions Bot disabled auto-merge October 30, 2026 07:38
@github-actions

Copy link
Copy Markdown
Contributor

quest land removed this pull request from the queue: it conflicts with the base or the PRs queued before it in .github/workflows/check.yml, .github/workflows/nightly.yml, doc/setup/dev.md, sh/gh/queue.test.ts; merge the base, push, and land it again (run).

…7070)

* chore(quest): claim quest/m0/nightly/gate-hang.md

Quest-Claim: fce0ca6d05eeb753

* ci: keep the nightly gate inside its job and name each running phase

Nightly's gate did not hang: its Rust lane was still compiling the test
build when the 60-minute job timed out. Since the isolated feature shapes
(cargo hack, one clippy pass per package at both extremes) began running on
whole-workspace selections, the lane outgrew the 4-vCPU hosted job. A
whole-workspace selection now leaves that sweep to a Features job
(`just rs feature-sweep`), which Nightly and release PRs run.

Buffered dispatcher lanes also announce each phase's start and end on the
run's stderr, so a run killed mid-phase names the phase it stopped in.

* ci: split Nightly's gate across hosted jobs with a dispatcher module filter

The maintainer kept the isolated feature shapes in the queue's gate for every
selection and split Nightly's gate instead. The shapes become their own
dispatcher module, rs_shapes, in the rs lane, and CHECK_MODULES (`just gate
[MODULE|-MODULE]...`) runs or skips named modules. Nightly's Tests job runs
`gate -rs_shapes` and Features runs `gate rs_shapes`; release-PR Check skips
rs_shapes too, since Features runs on release PRs.

This reverts the earlier whole-workspace skip and the separate feature-sweep
recipe.

* test(gh): pin the gate's split across Check, Tests, and Features

* test(ci): clear inherited CHECK_MODULES in dispatcher fixtures

Nightly's `gate -rs_shapes` and release-PR Check export the filter, which
the fixtures inherited, skipping the rs_shapes module their assertions expect.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@moq-bot
moq-bot Bot force-pushed the quest/m0/nightly/gate-hang branch from 647f500 to 9619a9b Compare October 30, 2026 09:26
@moq-bot
moq-bot Bot merged commit 9619a9b into main Oct 30, 2026
9 checks passed
@moq-bot
moq-bot Bot deleted the quest/m0/nightly/gate-hang branch October 30, 2026 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant