diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b4c58977d3..19fa3b4ce3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -914,6 +914,9 @@ jobs: - name: Check bans run: cargo make --no-workspace check-bans + - name: Check isolated package builds + run: cargo xtask check-isolated-package-builds + # ============================================================================ # BUILD STAGE - Helm Chart # ============================================================================ diff --git a/Cargo.lock b/Cargo.lock index b2d13f876a..73de46c862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12915,6 +12915,7 @@ dependencies = [ name = "xtask" version = "0.1.0" dependencies = [ + "cargo_metadata", "clap", "eyre", "similar 3.1.0", diff --git a/Cargo.toml b/Cargo.toml index 69589707a2..58005d8e23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,6 +97,7 @@ blake3 = "1.4" byteorder = "1.5.0" bytes = "^1" byte-unit = "5.1.6" +cargo_metadata = "0.9.1" casbin = "2.0" chrono = "0.4" clap_complete = "4.5.58" diff --git a/Makefile.toml b/Makefile.toml index 77d6651c09..f42d150ae9 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -540,6 +540,7 @@ dependencies = [ "check-format-flow", "check-format-nightly", "check-workspace-deps", + "check-isolated-package-builds", "check-licenses", "check-bans", ] @@ -711,6 +712,11 @@ script = [ "cargo --quiet xtask check-workspace-deps || (RC=$?; echo 'To fix automatically, run `cargo xtask check-workspace-deps --fix`'; exit $RC)", ] +[tasks.check-isolated-package-builds] +workspace = false +description = "Check that workspace packages build independently with default features" +script = ["cargo xtask check-isolated-package-builds"] + [tasks.check-licenses] workspace = false description = "Check cargo-deny against licenses we're using to validate that we're not introducing new licenses inadvertently" diff --git a/crates/ib-fabric/Cargo.toml b/crates/ib-fabric/Cargo.toml index 1080769420..29061fe44b 100644 --- a/crates/ib-fabric/Cargo.toml +++ b/crates/ib-fabric/Cargo.toml @@ -31,7 +31,7 @@ eyre = { workspace = true } http = { workspace = true } http-body-util = { workspace = true } hyper = { workspace = true } -hyper-rustls = { workspace = true } +hyper-rustls = { workspace = true, features = ["http2"] } hyper-timeout = { workspace = true } hyper-util = { workspace = true } opentelemetry = { workspace = true } diff --git a/crates/measured-boot/Cargo.toml b/crates/measured-boot/Cargo.toml index 882ce3561d..5bbdbd9dfb 100644 --- a/crates/measured-boot/Cargo.toml +++ b/crates/measured-boot/Cargo.toml @@ -38,7 +38,7 @@ prettytable-rs = { optional = true, workspace = true } clap = { workspace = true, optional = true } eyre = { optional = true, workspace = true } serde = { workspace = true } -chrono = { workspace = true } +chrono = { workspace = true, features = ["serde"] } [lints] workspace = true diff --git a/crates/xtask/Cargo.toml b/crates/xtask/Cargo.toml index 9c4df6c747..6e4377a271 100644 --- a/crates/xtask/Cargo.toml +++ b/crates/xtask/Cargo.toml @@ -26,6 +26,7 @@ toml_edit = { workspace = true } walkdir = { workspace = true } eyre = { workspace = true } clap = { workspace = true } +cargo_metadata = { workspace = true } similar = { workspace = true } version-compare = { workspace = true } diff --git a/crates/xtask/src/isolated_package_builds.rs b/crates/xtask/src/isolated_package_builds.rs new file mode 100644 index 0000000000..0240592628 --- /dev/null +++ b/crates/xtask/src/isolated_package_builds.rs @@ -0,0 +1,75 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +use std::process::Command; + +use cargo_metadata::MetadataCommand; +use eyre::{Context, ContextCompat, bail}; + +/// Checks that every workspace package builds independently with default features. +pub fn check() -> eyre::Result<()> { + let packages = workspace_packages()?; + let mut failures = Vec::new(); + + for package in packages { + println!("Checking isolated package build for {package}"); + + // Keep the check read-only; stale lockfiles should fail in CI. + let status = Command::new(cargo()) + .args(["check", "--locked", "-p", &package]) + .status() + .with_context(|| format!("failed to run cargo check for {package}"))?; + + if !status.success() { + failures.push(package); + } + } + + if failures.is_empty() { + return Ok(()); + } + + eprintln!( + "Isolated package builds failed for: {}", + failures.join(", ") + ); + + bail!("one or more isolated package builds failed") +} + +fn workspace_packages() -> eyre::Result> { + let metadata = MetadataCommand::new() + .no_deps() + .exec() + .context("failed to run cargo metadata")?; + + metadata + .workspace_members + .iter() + .map(|member| { + metadata + .packages + .iter() + .find(|package| &package.id == member) + .map(|package| package.name.clone()) + .with_context(|| format!("workspace member {member} missing from cargo metadata")) + }) + .collect::>>() +} + +fn cargo() -> String { + std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()) +} diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index c0b42e1063..e19972c9b4 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +mod isolated_package_builds; mod workspace_deps; use clap::Parser; @@ -26,6 +27,11 @@ enum Xtask { about = "Check for any dependency versions defined in crate-level Cargo.toml's instead of the workspace root" )] CheckWorkspaceDeps(CheckWorkspaceDeps), + #[clap( + name = "check-isolated-package-builds", + about = "Check that each workspace package builds independently with its default features" + )] + IsolatedPackageBuilds, } #[derive(Parser, Debug)] @@ -43,5 +49,6 @@ fn main() -> eyre::Result<()> { Xtask::CheckWorkspaceDeps(CheckWorkspaceDeps { fix }) => { workspace_deps::check(fix)?.report_and_exit() } - }; + Xtask::IsolatedPackageBuilds => isolated_package_builds::check(), + } }