From 8b9a14ea26b34cb06aad6d663d84a4d0eadc7658 Mon Sep 17 00:00:00 2001 From: John Vicondoa Date: Sat, 22 Aug 2026 12:50:33 -0700 Subject: [PATCH 1/5] ci: preinstall Rust before parallel build gates Prepare the pinned toolchain and required components before make check fans out its local Layer-1 jobs. This avoids concurrent rustup downloads corrupting the shared runner installation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/build.yaml | 17 +++++++++++++++++ CHANGELOG.md | 2 ++ packages/xtask/tests/policy_ci.rs | 12 ++++++++++++ 3 files changed, 31 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 86dfbb066c..01cdec15c4 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -202,6 +202,23 @@ jobs: set -euo pipefail test "$(git -C trusted rev-parse HEAD)" = "$D2B_TRUSTED_SHA" test "$(git -C workspace rev-parse HEAD)" = "$D2B_TESTED_SHA" + - name: Prepare pinned Rust toolchain for parallel Layer-1 gates + working-directory: workspace + run: | + set -euo pipefail + if ! command -v rustup >/dev/null 2>&1; then + echo "rustup is unavailable; Rust gates will use their Nix fallback." + exit 0 + fi + pinned_channel="$( + sed -n 's/^[[:space:]]*channel[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p' \ + packages/rust-toolchain.toml | head -1 + )" + [ -n "$pinned_channel" ] || { + echo "::error::could not read the pinned Rust channel" >&2 + exit 76 + } + rustup toolchain install "$pinned_channel" --profile minimal --component rustfmt --component clippy - name: Run credential-free local Layer-1 gate working-directory: workspace run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 19e54b4986..167ca699bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ deprecations ship one minor release before removal. - Fixed trusted `main` push validation and reusable workflow resolution so the BuildBuddy seed workflow executes its metadata checks instead of failing on shell test parsing. +- Prepared the pinned Rust toolchain before parallel local Layer-1 gates so + concurrent Rust and proof jobs do not race during rustup installation. ## [1.4.1] - 2026-07-12 diff --git a/packages/xtask/tests/policy_ci.rs b/packages/xtask/tests/policy_ci.rs index b50f4362a9..6520fb64f0 100644 --- a/packages/xtask/tests/policy_ci.rs +++ b/packages/xtask/tests/policy_ci.rs @@ -211,6 +211,18 @@ fn main_controlled_buildbuddy_workflows_preserve_trust_contract() { && build.contains("D2B_BAZEL_UNTRUSTED: \"1\""), "full PR coverage must retain a credential-free local Layer-1 gate" ); + let rust_bootstrap = build + .find("Prepare pinned Rust toolchain for parallel Layer-1 gates") + .expect("local Layer-1 gate must prepare the shared Rust toolchain"); + let local_gate = build + .find("Run credential-free local Layer-1 gate") + .expect("local Layer-1 gate step must be present"); + assert!( + rust_bootstrap < local_gate + && build.contains("rustup toolchain install \"$pinned_channel\" --profile minimal") + && build.contains("--component rustfmt --component clippy"), + "parallel local Layer-1 jobs must share a preinstalled pinned Rust toolchain" + ); assert!( build.contains("github.event_name == 'push'") && build.contains("github.event_name == 'push' }}"), From 680f703e4b0bfe8b8c38dba1cadaabafca255fa4 Mon Sep 17 00:00:00 2001 From: John Vicondoa Date: Sat, 22 Aug 2026 13:13:24 -0700 Subject: [PATCH 2/5] ci: bind Rust bootstrap policy to local gate Scope the workflow contract to the local job and require the workspace checkout and pinned toolchain install in the step preceding make check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- packages/xtask/tests/policy_ci.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/xtask/tests/policy_ci.rs b/packages/xtask/tests/policy_ci.rs index 6520fb64f0..0363c84862 100644 --- a/packages/xtask/tests/policy_ci.rs +++ b/packages/xtask/tests/policy_ci.rs @@ -211,16 +211,28 @@ fn main_controlled_buildbuddy_workflows_preserve_trust_contract() { && build.contains("D2B_BAZEL_UNTRUSTED: \"1\""), "full PR coverage must retain a credential-free local Layer-1 gate" ); - let rust_bootstrap = build - .find("Prepare pinned Rust toolchain for parallel Layer-1 gates") + let local_job_start = build + .find("\n local:\n") + .expect("build workflow must define a local job"); + let local_job_end = local_job_start + + build[local_job_start..] + .find("\n remote:\n") + .expect("build workflow must define a remote job"); + let local_job = &build[local_job_start..local_job_end]; + let rust_bootstrap = local_job + .find(" - name: Prepare pinned Rust toolchain for parallel Layer-1 gates") .expect("local Layer-1 gate must prepare the shared Rust toolchain"); - let local_gate = build - .find("Run credential-free local Layer-1 gate") + let local_gate = local_job + .find(" - name: Run credential-free local Layer-1 gate") .expect("local Layer-1 gate step must be present"); + let rust_bootstrap_step = &local_job[rust_bootstrap..local_gate]; assert!( rust_bootstrap < local_gate - && build.contains("rustup toolchain install \"$pinned_channel\" --profile minimal") - && build.contains("--component rustfmt --component clippy"), + && rust_bootstrap_step.contains("working-directory: workspace") + && rust_bootstrap_step.contains("packages/rust-toolchain.toml") + && rust_bootstrap_step + .contains("rustup toolchain install \"$pinned_channel\" --profile minimal") + && rust_bootstrap_step.contains("--component rustfmt --component clippy"), "parallel local Layer-1 jobs must share a preinstalled pinned Rust toolchain" ); assert!( From 81c2b625ee4867bdc6cbec8d60e4b13b8f627c57 Mon Sep 17 00:00:00 2001 From: John Vicondoa Date: Sat, 22 Aug 2026 13:36:09 -0700 Subject: [PATCH 3/5] ci: tolerate absent reusable workflow context Validate optional reusable workflow identifiers when GitHub provides them, while retaining the caller workflow SHA fallback for same-repository calls. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/build.yaml | 13 +++++++++++-- CHANGELOG.md | 3 +++ packages/xtask/tests/policy_ci.rs | 8 ++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 01cdec15c4..ca95c2fe2f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -89,11 +89,19 @@ jobs: git -C source check-ref-format --branch "$D2B_BRANCH" >/dev/null 2>&1 || fail "branch metadata is not an approved ref" + validate_optional_reusable_workflow() { + if [ -n "$D2B_JOB_WORKFLOW_REF" ] || [ -n "$D2B_JOB_WORKFLOW_SHA" ]; then + [ "$D2B_JOB_WORKFLOW_REF" = "vicondoa/d2b/.github/workflows/build.yaml@refs/heads/main" ] || + fail "reusable build controls must be sourced from protected main" + is_sha "$D2B_JOB_WORKFLOW_SHA" || + fail "reusable workflow SHA is not a full immutable commit SHA" + fi + } + if [ "$D2B_EVENT_NAME" = "pull_request_target" ]; then [ "$D2B_CALLER_WORKFLOW_REF" = "vicondoa/d2b/.github/workflows/pr.yml@refs/heads/main" ] || fail "PR workflow controls must be sourced from protected main" - [ "$D2B_JOB_WORKFLOW_REF" = "vicondoa/d2b/.github/workflows/build.yaml@refs/heads/main" ] || - fail "reusable build controls must be sourced from protected main" + validate_optional_reusable_workflow case "$D2B_BASE_REF" in main|v3) ;; *) fail "pull request target is not main or v3" ;; @@ -110,6 +118,7 @@ jobs: elif [ "$D2B_EVENT_NAME" = "push" ]; then [ "$D2B_CALLER_WORKFLOW_REF" = "vicondoa/d2b/.github/workflows/build.yaml@refs/heads/main" ] || fail "push workflow controls must be sourced from protected main" + validate_optional_reusable_workflow [ "$D2B_REF" = "refs/heads/main" ] || fail "trusted build pushes are restricted to main" [ -z "$D2B_BASE_REF" ] || fail "push events must not carry a base ref" diff --git a/CHANGELOG.md b/CHANGELOG.md index 167ca699bc..f150a29b06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,9 @@ deprecations ship one minor release before removal. - Fixed trusted `main` push validation and reusable workflow resolution so the BuildBuddy seed workflow executes its metadata checks instead of failing on shell test parsing. +- Accepted GitHub runs that omit `job_workflow_ref` and `job_workflow_sha` for + same-repository reusable workflows while still validating those immutable + identifiers whenever GitHub provides them. - Prepared the pinned Rust toolchain before parallel local Layer-1 gates so concurrent Rust and proof jobs do not race during rustup installation. diff --git a/packages/xtask/tests/policy_ci.rs b/packages/xtask/tests/policy_ci.rs index 0363c84862..11c48f3bce 100644 --- a/packages/xtask/tests/policy_ci.rs +++ b/packages/xtask/tests/policy_ci.rs @@ -170,6 +170,14 @@ fn main_controlled_buildbuddy_workflows_preserve_trust_contract() { && build.contains("merge_sha"), "build workflow must bind trusted and tested immutable OIDs" ); + assert!( + build.contains("trusted_sha=\"${D2B_JOB_WORKFLOW_SHA:-$D2B_CALLER_WORKFLOW_SHA}\"") + && build.contains( + "if [ -n \"$D2B_JOB_WORKFLOW_REF\" ] || [ -n \"$D2B_JOB_WORKFLOW_SHA\" ]; then" + ) + && build.contains("is_sha \"$D2B_JOB_WORKFLOW_SHA\""), + "optional reusable-workflow metadata must be validated when GitHub provides it" + ); assert!( build.matches("persist-credentials: false").count() >= 4, "trusted and source checkouts must not persist credentials" From 8696ddd430524ddfb18addbc66da85c1ea6fba28 Mon Sep 17 00:00:00 2001 From: John Vicondoa Date: Sat, 22 Aug 2026 14:06:54 -0700 Subject: [PATCH 4/5] ci: bind optional workflow metadata policy Require the protected workflow ref and both event-path call sites in the policy contract. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- packages/xtask/tests/policy_ci.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/xtask/tests/policy_ci.rs b/packages/xtask/tests/policy_ci.rs index 11c48f3bce..86f0c534da 100644 --- a/packages/xtask/tests/policy_ci.rs +++ b/packages/xtask/tests/policy_ci.rs @@ -175,9 +175,24 @@ fn main_controlled_buildbuddy_workflows_preserve_trust_contract() { && build.contains( "if [ -n \"$D2B_JOB_WORKFLOW_REF\" ] || [ -n \"$D2B_JOB_WORKFLOW_SHA\" ]; then" ) + && build.contains( + "[ \"$D2B_JOB_WORKFLOW_REF\" = \"vicondoa/d2b/.github/workflows/build.yaml@refs/heads/main\" ]" + ) && build.contains("is_sha \"$D2B_JOB_WORKFLOW_SHA\""), "optional reusable-workflow metadata must be validated when GitHub provides it" ); + let pr_validation_start = build + .find("if [ \"$D2B_EVENT_NAME\" = \"pull_request_target\" ]") + .expect("build workflow must validate pull_request_target metadata"); + let push_validation_start = build + .find("elif [ \"$D2B_EVENT_NAME\" = \"push\" ]") + .expect("build workflow must validate push metadata"); + assert!( + build[pr_validation_start..push_validation_start] + .contains("validate_optional_reusable_workflow") + && build[push_validation_start..].contains("validate_optional_reusable_workflow"), + "optional reusable-workflow metadata validation must bind to both event paths" + ); assert!( build.matches("persist-credentials: false").count() >= 4, "trusted and source checkouts must not persist credentials" From fd86f255c7bb4bc11b771396ab7b79df07cc8ec0 Mon Sep 17 00:00:00 2001 From: John Vicondoa Date: Sat, 22 Aug 2026 14:33:05 -0700 Subject: [PATCH 5/5] ci: bind workflow policy slices Keep optional metadata checks inside their helper and bind both event-path calls to the event switch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- packages/xtask/tests/policy_ci.rs | 40 +++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/packages/xtask/tests/policy_ci.rs b/packages/xtask/tests/policy_ci.rs index 86f0c534da..0c2200060a 100644 --- a/packages/xtask/tests/policy_ci.rs +++ b/packages/xtask/tests/policy_ci.rs @@ -171,26 +171,40 @@ fn main_controlled_buildbuddy_workflows_preserve_trust_contract() { "build workflow must bind trusted and tested immutable OIDs" ); assert!( - build.contains("trusted_sha=\"${D2B_JOB_WORKFLOW_SHA:-$D2B_CALLER_WORKFLOW_SHA}\"") - && build.contains( - "if [ -n \"$D2B_JOB_WORKFLOW_REF\" ] || [ -n \"$D2B_JOB_WORKFLOW_SHA\" ]; then" - ) - && build.contains( - "[ \"$D2B_JOB_WORKFLOW_REF\" = \"vicondoa/d2b/.github/workflows/build.yaml@refs/heads/main\" ]" - ) - && build.contains("is_sha \"$D2B_JOB_WORKFLOW_SHA\""), - "optional reusable-workflow metadata must be validated when GitHub provides it" + build.contains("trusted_sha=\"${D2B_JOB_WORKFLOW_SHA:-$D2B_CALLER_WORKFLOW_SHA}\""), + "trusted workflow SHA must fall back to the caller SHA when job metadata is absent" ); + let helper_start = build + .find(" validate_optional_reusable_workflow() {") + .expect("build workflow must define optional reusable-workflow validation"); let pr_validation_start = build - .find("if [ \"$D2B_EVENT_NAME\" = \"pull_request_target\" ]") + .find(" if [ \"$D2B_EVENT_NAME\" = \"pull_request_target\" ]") .expect("build workflow must validate pull_request_target metadata"); let push_validation_start = build - .find("elif [ \"$D2B_EVENT_NAME\" = \"push\" ]") + .find(" elif [ \"$D2B_EVENT_NAME\" = \"push\" ]") .expect("build workflow must validate push metadata"); + let helper_end = helper_start + + build[helper_start..pr_validation_start] + .find("\n }\n\n") + .expect("optional reusable-workflow validator must end before event validation"); + let helper = &build[helper_start..helper_end]; + assert!( + helper.contains( + "if [ -n \"$D2B_JOB_WORKFLOW_REF\" ] || [ -n \"$D2B_JOB_WORKFLOW_SHA\" ]; then" + ) && helper.contains( + "[ \"$D2B_JOB_WORKFLOW_REF\" = \"vicondoa/d2b/.github/workflows/build.yaml@refs/heads/main\" ]" + ) && helper.contains("is_sha \"$D2B_JOB_WORKFLOW_SHA\""), + "optional reusable-workflow metadata checks must stay inside their validator" + ); + let push_validation_end = push_validation_start + + build[push_validation_start..] + .find("\n else\n fail \"only pull_request_target and push events are accepted\"") + .expect("build workflow event validation must have a bounded fallback branch"); assert!( build[pr_validation_start..push_validation_start] - .contains("validate_optional_reusable_workflow") - && build[push_validation_start..].contains("validate_optional_reusable_workflow"), + .contains(" validate_optional_reusable_workflow\n") + && build[push_validation_start..push_validation_end] + .contains(" validate_optional_reusable_workflow\n"), "optional reusable-workflow metadata validation must bind to both event paths" ); assert!(