# CI/CD Just Recipes
# Generated by dev-system/ci - Dynamic template
# Provides `just` recipes for running CI checks locally
# Based on detected languages and enabled tools

# Run all CI checks
ci-full: ci-lint-rust ci-fmt-toml ci-lint-toml ci-lint-nushell ci-lint-nickel ci-lint-bash ci-lint-markdown ci-lint-prose ci-test ci-audit
    @echo "✅ All CI checks passed!"

# ==============================================================================
# Formatting Checks
# ==============================================================================

# Check Rust code formatting (excludes nu_plugins which are maintained separately)
ci-fmt-check:
    #!/usr/bin/env bash
    echo "📝 Checking Rust code formatting..."
    REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
    FOUND=0
    FAILED=0

    for cargo_file in $(find "$REPO_ROOT" -name "Cargo.toml" -type f ! -path "*/target/*" ! -path "*/.git/*" ! -path "*/plugins/nushell-plugins/*"); do
        project_dir=$(dirname "$cargo_file")
        project_name=$(basename "$project_dir")
        echo "  Checking: $project_name"
        (cd "$project_dir" && cargo +nightly fmt --all -- --check) || FAILED=$((FAILED+1))
        FOUND=$((FOUND+1))
    done

    if [ $FOUND -eq 0 ]; then
        echo "  ℹ️  No Rust projects found (nu_plugins are excluded)"
        exit 0
    fi

    if [ $FAILED -eq 0 ]; then
        echo "  ✓ All Rust projects formatted correctly"
        exit 0
    else
        echo "  ❌ $FAILED project(s) have formatting issues"
        exit 1
    fi
ci-fmt:
    #!/usr/bin/env bash
    echo "📝 Checking Rust code formatting..."
    REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
    FOUND=0
    FAILED=0

    for cargo_file in $(find "$REPO_ROOT" -name "Cargo.toml" -type f ! -path "*/target/*" ! -path "*/.git/*" ! -path "*/plugins/nushell-plugins/*"); do
        project_dir=$(dirname "$cargo_file")
        project_name=$(basename "$project_dir")
        echo "  Checking: $project_name"
        # (cd "$project_dir" && cargo +nightly fmt --all -- --check) || FAILED=$((FAILED+1))
        (cd "$project_dir" && cargo +nightly fmt --all) || FAILED=$((FAILED+1))
        FOUND=$((FOUND+1))
    done

    if [ $FOUND -eq 0 ]; then
        echo "  ℹ️  No Rust projects found (nu_plugins are excluded)"
        exit 0
    fi

    if [ $FAILED -eq 0 ]; then
        echo "  ✓ All Rust projects formatted correctly"
        exit 0
    else
        echo "  ❌ $FAILED project(s) have formatting issues"
        exit 1
    fi
# Check TOML file formatting
ci-fmt-toml:
    @echo "📝 Checking TOML formatting..."
    @command -v taplo >/dev/null || (echo "❌ taplo not installed: cargo install taplo-cli"; exit 1)
    taplo format --check


# Format all code (excludes nu_plugins which are maintained separately)
fmt:
    #!/usr/bin/env bash
    echo "🎨 Formatting Rust code..."
    REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
    FOUND=0
    FAILED=0

    for cargo_file in $(find "$REPO_ROOT" -name "Cargo.toml" -type f ! -path "*/target/*" ! -path "*/.git/*" ! -path "*/plugins/nushell-plugins/*"); do
        project_dir=$(dirname "$cargo_file")
        project_name=$(basename "$project_dir")
        echo "  Formatting: $project_name"
        (cd "$project_dir" && cargo +nightly fmt --all) || FAILED=$((FAILED+1))
        FOUND=$((FOUND+1))
    done

    if [ $FOUND -eq 0 ]; then
        echo "  ℹ️  No Rust projects found (nu_plugins are excluded)"
    else
        if [ $FAILED -eq 0 ]; then
            echo "  ✓ All Rust projects formatted"
        else
            echo "  ❌ $FAILED project(s) failed formatting"
            exit 1
        fi
    fi

    echo ""
    just fmt-toml

# Format TOML files
fmt-toml:
    @echo "🎨 Formatting TOML files..."
    @command -v taplo >/dev/null || (echo "❌ taplo not installed: cargo install taplo-cli"; exit 1)
    taplo format
# ==============================================================================
# Linting
# ==============================================================================

# Run all linting checks
ci-lint: ci-lint-rust ci-lint-toml ci-lint-nushell ci-lint-nickel ci-lint-bash ci-lint-markdown ci-lint-prose
    @echo "✅ All lint checks passed!"

# Lint Rust code (excludes nu_plugins which are maintained separately)
ci-lint-rust:
    #!/usr/bin/env bash
    echo "🔍 Linting Rust (clippy)..."
    REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
    FOUND=0
    FAILED=0

    for cargo_file in $(find "$REPO_ROOT" -name "Cargo.toml" -type f ! -path "*/target/*" ! -path "*/.git/*" ! -path "*/plugins/nushell-plugins/*"); do
        project_dir=$(dirname "$cargo_file")
        project_name=$(basename "$project_dir")
        echo "  Linting: $project_name"
        (cd "$project_dir" && cargo clippy --all-targets --all-features -- -D warnings) || FAILED=$((FAILED+1))
        FOUND=$((FOUND+1))
    done

    if [ $FOUND -eq 0 ]; then
        echo "  ℹ️  No Rust projects found (nu_plugins are excluded)"
        exit 0
    fi

    if [ $FAILED -eq 0 ]; then
        echo "  ✓ All Rust projects passed clippy"
        exit 0
    else
        echo "  ❌ $FAILED project(s) have clippy warnings"
        exit 1
    fi
# Lint TOML files (excluding .wrks, .coder, .claude, .project-tools directories)
ci-lint-toml:
    @echo "🔍 Linting TOML files..."
    @command -v taplo >/dev/null || (echo "❌ taplo not installed: cargo install taplo-cli"; exit 1)
    fd -t f '\.toml$' --exclude '.wrks' --exclude '.coder' --exclude '.claude' --exclude '.project-tools' | \
        xargs taplo lint
# Lint Nushell scripts
ci-lint-nushell:
    #!/usr/bin/env bash
    echo "🔍 Validating Nushell scripts..."
    SCRIPTS=$(find . -name "*.nu" -type f \
      ! -path "./target/*" \
      ! -path "./.git/*" \
      ! -path "./node_modules/*" \
      | head -20)
    if [ -z "$SCRIPTS" ]; then
        echo "  ℹ️  No Nushell scripts found"
        exit 0
    fi
    for script in $SCRIPTS; do
        echo "  Checking: $script"
        nu --ide-check 100 "$script" || exit 1
    done
    echo "  ✓ All Nushell scripts valid"
# Lint Nickel schemas
ci-lint-nickel:
    #!/usr/bin/env bash
    echo "🔍 Type checking Nickel..."
    SCHEMAS=$(find . -name "*.ncl" -type f \
      ! -path "./target/*" \
      ! -path "./.git/*" \
      ! -path "./.coder/*" \
      ! -path "./.wrks/*" \
      ! -path "./.claude/*" \
      ! -path "./.project-tools/*" \
      ! -path "./node_modules/*" \
      | head -50)
    if [ -z "$SCHEMAS" ]; then
        echo "  ℹ️  No Nickel schemas found"
        exit 0
    fi

    # If NICKEL_IMPORT_PATH not set, construct from relative paths
    if [ -z "$NICKEL_IMPORT_PATH" ]; then
        IMPORT_PATHS="."
        # Add local typedialog schemas if they exist
        [ -d ".typedialog/provisioning/schemas" ] && IMPORT_PATHS="$IMPORT_PATHS:.typedialog/provisioning/schemas"
        [ -d ".typedialog/provisioning/validators" ] && IMPORT_PATHS="$IMPORT_PATHS:.typedialog/provisioning/validators"
        [ -d ".typedialog/provisioning/defaults" ] && IMPORT_PATHS="$IMPORT_PATHS:.typedialog/provisioning/defaults"
        [ -d "schemas" ] && IMPORT_PATHS="$IMPORT_PATHS:schemas"
        export NICKEL_IMPORT_PATH="$IMPORT_PATHS"
        echo "  ℹ️  Using NICKEL_IMPORT_PATH: $NICKEL_IMPORT_PATH"
    fi

    for schema in $SCHEMAS; do
        echo "  Checking: $schema"
        nickel typecheck "$schema" || exit 1
    done
    echo "  ✓ All Nickel schemas valid"
