302 lines
9.6 KiB
Plaintext
Raw Normal View History

2025-12-18 01:18:59 +00:00
# ╔══════════════════════════════════════════════════════════════════════╗
# ║ CI/CD RECIPES ║
# ║ Validation and deployment tasks ║
2025-12-18 01:18:59 +00:00
# ╚══════════════════════════════════════════════════════════════════════╝
# Workspace root directory
WORKSPACE_ROOT := justfile_directory()
2025-12-18 01:18:59 +00:00
# Help for CI module
help:
@echo "CI/CD MODULE"
@echo ""
@echo "Validation:"
@echo " just ci::lint Lint all code"
@echo " just ci::test-all Test all features"
@echo " just ci::check Check + format + lint"
@echo " just ci::audit Audit dependencies (security)"
@echo ""
@echo "Compliance:"
@echo " just ci::verify-sbom Verify SBOMs are up to date"
@echo " just ci::audit Audit dependencies (security)"
@echo " just ci::deny Check dependencies with cargo-deny"
2025-12-18 01:18:59 +00:00
@echo ""
@echo "Build validation:"
@echo " just ci::build-debug Debug build"
@echo " just ci::build-release Release build"
@echo ""
@echo "Full pipeline:"
@echo " just ci::full Complete CI: check + test + build"
# === VALIDATION STAGE ===
# Format check
[doc("Check format")]
fmt-check:
@echo "=== Format validation ==="
cargo fmt -p typedialog-core -p typedialog -p typedialog-tui -p typedialog-web -p typedialog-ai -p typedialog-prov-gen -p typedialog-ag-core -p typedialog-ag -- --check
2025-12-18 01:18:59 +00:00
@echo "✓ Format valid"
# Lint
[doc("Run clippy")]
lint:
#!/bin/bash
set -e
echo "=== Linting ==="
if [ -d "target/debug" ]; then
echo " → Using: target/debug (exists)"
cargo clippy --all-targets --all-features -- -D warnings
else
echo " → Using: /tmp/typedialog-ci (target/debug does not exist)"
cargo clippy --target-dir=/tmp/typedialog-ci --all-targets --all-features -- -D warnings
fi
echo "✓ Lint passed"
# === MULTI-LANGUAGE LINTING ===
# Lint Rust
[doc("Lint Rust (CI)")]
lint-rust:
just dev::lint-rust
# Lint bash scripts
[doc("Lint bash (CI)")]
lint-bash:
just dev::lint-bash
2025-12-18 01:18:59 +00:00
# Lint Nickel files
[doc("Lint Nickel (CI)")]
lint-nickel:
just dev::lint-nickel
# Lint Nushell scripts
[doc("Lint Nushell (CI)")]
lint-nushell:
just dev::lint-nushell
# Lint Markdown
[doc("Lint Markdown (CI)")]
lint-markdown:
just dev::lint-markdown
# Lint all languages (CI)
[doc("Lint all languages (CI)")]
lint-all:
just dev::lint-all
# Check formatting and linting (all languages)
[doc("Check: format + lint (all)")]
2025-12-18 01:18:59 +00:00
check:
just ci::fmt-check
just ci::lint-all
2025-12-18 01:18:59 +00:00
@echo "✓ All checks passed"
# === TEST STAGE ===
# Test all features
[doc("Test all features")]
test-all:
#!/bin/bash
set -e
cd "{{ WORKSPACE_ROOT }}"
echo "=== Testing (all features) ==="
if [ -d "target/debug" ]; then
echo " → Using: target/debug (exists)"
cargo test --workspace --all-features
else
echo " → Using: /tmp/typedialog-ci (target/debug does not exist)"
cargo test --target-dir=/tmp/typedialog-ci --workspace --all-features
fi
echo "✓ All tests passed"
2025-12-18 01:18:59 +00:00
# Test default features
[doc("Test default features")]
test-default:
#!/bin/bash
set -e
cd "{{ WORKSPACE_ROOT }}"
echo "=== Testing (default features) ==="
if [ -d "target/debug" ]; then
echo " → Using: target/debug (exists)"
cargo test --workspace
else
echo " → Using: /tmp/typedialog-ci (target/debug does not exist)"
cargo test --target-dir=/tmp/typedialog-ci --workspace
fi
echo "✓ Tests passed (default features)"
2025-12-18 01:18:59 +00:00
# Test integration only
[doc("Test integration")]
test-integration:
#!/bin/bash
set -e
cd "{{ WORKSPACE_ROOT }}"
echo "=== Testing integration ==="
if [ -d "target/debug" ]; then
echo " → Using: target/debug (exists)"
cargo test --test '*' --all-features
else
echo " → Using: /tmp/typedialog-ci (target/debug does not exist)"
cargo test --target-dir=/tmp/typedialog-ci --test '*' --all-features
fi
echo "✓ Integration tests passed"
2025-12-18 01:18:59 +00:00
# === BUILD STAGE ===
# Debug build (commented out - large disk usage)
# [doc("Build debug")]
# build-debug:
# @echo "=== Building debug ==="
# cargo build --workspace --all-features
# @echo "✓ Debug build complete"
2025-12-18 01:18:59 +00:00
# Release build
[doc("Build release")]
build-release:
@echo "=== Building release (optimized) ==="
cargo build --workspace --all-features --release
@echo ""
@echo "Binaries:"
@ls -lh target/release/typedialog* 2>/dev/null | awk '{printf " %-30s %8s\n", $NF, $5}'
@echo "✓ Release build complete"
# === COMPLIANCE STAGE ===
# Audit dependencies for security issues
[doc("Audit dependencies for vulnerabilities")]
audit:
#!/bin/bash
set -e
echo "=== Auditing dependencies ==="
cd "{{ WORKSPACE_ROOT }}"
2025-12-18 01:18:59 +00:00
# Ensure HOME is set to absolute path, never literal ~
if [ -z "$HOME" ]; then
export HOME="$(getent passwd $(whoami) | cut -d: -f6)"
fi
export CARGO_HOME="${HOME}/.cargo"
# Use explicit --db path to prevent cargo audit from creating literal ~ directory
# This is a workaround for a cargo audit issue with ~ expansion
audit_db="${CARGO_HOME}/advisory-db"
mkdir -p "$audit_db"
if cargo audit --quiet --db "$audit_db" 2>&1 > /dev/null; then
echo "✓ No vulnerabilities found"
else
echo "⚠️ Check failed (run 'cargo audit' manually)"
fi
# cargo-deny check (licenses only, show errors but suppress warnings)
[doc("Check dependencies with cargo-deny")]
deny:
#!/bin/bash
set -e
echo "=== Running cargo-deny ==="
cd "{{ WORKSPACE_ROOT }}"
# Ensure HOME is set to absolute path
if [ -z "$HOME" ]; then
export HOME="$(getent passwd $(whoami) | cut -d: -f6)"
fi
{ cargo deny check licenses 2>&1 | sed '/^warning\[/,/^$$/d' | grep -q "error\[" && cargo deny check licenses 2>&1 | sed '/^warning\[/,/^$$/d' && exit 1; } || echo "✓ No license violations"
# Verify SBOMs can be generated
[doc("Verify SBOMs can be generated")]
2025-12-18 01:18:59 +00:00
verify-sbom:
#!/bin/bash
set -e
echo "=== Verifying SBOMs ==="
echo "Generating SBOMs to verify compliance..."
cd "{{ WORKSPACE_ROOT }}"
# Ensure HOME is set to absolute path
if [ -z "$HOME" ]; then
export HOME="$(getent passwd $(whoami) | cut -d: -f6)"
fi
cargo sbom --output-format spdx_json_2_3 > /tmp/sbom_spdx.json || echo "⚠️ SPDX SBOM generation failed"
cargo sbom --output-format cyclone_dx_json_1_4 > /tmp/sbom_cyclonedx.json || echo "⚠️ CycloneDX SBOM generation failed"
echo "✓ SBOM verification complete"
2025-12-18 01:18:59 +00:00
# === FULL PIPELINE ===
# Complete CI pipeline
[doc("Full CI: check + test + build")]
full:
#!/bin/bash
set -e
# Clean any stray ~ directory from previous runs (created by cargo audit download)
if [ -d "~" ]; then
rm -rf "~"
echo "✓ Cleaned stray ~ directory"
fi
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ TYPEDIALOG CI/CD PIPELINE ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
# Ensure HOME and CARGO_HOME are set to absolute paths (prevents cargo from creating literal ~ directory)
if [ -z "$HOME" ]; then
export HOME="$(getent passwd $(whoami) | cut -d: -f6)"
fi
# Force CARGO_HOME to absolute path to prevent literal ~ directory creation
export CARGO_HOME="${HOME}/.cargo"
# Pre-create CARGO_HOME if it doesn't exist
mkdir -p "$CARGO_HOME"
echo " Using HOME: $HOME"
echo " Using CARGO_HOME: $CARGO_HOME"
echo ""
# Detect if target/debug exists at start
debug_existed=0
if [ -d "target/debug" ]; then
debug_existed=1
echo " target/debug detected - will preserve after CI"
fi
echo ""
echo "=== Stage 1: Validation ==="
just ci::fmt-check
just ci::lint-all
echo ""
echo "=== Stage 2: Compliance ==="
2025-12-18 01:18:59 +00:00
just ci::verify-sbom
just ci::audit
just ci::deny
echo ""
echo "=== Stage 3: Testing ==="
2025-12-18 01:18:59 +00:00
just ci::test-all
echo ""
echo "=== Stage 4: Build Release ==="
2025-12-18 01:18:59 +00:00
just ci::build-release
echo ""
echo "=== Cleanup ==="
if [ $debug_existed -eq 0 ] && [ -d "/tmp/typedialog-ci" ]; then
rm -rf /tmp/typedialog-ci
echo "✓ Temporary artifacts cleaned"
else
if [ $debug_existed -eq 1 ]; then
echo "✓ Preserving target/debug (already existed)"
fi
if [ -d "/tmp/typedialog-ci" ]; then
echo "✓ Temporary CI directory left in place"
fi
fi
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ CI PIPELINE COMPLETE ✓ ║"
echo "╚═══════════════════════════════════════════════════════════╝"