From 0eed0836f581a8d1d0fb75f5de7f8c2ed34c69eb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 28 Sep 2026 12:49:46 +0900 Subject: [PATCH 1/5] fix(ci): prefetch locked Cargo fixtures for offline coverage --- .../workflows/opencode-review-dispatch.yml | 24 ++- ...encode-coverage-cargo-fixtures-20260928.md | 43 ++++ tests/fixtures/coverage-cargo/Cargo.lock | 194 ++++++++++++++++++ tests/fixtures/coverage-cargo/Cargo.toml | 9 + tests/fixtures/coverage-cargo/src/lib.rs | 1 + ...t_pr_review_autofix_nvidia_nim_contract.py | 2 +- 6 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md create mode 100644 tests/fixtures/coverage-cargo/Cargo.lock create mode 100644 tests/fixtures/coverage-cargo/Cargo.toml create mode 100644 tests/fixtures/coverage-cargo/src/lib.rs diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml index 0ac2ec1fd6..1cdabf6b1e 100644 --- a/.github/workflows/opencode-review-dispatch.yml +++ b/.github/workflows/opencode-review-dispatch.yml @@ -675,6 +675,20 @@ jobs: "$coverage_build_dir/install-base-python-locks.py" install -m 0755 "$trusted_vcs_import_root_resolver" \ "$coverage_build_dir/resolve-opencode-base-vcs-import-root.sh" + trusted_cargo_fixture="${GITHUB_WORKSPACE}/tests/fixtures/coverage-cargo" + if [ -L "$trusted_cargo_fixture" ] || [ -L "$trusted_cargo_fixture/src" ]; then + echo "::error::Trusted Cargo coverage fixture directories must not be symlinks." + exit 1 + fi + for fixture_file in Cargo.toml Cargo.lock src/lib.rs; do + if [ ! -f "$trusted_cargo_fixture/$fixture_file" ] || + [ -L "$trusted_cargo_fixture/$fixture_file" ]; then + echo "::error::Trusted Cargo coverage fixture is missing or not a regular file." + exit 1 + fi + install -D -m 0644 "$trusted_cargo_fixture/$fixture_file" \ + "$coverage_build_dir/coverage-cargo-fixtures/$fixture_file" + done python_change_files="${RUNNER_TEMP}/opencode-python-change-files" if ! git -C "$COVERAGE_SOURCE_WORKDIR" diff \ --name-only --diff-filter=ACMRTUXBD -z "$PR_BASE_SHA" HEAD \ @@ -783,6 +797,11 @@ jobs: vulkan-tools \ xz-utils \ && rm -rf /var/lib/apt/lists/* + COPY coverage-cargo-fixtures /tmp/coverage-cargo-fixtures + RUN CARGO_HOME=/opt/coverage-cargo-home cargo fetch --locked \ + --manifest-path /tmp/coverage-cargo-fixtures/Cargo.toml \ + && rm -rf /tmp/coverage-cargo-fixtures \ + && chmod -R a+rX /opt/coverage-cargo-home ENV LLVM_COV=/usr/bin/llvm-cov-19 ENV LLVM_PROFDATA=/usr/bin/llvm-profdata-19 ENV COREPACK_HOME=/opt/corepack @@ -980,12 +999,13 @@ jobs: # the read-only image -- so the baked offline vendor config from # /opt/base-rust-dependencies (see materialize_base_rust_dependencies.py) has to be # copied there explicitly rather than set as an image ENV default. + mkdir -p /work/.opencode-sandbox-home/.cargo + cp -a /opt/coverage-cargo-home/. /work/.opencode-sandbox-home/.cargo/ if [ -s /opt/base-rust-dependencies/cargo-config.toml ]; then - mkdir -p /work/.opencode-sandbox-home/.cargo install -m 0444 /opt/base-rust-dependencies/cargo-config.toml \ /work/.opencode-sandbox-home/.cargo/config.toml - chown -R "$OPENCODE_SANDBOX_UID:$OPENCODE_SANDBOX_GID" /work/.opencode-sandbox-home/.cargo fi + chown -R "$OPENCODE_SANDBOX_UID:$OPENCODE_SANDBOX_GID" /work/.opencode-sandbox-home/.cargo chmod 0700 "$RUNNER_TEMP" : >"$GITHUB_OUTPUT" chmod 0600 "$GITHUB_OUTPUT" diff --git a/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md new file mode 100644 index 0000000000..c542899e47 --- /dev/null +++ b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md @@ -0,0 +1,43 @@ +# OpenCode coverage Cargo fixture intake (2026-09-28) + +## Incident + +The current-head `.github#1026` OpenCode dispatch run `36348910783`, job +`108722448709`, reached the isolated coverage sandbox. Its full suite reported +four failures in `test_materialize_base_rust_dependencies.py` and +`test_maturin_offline_build_contract.py`, each before the tested behavior at +`cargo generate-lockfile` (3,538 passed, 4 failed, 4 skipped). The PR does not +change either test file. Both files construct registry-backed crates (`itoa`, +`ryu`, and PyO3) during the test, while the sandbox runs with `--network=none` +and its base-repository Rust materializer finds no Cargo lock in this PR's +validated base tree. + +With a fresh `CARGO_HOME` and `CARGO_NET_OFFLINE=true`, the two representative +tests failed at the same command. A direct `cargo generate-lockfile` on the +`itoa` fixture reported `no matching package named itoa found` in the offline +crates.io index. This establishes missing registry fixture input, rather than +a product-code assertion failure. The original hosted test helper captures +Cargo stderr, so the hosted log alone does not identify the missing crate. + +## Repair and trust boundary + +A trusted, lockfile-pinned fixture manifest covers the three registry crates +used by these tests. The networked coverage image build fetches that exact +closure with `cargo fetch --locked`. The PR tree never enters that build +context. The later untrusted test container still has `--network=none` and +receives only the trusted image's cached registry artifacts, copied into its +isolated `CARGO_HOME`. Existing base-repository Rust vendor configuration and +the sandbox's credentials and network restrictions remain in force. + +The image build fails if the trusted fixture files are absent, symbolic links, +or cannot be fetched against their checksummed lock. It does not turn a failed +test into a pass. + +## Verification boundary + +With the fixture cache and offline Cargo, three of the four previously failing +tests passed locally. The PyO3 extension build reached its real offline +compile step, then exceeded that test's 600-second limit on this concurrently +loaded macOS host. That is incomplete local proof for the compile path; a +terminal hosted rerun is required before claiming the coverage gate repaired. +The targeted workflow contract suite passed 82 tests with `GITHUB_ACTIONS=true`. diff --git a/tests/fixtures/coverage-cargo/Cargo.lock b/tests/fixtures/coverage-cargo/Cargo.lock new file mode 100644 index 0000000000..9a54521941 --- /dev/null +++ b/tests/fixtures/coverage-cargo/Cargo.lock @@ -0,0 +1,194 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "coverage-cargo-fixtures" +version = "0.0.0" +dependencies = [ + "itoa", + "pyo3", + "ryu", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f402062616ab18202ae8319da13fa4279883a2b8a9d9f83f20dbade813ce1884" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b14b5775b5ff446dd1056212d778012cbe8a0fbffd368029fd9e25b514479c38" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab5bcf04a2cdcbb50c7d6105de943f543f9ed92af55818fd17b660390fc8636" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fd24d897903a9e6d80b968368a34e1525aeb719d568dba8b3d4bfa5dc67d453" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c011a03ba1e50152b4b394b479826cad97e7a21eb52df179cd91ac411cbfbe" +dependencies = [ + "heck", + "proc-macro2", + "pyo3-build-config", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "unicode-ident" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" + +[[package]] +name = "unindent" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" diff --git a/tests/fixtures/coverage-cargo/Cargo.toml b/tests/fixtures/coverage-cargo/Cargo.toml new file mode 100644 index 0000000000..dbe13ab8ab --- /dev/null +++ b/tests/fixtures/coverage-cargo/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "coverage-cargo-fixtures" +version = "0.0.0" +edition = "2021" + +[dependencies] +itoa = "=1.0.15" +ryu = "=1.0.20" +pyo3 = { version = "=0.22.6", features = ["extension-module", "abi3-py310"] } diff --git a/tests/fixtures/coverage-cargo/src/lib.rs b/tests/fixtures/coverage-cargo/src/lib.rs new file mode 100644 index 0000000000..ace84d3771 --- /dev/null +++ b/tests/fixtures/coverage-cargo/src/lib.rs @@ -0,0 +1 @@ +pub fn fixture() {} diff --git a/tests/test_pr_review_autofix_nvidia_nim_contract.py b/tests/test_pr_review_autofix_nvidia_nim_contract.py index 4709af94f1..829739f5f9 100644 --- a/tests/test_pr_review_autofix_nvidia_nim_contract.py +++ b/tests/test_pr_review_autofix_nvidia_nim_contract.py @@ -17,7 +17,7 @@ DOCTORING_RECORD = Path("docs/doctoring/hourly-nvidia-nim-autofix.md") CHANGELOG = Path("CHANGELOG.md") REVIEW_DISPATCH_WORKFLOW = Path(".github/workflows/opencode-review-dispatch.yml") -REVIEW_DISPATCH_BLOB_SHA = "0ac2ec1fd69e60b228ac30b0b797403988d1a7ce" +REVIEW_DISPATCH_BLOB_SHA = "1cdabf6b1ecdeeafb94d3a65f5311c0f1aa29b62" def _workflow_text(path: Path) -> str: From c2a50d14ed11fd8f25f225b97c5f3c286b3e3711 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 28 Sep 2026 13:05:44 +0900 Subject: [PATCH 2/5] fix(ci): force offline Cargo resolution in coverage sandbox --- .github/workflows/opencode-review-dispatch.yml | 2 ++ .../doctoring/opencode-coverage-cargo-fixtures-20260928.md | 7 +++++-- tests/test_opencode_agent_contract.py | 1 + tests/test_pr_review_autofix_nvidia_nim_contract.py | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml index 1cdabf6b1e..f6063b38f0 100644 --- a/.github/workflows/opencode-review-dispatch.yml +++ b/.github/workflows/opencode-review-dispatch.yml @@ -1078,6 +1078,7 @@ jobs: HOME=/work/.opencode-sandbox-home \ XDG_CACHE_HOME=/work/.opencode-sandbox-cache \ CARGO_HOME=/work/.opencode-sandbox-home/.cargo \ + CARGO_NET_OFFLINE=true \ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \ "$@" >"$log_file" 2>&1 local rc=$? @@ -1200,6 +1201,7 @@ jobs: HOME=/work/.opencode-sandbox-home \ XDG_CACHE_HOME=/work/.opencode-sandbox-cache \ CARGO_HOME=/work/.opencode-sandbox-home/.cargo \ + CARGO_NET_OFFLINE=true \ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \ "$@" >"$log_file" 2>&1 local rc=$? diff --git a/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md index c542899e47..1102ea11ed 100644 --- a/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md +++ b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md @@ -26,8 +26,11 @@ used by these tests. The networked coverage image build fetches that exact closure with `cargo fetch --locked`. The PR tree never enters that build context. The later untrusted test container still has `--network=none` and receives only the trusted image's cached registry artifacts, copied into its -isolated `CARGO_HOME`. Existing base-repository Rust vendor configuration and -the sandbox's credentials and network restrictions remain in force. +isolated `CARGO_HOME`. Both untrusted command wrappers set +`CARGO_NET_OFFLINE=true`, so a lockfile generated by a test cannot attempt an +index refresh against the disconnected network. Existing base-repository Rust +vendor configuration and the sandbox's credentials and network restrictions +remain in force. The image build fails if the trusted fixture files are absent, symbolic links, or cannot be fetched against their checksummed lock. It does not turn a failed diff --git a/tests/test_opencode_agent_contract.py b/tests/test_opencode_agent_contract.py index df17a35688..573026baf6 100644 --- a/tests/test_opencode_agent_contract.py +++ b/tests/test_opencode_agent_contract.py @@ -841,6 +841,7 @@ def test_opencode_target_coverage_materializes_only_after_authorized_dispatch(): in measure_step ) assert "CARGO_HOME=/work/.opencode-sandbox-home/.cargo" in measure_step + assert measure_step.count("CARGO_NET_OFFLINE=true \\") == 2 assert "docker run --rm --init --network=none" in measure_step sandbox_runtime = measure_step.split( " export OPENCODE_SANDBOX_UID=65532", 1 diff --git a/tests/test_pr_review_autofix_nvidia_nim_contract.py b/tests/test_pr_review_autofix_nvidia_nim_contract.py index 829739f5f9..4fc3febfe9 100644 --- a/tests/test_pr_review_autofix_nvidia_nim_contract.py +++ b/tests/test_pr_review_autofix_nvidia_nim_contract.py @@ -17,7 +17,7 @@ DOCTORING_RECORD = Path("docs/doctoring/hourly-nvidia-nim-autofix.md") CHANGELOG = Path("CHANGELOG.md") REVIEW_DISPATCH_WORKFLOW = Path(".github/workflows/opencode-review-dispatch.yml") -REVIEW_DISPATCH_BLOB_SHA = "1cdabf6b1ecdeeafb94d3a65f5311c0f1aa29b62" +REVIEW_DISPATCH_BLOB_SHA = "f6063b38f080c07e9eef16c4057022d97c2d1d71" def _workflow_text(path: Path) -> str: From 59a55be7b61c6405a3a6612641b0d129ba465a7a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 28 Sep 2026 13:15:06 +0900 Subject: [PATCH 3/5] fix(ci): discard untrusted Cargo home before coverage --- .github/workflows/opencode-review-dispatch.yml | 1 + docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md | 2 +- tests/test_opencode_agent_contract.py | 3 +++ tests/test_pr_review_autofix_nvidia_nim_contract.py | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml index f6063b38f0..2a14c1e6a8 100644 --- a/.github/workflows/opencode-review-dispatch.yml +++ b/.github/workflows/opencode-review-dispatch.yml @@ -992,6 +992,7 @@ jobs: chown -R root:root /work/.git chmod -R go-w /work/.git fi + rm -rf -- /work/.opencode-sandbox-home mkdir -p "$RUNNER_TEMP" /work/.opencode-sandbox-home /work/.opencode-sandbox-cache chown "$OPENCODE_SANDBOX_UID:$OPENCODE_SANDBOX_GID" /work/.opencode-sandbox-home /work/.opencode-sandbox-cache # `run_and_capture`/`run_and_capture_advisory` below pin CARGO_HOME to diff --git a/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md index 1102ea11ed..d0e63f903d 100644 --- a/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md +++ b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md @@ -26,7 +26,7 @@ used by these tests. The networked coverage image build fetches that exact closure with `cargo fetch --locked`. The PR tree never enters that build context. The later untrusted test container still has `--network=none` and receives only the trusted image's cached registry artifacts, copied into its -isolated `CARGO_HOME`. Both untrusted command wrappers set +isolated `CARGO_HOME` after removing any PR-supplied sandbox home. Both untrusted command wrappers set `CARGO_NET_OFFLINE=true`, so a lockfile generated by a test cannot attempt an index refresh against the disconnected network. Existing base-repository Rust vendor configuration and the sandbox's credentials and network restrictions diff --git a/tests/test_opencode_agent_contract.py b/tests/test_opencode_agent_contract.py index 573026baf6..31fa282a98 100644 --- a/tests/test_opencode_agent_contract.py +++ b/tests/test_opencode_agent_contract.py @@ -842,6 +842,9 @@ def test_opencode_target_coverage_materializes_only_after_authorized_dispatch(): ) assert "CARGO_HOME=/work/.opencode-sandbox-home/.cargo" in measure_step assert measure_step.count("CARGO_NET_OFFLINE=true \\") == 2 + assert measure_step.index('rm -rf -- /work/.opencode-sandbox-home') < measure_step.index( + 'cp -a /opt/coverage-cargo-home/. /work/.opencode-sandbox-home/.cargo/' + ) assert "docker run --rm --init --network=none" in measure_step sandbox_runtime = measure_step.split( " export OPENCODE_SANDBOX_UID=65532", 1 diff --git a/tests/test_pr_review_autofix_nvidia_nim_contract.py b/tests/test_pr_review_autofix_nvidia_nim_contract.py index 4fc3febfe9..ee9d1ac8cf 100644 --- a/tests/test_pr_review_autofix_nvidia_nim_contract.py +++ b/tests/test_pr_review_autofix_nvidia_nim_contract.py @@ -17,7 +17,7 @@ DOCTORING_RECORD = Path("docs/doctoring/hourly-nvidia-nim-autofix.md") CHANGELOG = Path("CHANGELOG.md") REVIEW_DISPATCH_WORKFLOW = Path(".github/workflows/opencode-review-dispatch.yml") -REVIEW_DISPATCH_BLOB_SHA = "f6063b38f080c07e9eef16c4057022d97c2d1d71" +REVIEW_DISPATCH_BLOB_SHA = "2a14c1e6a8f9a009ffa0d7cdcae3b57a63da2396" def _workflow_text(path: Path) -> str: From 805ad4b1480acfd6377f63a953168ca903db71b1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 28 Sep 2026 13:40:57 +0900 Subject: [PATCH 4/5] test(ci): cover cached Cargo fixture dependencies --- .../opencode-coverage-cargo-fixtures-20260928.md | 3 +++ tests/fixtures/coverage-cargo/src/lib.rs | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md index d0e63f903d..b5c78b1d48 100644 --- a/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md +++ b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md @@ -44,3 +44,6 @@ compile step, then exceeded that test's 600-second limit on this concurrently loaded macOS host. That is incomplete local proof for the compile path; a terminal hosted rerun is required before claiming the coverage gate repaired. The targeted workflow contract suite passed 82 tests with `GITHUB_ACTIONS=true`. +The fixture crate's own `cargo llvm-cov --all-features --fail-under-lines 100` +run passed locally with one test and 100% line coverage, exercising its cached +`itoa` and `ryu` dependencies. diff --git a/tests/fixtures/coverage-cargo/src/lib.rs b/tests/fixtures/coverage-cargo/src/lib.rs index ace84d3771..475903b7b4 100644 --- a/tests/fixtures/coverage-cargo/src/lib.rs +++ b/tests/fixtures/coverage-cargo/src/lib.rs @@ -1 +1,13 @@ -pub fn fixture() {} +pub fn fixture() -> String { + let mut integer = itoa::Buffer::new(); + let mut float = ryu::Buffer::new(); + format!("{}:{}", integer.format(42), float.format(1.5)) +} + +#[cfg(test)] +mod tests { + #[test] + fn cached_formatters_link() { + assert_eq!(super::fixture(), "42:1.5"); + } +} From 88ac2c4ac10febfce169b0b0099feda65845eff5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 28 Sep 2026 14:33:40 +0900 Subject: [PATCH 5/5] fix(ci): scope Cargo offline policy to trusted sandbox home --- .../workflows/opencode-review-dispatch.yml | 6 ++--- ...encode-coverage-cargo-fixtures-20260928.md | 24 ++++++++++++------- tests/test_opencode_agent_contract.py | 3 ++- ...t_pr_review_autofix_nvidia_nim_contract.py | 2 +- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/.github/workflows/opencode-review-dispatch.yml b/.github/workflows/opencode-review-dispatch.yml index 2a14c1e6a8..58f11efc90 100644 --- a/.github/workflows/opencode-review-dispatch.yml +++ b/.github/workflows/opencode-review-dispatch.yml @@ -1003,9 +1003,11 @@ jobs: mkdir -p /work/.opencode-sandbox-home/.cargo cp -a /opt/coverage-cargo-home/. /work/.opencode-sandbox-home/.cargo/ if [ -s /opt/base-rust-dependencies/cargo-config.toml ]; then - install -m 0444 /opt/base-rust-dependencies/cargo-config.toml \ + install -m 0644 /opt/base-rust-dependencies/cargo-config.toml \ /work/.opencode-sandbox-home/.cargo/config.toml fi + printf '\n[net]\noffline = true\n' >>/work/.opencode-sandbox-home/.cargo/config.toml + chmod 0444 /work/.opencode-sandbox-home/.cargo/config.toml chown -R "$OPENCODE_SANDBOX_UID:$OPENCODE_SANDBOX_GID" /work/.opencode-sandbox-home/.cargo chmod 0700 "$RUNNER_TEMP" : >"$GITHUB_OUTPUT" @@ -1079,7 +1081,6 @@ jobs: HOME=/work/.opencode-sandbox-home \ XDG_CACHE_HOME=/work/.opencode-sandbox-cache \ CARGO_HOME=/work/.opencode-sandbox-home/.cargo \ - CARGO_NET_OFFLINE=true \ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \ "$@" >"$log_file" 2>&1 local rc=$? @@ -1202,7 +1203,6 @@ jobs: HOME=/work/.opencode-sandbox-home \ XDG_CACHE_HOME=/work/.opencode-sandbox-cache \ CARGO_HOME=/work/.opencode-sandbox-home/.cargo \ - CARGO_NET_OFFLINE=true \ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \ "$@" >"$log_file" 2>&1 local rc=$? diff --git a/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md index b5c78b1d48..1b5d0b65fd 100644 --- a/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md +++ b/docs/doctoring/opencode-coverage-cargo-fixtures-20260928.md @@ -26,9 +26,11 @@ used by these tests. The networked coverage image build fetches that exact closure with `cargo fetch --locked`. The PR tree never enters that build context. The later untrusted test container still has `--network=none` and receives only the trusted image's cached registry artifacts, copied into its -isolated `CARGO_HOME` after removing any PR-supplied sandbox home. Both untrusted command wrappers set -`CARGO_NET_OFFLINE=true`, so a lockfile generated by a test cannot attempt an -index refresh against the disconnected network. Existing base-repository Rust +isolated `CARGO_HOME` after removing any PR-supplied sandbox home. Its trusted +Cargo config enables offline registry resolution, so a lockfile generated by a +test cannot attempt an index refresh against the disconnected network. Tests +that intentionally create a separate Cargo home can still resolve local Git +fixtures before their own offline build step. Existing base-repository Rust vendor configuration and the sandbox's credentials and network restrictions remain in force. @@ -38,12 +40,16 @@ test into a pass. ## Verification boundary -With the fixture cache and offline Cargo, three of the four previously failing -tests passed locally. The PyO3 extension build reached its real offline -compile step, then exceeded that test's 600-second limit on this concurrently -loaded macOS host. That is incomplete local proof for the compile path; a -terminal hosted rerun is required before claiming the coverage gate repaired. -The targeted workflow contract suite passed 82 tests with `GITHUB_ACTIONS=true`. +An initial PyO3 extension build exceeded its 600-second limit on a loaded +macOS host. A later run with the project-local pinned maturin completed that +test in 32 seconds. With a fresh `CARGO_HOME` populated only by the locked +fixture and its trusted offline config, the complete two-file Rust dependency +and PyO3 suite passed all 29 tests with `GITHUB_ACTIONS=true`. The first +attempt at global `CARGO_NET_OFFLINE=true` failed one local Git dependency +fixture; scoping offline resolution to the default trusted Cargo home fixed +that failure. A terminal hosted rerun is still required before claiming the +coverage gate repaired. The targeted workflow contract suite passed 77 tests +with `GITHUB_ACTIONS=true` after this change. The fixture crate's own `cargo llvm-cov --all-features --fail-under-lines 100` run passed locally with one test and 100% line coverage, exercising its cached `itoa` and `ryu` dependencies. diff --git a/tests/test_opencode_agent_contract.py b/tests/test_opencode_agent_contract.py index 31fa282a98..57ff68b271 100644 --- a/tests/test_opencode_agent_contract.py +++ b/tests/test_opencode_agent_contract.py @@ -841,7 +841,8 @@ def test_opencode_target_coverage_materializes_only_after_authorized_dispatch(): in measure_step ) assert "CARGO_HOME=/work/.opencode-sandbox-home/.cargo" in measure_step - assert measure_step.count("CARGO_NET_OFFLINE=true \\") == 2 + assert "printf '\\n[net]\\noffline = true\\n' >>/work/.opencode-sandbox-home/.cargo/config.toml" in measure_step + assert "CARGO_NET_OFFLINE=true \\" not in measure_step assert measure_step.index('rm -rf -- /work/.opencode-sandbox-home') < measure_step.index( 'cp -a /opt/coverage-cargo-home/. /work/.opencode-sandbox-home/.cargo/' ) diff --git a/tests/test_pr_review_autofix_nvidia_nim_contract.py b/tests/test_pr_review_autofix_nvidia_nim_contract.py index ee9d1ac8cf..1161602a53 100644 --- a/tests/test_pr_review_autofix_nvidia_nim_contract.py +++ b/tests/test_pr_review_autofix_nvidia_nim_contract.py @@ -17,7 +17,7 @@ DOCTORING_RECORD = Path("docs/doctoring/hourly-nvidia-nim-autofix.md") CHANGELOG = Path("CHANGELOG.md") REVIEW_DISPATCH_WORKFLOW = Path(".github/workflows/opencode-review-dispatch.yml") -REVIEW_DISPATCH_BLOB_SHA = "2a14c1e6a8f9a009ffa0d7cdcae3b57a63da2396" +REVIEW_DISPATCH_BLOB_SHA = "58f11efc9072e35db6ec6365630db9f97d16f652" def _workflow_text(path: Path) -> str: