Skip to content

ci: build the Azurite and Storage Upgrade engine graphs once - #898

Merged
azimafroozeh merged 1 commit into
ModernRelay:mainfrom
azimafroozeh:ci-azurite-storage-upgrade-one-graph
Oct 8, 2026
Merged

azimafroozeh merged 1 commit into
ModernRelay:mainfrom
azimafroozeh:ci-azurite-storage-upgrade-one-graph

Conversation

@azimafroozeh

Copy link
Copy Markdown
Collaborator

What & why

Azurite Azure Integration runs its eleven cargo calls under six per-crate package selections, and each selection resolves its own feature graph: four of them carry the Lance stack (the engine with failpoints, cluster, server and the CLI differ on the engine's failpoints and tokio's io-std, so tokio and everything above it recompiles between them). That is 89 minutes on main's push run and a cancellation at the 90-minute budget on #896's run, still compiling omnigraph-engine. Storage Upgrade Compatibility runs three -p omnigraph-engine --features failpoints scopes after its --workspace crossversion scope, a third graph at about 20 minutes warm. Both break the cache rule in docs/dev/ci.md (a second cargo invocation in a job must not change the dependency graph), the same mechanism as #755 and #896.

Every cargo call in each job now selects the Test Workspace packages, --workspace --exclude omnigraph-gqt --exclude omnigraph-dst --features "$FAILPOINT_FEATURES", and an owner names only its target (--lib, or --test <file>). Each job resolves one graph, the one Test Workspace already builds, so a cold run is a single engine build.

scripts/check-storage-upgrade-ci.py pins the scope commands, so they move with the workflow; its log validator accepts the all-zero summaries that a workspace selection prints for binaries that filtered to nothing and still requires exactly one summary that executed tests; the four old spellings are self-test rows, so a revert of the selection fails the guard. docs/dev/ci.md describes the shared selection in the Storage Upgrade paragraph, the Azurite bullet and the cache rule.

Backing issue / RFC

Checklist

  • Change is focused (one logical change: one package selection per job)
  • Tests added/updated for behavior changes: the check script's self-test gains the old command spellings as regression rows and the multi-summary log cases
  • Public docs updated: docs/dev/ci.md
  • Reviewed against docs/dev/invariants.md: no invariant touched, no deny-list item

Local verification

Run from the branch's tree on macOS, with the Test Workspace world built by cargo test --workspace --exclude omnigraph-gqt --exclude omnigraph-dst --locked --features omnigraph-engine/failpoints,omnigraph-cluster/failpoints --no-run:

  • python3 scripts/check-storage-upgrade-ci.py --self-test — 13 tests OK
  • python3 scripts/check-storage-upgrade-ci.py — Storage upgrade CI OK
  • python3 scripts/check-ci-cells.py --self-test — self-test ok, 49 required test names defined
  • python3 scripts/check-classify-copy.py, scripts/check-workflow-action-pins.py, scripts/check-merge-group-triggers.py --self-test, scripts/check-change-classes.py --self-test — all ok
  • typos .github/workflows/ci.yml docs/dev/ci.md scripts/check-storage-upgrade-ci.py — clean
  • Storage Upgrade protocol scope, new spelling — one binary, 35 passed; --check-log protocol OK
  • Storage Upgrade engine scope, new spelling (--workspace … --lib db::upgrade::tests) — 16 lib binaries, one executed (50 passed, 384 filtered out), fifteen all-zero summaries; --check-log engine OK
  • Azurite engine owner through the shared selection (--test failpoints azure_write_detached_pin_survives_next_write -- --exact) — both failpoints binaries run, cluster's 0 passed / 8 filtered, engine's 1 passed (skips without Azurite, still ok)
  • Azurite storage owner (--lib tests::contract_suite_azure_when_configured -- --exact) — every lib binary runs filtered, the storage one reports ok
  • scripts/check-docs.py — not run (pinned doc-tooling packages not installed locally)
  • Lance scope, hosted cold timings and the owners against a live Azurite — not run; CI supplies them

Feature-graph evidence: cargo tree --locked -e features -f "{p} {f}" --prefix none per selection on a951b0ea, diffed per package: storage 265 packages, azure-admission 299, engine+failpoints 1184, cluster 1059, server 1142, cli 1174, all pairwise different; the shared selection 1307.

