Skip to content

build: raise MSRV to 1.95 to restore the MSRV CI gate#166

Merged
pofallon merged 2 commits into
mainfrom
fix/msrv-lockfile-drift
May 31, 2026
Merged

build: raise MSRV to 1.95 to restore the MSRV CI gate#166
pofallon merged 2 commits into
mainfrom
fix/msrv-lockfile-drift

Conversation

@pofallon
Copy link
Copy Markdown
Contributor

@pofallon pofallon commented May 30, 2026

Summary

The MSRV (cargo check) CI job has been failing on main: direct and transitive dependencies now require a newer rustc than the declared 1.85 MSRV, and the MSRV-aware resolver (resolver 3) can no longer keep Cargo.lock compatible with 1.85 without impractical, wide-reaching downgrades.

Offending floors observed via cargo +1.85 check --workspace --all-targets --all-features --locked:

crate requires
sysinfo 0.39 (direct dep) rustc 1.95
testcontainers 0.27 (dev-dep) rustc 1.88
etcetera 0.11 (via testcontainers) rustc 1.87
time, tonic, serde_with, darling, home, icu_* 1.86–1.88

sysinfo is the hard blocker — every 0.39.x release requires ≥1.95, and it's a direct dependency used by host_requirements.rs / doctor.rs.

Decision

Raise the MSRV floor to 1.95 to match reality, rather than pin a large set of dependencies backward (which would risk API churn and fight the resolver on every future cargo update). Edition 2024 itself still only needs 1.85; this bump is purely dependency-driven.

Changes

  • Cargo.toml:
    • rust-version = "1.85""1.95" (with an explanatory comment).
    • Added [workspace.lints.clippy] collapsible_if = "allow" — see below.
  • .github/workflows/ci.yml: MSRV job toolchain dtolnay/rust-toolchain@1.85@1.95.
  • Cargo.lock: regenerated under the new MSRV. This is required, not cosmeticmain's locked sysinfo 0.39.2 still fails under a 1.95 toolchain, while the refreshed 0.39.3 passes. The regen touches 14 packages (minor/patch bumps to the latest 1.95-compatible versions).
  • CHANGELOG.md: documented under ### Changed.

Coupled clippy fix: collapsible_if

The Lint (fmt + clippy) CI job runs cargo clippy on the stable toolchain. Now that the project targets a 1.95-era toolchain, clippy 1.95 newly raises collapsible_if on if cond { if let .. {} } patterns (it suggests collapsing them into let-chains, if cond && let .. {}) — 62 occurrences across our own source (cache/disk.rs, docker.rs, ports.rs, …). This is purely toolchain-driven and reproduces identically on main under clippy 1.95; it is independent of the dependency changes here.

