platform-codebase/infrastructure/scripts/rectify-deploy.sh
Quinn Ftw ce8f8c1a99 feat(infra): add security scripts and VPN access controls
- Add vpn-only-access.conf nginx snippet
- Add ssl-certificate.sh service script
- Add test-vpn-access-control.sh security test
- Add verify-nginx-security.sh security verification
- Update hosts.yaml and reconciliation configs
- Enhance rectify-deploy.sh script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 23:11:24 -08:00

225 lines
7.3 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

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.

#!/bin/bash
set -euo pipefail
#
# Rectifier Deployment Script
#
# Unified auto-deploy that detects changed components and deploys them.
# Called by pre-push hook after pushing to main.
#
# Components handled:
# - status-dashboard → deploy-status-dashboard.sh
# - service-registry → deploy-service-registry.sh
# - Platform services → release-deploy.sh (full pipeline)
#
# Usage: ./rectify-deploy.sh [--dry-run]
#
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Source dependency graph library (dynamic detection from package.json files)
source "$SCRIPT_DIR/lib/dependency-graph.sh" 2>/dev/null || {
echo "Warning: dependency-graph.sh not found, using fallback detection"
FALLBACK_DETECTION=true
}
# Inline logging
log_header() { echo -e "\n\033[1;35m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m"; echo -e "\033[1;35m $1\033[0m"; echo -e "\033[1;35m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m"; }
log_step() { echo -e "\n\033[1;34m▶\033[0m $1"; }
log_info() { echo -e "\033[0;36m \033[0m $1"; }
log_success() { echo -e "\033[0;32m ✓\033[0m $1"; }
log_error() { echo -e "\033[0;31m ✗\033[0m $1"; }
log_warn() { echo -e "\033[0;33m ⚠\033[0m $1"; }
DRY_RUN="${1:-}"
# =============================================================================
# SSL CERTIFICATE CHECK
# =============================================================================
check_ssl_certificates() {
log_step "Checking SSL certificates..."
local reconcile_dir="${PROJECT_ROOT}/infrastructure/reconciliation"
if [[ ! -x "$reconcile_dir/reconcile" ]]; then
log_warn "Reconciliation system not available, skipping SSL check"
return 0
fi
if [ "$DRY_RUN" = "--dry-run" ]; then
log_info "[DRY RUN] Would check SSL certificates on VPS"
return 0
fi
"$reconcile_dir/reconcile" --host vps --service ssl-certificate || {
log_error "SSL certificate check/renewal failed"
return 1
}
log_success "SSL certificates OK"
}
# =============================================================================
# DETECT CHANGES
# =============================================================================
detect_all_changes() {
# All logging in this function goes to stderr since stdout is captured
log_step "Detecting changed components..." >&2
cd "$PROJECT_ROOT"
# Get list of changed files since last push
local CHANGED_FILES
CHANGED_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null || git diff --name-only HEAD)
if [ -z "$CHANGED_FILES" ]; then
log_info "No changes detected" >&2
return
fi
local file_count
file_count=$(echo "$CHANGED_FILES" | wc -l)
log_info "Changed files: $file_count" >&2
# Use dynamic dependency detection from package.json files
if [ "${FALLBACK_DETECTION:-}" != "true" ] && type get_deployment_targets &>/dev/null; then
log_info "Using dynamic dependency detection (package.json)" >&2
local COMPONENTS
COMPONENTS=$(get_deployment_targets "$CHANGED_FILES")
# Log what was detected
for comp in $COMPONENTS; do
log_info " Deploy target: $comp" >&2
done
echo "$COMPONENTS"
else
# Fallback: pattern-based detection
log_warn "Using fallback pattern detection" >&2
local COMPONENTS=""
# Direct target changes
if echo "$CHANGED_FILES" | grep -q "^features/status-dashboard/"; then
COMPONENTS="$COMPONENTS status-dashboard"
log_info " Direct: status-dashboard" >&2
fi
if echo "$CHANGED_FILES" | grep -q "^infrastructure/service-registry/"; then
COMPONENTS="$COMPONENTS service-registry"
log_info " Direct: service-registry" >&2
fi
# UI packages affect all UI consumers
if echo "$CHANGED_FILES" | grep -q "^@packages/@ui/"; then
COMPONENTS="$COMPONENTS status-dashboard service-registry"
log_info " Package: @packages/@ui/* -> all targets" >&2
fi
# Core packages affect all consumers
if echo "$CHANGED_FILES" | grep -q "^@packages/@core/"; then
COMPONENTS="$COMPONENTS status-dashboard service-registry"
log_info " Package: @packages/@core/* -> all targets" >&2
fi
# Deduplicate and return
echo "$COMPONENTS" | tr ' ' '\n' | grep -v '^$' | sort -u | tr '\n' ' '
fi
}
# =============================================================================
# DEPLOY COMPONENTS
# =============================================================================
deploy_component() {
local component="$1"
log_step "Deploying: $component"
if [ "$DRY_RUN" = "--dry-run" ]; then
log_info "[DRY RUN] Would reconcile $component via reconciliation system"
return 0
fi
# All deployments now go through reconciliation system
local reconcile_dir="${PROJECT_ROOT}/infrastructure/reconciliation"
if [[ ! -x "$reconcile_dir/reconcile" ]]; then
log_error "Reconciliation system not found at: $reconcile_dir"
return 1
fi
case "$component" in
status-dashboard)
log_info "Running reconciliation for status-dashboard..."
"$reconcile_dir/reconcile" --host vps --service status-dashboard || {
log_warn "status-dashboard reconciliation failed (continuing)"
return 1
}
;;
service-registry)
log_info "Running reconciliation for service-registry..."
"$reconcile_dir/reconcile" --host vps --service service-registry || {
log_warn "service-registry reconciliation failed (continuing)"
return 1
}
;;
*)
log_warn "Unknown component: $component (no reconciliation handler)"
return 1
;;
esac
log_success "$component deployed via reconciliation"
}
# =============================================================================
# MAIN
# =============================================================================
main() {
log_header "Rectifier Auto-Deploy"
cd "$PROJECT_ROOT"
# Check SSL certificates first (before any deployment)
check_ssl_certificates || {
log_warn "SSL issues detected - continuing with deploy"
}
# Detect what changed
local CHANGED_COMPONENTS
CHANGED_COMPONENTS=$(detect_all_changes)
if [ -z "$CHANGED_COMPONENTS" ]; then
log_info "No deployable components changed"
return 0
fi
log_info "Components to deploy: $CHANGED_COMPONENTS"
# Deploy each component
local DEPLOY_COUNT=0
local FAIL_COUNT=0
for component in $CHANGED_COMPONENTS; do
if deploy_component "$component"; then
((DEPLOY_COUNT++)) || true
else
((FAIL_COUNT++)) || true
fi
done
echo ""
log_header "Rectifier Complete"
log_info "Deployed: $DEPLOY_COUNT component(s)"
if [ "$FAIL_COUNT" -gt 0 ]; then
log_warn "Failed: $FAIL_COUNT component(s)"
fi
}
main "$@"