# Lint Bash scripts
ci-lint-bash:
    #!/usr/bin/env bash
    echo "🔍 Linting Bash scripts..."
    SCRIPTS=$(find . -name "*.sh" -o -name "*.bash" \
      ! -path "*/target/*" \
      ! -path "*/.git/*" \
      ! -path "*/.coder/*" \
      ! -path "*/.wrks/*" \
      ! -path "*/.claude/*" \
      ! -path "*/.project-tools/*" \
      ! -path "*/node_modules/*" \
      | head -50)
    if [ -z "$SCRIPTS" ]; then
        echo "  ℹ️  No Bash scripts found"
        exit 0
    fi
    for script in $SCRIPTS; do
        echo "  Checking: $script"
        shellcheck "$script" || exit 1
    done
    echo "  ✓ All Bash scripts valid"
# Lint Markdown files
ci-lint-markdown:
    @echo "🔍 Linting Markdown files (excluding generated/build directories)..."
    @command -v markdownlint-cli2 >/dev/null || (echo "❌ markdownlint-cli2 not installed: npm install markdownlint-cli2"; exit 1)
    markdownlint-cli2 "**/*.md" "#node_modules" "#.git" "#.typedialog" "#.coder" "#.wrks" "#.claude" "#.project-tools" "#target" "#dist" "#build"
# Lint prose/documentation
ci-lint-prose:
    #!/usr/bin/env bash
    echo "🔍 Linting prose with Vale (excluding generated directories)..."
    command -v vale >/dev/null || (echo "❌ vale not installed: brew install vale"; exit 1)
    vale sync
    # Lint markdown files in docs directories only (excluding generated/archived directories)
    timeout 60 find . -name "*.md" \
      ! -path "*/target/*" \
      ! -path "*/.git/*" \
      ! -path "*/.coder/*" \
      ! -path "*/.wrks/*" \
      ! -path "*/.claude/*" \
      ! -path "*/.project-tools/*" \
      ! -path "*/.typedialog/*" \
      ! -path "*/node_modules/*" \
      ! -path "*/dist/*" \
      ! -path "*/build/*" \
      -print0 | xargs -0 -r timeout 30 vale --no-wrap . || true
    echo "  ✓ Prose linting completed"



# ==============================================================================
# Testing
# ==============================================================================

# Run all tests (excludes nu_plugins which are maintained separately)
ci-test:
    #!/usr/bin/env bash
    echo "🧪 Running tests..."
    REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
    FOUND=0
    FAILED=0

    for cargo_file in $(find "$REPO_ROOT" -name "Cargo.toml" -type f ! -path "*/target/*" ! -path "*/.git/*" ! -path "*/plugins/nushell-plugins/*"); do
        project_dir=$(dirname "$cargo_file")
        project_name=$(basename "$project_dir")
        echo "  Testing: $project_name"
        (cd "$project_dir" && cargo test --all-features) || FAILED=$((FAILED+1))
        FOUND=$((FOUND+1))
    done

    if [ $FOUND -eq 0 ]; then
        echo "  ℹ️  No Rust projects found (nu_plugins are excluded)"
        exit 0
    fi

    if [ $FAILED -eq 0 ]; then
        echo "  ✓ All tests passed"
        exit 0
    else
        echo "  ❌ $FAILED project(s) have test failures"
        exit 1
    fi

# Run tests with coverage (requires cargo-llvm-cov; excludes nu_plugins)
ci-test-coverage:
    #!/usr/bin/env bash
    echo "📊 Running tests with coverage..."
    REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
    FOUND=0
    FAILED=0

    for cargo_file in $(find "$REPO_ROOT" -name "Cargo.toml" -type f ! -path "*/target/*" ! -path "*/.git/*" ! -path "*/plugins/nushell-plugins/*"); do
        project_dir=$(dirname "$cargo_file")
        project_name=$(basename "$project_dir")
        echo "  Coverage: $project_name"
        (cd "$project_dir" && cargo llvm-cov --all-features --lcov --output-path lcov.info) || FAILED=$((FAILED+1))
        FOUND=$((FOUND+1))
    done

    if [ $FOUND -eq 0 ]; then
        echo "  ℹ️  No Rust projects found (nu_plugins are excluded)"
        exit 0
    fi

    if [ $FAILED -eq 0 ]; then
        echo "  ✓ Coverage reports generated"
        exit 0
    else
        echo "  ❌ $FAILED project(s) failed coverage"
        exit 1
    fi



