From 642472c5483cd2d8104699471c01b9c0a1531a37 Mon Sep 17 00:00:00 2001 From: Jason Hall Date: Sat, 7 Jun 2025 21:17:30 -0400 Subject: [PATCH] Ensure all tests run on all platforms without skipping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove test skipping based on target availability - Install cross-compilation toolchains for all platforms in CI: - Ubuntu: musl-tools - macOS: musl-cross with proper cargo config - Windows: rust-lld linker - Update builder to use platform-appropriate linkers - Make full build/run workflow test mandatory in CI - Add Docker setup and local registry for integration tests - Set RUSTFLAGS with --cfg ci to enable CI-specific test behavior 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++++ Cargo.toml | 1 + example/hello-krust/.cargo/config.toml | 8 ------- src/builder/mod.rs | 21 +++++++++++++++++ tests/integration_test.rs | 32 ++++++++++++++------------ 5 files changed, 71 insertions(+), 23 deletions(-) delete mode 100644 example/hello-krust/.cargo/config.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00752c6..fcb9996 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,7 @@ on: env: CARGO_TERM_COLOR: always + RUSTFLAGS: "--cfg ci" jobs: test: @@ -23,6 +24,29 @@ jobs: uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} + targets: x86_64-unknown-linux-musl + - name: Install cross-compilation tools (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y musl-tools + - name: Install cross-compilation tools (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install musl-cross + # Set up cargo config for cross-compilation + mkdir -p ~/.cargo + echo '[target.x86_64-unknown-linux-musl]' >> ~/.cargo/config.toml + echo 'linker = "x86_64-linux-musl-gcc"' >> ~/.cargo/config.toml + - name: Install cross-compilation tools (Windows) + if: matrix.os == 'windows-latest' + run: | + # On Windows, we'll use rust-lld as the linker for musl targets + rustup component add llvm-tools-preview + # Create cargo config + mkdir -p ~/.cargo + echo '[target.x86_64-unknown-linux-musl]' >> ~/.cargo/config.toml + echo 'linker = "rust-lld"' >> ~/.cargo/config.toml - name: Cache cargo registry uses: actions/cache@v4 with: @@ -72,6 +96,12 @@ jobs: integration: name: Integration Test runs-on: ubuntu-latest + needs: [test, fmt, clippy] # Only run after other tests pass + services: + registry: + image: registry:2 + ports: + - 5000:5000 steps: - uses: actions/checkout@v4 - name: Install Rust @@ -82,6 +112,8 @@ jobs: run: | sudo apt-get update sudo apt-get install -y musl-tools + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - name: Build krust run: cargo build --release - name: Add krust to PATH diff --git a/Cargo.toml b/Cargo.toml index 4805f2e..e6acb4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } dirs = "5.0" toml = "0.8" +which = "6.0" [dev-dependencies] tempfile = "3.9" diff --git a/example/hello-krust/.cargo/config.toml b/example/hello-krust/.cargo/config.toml deleted file mode 100644 index 3eba26b..0000000 --- a/example/hello-krust/.cargo/config.toml +++ /dev/null @@ -1,8 +0,0 @@ -[target.x86_64-unknown-linux-musl] -linker = "x86_64-linux-musl-gcc" - -[target.aarch64-unknown-linux-musl] -linker = "aarch64-linux-musl-gcc" - -[target.armv7-unknown-linux-musleabihf] -linker = "armv7-linux-musleabihf-gcc" \ No newline at end of file diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 5c8bef2..b7e5746 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -46,6 +46,27 @@ impl RustBuilder { }; cmd.env("RUSTFLAGS", rustflags); + // For cross-compilation on non-Linux platforms, set linker if available + if cfg!(not(target_os = "linux")) && self.target.contains("linux") { + // Check if we have a musl cross-compiler available + if self.target.contains("x86_64-unknown-linux-musl") { + // On Windows, prefer rust-lld + if cfg!(target_os = "windows") { + cmd.env("CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER", "rust-lld"); + debug!("Using linker: rust-lld"); + } else { + // Try common linker names on other platforms + for linker in &["x86_64-linux-musl-gcc", "musl-gcc", "x86_64-linux-gnu-gcc"] { + if which::which(linker).is_ok() { + cmd.env("CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER", linker); + debug!("Using linker: {}", linker); + break; + } + } + } + } + } + for arg in &self.cargo_args { cmd.arg(arg); } diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 469f58a..9bb59e0 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -4,6 +4,7 @@ use predicates::prelude::*; use std::env; use std::process::Command as StdCommand; + #[test] fn test_version_command() -> Result<()> { let mut cmd = Command::cargo_bin("krust")?; @@ -56,11 +57,9 @@ fn test_build_requires_repo_or_image() -> Result<()> { .current_dir(&example_dir) .env_remove("KRUST_REPO"); - cmd.assert() - .failure() - .stderr(predicate::str::contains( - "Either --image or KRUST_REPO must be set", - )); + cmd.assert().failure().stderr(predicate::str::contains( + "Either --image or KRUST_REPO must be set", + )); Ok(()) } @@ -76,11 +75,12 @@ fn test_build_with_krust_repo_env() -> Result<()> { .env("KRUST_REPO", "test.local") .current_dir(&example_dir); - cmd.assert().success().stderr(predicate::str::contains( - "Building Rust project", - )).stderr(predicate::str::contains( - "Successfully built image: test.local/hello-krust:latest", - )); + cmd.assert() + .success() + .stderr(predicate::str::contains("Building Rust project")) + .stderr(predicate::str::contains( + "Successfully built image: test.local/hello-krust:latest", + )); Ok(()) } @@ -101,7 +101,10 @@ fn test_command_substitution_syntax() -> Result<()> { // Stdout should be empty when --no-push is used let stdout = String::from_utf8_lossy(&output.stdout); - assert!(stdout.trim().is_empty(), "Stdout should be empty with --no-push"); + assert!( + stdout.trim().is_empty(), + "Stdout should be empty with --no-push" + ); // Stderr should contain log messages let stderr = String::from_utf8_lossy(&output.stderr); @@ -129,12 +132,11 @@ fn test_verbose_logging() -> Result<()> { } #[test] -#[ignore] // This test requires Docker and a registry +#[cfg_attr(not(ci), ignore)] // Run in CI, but allow skipping locally fn test_full_build_and_run_workflow() -> Result<()> { - // Skip if Docker is not available + // This test requires Docker if StdCommand::new("docker").arg("version").output().is_err() { - eprintln!("Skipping test: Docker not available"); - return Ok(()); + panic!("Docker is required for this test but is not available"); } // Get the example project directory