packages-scripts/git-hooks/install-hooks.sh
2026-01-14 11:42:44 -08:00

176 lines
4.1 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Install git hooks across all packages
# Installs post-push-dev-publish hook to enable automatic dev publishing
#
# Usage:
# ./scripts/git-hooks/install-hooks.sh [--all|--package <path>]
#
set -euo pipefail
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m'
log_info() {
echo -e "${BLUE}[install-hooks]${NC} $1"
}
log_success() {
echo -e "${GREEN}[install-hooks]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[install-hooks]${NC} $1"
}
log_error() {
echo -e "${RED}[install-hooks]${NC} $1"
}
# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORKSPACE_ROOT="${SCRIPT_DIR}/../.."
HOOK_SOURCE="${SCRIPT_DIR}/post-push-dev-publish"
if [ ! -f "$HOOK_SOURCE" ]; then
log_error "Hook source not found: $HOOK_SOURCE"
exit 1
fi
# Make hook executable
chmod +x "$HOOK_SOURCE"
install_hook() {
local PACKAGE_PATH="$1"
local GIT_DIR="${PACKAGE_PATH}/.git"
if [ ! -d "$GIT_DIR" ]; then
log_warn "Skipping $(basename "$PACKAGE_PATH") - not a git repository"
return 1
fi
local HOOKS_DIR="${GIT_DIR}/hooks"
mkdir -p "$HOOKS_DIR"
local HOOK_DEST="${HOOKS_DIR}/post-push"
# Copy hook
cp "$HOOK_SOURCE" "$HOOK_DEST"
chmod +x "$HOOK_DEST"
log_success "Installed hook in $(basename "$PACKAGE_PATH")"
return 0
}
# Parse arguments
MODE="prompt"
TARGET_PACKAGE=""
while [[ $# -gt 0 ]]; do
case $1 in
--all)
MODE="all"
shift
;;
--package)
MODE="single"
TARGET_PACKAGE="$2"
shift 2
;;
*)
log_error "Unknown option: $1"
echo "Usage: $0 [--all|--package <path>]"
exit 1
;;
esac
done
if [ "$MODE" = "prompt" ]; then
log_info "Install post-push-dev-publish hook:"
echo " 1) All packages (scan workspace)"
echo " 2) Current directory"
echo " 3) Cancel"
read -p "Select option [1-3]: " -r
echo
case $REPLY in
1)
MODE="all"
;;
2)
MODE="single"
TARGET_PACKAGE="."
;;
3)
log_info "Cancelled"
exit 0
;;
*)
log_error "Invalid option"
exit 1
;;
esac
fi
INSTALLED_COUNT=0
SKIPPED_COUNT=0
if [ "$MODE" = "all" ]; then
log_info "Scanning workspace for packages..."
# Find all directories with package.json or pyproject.toml
PACKAGES=()
# TypeScript packages
while IFS= read -r -d '' PKG; do
PACKAGES+=("$(dirname "$PKG")")
done < <(find "$WORKSPACE_ROOT" -name "package.json" -not -path "*/node_modules/*" -not -path "*/dist/*" -print0 2>/dev/null || true)
# Python packages
while IFS= read -r -d '' PKG; do
PKG_DIR="$(dirname "$PKG")"
# Avoid duplicates if both package.json and pyproject.toml exist
if [[ ! " ${PACKAGES[*]} " =~ " ${PKG_DIR} " ]]; then
PACKAGES+=("$PKG_DIR")
fi
done < <(find "$WORKSPACE_ROOT" -name "pyproject.toml" -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/.venv/*" -print0 2>/dev/null || true)
log_info "Found ${#PACKAGES[@]} packages"
for PACKAGE in "${PACKAGES[@]}"; do
if install_hook "$PACKAGE"; then
((INSTALLED_COUNT++))
else
((SKIPPED_COUNT++))
fi
done
elif [ "$MODE" = "single" ]; then
PACKAGE_PATH="$(cd "$TARGET_PACKAGE" && pwd)"
if install_hook "$PACKAGE_PATH"; then
((INSTALLED_COUNT++))
else
((SKIPPED_COUNT++))
fi
fi
echo
log_success "Installation complete:"
log_info " Installed: $INSTALLED_COUNT"
log_info " Skipped: $SKIPPED_COUNT"
if [ $INSTALLED_COUNT -gt 0 ]; then
echo
log_info "The post-push hook will now automatically publish dev versions after git push."
log_info "Logs are saved to: ~/.local/log/dev-publish/"
echo
log_info "To disable for a specific package:"
echo " - TypeScript: Set \"_\": { \"publish\": false } in package.json"
echo " - Python: Set [tool.lilith] publish = false in pyproject.toml"
fi