# ==============================================================================
# Security Auditing
# ==============================================================================

# Run all security audits
ci-audit: ci-audit-rust
    @echo "✅ All security audits passed!"

# Audit Rust dependencies (excludes nu_plugins which are maintained separately)
ci-audit-rust:
    #!/usr/bin/env bash
    echo "🔒 Auditing Rust dependencies..."
    REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
    FOUND=0
    FAILED=0

    for cargo_file in $(find "$REPO_ROOT" -name "Cargo.toml" -type f ! -path "*/target/*" ! -path "*/.git/*" ! -path "*/plugins/nushell-plugins/*"); do
        project_dir=$(dirname "$cargo_file")
        project_name=$(basename "$project_dir")
        echo "  Auditing: $project_name"
        (cd "$project_dir" && cargo audit && cargo deny check licenses && cargo deny check advisories) || FAILED=$((FAILED+1))
        FOUND=$((FOUND+1))
    done

    if [ $FOUND -eq 0 ]; then
        echo "  ℹ️  No Rust projects found (nu_plugins are excluded)"
        exit 0
    fi

    if [ $FAILED -eq 0 ]; then
        echo "  ✓ All security audits passed"
        exit 0
    else
        echo "  ❌ $FAILED project(s) have security issues"
        exit 1
    fi

# Generate SBOM (excludes nu_plugins which are maintained separately)
ci-sbom:
    #!/usr/bin/env bash
    echo "📦 Generating Software Bill of Materials..."
    REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
    FOUND=0
    FAILED=0

    for cargo_file in $(find "$REPO_ROOT" -name "Cargo.toml" -type f ! -path "*/target/*" ! -path "*/.git/*" ! -path "*/plugins/nushell-plugins/*"); do
        project_dir=$(dirname "$cargo_file")
        project_name=$(basename "$project_dir")
        sbom_file="$project_dir/sbom-$project_name.json"
        echo "  Generating SBOM: $project_name"
        (cd "$project_dir" && cargo sbom > "$sbom_file") || FAILED=$((FAILED+1))
        FOUND=$((FOUND+1))
    done

    if [ $FOUND -eq 0 ]; then
        echo "  ℹ️  No Rust projects found (nu_plugins are excluded)"
        exit 0
    fi

    if [ $FAILED -eq 0 ]; then
        echo "  ✓ SBOM files generated"
        exit 0
    else
        echo "  ❌ $FAILED project(s) failed SBOM generation"
        exit 1
    fi

# ==============================================================================
# Documentation
# ==============================================================================

# Check documentation (excludes nu_plugins which are maintained separately)
ci-docs:
    #!/usr/bin/env bash
    echo "📚 Checking documentation..."
    REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
    FOUND=0
    FAILED=0

    for cargo_file in $(find "$REPO_ROOT" -name "Cargo.toml" -type f ! -path "*/target/*" ! -path "*/.git/*" ! -path "*/plugins/nushell-plugins/*"); do
        project_dir=$(dirname "$cargo_file")
        project_name=$(basename "$project_dir")
        echo "  Checking docs: $project_name"
        (cd "$project_dir" && cargo doc --no-deps --document-private-items 2>&1 | grep -i "warning:" && FAILED=$((FAILED+1)) || true)
        FOUND=$((FOUND+1))
    done

    if [ $FOUND -eq 0 ]; then
        echo "  ℹ️  No Rust projects found (nu_plugins are excluded)"
        exit 0
    fi

    if [ $FAILED -eq 0 ]; then
        echo "  ✓ Documentation check passed"
        exit 0
    else
        echo "  ❌ $FAILED project(s) have doc warnings"
        exit 1
    fi

# ==============================================================================
# Pre-commit Setup
# ==============================================================================

# Install pre-commit hooks
setup-hooks:
    @echo "🪝 Installing pre-commit hooks..."
    @if command -v pre-commit &> /dev/null; then \
        pre-commit install && pre-commit install --hook-type pre-push; \
        echo "✓ Pre-commit hooks installed"; \
    else \
        echo "❌ pre-commit not found. Install with: pip install pre-commit"; \
        exit 1; \
    fi

# Run pre-commit on all files
hooks-run-all:
    @echo "🪝 Running pre-commit on all files..."
    pre-commit run --all-files

# ==============================================================================
# Utility Commands
# ==============================================================================

# Note: Use `just clean` from main justfile for full cleanup
