From 7a84d2f09f277c1bb0b23e494d92c9ee0d9123b4 Mon Sep 17 00:00:00 2001 From: Keith Smith Date: Fri, 4 Sep 2026 21:31:08 -0600 Subject: [PATCH] Deploy and upgrade only from tagged releases, not branch tip deploy/upgrade.sh now fetches tags and checks out whichever sorts newest (detached HEAD) instead of git pull --ff-only on a branch, now that the project has a real release process (dated tags, e.g. v2026.9.3) and a public mirror. Keeps production from ever landing on an untagged commit. DEPLOYMENT.md's initial-clone steps and Upgrades section updated to match. Co-Authored-By: Claude Sonnet 5 --- DEPLOYMENT.md | 24 +++++++++++++++++------- deploy/upgrade.sh | 13 +++++++++++-- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 24abc94..49e8941 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -159,9 +159,16 @@ anyone else under normal file permissions. `deploy/upgrade.sh`'s later setup needed. Fine as long as the token is scoped to read-only access on just this repo. -Either way, now that the repo is cloned: +Either way, now that the repo is cloned, check out the latest release tag +rather than deploying whatever the default branch's tip happens to be — +`deploy/upgrade.sh` follows the same rule on every later upgrade (see §6), +so this keeps the very first deploy consistent with all the ones after it: ```bash +cd /srv/ds-chat +sudo -u ds-chat git fetch --tags +LATEST_TAG="$(sudo -u ds-chat git tag --sort=-creatordate | head -n1)" +sudo -u ds-chat git checkout --detach "$LATEST_TAG" sudo -u ds-chat mkdir -p /srv/ds-chat/uploads ``` @@ -330,12 +337,15 @@ This is config in NPM's own UI/database, not a file this repo ships: sudo -u ds-chat /srv/ds-chat/deploy/upgrade.sh ``` -Pulls latest `main`, reinstalls backend deps, runs `alembic upgrade head`, -rebuilds the frontend, restarts `ds-chat`, and curls `/api/health` to -confirm it came back up. Fails loudly (`set -euo pipefail`) and stops -before restarting anything if an earlier step — most importantly a failed -migration — errors out, so a bad deploy doesn't take down the previously -working one. +Fetches tags and checks out whichever one sorts newest (`git tag +--sort=-creatordate`) — deliberately not the default branch's tip, so +running this between releases is a safe no-op rather than pulling in +whatever's mid-flight on `main`. Then reinstalls backend deps, runs +`alembic upgrade head`, rebuilds the frontend, restarts `ds-chat`, and +curls `/api/health` to confirm it came back up. Fails loudly +(`set -euo pipefail`) and stops before restarting anything if an earlier +step — most importantly a failed migration — errors out, so a bad deploy +doesn't take down the previously working one. Active users get disconnected for a few seconds during the restart and reconnect automatically (same reconnect logic as §4's NPM-timeout note) — diff --git a/deploy/upgrade.sh b/deploy/upgrade.sh index ff6b9b5..4c55c5e 100755 --- a/deploy/upgrade.sh +++ b/deploy/upgrade.sh @@ -16,9 +16,18 @@ BACKEND_DIR="${REPO_DIR}/backend" FRONTEND_DIR="${REPO_DIR}/frontend" ENV_FILE="/etc/ds-chat/env" -echo "==> Pulling latest code" +echo "==> Fetching latest release" cd "$REPO_DIR" -git pull --ff-only +git fetch --tags --force +LATEST_TAG="$(git tag --sort=-creatordate | head -n1)" +if [[ -z "$LATEST_TAG" ]]; then + echo "No tags found -- nothing to deploy" >&2 + exit 1 +fi +echo "Deploying $LATEST_TAG" +# Detached HEAD, not a branch checkout -- this directory only ever runs a +# tagged release, never whatever the default branch's tip happens to be. +git checkout --quiet --detach "$LATEST_TAG" echo "==> Installing backend dependencies" cd "$BACKEND_DIR"