fix(cinny): upstream-merge script pushes and hands off to CI instead of deploying
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 36s
Lint / Secret scan (gitleaks) (push) Successful in 4s

lotus-build.sh merged the latest upstream tag, then built, copied to the
web root, reloaded nginx and only then pushed — the one path that could
change production without any CI gate (cinny#98). It now merges, runs the
same local gates CI runs (npm ci, typecheck, eslint, prettier, tests),
and pushes; the push triggers Gitea CI and lotus_deploy.sh deploys once
"Build & Quality Checks" is green, like every other lotus commit. A
failed gate leaves the merge local for inspection and notifies the room.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
2026-09-13 00:44:44 -04:00
co-authored by Claude Opus 5
parent 75d9599e22
commit 67a08c7402
+26 -23
View File
@@ -1,5 +1,9 @@
#!/bin/bash #!/bin/bash
# Merges the latest upstream stable release tag into the lotus branch, builds, and deploys. # Merges the latest upstream stable release tag into the lotus branch, runs the
# local quality gates, and PUSHES. It no longer builds or deploys itself: the push
# triggers the normal Gitea CI run and lotus_deploy.sh deploys only once the
# "Build & Quality Checks" status is green — the same path every other lotus
# commit takes (cinny#98: this script used to build+deploy+push, bypassing CI).
# Triggered via webhook by LotusBot !cinny-update command. # Triggered via webhook by LotusBot !cinny-update command.
# Requires: # Requires:
# /etc/cinny-monitor.env — MATRIX_TOKEN, MATRIX_SERVER, MATRIX_ROOM # /etc/cinny-monitor.env — MATRIX_TOKEN, MATRIX_SERVER, MATRIX_ROOM
@@ -8,9 +12,6 @@
set -euo pipefail set -euo pipefail
REPO_DIR="/opt/lotus-cinny" REPO_DIR="/opt/lotus-cinny"
WEB_ROOT="/var/www/html"
CONFIG_BACKUP="/opt/lotus-cinny/.cinny-config.json"
BUILD_DIR="/opt/lotus-cinny/dist"
STATE_FILE="/var/lib/cinny-monitor/last-upstream-tag" STATE_FILE="/var/lib/cinny-monitor/last-upstream-tag"
ENV_FILE="/etc/cinny-monitor.env" ENV_FILE="/etc/cinny-monitor.env"
LOG="/var/log/cinny-build.log" LOG="/var/log/cinny-build.log"
@@ -82,38 +83,40 @@ fi
matrix_notify "cinny-build: merging $LATEST_TAG into lotus branch..." matrix_notify "cinny-build: merging $LATEST_TAG into lotus branch..."
# Back up live config before touching anything
[ -f "$WEB_ROOT/config.json" ] && cp "$WEB_ROOT/config.json" "$CONFIG_BACKUP"
if ! git merge "$LATEST_TAG" --no-edit 2>&1; then if ! git merge "$LATEST_TAG" --no-edit 2>&1; then
git merge --abort 2>/dev/null || true git merge --abort 2>/dev/null || true
matrix_notify "cinny-build: FAILED — merge conflict at $LATEST_TAG. SSH to LXC 106 and resolve manually. See /var/log/cinny-build.log" matrix_notify "cinny-build: FAILED — merge conflict at $LATEST_TAG. SSH to LXC 106 and resolve manually. See /var/log/cinny-build.log"
exit 1 exit 1
fi fi
# ── Local pre-flight (same gates CI runs, minus the build) ──────────────────
# An upstream merge touches hundreds of files we didn't write, so catch an
# obviously broken merge here before it lands on origin. CI is still the
# authority: a failure here leaves the merge commit LOCAL (not pushed) so it can
# be inspected/fixed on the box.
echo "Running npm ci..." echo "Running npm ci..."
npm ci 2>&1 | tail -5 if ! npm ci 2>&1 | tail -5; then
matrix_notify "cinny-build: FAILED — npm ci failed after merging $LATEST_TAG. Merge is local only (not pushed). See /var/log/cinny-build.log"
rm -rf "$BUILD_DIR"
export NODE_OPTIONS='--max_old_space_size=6144'
echo "Building $LATEST_TAG..."
npm run build 2>&1 | tail -10
if [ ! -f "$BUILD_DIR/index.html" ]; then
matrix_notify "cinny-build: FAILED — build produced no output at $LATEST_TAG. See /var/log/cinny-build.log"
exit 1 exit 1
fi fi
rm -rf "${WEB_ROOT:?}"/* for gate in "npm run typecheck" "npm run check:eslint" "npm run check:prettier" "npm test"; do
cp -r "$BUILD_DIR"/* "$WEB_ROOT/" echo "Gate: $gate"
[ -f "$CONFIG_BACKUP" ] && cp "$CONFIG_BACKUP" "$WEB_ROOT/config.json" if ! $gate 2>&1 | tail -20; then
nginx -s reload matrix_notify "cinny-build: FAILED — '$gate' failed after merging $LATEST_TAG. Merge is local only (not pushed). SSH to LXC 106 to fix forward."
exit 1
fi
done
# Push merged lotus branch to origin # ── Hand off to CI + lotus_deploy.sh ────────────────────────────────────────
# Pushing is what deploys: Gitea CI builds and runs every gate, and the
# lotus-deploy webhook polls the "Build & Quality Checks" status and only then
# rsyncs dist/ to the web root (preserving the live config.json). Nothing is copied
# to the web root from here.
git push origin lotus git push origin lotus
# Update state file so upstream-check knows we're on this tag # Update state file so upstream-check knows we're on this tag
echo "$LATEST_TAG" > "$STATE_FILE" echo "$LATEST_TAG" > "$STATE_FILE"
matrix_notify "cinny-build: deployed $LATEST_TAG — Lotus Cinny is live." matrix_notify "cinny-build: merged $LATEST_TAG and pushed — CI is running; lotus_deploy.sh will go live once 'Build & Quality Checks' passes (~11 min). Watch https://code.lotusguild.org/LotusGuild/cinny/actions"
echo "=== Build complete: $LATEST_TAG ===" echo "=== Merge pushed: $LATEST_TAG (deploy via CI) ==="