Skip to content

Add minimal-versions CI check#1940

Merged
clux merged 6 commits into
kube-rs:mainfrom
doxxx93:feat/minimal-versions-ci
Feb 19, 2026
Merged

Add minimal-versions CI check#1940
clux merged 6 commits into
kube-rs:mainfrom
doxxx93:feat/minimal-versions-ci

Conversation

@doxxx93
Copy link
Copy Markdown
Member

@doxxx93 doxxx93 commented Feb 19, 2026

Motivation

After #1939, lower bounds declared in Cargo.toml can silently drift from what actually compiles. Since we don't use lockfiles, there's no safety net to catch this.

Solution

Add a minimal-versions job to features.yml that resolves all dependencies to their minimum declared versions and checks that the workspace still compiles.

  • cargo hack --remove-dev-deps --workspace to prevent dev-deps from affecting resolution
  • cargo +nightly update -Z minimal-versions to lock to lowest allowed versions
  • cargo check --workspace --all-features to verify compilation

Also adds a just minimal-versions recipe for local use.

@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.2%. Comparing base (5c97036) to head (1783184).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##            main   #1940     +/-   ##
=======================================
- Coverage   76.3%   76.2%   -0.0%     
=======================================
  Files         89      89             
  Lines       8487    8487             
=======================================
- Hits        6468    6466      -2     
- Misses      2019    2021      +2     

see 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@doxxx93
Copy link
Copy Markdown
Member Author

doxxx93 commented Feb 19, 2026

@clux I put this as a separate job in features.yml since it needs nightly (unlike the existing cargo-hack job on stable), so merging them into one job wasn't practical.

One thing I'm wondering: should this run on PRs (ci.yml) instead of just on main push? The original issue (#1938) came from a code change PR (#1933) that used a newer API without bumping the minimum version — if minimal-versions had run on that PR, it would have been caught before merge. It would also catch dependabot PRs that bump versions breaking minimal-versions compatibility. It's just a single cargo check, so it shouldn't add much CI time.

What do you think?

@clux
Copy link
Copy Markdown
Member

clux commented Feb 19, 2026

@clux I put this as a separate job in features.yml since it needs nightly (unlike the existing cargo-hack job on stable), so merging them into one job wasn't practical.

yeah, makes sense.

One thing I'm wondering: should this run on PRs (ci.yml) instead of just on main push? The original issue (#1938) came from a code change PR (#1933) that used a newer API without bumping the minimum version — if minimal-versions had run on that PR, it would have been caught before merge. It would also catch dependabot PRs that bump versions breaking minimal-versions compatibility. It's just a single cargo check, so it shouldn't add much CI time.

What do you think?

mh, yeah, it would actually be good to have this pre-merge. maybe a check / minimal-versions would be a good initial name/grouping for it (check.yml).
EDIT: or maybe it can be put into the lint group initially. i don't know. wdyt?

@clux clux added the changelog-exclude changelog excluded prs label Feb 19, 2026
@clux clux added this to the 3.1.0 milestone Feb 19, 2026
@doxxx93
Copy link
Copy Markdown
Member Author

doxxx93 commented Feb 19, 2026

I think ci.yml would be the best fit for now — it already has other check-style jobs like msrv (cargo check on minimum Rust version) and doc (cargo doc build check), which share the same "does it compile under X constraint" nature as minimal-versions.

If we want a dedicated check.yml later, we could move msrv, doc, and minimal-versions together at that point.

What do you think about putting it in ci.yml?


Another thought: if we eventually create a check.yml, we could set it up as a prerequisite using needs — so heavier jobs (tests, integration) only run after the check jobs pass. That way we'd fail fast on compilation issues.

@clux
Copy link
Copy Markdown
Member

clux commented Feb 19, 2026

ci.yml sounds good. needs dependency also makes sense to save some CI time. 👍

@doxxx93
Copy link
Copy Markdown
Member Author

doxxx93 commented Feb 19, 2026

@clux The minimal-versions check is failing because --all-features enables aws-lc-rs, which pulls in aws-lc-sys v0.21.0 (its minimal version) that doesn't compile with current Rust.

Since this is an upstream issue (hyper-rustls → rustls → aws-lc-rs → aws-lc-sys chain), I'm thinking of using cargo hack check --each-feature --no-private -p kube --skip=aws-lc-rs,oauth,oidc instead of cargo check --all-features — similar to how just hack already skips oauth,oidc.

Does that sound reasonable?

@clux
Copy link
Copy Markdown
Member

clux commented Feb 19, 2026

oh, convenient, it's actually failing now.

@clux
Copy link
Copy Markdown
Member

clux commented Feb 19, 2026