Notes for reviewers

  • failpoints is a test target of both the engine and the cluster crate, so the three engine owners also run the cluster binary at zero matching tests; require_cell reads the engine's ok line.
  • --workspace --lib compiles every member's unit-test harness once (workspace crates only, no dependency rebuild); that is the price of one graph for the two --lib owners and the engine scope.
  • Not in this change: the budgets stay at 90 (lower them on observed cold runs); no guard enforces the one-selection rule yet (third regression of the class); the rust-cache runner-image key term from ci(gqt): build the ordinary job's engine graph once #896.
  • CI-only, so no changelog fragment.

@azimafroozeh
azimafroozeh enabled auto-merge October 8, 2026 09:23

@ragnorc ragnorc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Recommendation: approve, subject to the required CI checks and the Azure integration result. I found no blocking defect at bc4924cf5df7ccec30ec3c9d8bc83d5d2e6519f7.

This PR stops two test jobs from repeatedly compiling the same engine dependencies. Previously, each test owner selected its own packages and features. Those selections changed the dependency build and consumed much of the job's time limit. The jobs now use the existing workspace selection and choose individual test targets within it. The storage-upgrade log checker also accepts the empty results from unrelated, filtered test binaries.

The required contract is complete, failing-on-error qualification on hosted Linux, including runners with no cache. The Azure job must exercise its configured storage and admission paths. The upgrade job must test genuine predecessor data and every required upgrade owner. These obligations matter more than a shorter green job.

The change preserves those obligations by inspection:

  • The Azure selection keeps every named owner, exact test filtering, required success lines, and the final rejection of unconfigured skips. set -euo pipefail still propagates Cargo failures through tee.
  • The upgrade checker still requires every expected case to pass. It accepts only one successful summary with positive coverage. Additional summaries must have zero passed, failed, ignored, and measured tests. Missing cases, ignored cases, and two executing binaries still fail.
  • The genuine predecessor build, released CLI checks, required context, and missing-predecessor refusal remain unchanged.

Tradeoffs and liability: this fixes the package-selection cause through Cargo's existing feature rules. It adds no storage mechanism or production API. Azure gains one shared shell selection. Upgrade validation extends its existing owner instead of adding another checker. The 44 net added lines therefore reduce operational liability despite increasing source size.

The broader selection has a cost. --lib compiles 16 workspace test harnesses, although only the named owner executes tests. These jobs now depend on unrelated workspace crates compiling. Azure server and CLI tests also share the workspace failpoint features instead of their former separate selections. Test names remain covered, but the former feature combinations do not. This is an acceptable exchange for one maintained build configuration. Five similar jobs should reuse that configuration, rather than create five new package lists.

Local validation from the clean review checkout:

  • All 13 storage-upgrade guard tests passed. I ran the existing multi-summary regression against the old validator: it failed as expected. It passed with the new validator. No source edits were needed.
  • Generated Linux-target Cargo build plans for all ten distinct target selections. Each selected engine, Lance, DataFusion, Arrow-array, and Tokio build has the same recursive dependency signature across those plans. The supervisor target does not need the engine. This checks build resolution, not elapsed build time.
  • Checked the actual manifests and pinned Lance 11.0.0 feature declarations. The shared engine enables failpoints, with no dst feature. The shared Lance build includes the workspace's additional backend features.
  • Workflow guards, applicable self-tests, spelling, and all 217 documentation files passed.

Exact-head CI passed the workflow guard, Azure integration, and the complete Storage Upgrade Compatibility job. The Azure log shows a 21m53s first build and later target builds of at most 23.80s. It shows one Tokio and one Lance compilation. This supports build reuse on that runner. I did not run Azurite or rebuild the full Rust workspace locally. Cache-independent timing and disk costs remain unverified here. One passing run does not establish a 90-minute bound.

@azimafroozeh
azimafroozeh added this pull request to the merge queue Oct 8, 2026
Merged via the queue into ModernRelay:main with commit aec0525 Oct 8, 2026
30 checks passed
@azimafroozeh
azimafroozeh deleted the ci-azurite-storage-upgrade-one-graph branch October 8, 2026 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants