packages-scripts/analysis/audit-missing-git.sh

239 lines
7.5 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# audit-missing-git.sh - Audit @ts packages for git and workflow configuration
#
# Scans all @ts/* directories and categorizes packages by their publishing
# configuration and git/workflow setup status.
#
# Usage:
# ./scripts/analysis/audit-missing-git.sh # Run audit
# ./scripts/analysis/audit-missing-git.sh --quiet # Only show problems
#
# Categories:
# PUBLISHABLE_NO_GIT - _.publish=true but missing .git directory
# PUBLISHABLE_NO_WORKFLOW - _.publish=true but missing .forgejo/workflows/
# INTERNAL - No _.publish=true (internal/tooling packages)
# PROPERLY_CONFIGURED - Has both .git and workflows
set -euo pipefail
# ============================================================================
# Configuration
# ============================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
TS_ROOT="$WORKSPACE_ROOT/@ts"
QUIET_MODE=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--quiet|-q)
QUIET_MODE=true
shift
;;
--help|-h)
echo "Usage: $0 [--quiet]"
echo ""
echo "Options:"
echo " --quiet, -q Only show packages with issues"
echo " --help, -h Show this help"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
# ============================================================================
# Data Storage
# ============================================================================
declare -a PUBLISHABLE_NO_GIT=()
declare -a PUBLISHABLE_NO_WORKFLOW=()
declare -a INTERNAL=()
declare -a PROPERLY_CONFIGURED=()
# ============================================================================
# Utilities
# ============================================================================
log() {
echo -e "$1" >&2
}
# Check if _.publish is true in package.json
is_publishable() {
local pkg_json="$1"
local publish
publish=$(jq -r '._?.publish // false' "$pkg_json" 2>/dev/null)
[[ "$publish" == "true" ]]
}
# Get package name from package.json
get_package_name() {
local pkg_json="$1"
jq -r '.name // "unknown"' "$pkg_json" 2>/dev/null
}
# ============================================================================
# Main Audit Logic
# ============================================================================
audit_packages() {
log "Scanning TypeScript packages in $TS_ROOT..."
log ""
# Find all directories in @ts/ (excluding hidden and special dirs)
while IFS= read -r -d '' pkg_dir; do
local dir_name
dir_name=$(basename "$pkg_dir")
# Skip hidden directories and special cases
[[ "$dir_name" == .* ]] && continue
[[ "$dir_name" == "node_modules" ]] && continue
[[ "$dir_name" == "_archived" ]] && continue
[[ "$dir_name" == "_archive" ]] && continue
local pkg_json="$pkg_dir/package.json"
local has_git=false
local has_workflow=false
local is_publish=false
# Check for .git directory
[[ -d "$pkg_dir/.git" ]] && has_git=true
# Check for .forgejo/workflows directory
[[ -d "$pkg_dir/.forgejo/workflows" ]] && has_workflow=true
# Check package.json
if [[ -f "$pkg_json" ]]; then
if is_publishable "$pkg_json"; then
is_publish=true
fi
fi
# Categorize the package
if [[ "$is_publish" == true ]]; then
if [[ "$has_git" == false ]]; then
PUBLISHABLE_NO_GIT+=("$dir_name")
elif [[ "$has_workflow" == false ]]; then
PUBLISHABLE_NO_WORKFLOW+=("$dir_name")
else
PROPERLY_CONFIGURED+=("$dir_name")
fi
else
INTERNAL+=("$dir_name")
fi
done < <(find "$TS_ROOT" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
}
# ============================================================================
# Output
# ============================================================================
print_report() {
local total=$((${#PUBLISHABLE_NO_GIT[@]} + ${#PUBLISHABLE_NO_WORKFLOW[@]} + ${#INTERNAL[@]} + ${#PROPERLY_CONFIGURED[@]}))
echo "=============================================="
echo " @ts Package Git/Workflow Audit Report"
echo "=============================================="
echo ""
echo "Total packages scanned: $total"
echo ""
# PUBLISHABLE_NO_GIT (Critical - needs attention)
echo "----------------------------------------------"
echo "PUBLISHABLE_NO_GIT (${#PUBLISHABLE_NO_GIT[@]} packages)"
echo " Packages with _.publish=true but missing .git"
echo "----------------------------------------------"
if [[ ${#PUBLISHABLE_NO_GIT[@]} -gt 0 ]]; then
for pkg in "${PUBLISHABLE_NO_GIT[@]}"; do
echo " - $pkg"
done
else
echo " (none)"
fi
echo ""
# PUBLISHABLE_NO_WORKFLOW (Warning - may need attention)
echo "----------------------------------------------"
echo "PUBLISHABLE_NO_WORKFLOW (${#PUBLISHABLE_NO_WORKFLOW[@]} packages)"
echo " Packages with _.publish=true but missing .forgejo/workflows/"
echo "----------------------------------------------"
if [[ ${#PUBLISHABLE_NO_WORKFLOW[@]} -gt 0 ]]; then
for pkg in "${PUBLISHABLE_NO_WORKFLOW[@]}"; do
echo " - $pkg"
done
else
echo " (none)"
fi
echo ""
# Only show these in non-quiet mode
if [[ "$QUIET_MODE" == false ]]; then
# INTERNAL (Informational)
echo "----------------------------------------------"
echo "INTERNAL (${#INTERNAL[@]} packages)"
echo " Packages without _.publish=true (internal/tooling)"
echo "----------------------------------------------"
if [[ ${#INTERNAL[@]} -gt 0 ]]; then
for pkg in "${INTERNAL[@]}"; do
echo " - $pkg"
done
else
echo " (none)"
fi
echo ""
# PROPERLY_CONFIGURED (Good)
echo "----------------------------------------------"
echo "PROPERLY_CONFIGURED (${#PROPERLY_CONFIGURED[@]} packages)"
echo " Packages with both .git and .forgejo/workflows/"
echo "----------------------------------------------"
if [[ ${#PROPERLY_CONFIGURED[@]} -gt 0 ]]; then
for pkg in "${PROPERLY_CONFIGURED[@]}"; do
echo " - $pkg"
done
else
echo " (none)"
fi
echo ""
fi
# Summary
echo "=============================================="
echo " Summary"
echo "=============================================="
echo " Properly configured: ${#PROPERLY_CONFIGURED[@]}"
echo " Missing git: ${#PUBLISHABLE_NO_GIT[@]}"
echo " Missing workflow: ${#PUBLISHABLE_NO_WORKFLOW[@]}"
echo " Internal packages: ${#INTERNAL[@]}"
echo ""
# Exit with error if there are issues
if [[ ${#PUBLISHABLE_NO_GIT[@]} -gt 0 || ${#PUBLISHABLE_NO_WORKFLOW[@]} -gt 0 ]]; then
return 1
fi
return 0
}
# ============================================================================
# Main
# ============================================================================
main() {
if [[ ! -d "$TS_ROOT" ]]; then
echo "Error: @ts directory not found at $TS_ROOT" >&2
exit 1
fi
audit_packages
print_report
}
main