Repository navigation
Conversation
ac-pplx
force-pushed
the
ac/kind-release-build-lane
branch
3 times, most recently
from
October 21, 2026 04:25
9d7999e to
9f7ab9f
Compare
ac-pplx
marked this pull request as ready for review
October 21, 2026 04:31
ac-pplx
force-pushed
the
ac/kind-release-build-lane
branch
3 times, most recently
from
October 21, 2026 18:45
31bb009 to
9ed6626
Compare
nikhilgupta-pplx
approved these changes
Oct 21, 2026
nikhilgupta-pplx
left a comment
Member
There was a problem hiding this comment.
The release lane is opt-in, and the build/cache isolation looks sound. Default chart renders only gain build labels; the umbrella render is unchanged. The 45-file scope is consistent with carrying the build through artifacts, workloads and smoke selection.
Validated 572 Python tests, the focused artifact/reuse/bootstrap shell tests, and chart renders against the merge base. No code blockers. Required CI still needs to finish; run the new dispatch lane after it lands before treating it as CI-proven.
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Oct 21, 2026
ac-pplx
force-pushed
the
ac/kind-release-build-lane
branch
from
October 21, 2026 19:41
9ed6626 to
2742379
Compare
Every Kind binary is built with the test-hooks feature, so the hooks the charts set (`pplx_space_common_core::env::test_hook`) take effect on every run, and nothing exercised the platform with binaries built without them. SPACE_KIND_RUST_BUILD=release (lib/rust-build.sh; default test-hooks) selects a lane for Tilt, bootstrap.sh, the smoke bring-up and CI's prebuilt handoff: - build-rust-artifacts.sh builds the default bin and feature lists with both test-hook lists of Dockerfile.rust-build-kind empty and thin LTO, so that no crate's test-hooks feature is enabled. That requires leaving the test-support member pplx-space-db-test-fixtures out of the package selection: the host builds pass --workspace --exclude, and the Docker cook names every other member with -p (cargo chef has no --exclude), and cooks the guest with its build's packages, so the build recompiles no dependency. The lane refuses dev-release and never exports to the layer cache, in either artifact mode. - The artifact image records its build in a space.pplx.net/kind-rust-build label that prebuilt mode checks, and runtime-image-cache.sh copies it onto every Rust runtime image built from it. The release lane's Rust input key also names the build, so it never matches a test-hooks image's key (the default build's key is unchanged), and Kind CI's reuse of main's published artifact image is skipped for a release run. - The charts render with rustBuild=release, dropping every hook they set (sandbox-manager's snapshot reaper timings, template-manager's GC timings and prefetch latest-N, the disk-admission reservation, and node-manager's loop-device target when one is passed). Every Rust workload's pod template records its build, so a change of build rolls them all; charts rendered without rustBuild, such as the space-cluster umbrella's, are unchanged. - scripts/deployed-rust-build.py reads the build from the image each running SPACE Rust container uses, on its node, and requires it to agree with every other container and with the pod's rendered label. bootstrap.sh refuses artifact or runtime images of the other build before rendering and checks the pods after the rollouts; the smoke bring-up waits for every Rust rollout and checks the same way. - Scenarios declare test_hooks=; the typed smoke skips them on a release bench, and the bring-up and suite refuse a bench of the other build when SPACE_KIND_RUST_BUILD is set. - kind-release-ci.yml runs kind-ci.yml with rust_build: release on workflow_dispatch only. The default lane builds the same binaries and renders the same env as before; its Rust pods gain only the build label.
ac-pplx
force-pushed
the
ac/kind-release-build-lane
branch
from
October 21, 2026 20:59
2742379 to
121821d
Compare
This branch has not been deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The gap
Every Kind Rust binary is built with
test-hooks(docker/Dockerfile.rust-build-kind's feature lists), so each environment variable read throughpplx_space_common_core::env::test_hook/test_hook_vartakes effect, and the Kind charts set several on every run. Nothing exercised the platform with binaries built without the feature, or checked that a bench claiming such binaries actually runs them.Inventory: the test hooks the Kind charts set
SPACE_SBX_GC_TARGET_FRACTION,_INTERVAL_SECS,_GRACE_SECS,_IDLE_SECSsnapshot_gc::GcConfig::from_envlocal.snapshot_reaper_reclaims_backed_fork_snapshotSPACE_TEMPLATE_GC_INTERVAL_SECS,SPACE_TEMPLATE_GC_GRACE_SECSeviction::GcConfiglocal.template_cache_lru_eviction_reclaimsSPACE_TEMPLATE_PREFETCH_LATEST_Nprefetch(LATEST_N_TEST_HOOK)SPACE_NODE_DISK_ADMISSION_ALLOCATION_RESERVATION_BYTESCacheDiskAdmissionConfig::from_envSPACE_LOOP_DEVICE_TARGETloop_devices::override_from_envbootstrap.shpass-through)The five scenarios the lane skips also stage hooks of their own at run time (the retention sweeper's dry-run, tick and minimum age; the activation-admission burst); see Skipped in the lane.
The change
SPACE_KIND_RUST_BUILD=release(newinfra/space/kind/lib/rust-build.sh; the default istest-hooks) is read by the Tiltfile,bootstrap.sh,build-rust-artifacts.shand the smoke bring-up.Dockerfile.rust-build-kindbecome build args (SPACE_KIND_TEST_HOOK_FEATURES,SPACE_KIND_GUEST_TEST_HOOK_FEATURES). Both artifact modes read them: Docker passes them empty, and incremental leaves them out. The lane builds every Kind service with no crate'stest-hooksfeature enabled. That requires leaving the test-support memberpplx-space-db-test-fixturesout of the package selection (SPACE_KIND_CARGO_EXCLUDE): the host builds pass--workspace --exclude pplx-space-db-test-fixtures, the Docker cook names every other member with-p(cargo chef cookhas no--exclude; the planner derives the list fromcargo metadata), and the guest cook selects the guest build's own packages, so the cook and the build resolve the same features. The lane also setsCARGO_PROFILE_RELEASE_LTO=thin, refusesSPACE_KIND_RUST_PROFILE=dev-release, and never exports to the shared layer cache: the guard runs as soon as the build mode is resolved, before chef-base, the health probe or either artifact mode is built.space.pplx.net/kind-rust-build, whichprebuiltmode checks, andruntime-image-cache.shcopies that label onto every runtime image built from the artifact image (itsSPACE_RUST_BUILD_IMAGEbuild arg). The incremental reuse key includes the build.rustBuild=<build>. In release, thespace-node-servicelibrary'srustBuildhelper gates the reservation hook, sandbox-manager's four reaper hooks, template-manager's three cache hooks and node-manager'sSPACE_LOOP_DEVICE_TARGET. The release-read settings next to them stay:SPACE_SBX_GC_ENABLED,_ENGAGE_FRACTION,SPACE_TEMPLATE_CACHE_BUDGET_BYTESand_MIN_AVAILABLE_BYTES. Every Rust workload's pod template (api, admin-api, internal-api, credmgr-authority, key broker, data-plane, cluster-controller, every node service and the operator shell) carries thespace.pplx.net/kind-rust-buildlabel, so a change of build rolls all of them. The label renders only whenrustBuildis set, so thespace-clusterumbrella chart, which never sets it, renders exactly as onmain.infra/space/kind/scripts/deployed-rust-build.pydecides the bench's build from what runs: for every running container of a SPACE Rust image (space-api,space-data-plane,space-cluster-controller,space-worker,space-kind-key-broker) it reads the label of the image that container runs, on its node (crictl inspecti), and requires every container, and each pod's rendered label, to agree.--waitfirst waits for every Deployment and DaemonSet that runs one of those images to roll out, and--podsprints the per-pod evidence.bootstrap.shrefuses to render the charts when the artifact image or a Rust runtime:localimage carries the other build (as--skip-imagescan leave them), and fails unless every container runs the requested build after the rollouts. The smoke bring-up (bootstrap-kind-stack.sh) uses the same reader before deciding whether to restart Tilt, and after Tilt settles it waits for every Rust rollout and checks again. The typed smoke's_apply_rust_builduses it too.test_hooks=(naming the hooks a scenario needs), is set on the five scenarios that cannot pass without one. On a release bench the suite skips those five and prints them asSKIPPED. WhenSPACE_KIND_RUST_BUILDis set and the bench runs the other build (or no single build), the suite fails. The bring-up restarts Tilt into the requested build, or refuses underSKIP_BOOTSTRAP=1, mirroring the storage-credentials mode..github/workflows/kind-release-ci.yml(workflow_dispatchonly) callskind-ci.ymlwith the newrust_build: releaseinput. The producer builds the release image in Docker mode; the four shards verify its label, then run the baseline and their typed partition. The default caller passes nothing, andSPACE_KIND_RUST_BUILDstays empty there, so the required lane runs as before.Why this is faithful. The lane compiles the same bins and features as the default, inside the same
chef-basebuilder, with thin LTO, and selects packages so that no crate'stest-hooksfeature is on. The charts render only settings a binary without the feature reads. The default lane builds the same binaries and renders the same env; its Rust pods only gain the label.Skipped in the lane:
local.template_cache_lru_eviction_reclaims: the code-default GC grace is 1800 s, past its 900 s budget.local.snapshot_reaper_reclaims_backed_fork_snapshot: the code-default idle threshold is a day.local.retention_claim_finish_forwardandlocal.retention_restore_source_guard: the code-default tick is 300 s and min age is an hour, against an 80 s budget sized from the 5 s tick they stage.local.rate_limiters_enforce_and_fail_open: draining a burst of 60 would take sixty real boots.What still differs
MIN_AVAILABLE_BYTESfloor is a setting the binaries read without the feature, and stays at 1 GiB.build-seed.sh; its publish Job's pod does not stay running, so the reader does not inspect it.README "Differences" rows changed (and nothing else in the table):
main; the right column adds the lane.test-hooks": the lane builds with thin LTO and no crate'stest-hooksfeature.Also added: a new
## Release-build lanesection, one sentence in the Tilt paragraph, and one line in the KindAGENTS.md.Validation
The Kind runs below validated
0fe935don baseb95b6ab, except run 6, which validated the final head9d7999eon basebe16af3(the same patch rebased;git range-diffshows it unchanged). Settings matched CI:SPACE_KIND_TELEMETRY_MODE=otel,DATA_PLANE_URL=http://127.0.0.1:8090, and the admin token file and cold-receipts dir as inkind-ci.yml. The health gate (Tilt quiet, no ReplicaSet younger than 180 s, nodes Ready and published, 120 s settle) ran before the typed suite. Provenance is by binary sha256: for nine services (api, internal-api, data-plane, cluster-controller, credmgr-authority, key broker, sandbox-manager, template-manager, node-manager), the binary in a running pod matched the one in the staged build, and the reader's per-pod output (deployed-rust-build.py --pods) covered all 50 running Rust containers.Release build time, Docker mode (the CI producer's path), cold: build cache pruned, chef-base rebuilt
4b86967's Dockerfile)The cook now resolves the same features as the host and guest builds, so those builds recompile no dependency. Wall time didn't change: the host build's critical path is the workspace crates and the thin-LTO links. The supervisor is a separate invocation with its own feature set, as in the default lane, so it still recompiles some dependencies.
Results
cargo tree -e normal,build,featuresover the lane's selection and features shows no crate withtest-hooksenabled, for the host, guest and supervisor invocations. In the release binaries, the hook-only namesSPACE_SBX_GC_IDLE_SECS,SPACE_TEMPLATE_GC_INTERVAL_SECSandSPACE_NODE_DISK_ADMISSION_ALLOCATION_RESERVATION_BYTESare absent; settings read without the feature, such asSPACE_SBX_GC_ENGAGE_FRACTION, remain.space-clusterumbrella (values.example.yaml) renders byte-identical tomain. The first round's head added 31kind-rust-build: test-hookslabels there. Every changed Kind chart in default mode differs frommainonly by the build label. Release mode drops exactly the eight chart hooks, plusSPACE_LOOP_DEVICE_TARGETwhen one is passed.[7/7] PASS round-trip ok). 50 of 50 Rust containers runtest-hooksimages, renderedtest-hooks.bootstrap.shbootstrap.sh(default,:localimages):SPACE_KIND_RUST_BUILD=release --skip-imagesrefused before rendering any chart (space-rust-build-kind:local is the test-hooks Rust build …), and no workload's generation changed.SPACE_KIND_RUST_BUILD=releasewith images rolled all 25 Rust Deployments and DaemonSets: 50 of 50 containers run release images, and the sampled binaries match the release build and differ from the default one. Reverse: default--skip-imagesrefused the same way, then defaultbootstrap.shrolled back to 50 of 50test-hooks, with binaries byte-identical to run 1's.SPACE_KIND_RUST_BUILD=release smoke-kind-e2e.shstarted Tilt in release, waited for all 25 Rust rollouts, then read 50 of 50 release containers; e2e passed. On that bench,SKIP_BOOTSTRAP=1with the default request was refused (runs the release Rust build (read from its Rust containers' images)). The typed suite's gate, run against it, kept 78 of 83 ECW scenarios withrelease(the fiveSKIPPED) and returned the mismatch error withtest-hooks.smoke-kind-e2e.sh(default) restarted Tilt, waited for all 25 rollouts, then read 50 of 50test-hookscontainers, with binaries identical to run 1's; e2e passed.smoke-kind-typed.sh all, 73 min: ECW 78 passed / 0 failed, includinglocal.ecw_template_build_from_oci_boots,local.concurrent_restore_converges_to_one_executionandlocal.cold_sandbox_eviction_wake_round_trip. Native: 25 passed / 1 failed, includingnative_contract.zero_vcpu_admission. The five hook scenarios printed asSKIPPED. The failure isnative.m1_generated_sdk_conformance(AttributeError: 'str' object has no attribute 'to_dict'); it failed the same way on a rerun. PRE-EXISTING: Main CI fails shard 4 with the same error onb95b6ab.space_smokeandtest_kind_registry_cache.py(554 passed, 1 skipped),test-kind-rust-artifacts-{mode,reuse,prebuilt}.sh,test-kind-port-forward-parity.sh,test-kind-stale-tilt-recovery.sh,test-kind-tombstone-sweep.sh.9d7999e, every check passed except Kind shard 4, which fails onlynative.m1_generated_sdk_conformancewith the sameAttributeError. PRE-EXISTING: Main CI fails shard 4 the same way onb95b6abandbe16af3, and passed on188c1a3. Shards 1–3 passed, as did the default-lane producer build. The new dispatch workflow can be dispatched only after it exists on the default branch, so it is not exercised here.No new tests: the change is limited to charts, scripts, the smoke harness and CI, so the mismatch, refusal and skip paths were exercised by the real runs above. Two existing harness tests' fixtures now stub the new reader instead of the old DaemonSet read.
Bench disk. Each Tilt rebuild cycle on this box left about 11 GB of BuildKit cache on a 49 GB Docker root. Free space fell to 4 GB during one cycle's image builds (no build failed), and the cache was pruned between runs.
Nightly schedule? Worth it once the lane has a few green dispatches. The lane is the only check of binaries built without the feature, and a regression that appears only without hooks (a default the charts override) would otherwise go unseen. One nightly run costs a producer and four shards. Not added here.
Review follow-up
The PR text, README, Dockerfile comments and commit message described more than the lane: fixed. They now describe only the lane's mechanism (no crate's
test-hooksfeature enabled, which requires excluding the test-support member). The "Release binaries read no test hooks" row's left column is back tomain's wording, and the inventory lists only hooks the Kind charts set.Switching a reused cluster could leave the control plane on test-hook binaries while the check passed: fixed. The build now reaches every Rust workload's pod template, the bring-ups wait for the replacement pods, and the build is read from each running container's image on its node and checked against the pod's render.
bootstrap.shalso refuses images of the other build before rendering.The release lane could still export chef-base and the health probe, and incremental mode never applied the guard: fixed. Cache exports are now disabled as soon as release mode is resolved.
The release cook selected every member while the build excluded the fixtures crate: fixed. The host cook now gets the build's selection as
-p, and the guest cook its build's packages. Dependencies recompiled in the build drop to zero; the wall time didn't change (see Validation).SPACE_LOOP_DEVICE_TARGETstill rendered in release mode: fixed by gating it like the other hooks. The chart value feeds only node-manager, which reads it throughtest_hook_var; the node image's staging reads its own env file, so nothing needed splitting.Stale comments (the adapter's "every workload is labelled", the Tiltfile's and
build-images.sh's "LTO off"): fixed. No tests were added for the harness's mismatch and skip paths, per the repository's test policy for harness changes; they are exercised by real runs instead.Rebased onto main after the Rust input-key reuse landed: the release lane's input key now names its build (
rust-build release), so it can never match a published test-hooks image, while the default build's key is unchanged; Kind CI skips the reuse of main's artifact image for a release run; prebuilt mode checks both the build label and, for another commit, the input key. Checked locally: the default and explicittest-hookskeys are equal and the release key differs.Rebased onto main after kind: run the reconcile-queue GC against a fake EC2 endpoint #698 and the per-scenario recheck (
kind_stack_recheck_for_scenario) landed: theSKIP_BOOTSTRAP=1path checks the Rust build first, then the shared storage-mode refusal and the reconcile-queue GC wiring. The recheck's comment now names the Rust build check beside image provenance as one only a Tilt build changes, so it stays out of the per-scenario recheck.Rollback
Revert the commit. The default lane renders the same env and builds the same binaries. Clusters brought up with the revert lose only the
space.pplx.net/kind-rust-buildpod label, which rolls the Rust pods once.🤖 Generated with Claude Code