Repository navigation
test: build the Kubernetes lifecycle workspace from the bundle - #12981
Merged
Merged
Conversation
Contributor
|
v1 documentation preview: https://nvidia-preview-nemoclaw-v1-pr-12981.docs.buildwithfern.com/nemoclaw |
cv
added a commit
that referenced
this pull request
Oct 11, 2026
Part of #12882. ## Failure The pinned `kreuzwerker/docker` provider waits 2 s before every `docker_network` read and after every removal. Every runtime plan, apply, export, or destroy reads the network once it exists, and a destroy also waits for the removal. Only the `remote_service` lifecycle tests deploy a service with a Docker network: the SSH simulator is the only fake engine that serves `/networks`. I counted the network reads per test from a request log in the SSH simulator (local `linux_arm64` bundle; the logging is not part of this change). The 12 tests made 75 reads, about 150 s of their 404 s of test time: | Test | Reads | |---|---| | `managed_bearer_storage_or_key_damage_stops_plan_and_apply_without_changing_bindings` | 13 | | `remote_model_reapply_and_drift_keep_bindings_and_stop_on_observation_failure` | 11 | | `remote_ollama_reapply_and_drift_keep_bindings_and_stop_on_observation_failure` | 11 | | `managed_bearer_credentials_survive_recovery_reapply_and_replacement_outside_state` | 10 | | `managed_pi_applies_without_generation_and_refused_sandbox_changes_keep_intent` | 9 | | `managed_bearer_replacement_cleanup_recovers_and_teardown_accepts_both_identities` | 7 | | `remote_model_apply_recovers_failed_creation_and_lost_process_or_cache_keeping_data` | 7 | | `remote_ollama_apply_recovers_failed_creation_and_lost_process_or_cache_keeping_data` | 7 | | partial-destroy and pulled-image tests (4) | 0 | Several tests created and destroyed a runtime only to repeat checks that another scenario already ran against the same kind of runtime. ## Decision Run each check against one runtime per scenario, and only once. The Docker provider is unchanged. | Before | After | |---|---| | `remote_model_apply_recovers_failed_creation_and_lost_process_or_cache_keeping_data` | Removed. vLLM failed-creation, startup, lost-process, and cache recovery run in `managed_bearer_credentials_survive_recovery_reapply_and_replacement_outside_state`, against the same vLLM runtime with a bearer. Present-image compatibility runs in the Ollama and Pi tests, and the pull-policy plan runs in the Ollama test. | | `remote_ollama_apply_recovers_…` and `remote_ollama_reapply_and_drift_…` | `remote_ollama_recovers_reapplies_and_stops_on_observation_failure_keeping_data`: recovery, then export and reapply, the transport failure, and teardown against the recovered runtime. The readiness gate, compute replacement plan, and pull-policy reapply do not depend on the runtime kind and run against vLLM in `remote_model_reapply_and_drift_…`. `managed_installers_accept_current_runtime_readiness_without_collecting_model_files` in `nemoclaw-provider` covers each runtime's readiness observation. | | `managed_bearer_storage_or_key_damage_…` and `managed_bearer_replacement_cleanup_…` | `managed_bearer_cleanup_recovers_damage_keeps_bindings_and_teardown_accepts_both_identities`: the daemon retargeting, credential-volume damage, and insecure-key checks run against the state that replacement cleanup settles, before the teardown with both identities. | | Missing, foreign, and substituted credential volumes through CLI plan and apply | New `service_storage::missing_foreign_or_substituted_storage_stops_plan_and_apply_without_changing_state` contract test, for both storage kinds, through pinned OpenTofu against a fake engine. The lifecycle test keeps one substituted volume to show the CLI stops before changing bindings. | | Pi: failed-creation recovery, then an export after the last refusal | Pi applies once; the bearer and Ollama tests own recovery. The export after the last refusal is dropped: the intent is byte-identical to the one the earlier export already reproduced, and the destroy that follows reads the same state. | The partial-destroy and pulled-image tests are unchanged. ## Validation - Local `linux_arm64` run of `remote_service`, same request log: | | Tests | Network reads | Summed test time | Wall (4 threads) | |---|---|---|---|---| | Before | 12 | 75 | 404 s | 110 s | | After | 9 | 48 | 280 s | 97 s | After the change, by test: vLLM reapply 11, Ollama 9, bearer credentials 10, bearer cleanup and damage 12, Pi 6. - The new contract test asserts each refusal reason (`bound persistent storage is absent; recreation forbidden`, `observed ownership, generation, or durable identity changed`). - `remote_service` and `service_storage` lifecycle tests pass locally; `cargo fmt --all --check` and `cargo clippy --workspace --all-targets -- -D warnings` are clean. - `v1` at a49fc77 does not compile the provider contract tests (`kubernetes_lifecycle.rs`). This branch carries the same fix as #12981 in its own commit so CI can run, and merging `v1` after #12981 lands leaves one copy. - CI lifecycle JUnit reports from run [38100630144](https://github.com/NVIDIA/NemoClaw/actions/runs/38100630144), compared with the `v1` run for #12974 ([38098264065](https://github.com/NVIDIA/NemoClaw/actions/runs/38098264065)), the latest `v1` run whose lifecycle tests ran. Cells are partition wall seconds / summed test seconds / `remote_service` summed seconds: | Partition | Before | After | |---|---|---| | linux_arm64 / 1 | 198.8 / 788 / 175 | 200.2 / 795 / 171 | | linux_arm64 / 2 | 178.0 / 711 / 252 | 149.3 / 587 / 120 | | linux_amd64 / 1 | 221.0 / 878 / 209 | 208.0 / 825 / 186 | | linux_amd64 / 2 | 174.0 / 696 / 247 | 165.6 / 654 / 142 | `remote_service` went from 427 s to 291 s summed on linux_arm64, and from 456 s to 328 s on linux_amd64. Across the 9 `Rust desired-state` runs before #12974, it ranged 446–454 s on linux_arm64. The network read counts above come from the local request log; CI runs the same commands. The linux_arm64 lifecycle step is still bounded by partition 1, which kept its share of the `remote_service` tests and did not get shorter; partition 2 dropped 29 s.
cv
added a commit
that referenced
this pull request
Oct 11, 2026
## Failure Lifecycle tests are split into partitions with nextest's `hash:` mode. With 129 tests, the hash puts 74 of them in partition 1 and 55 in partition 2 on Linux and macOS. On Windows the three partitions get 35, 41, and 39 tests. Each partition keeps its four test slots busy, so its wall time is about its summed test time divided by four, and the slowest partition sets the step's wall time. Execute step times on recent v1 runs, in seconds: | Run | linux_arm64 | linux_amd64 | darwin_arm64 | windows_amd64 | |---|---|---|---|---| | [#12981](https://github.com/NVIDIA/NemoClaw/actions/runs/38130235163) | 208 / 158 | 203 / 157 | 187 / 145 | 105 / 176 / 152 | | [#12982](https://github.com/NVIDIA/NemoClaw/actions/runs/38129638172) | 208 / 158 | 233 / 173 | 215 / 139 | 84 / 145 / 156 | | [#12974](https://github.com/NVIDIA/NemoClaw/actions/runs/38098264065) | 207 / 186 | 231 / 184 | 183 / 175 | 113 / 169 / 227 | ## Decision Use `--partition slice:m/n`. Nextest sorts the selected tests by binary and name and deals them round-robin. The slow scenarios are `nemoclaw-e2e` `deployment::` and `remote_service::` tests, and they sort next to each other, so dealing them alternately splits them evenly. Each partition now gets 64 or 65 tests on Linux. I replayed the per-test times from two v1 runs' JUnit reports through a four-slot scheduler that follows nextest's order. For the hash partitions, it reproduces the measured partition times to within about 1 s. For linux_arm64, I checked the slice membership against `cargo nextest list --partition slice:m/2` on that run's CI archive. Predicted nextest wall time, in seconds: | Platform | Hash, slowest partition | Slice, per partition | Ideal (sum / slots) | |---|---|---|---| | linux_arm64 | 201 | 177 / 174 | 174 | | linux_amd64 | 193–222 | 170 / 170 – 193 / 193 | 169–191 | | darwin_arm64 | 178–205 | 160 / 150 – 172 / 165 | 152–163 | | windows_amd64 | 142–164 | 128 / 141 / 147 – 127 / 135 / 120 | 105–120 | Alternatives considered: - Test priorities that start the `remote_service::` and `deployment::` scenarios first would only help Windows, by about 15 s on top of slices. They would also tie the nextest config to module names, so I left them out. - A third Linux or macOS partition would bring each one to about 120–135 s. It would also add a runner and about 20 s of job setup and extraction per partition. On Linux, lifecycle is not on the critical path: Live / Docker and Live / Kind start at the same time and run for 490–750 s. - Two Windows partitions would take about 170–187 s, which is slower than three hash partitions are today. Trade-off: with slice partitions, membership depends on the selected test list. Adding or removing a lifecycle test moves later tests to other partitions. For a given revision and platform, partitions stay fixed. Part of #12882. ## Validation - Locally: `cargo fmt --all --check` and `cargo clippy --workspace --all-targets -- -D warnings`. The change is to CI configuration and docs, with no Rust behavior to test; `crates/nemoclaw-build/tests/ci_lifecycle.rs` already covers passing `--partition` through. - `cargo nextest list --profile lifecycle --run-ignored only --partition hash:m/2` on run 38130235163's linux_arm64 archive lists 74 / 55 tests, matching CI. `slice:m/2` lists 65 / 64. - [CI on this PR](https://github.com/NVIDIA/NemoClaw/actions/runs/38133026550): every lifecycle partition passed. Execute step times in seconds, with nextest wall time and summed test time from the JUnit reports: | Platform | Before, slowest step (3 v1 runs) | After, steps | After, nextest wall | After, summed test time | |---|---|---|---|---| | linux_arm64 | 207–208 | 184 / 184 | 175 / 175 | 695 / 694 | | linux_amd64 | 203–233 | 202 / 207 | 190 / 196 | 757 / 777 | | darwin_arm64 | 183–215 | 159 / 145 | 151 / 137 | 578 / 542 | | windows_amd64 | 156–227 | 143 / 131 / 152 | 132 / 118 / 142 | 441 / 425 / 499 | This run's linux_amd64 tests summed to 1,534 s. That is close to the 1,528 s of the #12982 run, whose slowest hash partition took 233 s; the slice partitions finished within 6 s of each other.
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.
Failure
v1doesn't compile since #12972. Its newnemoclaw-provider/tests/contract/kubernetes_lifecycle.rscallsTofuWorkspace::new(tofu, provider), with OpenTofu and the provider read fromNEMOCLAW_TEST_TOFUandNEMOCLAW_TEST_PROVIDER. #12971 merged first and changed that function toTofuWorkspace::new(&Bundle, nemoclaw). Since #12971,cargo ci lifecyclealso no longer sets either variable. Each PR passed CI against av1without the other.Every PR's CI now fails at
Lint Rust:Decision
Build the workspace with
crate::workspace(), as the crate's other contract tests do since #12971: OpenTofu and theopenshellandfabricproviders fromNEMOCLAW_TEST_BUNDLE, and thenemoclawprovider built from the checkout. That drops the two environment variables and the now-unusedPathBufimport.Validation
cargo clippy -p nemoclaw-provider --tests -- -D warningsis clean.cargo cipassed: 1,331 workspace tests and 131 lifecycle tests. Both of the file's tests ran from the bundle and passed:kubernetes_resources_apply_observe_the_release_and_tear_down_keeping_storagekubernetes_resources_refuse_replaced_or_missing_objects_without_recreating_them