2025-12-24 03:24:31 +00:00

302 lines
9.6 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ╔══════════════════════════════════════════════════════════════════════╗
# ║ CI/CD RECIPES ║
# ║ Validation and deployment tasks ║
# ╚══════════════════════════════════════════════════════════════════════╝
# Workspace root directory
WORKSPACE_ROOT := justfile_directory()
# 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"
@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
@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
# 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)")]
check:
just ci::fmt-check
just ci::lint-all
@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"
# 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)"
# 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"
# === 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"
# 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 }}"
# 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")]
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"
# === 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 ==="
just ci::verify-sbom
just ci::audit
just ci::deny
echo ""
echo "=== Stage 3: Testing ==="
just ci::test-all
echo ""
echo "=== Stage 4: Build Release ==="
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 "╚═══════════════════════════════════════════════════════════╝"