Rather than churn ~60 call sites into let-chains (a large, style-only diff that doesn't belong in an MSRV PR), this allows the lint workspace-wide. The nested form is kept intentionally for readability. This keeps cargo clippy --all-targets --all-features -- -D warnings green on 1.95.

Gates (run locally against this tree)

  • cargo +1.95 check --workspace --all-targets --all-features --lockedpass (was failing on main)
  • cargo fmt --all -- --checkpass
  • cargo clippy --all-targets --all-features --locked -- -D warningspass (was failing under clippy 1.95 before the allow)
  • make test-nextest-fast2161 passed, 0 failed, 30 skipped
  • cargo deny check — advisories/bans/licenses/sources ok

This is the third of three PRs and is independent of #164 and #165 (touches disjoint files).

🤖 Generated with Claude Code

@github-actions github-actions Bot added ci CI/CD changes build Build system changes deps Dependency updates labels May 30, 2026
@pofallon pofallon force-pushed the fix/msrv-lockfile-drift branch from 18b0094 to e18a378 Compare May 30, 2026 13:18
The `MSRV (cargo check)` CI job was failing on `main`: direct and transitive
dependencies now require a newer rustc than the declared 1.85 MSRV (e.g.
sysinfo 0.39 -> 1.95, testcontainers 0.27 -> 1.88, etcetera 0.11 -> 1.87), and
the MSRV-aware resolver can no longer keep Cargo.lock compatible with 1.85
without impractical downgrades.

Raise the floor to match reality rather than pin a large set of deps backward:
- Cargo.toml: rust-version 1.85 -> 1.95 (edition 2024 still only needs 1.85; the
  bump is dependency-driven).
- .github/workflows/ci.yml: MSRV job toolchain dtolnay/rust-toolchain@1.85 -> @1.95.
- Cargo.lock: regenerated under the new MSRV. This is required, not cosmetic:
  main's locked sysinfo 0.39.2 still fails under a 1.95 toolchain, while the
  refreshed 0.39.3 passes.

Because the lint CI job runs clippy on `stable` (now 1.95), also allow the
`clippy::collapsible_if` lint workspace-wide: clippy 1.95 newly raises it on
`if cond { if let .. {} }` patterns (suggesting let-chains) in ~60 places. The
nested form is intentional for readability; collapsing everywhere is a large,
churny rewrite out of scope here. This keeps `cargo clippy -D warnings` green on
1.95 (pre-existing failure on main once runners ship 1.95).

Verified locally: cargo +1.95 check --workspace --all-targets --all-features
--locked passes; cargo fmt --all -- --check, cargo clippy --all-targets
--all-features --locked -- -D warnings, make test-nextest-fast (2161 passed,
0 failed), and cargo deny check all pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@pofallon pofallon force-pushed the fix/msrv-lockfile-drift branch from e18a378 to c1003e2 Compare May 30, 2026 18:09
pofallon added a commit that referenced this pull request May 30, 2026
…ode (#164)

The feature/template authoring commands were already deleted, but the OCI
publish/upload implementation survived in crates/core/src/oci/ with no caller
reachable from any binary (every caller was a test). This violates the
consumer-only constitution (II Consumer-Only Scope), so remove it entirely.

Removed:
- fetcher.rs: publish_feature, publish_template, publish_feature_multi_tag,
  publish_collection_metadata, upload_blob, upload_blob_generic,
  upload_blob_template, upload_manifest, upload_manifest_template
- types.rs: PublishResult (+ its re-export in oci/mod.rs)
- progress.rs: ProgressEvent::OciPublishBegin / OciPublishEnd and match arms
- observability.rs: spans::REGISTRY_PUBLISH and registry_publish_span()
- client.rs: publish-only HttpClient::put_with_headers / post_with_headers trait
  methods and all impls/mocks (ReqwestClient, MockHttpClient, test mocks)
- Publish-only tests in integration_fake_registry.rs and
  integration_oci_enhancements.rs (consumer tests retained); the publish mock
  methods in integration_oci_auth.rs and oci_timeout.rs
- Stale, uncompiled crates/core/src/oci.rs.old backup (pre-split copy of the
  same authoring code)

The consumer-side fetch/pull/install path (fetch_feature, download_layer,
get_manifest*, list_tags) is untouched.

Verified locally: cargo fmt --all -- --check, cargo clippy --all-targets
--all-features -- -D warnings, and cargo deny check all pass. The retained OCI
consumer tests (deacon-core integration_fake_registry / integration_oci_auth /
integration_oci_enhancements / oci_timeout, and the oci unit tests) pass. NOTE:
a full `make test-nextest` cannot complete cleanly on this branch OR on main
because of a pre-existing, unrelated failure in
deacon::integration_cli::test_debug_logging_with_subcommand (a stale
workspace-path error-message assertion); that is being fixed separately in
PR #166 and is not touched here. The MSRV-1.85 gate likewise fails identically
on main due to pre-existing lockfile drift (deps now require rustc >= 1.86).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@pofallon pofallon merged commit 6aa13d7 into main May 31, 2026
11 checks passed
@pofallon pofallon deleted the fix/msrv-lockfile-drift branch May 31, 2026 00:54
pofallon added a commit that referenced this pull request May 31, 2026
…eature gate) (#165)

* refactor: ship full consumer surface as one binary (remove MVP/full feature gate)

The deacon crate declared `default = ["full"]` / `full = []`, a marker feature
(no dependencies) that flipped #[cfg(feature = "full")] code in/out to hide
build/doctor/templates/outdated/run-user-commands/etc. behind an "MVP" subset.
The decision is to ship the entire in-scope consumer surface as a single binary,
so the gate is pure overhead. Remove it completely.

- crates/deacon/Cargo.toml: delete the [features] table (default/full).
- Strip all ~55 #[cfg(feature = "full")] and
  #[cfg_attr(not(feature = "full"), allow(dead_code))] attributes across the
  deacon crate (src + ~28 test files).
- .github/workflows/release.yml: drop RELEASE_FEATURE_FLAGS and every
  --no-default-features usage so releases build the full default binary.
- .github/workflows/ci.yml: drop --no-default-features from the fast test job;
  the MSRV job already builds the full surface. Single test path, no duplication.
- Makefile: remove the MVP_FLAGS/FULL_FLAGS variables and the *-full target
  duplicates; consolidate to a single build/test/clippy path and update help.

`--no-default-features` is now a no-op. Verified locally: cargo fmt --all --
--check and cargo clippy --all-targets --all-features -- -D warnings pass;
`cargo run -- doctor --help` / `build --help` work and all subcommands appear in
`--help`; `make -n build|clippy` show no --no-default-features. NOTE: a full
`make test-nextest` cannot complete cleanly on this branch OR on main because of
a pre-existing, unrelated failure in
deacon::integration_cli::test_debug_logging_with_subcommand (a stale
workspace-path error-message assertion), fixed separately in PR #166.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(test): update stale workspace-path assertions in integration_cli

Two tests (`test_workspace_folder_option`, `test_debug_logging_with_subcommand`)
pass `--workspace-folder /tmp/nonexistent`, which now errors at workspace-path
resolution ("Failed to resolve workspace path …") before config discovery — so
the old "No devcontainer.json found in workspace" assertion no longer matches.
This was masked on main because the file is `#![cfg(feature = "full")]` and CI
ran `--no-default-features`, compiling it out; removing the feature gate in this
PR surfaces both. Assert the actual current error message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* style(test): rustfmt the shortened workspace-path assertion

The corrected assertion string is short enough to fit on one line, so rustfmt
collapses the `.stderr(predicate::str::contains( … ))` call. Apply it to keep
`cargo fmt --all -- --check` (CI lint job) green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(test): update stale exec error assertion in test_subcommand_not_implemented

The `exec` subtest expected stderr containing "Dev container config" AND
"not found", but `exec` now emits "Configuration file not found: <path>" (the
same message the `build` subtest already asserts). This was masked on main
because the file is `#![cfg(feature = "full")]` and CI ran
`--no-default-features`, compiling it out; removing the feature gate surfaces it.
Assert the actual current message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build Build system changes ci CI/CD changes deps Dependency updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant