crusader > copter #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # CI workflow for cargo-crusader | |
| # | |
| # This workflow tests: | |
| # - Code compilation and unit tests | |
| # - Integration tests with test fixtures | |
| # - Docker build and execution | |
| # - Security isolation features | |
| # - Real crate testing (against small, stable crates) | |
| name: CI | |
| on: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| branches: [main, master] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| # Test 1: Basic compilation and unit tests | |
| test-build: | |
| name: Build and Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cargo/registry | |
| key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Cache cargo index | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cargo/git | |
| key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Cache cargo build | |
| uses: actions/cache@v4 | |
| with: | |
| path: target | |
| key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Check formatting | |
| run: cargo fmt -- --check | |
| - name: Clippy | |
| run: cargo clippy --all-targets --all-features -- -D warnings | |
| - name: Build | |
| run: cargo build --release --locked | |
| - name: Run unit tests | |
| run: cargo test --lib | |
| - name: Run integration tests | |
| run: cargo test --test '*' | |
| - name: Verify binary works | |
| run: | | |
| ./target/release/cargo-crusader --version | |
| ./target/release/cargo-crusader --help | |
| # Test 2: Offline integration tests with fixtures | |
| test-fixtures: | |
| name: Test with Fixtures | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Build cargo-crusader | |
| run: cargo build --release | |
| - name: Test with test fixtures | |
| run: | | |
| cd tests/fixtures/base-crate | |
| echo "=== Testing dependent-passing ===" | |
| ../../../target/release/cargo-crusader \ | |
| --dependent-paths ../dependent-passing \ | |
| --baseline-path . || true | |
| echo "=== Testing dependent-regressed ===" | |
| ../../../target/release/cargo-crusader \ | |
| --dependent-paths ../dependent-regressed \ | |
| --baseline-path . || true | |
| echo "=== Testing dependent-broken ===" | |
| ../../../target/release/cargo-crusader \ | |
| --dependent-paths ../dependent-broken \ | |
| --baseline-path . || true | |
| - name: Verify reports generated | |
| run: | | |
| cd tests/fixtures/base-crate | |
| ls -lh crusader-*.html crusader-*.md || echo "Some reports missing" | |
| # Test 3: Real crate testing | |
| test-real-crate: | |
| name: Test Real Crate | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Build cargo-crusader | |
| run: cargo build --release | |
| - name: Clone a stable test crate | |
| run: | | |
| # Use semver crate as it's small and stable | |
| git clone --depth 1 --branch 1.0.20 https://github.com/dtolnay/semver.git /tmp/test-crate | |
| cd /tmp/test-crate | |
| - name: Run crusader on real crate | |
| run: | | |
| cd /tmp/test-crate | |
| ${{ github.workspace }}/target/release/cargo-crusader \ | |
| --top-dependents 3 || true | |
| - name: Upload real crate reports | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: real-crate-reports | |
| path: | | |
| /tmp/test-crate/crusader-report.html | |
| /tmp/test-crate/crusader-analysis.md | |
| retention-days: 7 | |
| # Test 4: Docker build and execution | |
| test-docker: | |
| name: Test Docker Build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Build Docker image | |
| run: docker build -t cargo-crusader:test . | |
| - name: Test Docker image | |
| run: | | |
| docker run --rm cargo-crusader:test --version | |
| docker run --rm cargo-crusader:test --help | |
| - name: Test Docker with wrapper script | |
| run: | | |
| # Create a minimal test crate | |
| mkdir -p /tmp/docker-test | |
| cd /tmp/docker-test | |
| cat > Cargo.toml <<'EOF' | |
| [package] | |
| name = "docker-test" | |
| version = "0.1.0" | |
| edition = "2021" | |
| [dependencies] | |
| serde = "1.0" | |
| EOF | |
| mkdir -p src | |
| echo 'fn main() {}' > src/main.rs | |
| # Run crusader in Docker | |
| docker run --rm \ | |
| --user $(id -u):$(id -g) \ | |
| --volume "$PWD:/workspace:ro" \ | |
| --volume "$PWD/output:/output:rw" \ | |
| --env CARGO_HOME=/tmp/cargo \ | |
| cargo-crusader:test \ | |
| bash -c ' | |
| cargo build --release --manifest-path /workspace/Cargo.toml || true | |
| echo "Docker test: OK" | |
| ' | |
| # Test 5: Security verification | |
| test-security: | |
| name: Test Security Features | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Build cargo-crusader | |
| run: cargo build --release | |
| - name: Test isolated cargo home | |
| run: | | |
| export CARGO_HOME=${{ runner.temp }}/isolated-cargo | |
| mkdir -p "$CARGO_HOME" | |
| # Create test crate | |
| mkdir -p /tmp/security-test | |
| cd /tmp/security-test | |
| cat > Cargo.toml <<'EOF' | |
| [package] | |
| name = "security-test" | |
| version = "0.1.0" | |
| edition = "2021" | |
| EOF | |
| mkdir -p src | |
| echo 'fn main() {}' > src/main.rs | |
| # Verify cargo home is empty | |
| if [ -d "$CARGO_HOME/registry" ]; then | |
| echo "FAIL: Cargo home should be empty" | |
| exit 1 | |
| fi | |
| echo "PASS: Isolated cargo home works" | |
| - name: Test no credential access | |
| run: | | |
| # Create fake credentials that should not be used | |
| export CARGO_HOME=${{ runner.temp }}/creds-test | |
| mkdir -p "$CARGO_HOME" | |
| cat > "$CARGO_HOME/credentials.toml" <<'EOF' | |
| [registry] | |
| token = "fake-token" | |
| EOF | |
| # Verify file exists | |
| test -f "$CARGO_HOME/credentials.toml" | |
| echo "PASS: Credentials file created for testing" | |
| echo "Note: Crusader uses CARGO_HOME for caching only" | |
| - name: Test Docker security | |
| run: | | |
| docker build -t crusader-sec:test . | |
| # Test runs as non-root | |
| USER_CHECK=$(docker run --rm crusader-sec:test whoami) | |
| if [ "$USER_CHECK" = "root" ]; then | |
| echo "FAIL: Container should not run as root" | |
| exit 1 | |
| fi | |
| echo "PASS: Container runs as non-root user: $USER_CHECK" | |
| # Test network isolation (docker --network none) | |
| docker run --rm --network none crusader-sec:test echo "Network isolation: OK" | |
| # Test read-only filesystem | |
| if docker run --rm --read-only --tmpfs /tmp:rw crusader-sec:test \ | |
| sh -c 'touch /test-file 2>/dev/null'; then | |
| echo "FAIL: Should not be able to write to read-only filesystem" | |
| exit 1 | |
| fi | |
| echo "PASS: Read-only filesystem works" | |
| # Test 6: Script validation | |
| test-scripts: | |
| name: Test Scripts | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Check script shebangs | |
| run: | | |
| if ! head -1 crusader-docker.sh | grep -q '^#!/bin/bash'; then | |
| echo "FAIL: Missing or incorrect shebang" | |
| exit 1 | |
| fi | |
| echo "PASS: Script shebangs correct" | |
| - name: Check script is executable | |
| run: | | |
| if [ ! -x crusader-docker.sh ]; then | |
| echo "FAIL: Script is not executable" | |
| exit 1 | |
| fi | |
| echo "PASS: Script is executable" | |
| - name: Test script help | |
| run: | | |
| ./crusader-docker.sh --help | grep -q "crusader-docker.sh" | |
| echo "PASS: Help text works" | |
| # Test 7: Workflow validation | |
| test-workflows: | |
| name: Validate Workflows | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Check workflow syntax | |
| run: | | |
| for workflow in .github/workflows/*.yml; do | |
| echo "Checking $workflow" | |
| # Basic YAML syntax check | |
| python3 -c "import yaml; yaml.safe_load(open('$workflow'))" | |
| done | |
| echo "PASS: All workflows have valid YAML syntax" | |
| - name: Verify security settings | |
| run: | | |
| echo "Checking for security best practices..." | |
| # Check all workflows have permissions defined | |
| for workflow in .github/workflows/*.yml; do | |
| if ! grep -q "permissions:" "$workflow"; then | |
| echo "WARNING: $workflow missing permissions block" | |
| fi | |
| done | |
| # Check for persist-credentials: false | |
| if ! grep -q "persist-credentials: false" .github/workflows/crusader-*.yml; then | |
| echo "WARNING: Some workflows may persist credentials" | |
| fi | |
| echo "PASS: Security settings validated" | |
| # Summary job | |
| ci-success: | |
| name: CI Success | |
| runs-on: ubuntu-latest | |
| needs: | |
| - test-build | |
| - test-fixtures | |
| - test-real-crate | |
| - test-docker | |
| - test-security | |
| - test-scripts | |
| - test-workflows | |
| steps: | |
| - name: Summary | |
| run: | | |
| echo "✅ All CI tests passed!" | |
| echo "" | |
| echo "Tests completed:" | |
| echo " ✓ Build and unit tests" | |
| echo " ✓ Integration tests with fixtures" | |
| echo " ✓ Real crate testing" | |
| echo " ✓ Docker build and execution" | |
| echo " ✓ Security verification" | |
| echo " ✓ Script validation" | |
| echo " ✓ Workflow validation" |