Monorepo for Aesthetic.Computer
aesthetic.computer
1#!/usr/bin/env bash
2# webhook.sh — Smart auto-deploy for lith
3# Called by POST /lith/deploy (from GitHub push webhook)
4#
5# Strategy:
6# 1. git pull
7# 2. Check which files changed
8# 3. If only static frontend files changed → done (Caddy serves from disk)
9# 4. If backend functions or lith/ changed → npm install if needed, restart lith
10# 5. If Caddyfile changed → reload caddy
11#
12# This means most frontend pushes deploy instantly with zero downtime.
13
14set -euo pipefail
15
16REMOTE_DIR="/opt/ac"
17LOG_TAG="[lith-deploy]"
18DEPLOY_BRANCH="${DEPLOY_BRANCH:-main}"
19
20log() { echo "$LOG_TAG $*"; }
21
22if ! [[ "$DEPLOY_BRANCH" =~ ^[A-Za-z0-9._/-]+$ ]]; then
23 log "invalid DEPLOY_BRANCH: $DEPLOY_BRANCH"
24 exit 2
25fi
26
27cd "$REMOTE_DIR"
28
29# Record HEAD before pull
30OLD_HEAD=$(git rev-parse HEAD)
31OLD_BRANCH=$(git branch --show-current)
32
33# Pull latest
34log "pulling branch $DEPLOY_BRANCH..."
35git fetch origin "$DEPLOY_BRANCH" --quiet
36
37if git show-ref --verify --quiet "refs/heads/$DEPLOY_BRANCH"; then
38 git checkout "$DEPLOY_BRANCH" --quiet
39else
40 git checkout -B "$DEPLOY_BRANCH" "origin/$DEPLOY_BRANCH" --quiet
41fi
42
43git reset --hard "origin/$DEPLOY_BRANCH" --quiet
44
45NEW_HEAD=$(git rev-parse HEAD)
46NEW_BRANCH=$(git branch --show-current)
47
48if [ "$OLD_HEAD" = "$NEW_HEAD" ]; then
49 log "already up to date on $NEW_BRANCH ($NEW_HEAD)"
50 exit 0
51fi
52
53# Write commit ref for version endpoint
54echo "$NEW_HEAD" > system/public/.commit-ref
55
56# Get list of changed files
57CHANGED=$(git diff --name-only "$OLD_HEAD" "$NEW_HEAD")
58log "updated $OLD_BRANCH/$OLD_HEAD -> $NEW_BRANCH/$NEW_HEAD"
59log "changed files:"
60echo "$CHANGED" | sed 's/^/ /'
61
62NEED_RESTART=false
63NEED_CADDY_RELOAD=false
64NEED_NPM_INSTALL=false
65NEED_DP1_FEED_RESTART=false
66
67while IFS= read -r file; do
68 case "$file" in
69 lith/server.mjs|lith/package.json)
70 NEED_RESTART=true
71 ;;
72 lith/Caddyfile)
73 NEED_CADDY_RELOAD=true
74 ;;
75 lith/package-lock.json)
76 NEED_NPM_INSTALL=true
77 NEED_RESTART=true
78 ;;
79 system/netlify/functions/*)
80 NEED_RESTART=true
81 ;;
82 system/package.json|system/package-lock.json)
83 NEED_NPM_INSTALL=true
84 NEED_RESTART=true
85 ;;
86 shared/*)
87 NEED_RESTART=true
88 ;;
89 lith/dp1-feed-config.yaml|lith/dp1-feed.service)
90 NEED_DP1_FEED_RESTART=true
91 ;;
92 system/public/*)
93 # Static files — Caddy serves directly from disk, no action needed
94 ;;
95 *)
96 # Other files (docs, tests, etc.) — no action needed
97 ;;
98 esac
99done <<< "$CHANGED"
100
101if $NEED_NPM_INSTALL; then
102 log "installing dependencies..."
103 cd "$REMOTE_DIR/system" && npm install --omit=dev --quiet 2>&1 | tail -1
104 cd "$REMOTE_DIR/lith" && npm install --omit=dev --quiet 2>&1 | tail -1
105fi
106
107if $NEED_CADDY_RELOAD; then
108 log "reloading caddy..."
109 systemctl reload caddy
110fi
111
112if $NEED_DP1_FEED_RESTART; then
113 if systemctl is-active dp1-feed &>/dev/null; then
114 log "updating dp1-feed config..."
115 cp "$REMOTE_DIR/lith/dp1-feed-config.yaml" /opt/dp1-feed/config.yaml
116 cp "$REMOTE_DIR/lith/dp1-feed.service" /etc/systemd/system/dp1-feed.service
117 systemctl daemon-reload
118 systemctl restart dp1-feed
119 fi
120fi
121
122if $NEED_RESTART; then
123 log "restarting lith (backend changes detected)..."
124 systemctl restart lith
125else
126 log "static-only deploy — no restart needed"
127fi
128
129log "done"