446 lines
16 KiB
Plaintext
446 lines
16 KiB
Plaintext
|
|
# 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
|