From 2b7f32f43ea5faa8c87bb1ea49caa018b4d6f0c4 Mon Sep 17 00:00:00 2001 From: Zeeshan Lakhani Date: Wed, 10 Jul 2024 14:58:27 +0000 Subject: [PATCH] xtask + version pinning --- .github/buildomat/jobs/check-features.sh | 10 +- .github/workflows/rust.yml | 5 +- dev-tools/xtask/src/check_features.rs | 125 +++++++++++++++++++++++ dev-tools/xtask/src/main.rs | 4 + 4 files changed, 138 insertions(+), 6 deletions(-) create mode 100644 dev-tools/xtask/src/check_features.rs diff --git a/.github/buildomat/jobs/check-features.sh b/.github/buildomat/jobs/check-features.sh index 129462c9ea4..cf09a693361 100644 --- a/.github/buildomat/jobs/check-features.sh +++ b/.github/buildomat/jobs/check-features.sh @@ -6,7 +6,8 @@ #: rust_toolchain = true #: output_rules = [] -# Run cargo check on illumos with feature-specifics like `no-default-features`. +# Run cargo check on illumos with feature-specifics like `no-default-features` +# or `feature-powerset`. set -o errexit set -o pipefail @@ -15,6 +16,10 @@ set -o xtrace cargo --version rustc --version +# NOTE: This version should be in sync with the recommended version in +# ./dev-tools/xtask/src/check-features.rs. +CARGO_HACK_VERSION='0.6.28' + # # Set up our PATH for use with this workspace. # @@ -32,5 +37,4 @@ RUSTDOCFLAGS="--document-private-items -D warnings" ptime -m cargo doc --workspa # `cargo-hack` check feature-powerset # banner hack -cargo install cargo-hack --locked -ptime -m timeout 2h cargo hack check --workspace --feature-powerset --no-dev-deps --exclude-features image-trampoline,image-standard +ptime -m timeout 2h cargo xtask check-features --version "$CARGO_HACK_VERSION" --exclude-features image-trampoline,image-standard diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 41c15261c48..56024b13eee 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -86,6 +86,7 @@ jobs: runs-on: ubuntu-22.04 env: CARGO_INCREMENTAL: 0 + CARGO_HACK_VERSION: 0.6.28 steps: # This repo is unstable and unnecessary: https://github.com/microsoft/linux-package-repositories/issues/34 - name: Disable packages.microsoft.com repo @@ -107,11 +108,9 @@ jobs: run: ./tools/install_builder_prerequisites.sh -y - name: Run Cargo Check (No Default Features) run: cargo check --workspace --bins --tests --no-default-features - - name: Install cargo-hack - uses: taiki-e/install-action@cargo-hack - name: Run Cargo Hack Check (Feature-Powerset, No-Dev-Deps) timeout-minutes: 120 # 2 hours - run: cargo hack check --workspace --feature-powerset --no-dev-deps --exclude-features image-trampoline,image-standard + run: cargo xtask check-features --version ${{ env.CARGO_HACK_VERSION }} --exclude-features image-trampoline,image-standard # This is just a test build of docs. Publicly available docs are built via # the separate "rustdocs" repo. diff --git a/dev-tools/xtask/src/check_features.rs b/dev-tools/xtask/src/check_features.rs new file mode 100644 index 00000000000..e1030fbeae5 --- /dev/null +++ b/dev-tools/xtask/src/check_features.rs @@ -0,0 +1,125 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Subcommand: cargo xtask check-features + +use anyhow::{bail, Context, Result}; +use clap::Parser; +use std::process::Command; + +/// The default version of `cargo-hack` to install. +/// We use a patch-floating version to avoid breaking the build when a new +/// version is released (locally). +const FLOAT_VERSION: &str = "~0.6.28"; + +#[derive(Parser)] +pub struct Args { + #[clap(long)] + exclude_features: Option>, + #[clap(long)] + depth: Option, + /// Error format passed to `cargo hack check`. + #[clap(long, value_name = "FMT")] + message_format: Option, + #[clap(long)] + version: Option, +} + +/// Run `cargo hack check`. +pub fn run_cmd(args: Args) -> Result<()> { + install_cargo_hack(args.version).unwrap(); + + let cargo = + std::env::var("CARGO").unwrap_or_else(|_| String::from("cargo")); + let mut command = Command::new(&cargo); + + command.args(&["hack", "check"]); + + if let Some(features) = args.exclude_features { + let ex = format!("--exclude-features={}", features.join(",")); + command.arg(ex); + } + + if let Some(depth) = args.depth { + let depth = format!("depth={}", depth); + command.arg(depth); + } + + // Pass along the `--message-format` flag if it was provided. + if let Some(fmt) = args.message_format { + command.args(["--message-format", &fmt]); + } + + command + // Make sure we check everything. + .arg("--workspace") + .arg("--bins") + // We want to check the feature powerset. + .arg("--feature-powerset") + .arg("--no-dev-deps") + .arg("--exclude-no-default-features"); + + eprintln!( + "running: {:?} {}", + &cargo, + command + .get_args() + .map(|arg| format!("{:?}", arg.to_str().unwrap())) + .collect::>() + .join(" ") + ); + + let exit_status = command + .spawn() + .context("failed to spawn child process")? + .wait() + .context("failed to wait for child process")?; + + if !exit_status.success() { + bail!("check-features failed: {}", exit_status); + } + + Ok(()) +} + +fn install_cargo_hack(version: Option) -> Result<()> { + let cargo = + std::env::var("CARGO").unwrap_or_else(|_| String::from("cargo")); + + let mut command = Command::new(&cargo); + + if let Some(version) = version { + command.args(&["install", "cargo-hack", "--version", &version]); + } else { + command.args(&[ + "install", + "cargo-hack", + "--locked", + "--version", + FLOAT_VERSION, + ]); + } + + eprintln!( + "running: {:?} {}", + &cargo, + command + .get_args() + .map(|arg| format!("{:?}", arg.to_str().unwrap())) + .collect::>() + .join(" ") + ); + + let exit_status = command + .spawn() + .expect("failed to spawn child process") + .wait() + .expect("failed to wait for child process"); + + if !exit_status.success() { + bail!("cargo-hack install failed: {}", exit_status); + } + + Ok(()) +} diff --git a/dev-tools/xtask/src/main.rs b/dev-tools/xtask/src/main.rs index 3d8acceb3d6..77e7c790a6c 100644 --- a/dev-tools/xtask/src/main.rs +++ b/dev-tools/xtask/src/main.rs @@ -10,6 +10,7 @@ use anyhow::{Context, Result}; use cargo_metadata::Metadata; use clap::{Parser, Subcommand}; +mod check_features; mod check_workspace_deps; mod clippy; mod download; @@ -38,6 +39,8 @@ enum Cmds { /// Run Argon2 hash with specific parameters (quick performance check) Argon2(external::External), + /// Check that all features are flagged correctly + CheckFeatures(check_features::Args), /// Check that dependencies are not duplicated in any packages in the /// workspace CheckWorkspaceDeps, @@ -86,6 +89,7 @@ async fn main() -> Result<()> { external.cargo_args(["--release"]).exec_example("argon2") } Cmds::Clippy(args) => clippy::run_cmd(args), + Cmds::CheckFeatures(args) => check_features::run_cmd(args), Cmds::CheckWorkspaceDeps => check_workspace_deps::run_cmd(), Cmds::Download(args) => download::run_cmd(args).await, #[cfg(target_os = "illumos")]