1
0
Fork 0
mirror of https://github.com/imjasonh/krust synced 2026-07-07 22:35:25 +00:00

Add e2e tests and CI integration for docker run workflow

- Add comprehensive e2e tests for build functionality
- Add integration job to CI that tests `docker run $(krust build)`
- Test KRUST_REPO environment variable usage
- Test --no-push flag and clean stdout for command substitution
- Add tests for verbose logging
- Remove outdated basic_test.rs

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jason Hall 2025-06-07 21:03:33 -04:00
parent 2cf7ab1c17
commit 93bb4561fc
Failed to extract signature
3 changed files with 168 additions and 31 deletions

View file

@ -69,14 +69,53 @@ jobs:
- name: Run clippy
run: cargo clippy -- -D warnings
coverage:
name: Code coverage
integration:
name: Integration Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-tarpaulin
run: cargo install cargo-tarpaulin
- name: Generate code coverage
run: cargo tarpaulin --verbose --workspace
with:
targets: x86_64-unknown-linux-musl
- name: Install musl tools
run: |
sudo apt-get update
sudo apt-get install -y musl-tools
- name: Build krust
run: cargo build --release
- name: Add krust to PATH
run: echo "${{ github.workspace }}/target/release" >> $GITHUB_PATH
- name: Test krust version
run: krust version
- name: Build and run example with krust
run: |
cd example/hello-krust
# Build and push to ttl.sh (ephemeral registry)
export KRUST_REPO=ttl.sh/${{ github.run_id }}
IMAGE_REF=$(krust build ./)
echo "Built image: $IMAGE_REF"
# Run the image
docker run --rm $IMAGE_REF
- name: Test docker run with command substitution
run: |
cd example/hello-krust
export KRUST_REPO=ttl.sh/${{ github.run_id }}-test2
docker run --rm $(krust build ./)
- name: Test build with --no-push
run: |
cd example/hello-krust
krust build --no-push --image local.test/hello:latest ./
# Takes too long to run on CI, so it's commented out for now.
# coverage:
# name: Code coverage
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: Install Rust
# uses: dtolnay/rust-toolchain@stable
# - name: Install cargo-tarpaulin
# run: cargo install cargo-tarpaulin
# - name: Generate code coverage
# run: cargo tarpaulin --verbose --workspace

View file

@ -1,25 +0,0 @@
use std::process::Command;
#[test]
fn test_help_flag() {
let output = Command::new("cargo")
.args(&["run", "--", "--version"])
.output()
.expect("Failed to execute command");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("krust"));
assert!(output.status.success());
}
#[test]
fn test_basic_run() {
let output = Command::new("cargo")
.arg("run")
.output()
.expect("Failed to execute command");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("Hello from krust!"));
assert!(output.status.success());
}

View file

@ -1,6 +1,8 @@
use anyhow::Result;
use assert_cmd::Command;
use predicates::prelude::*;
use std::env;
use std::process::Command as StdCommand;
#[test]
fn test_version_command() -> Result<()> {
@ -41,3 +43,124 @@ fn test_build_help() -> Result<()> {
));
Ok(())
}
#[test]
fn test_build_requires_repo_or_image() -> Result<()> {
// Use the example directory
let example_dir = env::current_dir()?.join("example").join("hello-krust");
// Run krust build without KRUST_REPO or --image
let mut cmd = Command::cargo_bin("krust")?;
cmd.arg("build")
.arg("--no-push")
.current_dir(&example_dir)
.env_remove("KRUST_REPO");
cmd.assert()
.failure()
.stderr(predicate::str::contains(
"Either --image or KRUST_REPO must be set",
));
Ok(())
}
#[test]
fn test_build_with_krust_repo_env() -> Result<()> {
// Use the example directory
let example_dir = env::current_dir()?.join("example").join("hello-krust");
// Run krust build with KRUST_REPO env var
let mut cmd = Command::cargo_bin("krust")?;
cmd.arg("build")
.arg("--no-push")
.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",
));
Ok(())
}
#[test]
fn test_command_substitution_syntax() -> Result<()> {
// Get the example project directory
let example_dir = env::current_dir()?.join("example").join("hello-krust");
// Test that output is clean for command substitution
let mut cmd = Command::cargo_bin("krust")?;
let output = cmd
.arg("build")
.arg("--no-push")
.arg("--image")
.arg("test.local/hello:latest")
.current_dir(&example_dir)
.output()?;
// 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");
// Stderr should contain log messages
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("Building Rust project"));
assert!(stderr.contains("Successfully built image"));
Ok(())
}
#[test]
fn test_verbose_logging() -> Result<()> {
let example_dir = env::current_dir()?.join("example").join("hello-krust");
let mut cmd = Command::cargo_bin("krust")?;
cmd.arg("--verbose")
.arg("build")
.arg("--no-push")
.arg("--image")
.arg("test.local/hello:latest")
.current_dir(&example_dir);
cmd.assert()
.success()
.stderr(predicate::str::contains("DEBUG"));
Ok(())
}
#[test]
#[ignore] // This test requires Docker and a registry
fn test_full_build_and_run_workflow() -> Result<()> {
// Skip if Docker is not available
if StdCommand::new("docker").arg("version").output().is_err() {
eprintln!("Skipping test: Docker not available");
return Ok(());
}
// Get the example project directory
let example_dir = env::current_dir()?.join("example").join("hello-krust");
// Build and push to ttl.sh
let mut cmd = Command::cargo_bin("krust")?;
let output = cmd
.arg("build")
.env("KRUST_REPO", "ttl.sh/krust-test")
.current_dir(&example_dir)
.output()?;
assert!(output.status.success(), "Build failed");
// Get the image reference from stdout
let image_ref = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert!(image_ref.starts_with("ttl.sh/krust-test/hello-krust@sha256:"));
// Try to run the image
let docker_output = StdCommand::new("docker")
.args(&["run", "--rm", &image_ref])
.output()?;
assert!(docker_output.status.success(), "Docker run failed");
let docker_stdout = String::from_utf8_lossy(&docker_output.stdout);
assert!(docker_stdout.contains("Hello from krust example!"));
Ok(())
}