#!/bin/bash # deploy — Build and deploy claudomator to /site/doot.terst.org # Usage: ./scripts/deploy [--dirty] [--branch ] # --branch Deploy a named local branch as claudomator- (e.g. oss) # --dirty Skip stash check (main deploy only) # Example: sudo ./scripts/deploy # sudo ./scripts/deploy --branch oss set -euo pipefail DIRTY=false BRANCH="" while [[ $# -gt 0 ]]; do case "$1" in --dirty) DIRTY=true; shift ;; --branch) BRANCH="$2"; shift 2 ;; --branch=*) BRANCH="${1#--branch=}"; shift ;; *) echo "Unknown argument: $1" >&2; exit 1 ;; esac done FQDN="doot.terst.org" SITE_DIR="/site/${FQDN}" BIN_DIR="${SITE_DIR}/bin" REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)" export GOCACHE="${SITE_DIR}/cache/go-build" export GOPATH="${SITE_DIR}/cache/gopath" mkdir -p "${GOCACHE}" "${GOPATH}" if [ -n "$BRANCH" ]; then # ── Branch deploy ────────────────────────────────────────────────────────── # Builds a named branch in an isolated git worktree so the main checkout is # undisturbed. The resulting binary is deployed as claudomator- and # managed by the claudomator-@ service. BINARY_NAME="claudomator-${BRANCH}" SERVICE="claudomator-${BRANCH}@${FQDN}.service" WORKTREE="/tmp/claudomator-deploy-${BRANCH}" cleanup() { git -C "${REPO_DIR}" worktree remove "${WORKTREE}" --force 2>/dev/null || true; } trap cleanup EXIT cd "${REPO_DIR}" echo "==> Fetching all remotes..." git fetch --all 2>/dev/null || git fetch local 2>/dev/null || true echo "==> Setting up worktree for ${BRANCH}..." git worktree remove "${WORKTREE}" --force 2>/dev/null || true git worktree add "${WORKTREE}" "${BRANCH}" echo "==> Fast-forwarding ${BRANCH} to tracking remote..." git -C "${WORKTREE}" merge --ff-only "@{u}" 2>/dev/null || echo " (no upstream or already current)" echo "==> Verifying ${BRANCH} (build + tests)..." (cd "${WORKTREE}" && go build ./... && go test -race ./...) echo "==> All checks passed." echo "==> Building ${BINARY_NAME}..." (cd "${WORKTREE}" && go build -o "${BIN_DIR}/${BINARY_NAME}" ./cmd/claudomator/) else # ── Main deploy ──────────────────────────────────────────────────────────── BINARY_NAME="claudomator" SERVICE="claudomator@${FQDN}.service" cd "${REPO_DIR}" echo "==> Pulling latest from bare repo..." git pull --ff-only local main STASHED=false if [ "$DIRTY" = false ] && [ -n "$(git status --porcelain)" ]; then echo "==> Stashing uncommitted changes..." git stash push -u -m "Auto-stash before deploy" STASHED=true trap 'if [ "$STASHED" = true ]; then echo "==> Popping stash..."; git stash pop; fi' EXIT fi echo "==> Verifying (build + tests)..." "${REPO_DIR}/scripts/verify" echo "==> Building claudomator..." go build -o "${BIN_DIR}/claudomator" ./cmd/claudomator/ echo "==> Copying scripts..." mkdir -p "${SITE_DIR}/scripts" find "${REPO_DIR}/scripts" -maxdepth 1 -type f -exec cp -p {} "${SITE_DIR}/scripts/" \; echo "==> Installing to /usr/local/bin..." install -m 755 "${BIN_DIR}/claudomator" /usr/local/bin/claudomator echo "==> Verifying system CLI version..." /usr/local/bin/claudomator version echo "==> Fixing permissions..." "${REPO_DIR}/scripts/fix-permissions" echo "==> Syncing credentials..." "${REPO_DIR}/scripts/sync-credentials" echo "==> Ensuring binary and scripts are executable..." chmod +x "${BIN_DIR}/claudomator" /usr/local/bin/claudomator find "${SITE_DIR}/scripts" -maxdepth 1 -type f -exec chmod +x {} + fi echo "==> Ensuring ${BINARY_NAME} is executable..." chmod +x "${BIN_DIR}/${BINARY_NAME}" chown www-data:www-data "${BIN_DIR}/${BINARY_NAME}" echo "==> Restarting ${SERVICE}..." sudo systemctl restart "${SERVICE}" sudo systemctl status "${SERVICE}" --no-pager -l echo "==> Done!"