From 65c9d9844c588298d2a35ad79a1796a6d6f9ba01 Mon Sep 17 00:00:00 2001 From: Nina Date: Tue, 25 Aug 2026 15:58:16 +0100 Subject: [PATCH] min publish age --- .cargo/config.toml | 12 ++++++++ .github/workflows/lint.yaml | 13 +++++++-- .github/workflows/perf.yaml | 2 +- .github/workflows/test.yaml | 4 +-- justfile | 56 ++++++++++++++++++++++++++++--------- 5 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..a6876e4d --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,12 @@ +# Supply-chain cooldown for dependency resolution (unstable min-publish-age, +# tracking issue rust-lang/cargo#17009): crate versions published less than +# 14 days ago are excluded when the resolver runs on a nightly cargo. +# Stable cargo ignores these tables silently, so builds from the committed +# Cargo.lock are unaffected; run `just update` to resolve under the policy. +# When the feature stabilizes, drop the [unstable] table and the nightly +# resolver pin in the justfile: the policy then binds all resolution. +[unstable] +min-publish-age = true + +[registry] +global-min-publish-age = "14 days" diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 7c69cd88..96cd7e2d 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -25,7 +25,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: nightly-2025-06-01 + toolchain: nightly-2026-06-21 components: clippy, rustfmt - name: Install buf @@ -39,10 +39,19 @@ jobs: just-version: 1.5.0 - name: Check compilation - run: cargo check + run: cargo check --locked - name: Check formatting run: just fmt-check - name: Check clippy run: just clippy + + # Stable cargo ignores the publish-age policy, so the lockfile can pin + # too-young crates (or deliberately via `just update-allow`); surface them. + - name: Check lockfile against the publish-age cooldown + run: | + out=$(just cooldown-check 2>&1) || true + if [ -n "$out" ]; then + echo "::warning title=Publish-age cooldown::$(echo "$out" | head -20 | sed ':a;N;$!ba;s/\n/%0A/g')" + fi diff --git a/.github/workflows/perf.yaml b/.github/workflows/perf.yaml index ba853b31..9c13d41d 100644 --- a/.github/workflows/perf.yaml +++ b/.github/workflows/perf.yaml @@ -29,7 +29,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: nightly-2025-06-01 + toolchain: nightly-2026-06-21 - name: Install buf uses: bufbuild/buf-action@v1 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 6cae0b96..fc4141d3 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -25,7 +25,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: nightly-2025-06-01 + toolchain: nightly-2026-06-21 - name: Install buf uses: bufbuild/buf-action@v1 @@ -36,4 +36,4 @@ jobs: run: make -C crates/beacon_state/tile - name: Run tests - run: cargo test --features "silver_beacon_state/ef_tests,silver_e2e/lh-client" --no-fail-fast + run: cargo test --locked --features "silver_beacon_state/ef_tests,silver_e2e/lh-client" --no-fail-fast diff --git a/justfile b/justfile index 38cdec24..59cae390 100644 --- a/justfile +++ b/justfile @@ -1,21 +1,51 @@ -toolchain := "nightly-2025-06-01" +# rustfmt.toml relies on nightly-only options, and min-publish-age is a nightly +# cargo feature. Everything else runs on the stable pin in rust-toolchain.toml, +# so lints and tests always match the shipped compiler. +nightly := "nightly-2026-06-21" + +# Update dependencies under the publish-age cooldown (.cargo/config.toml): +# versions published less than 14 days ago are excluded from resolution. +# Resolution done on stable (cargo add, plain cargo update) is NOT covered; +# this recipe is the intended path for routine updates. Git dependencies are +# outside the cooldown entirely — no publish age exists for them. Ours are +# rev-pinned, so review the rev when you bump it by hand. +update *args: + rustup toolchain install {{nightly}} --profile minimal > /dev/null 2>&1 && \ + cargo +{{nightly}} update -Z min-publish-age {{args}} + +# Escape hatch for an urgent update to a version younger than the cooldown, +# e.g. `just update-allow h2 0.4.16`. The bypass applies to the WHOLE +# resolution of this invocation (transitive picks included), so review the +# full Cargo.lock diff, not just the target package. +update-allow package version: + @echo "NOTE: the cooldown bypass is invocation-global; review the full Cargo.lock diff." + rustup toolchain install {{nightly}} --profile minimal > /dev/null 2>&1 && \ + CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow \ + cargo +{{nightly}} update -Z min-publish-age -p {{package}} --precise {{version}} + +# Warn when the committed Cargo.lock pins crates younger than the cooldown. +cooldown-check: + @rustup toolchain install {{nightly}} --profile minimal > /dev/null 2>&1 || \ + { echo "SKIPPED: could not install {{nightly}}"; exit 0; }; \ + out=$(cargo +{{nightly}} update --dry-run -Z min-publish-age 2>&1 | grep -E "Downgrading|is too new" || true); \ + if [ -n "$out" ]; then echo "WARNING: lockfile pins crates younger than the publish-age cooldown:"; echo "$out"; fi fmt: - rustup toolchain install {{toolchain}} --component rustfmt > /dev/null 2>&1 && \ - cargo +{{toolchain}} fmt + rustup toolchain install {{nightly}} --component rustfmt > /dev/null 2>&1 && \ + cargo +{{nightly}} fmt fmt-check: - rustup toolchain install {{toolchain}} --component rustfmt > /dev/null 2>&1 && \ - cargo +{{toolchain}} fmt --check + rustup toolchain install {{nightly}} --component rustfmt > /dev/null 2>&1 && \ + cargo +{{nightly}} fmt --check clippy: - cargo clippy --all-features --no-deps -- -D warnings -A clippy::collapsible_if + cargo clippy --locked --all-features --no-deps -- -D warnings -A clippy::collapsible_if clippy-fix: - cargo clippy --fix --all-features --no-deps --allow-dirty -- -D warnings -A clippy::collapsible_if + cargo clippy --fix --locked --all-features --no-deps --allow-dirty -- -D warnings -A clippy::collapsible_if machete: - cargo install cargo-machete && \ + cargo install --locked cargo-machete && \ cargo machete ef-tests-download: @@ -31,18 +61,18 @@ checkpoint-fixtures: # on so invariant checks run. Run `just ef-tests-download` + `just # checkpoint-fixtures` first if you don't have the fixtures locally. test: - cargo test --workspace --features "silver_beacon_state/ef_tests,silver_e2e/lh-client" --profile release-with-debug --no-fail-fast 2>&1 + cargo test --locked --workspace --features "silver_beacon_state/ef_tests,silver_e2e/lh-client" --profile release-with-debug --no-fail-fast 2>&1 # As above but using `nextest` nextest: cargo install --locked cargo-nextest && \ - cargo nextest r --features "silver_beacon_state/ef_tests,silver_e2e/lh-client" --cargo-profile release-with-debug --no-fail-fast --status-level skip + cargo nextest r --locked --features "silver_beacon_state/ef_tests,silver_e2e/lh-client" --cargo-profile release-with-debug --no-fail-fast --status-level skip # Run the perf-regression harness on the committed mainnet fixtures. # Release-only (no debug-assertions — they skew the counters); reads crates/e2e/data/perf (git-lfs). CI runs this too. # Pass a path to also dump the raw #[timed] FXT trace (Perfetto/magic-trace), e.g. `just perf-local perf-local.fxt`. perf-local file="" events="instructions,cycles,l1d-misses,l2-misses,l3-misses": - PERF_FXT="{{file}}" PERF_EVENTS="{{events}}" cargo test --release -p silver_e2e --features perf-counters,alloc-profile --test sync_pm_bs_perf -- --ignored --nocapture + PERF_FXT="{{file}}" PERF_EVENTS="{{events}}" cargo test --locked --release -p silver_e2e --features perf-counters,alloc-profile --test sync_pm_bs_perf -- --ignored --nocapture # Run surfer (the metrics TUI). It folds the watched silver's `#[timed]` perf # counters into the flamegraph whenever that silver published them (the producer @@ -50,10 +80,10 @@ perf-local file="" events="instructions,cycles,l1d-misses,l2-misses,l3-misses": # only. Counter labels come from the silver's published schema, so no event list # is needed here. Extra args pass through as `[BASE_DIR] [APP_NAME]`. surfer *args='': - cargo run --release -p silver_surfer -- {{args}} + cargo run --locked --release -p silver_surfer -- {{args}} # Refresh crates/e2e/data/perf from mainnet (~13 min for the default 128 # blocks at lodestar's ~1 req / 6 s cap). Commit the result via git-lfs. # Pass `--continue` (and/or `--blocks N`) to resume after a network blip. perf-update-fixtures *args='--blocks 128': - cargo run --release -p silver_e2e --bin perf_update_fixtures -- {{args}} + cargo run --locked --release -p silver_e2e --bin perf_update_fixtures -- {{args}}