Since this is an upstream issue (hyper-rustls → rustls → aws-lc-rs → aws-lc-sys chain), I'm thinking of using cargo hack check --each-feature --skip=aws-lc-rs instead of cargo check --all-features — similar to how just hack already skips oauth,oidc.

hmm, we skip that in the feature powerset job purely because it's impractically large/long runtime otherwise.

but i guess there's nothing that we can actually bump to fix this as it's not a direct dependency for us so skipping it still makes sense. (unless we took an explicit dep on aws-lc-rs and bumped two patch versions, but that's not something we should do without a lockfile)

@doxxx93
Copy link
Copy Markdown
Member Author

doxxx93 commented Feb 19, 2026

@clux After more local testing on the actual repo, --each-feature keeps hitting upstream minimal-versions failures:

  • aws-lc-rsaws-lc-sys v0.21.0 build failure
  • gzipcrc32fast v1.1.0 build failure
  • runtimenum-bigint v0.4.0 build failure
  • oauth, oidc → need TLS stack (same as just hack)
  • k8s-openapi → needs K8S_OPENAPI_ENABLED_VERSION env var since --remove-dev-deps strips the version feature

The skip list keeps growing, which reduces coverage.

I see two options:

  1. --each-feature with skips — more coverage but maintains a growing skip list
  2. cargo check -p kube (default features only) — simple, still catches issues like tower-http dependency should be updated to 0.6.4 #1938, and can expand later as upstream crates fix their minimum versions

What's your preference?

(Apologies for not testing on the actual repo earlier — I only ran it on a minimal test repo initially.)


Update: Verified option 2 passes locally. This also means cargo-hack is only needed for --remove-dev-deps, not for the check step itself.


Update 2: Found a better approach — -Z direct-minimal-versions instead of -Z minimal-versions.

The difference: -Z minimal-versions pins all deps (including transitive) to minimum, which is why upstream crates like aws-lc-sys, crc32fast, num-bigint break. -Z direct-minimal-versions only pins direct dependencies to minimum while resolving transitive deps normally.

This means:

When I tested locally, it actually found 11 lower bounds in Cargo.toml that were inconsistent (e.g. hyper = "1.2.0" but hyper-util 0.1.16 requires hyper >= 1.6.0). These would be fixed alongside.

Updated recipe:

minimal-versions:
  cargo hack --remove-dev-deps --workspace
  cargo +nightly update -Z direct-minimal-versions
  K8S_OPENAPI_ENABLED_VERSION=1.31 cargo check --all-features

Note: K8S_OPENAPI_ENABLED_VERSION is unavoidable here — k8s-openapi version features (e.g. latest) are only enabled via [dev-dependencies], which --remove-dev-deps strips. The env var is the intended fallback in k8s-openapi's build.rs for exactly this case.

@doxxx93 doxxx93 marked this pull request as draft February 19, 2026 11:58
@clux
Copy link
Copy Markdown
Member

clux commented Feb 19, 2026

Ah, yes. Direct minimal sounds like a much better and more maintainable approach for a library without a lockfile! Let's do that, and bump the pins to the new required minimal versions while we are at it!

@doxxx93 doxxx93 marked this pull request as ready for review February 19, 2026 13:46
Copy link
Copy Markdown
Member

@clux clux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing. Thank you!

@clux clux removed the changelog-exclude changelog excluded prs label Feb 19, 2026
@doxxx93
Copy link
Copy Markdown
Member Author

doxxx93 commented Feb 19, 2026

This turned out to be a much deeper rabbit hole than expected, but happy with where it landed. With -Z direct-minimal-versions, we get accurate lower bound validation without fighting upstream transitive failures.

Going forward, when k8s-openapi bumps its supported Kubernetes version, we just update K8S_OPENAPI_ENABLED_VERSION in the recipe — and the CI will catch any stale lower bounds before they hit users.

@clux clux added the changelog-fix changelog fix category for prs label Feb 19, 2026
@clux
Copy link
Copy Markdown
Member

clux commented Feb 19, 2026

Going forward, when k8s-openapi bumps its supported Kubernetes version, we just update K8S_OPENAPI_ENABLED_VERSION in the recipe — and the CI will catch any stale lower bounds before they hit users.

ah, right. do you mind putting that in the justfile where we are doing just bump-k8s in that case? (can be an sd call)

@doxxx93
Copy link
Copy Markdown
Member Author

doxxx93 commented Feb 19, 2026

no problem!

Copy link
Copy Markdown
Member

@clux clux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great!

@doxxx93
Copy link
Copy Markdown
Member Author

doxxx93 commented Feb 19, 2026

Definitely the toughest PR I've worked on recently 😅

@clux clux merged commit 3980e3e into kube-rs:main Feb 19, 2026
18 checks passed
@doxxx93 doxxx93 deleted the feat/minimal-versions-ci branch February 20, 2026 02:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-fix changelog fix category for prs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants