- docs-deploy-poll.service and the receiver now build from /home/ubuntu/.docs-publisher, so uncommitted edits in a working clone can never block a deploy - the poller compares origin/main against the last DEPLOYED commit (state file), so a push made from the deploy clone itself also triggers a deploy
71 lines
2.6 KiB
Bash
Executable File
71 lines
2.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Poll Gitea for new commits on main and deploy the docs site when it moves.
|
|
#
|
|
# Why polling: the agent host's cloud firewall only admits inbound SSH, so a
|
|
# Gitea webhook cannot reach the receiver (publishing/webhook-receiver.py) —
|
|
# every port is silently dropped. Outbound to git.inference.coop works, so the
|
|
# agent host polls instead: a push to main is picked up within ~a minute and
|
|
# deployed with no human action. When the operator opens a TCP port to the
|
|
# agent host in the Infomaniak panel, the webhook takes over (its unit is
|
|
# already installed); until then this watcher is the automation.
|
|
#
|
|
# Runs on the agent host as a systemd service (docs-deploy-poll.service).
|
|
# Deploy steps are serialised with the same lock the webhook receiver uses, so
|
|
# the two mechanisms can never deploy concurrently.
|
|
|
|
set -uo pipefail
|
|
|
|
REPO_DIR="${DOCS_REPO_DIR:-/home/ubuntu/repos/docs}"
|
|
ENV_FILE="${DOCS_ENV_FILE:-/home/ubuntu/.hermes/.env}"
|
|
LOG_FILE="${DOCS_DEPLOY_LOG:-/home/ubuntu/docs-deploy.log}"
|
|
LOCK_FILE="${DOCS_DEPLOY_LOCK:-/home/ubuntu/.docs-deploy.lock}"
|
|
STATE_FILE="${DOCS_DEPLOY_STATE:-/home/ubuntu/.docs-deploy.state}"
|
|
INTERVAL="${DOCS_POLL_INTERVAL:-60}"
|
|
|
|
cd "$REPO_DIR"
|
|
|
|
log() { echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) [poll] $*" | tee -a "$LOG_FILE" >&2; }
|
|
|
|
# The Cloudron token travels by environment only; it is read from the env file
|
|
# and never echoed.
|
|
CLOUDRON_TOKEN="$(sed -n 's/^CLOUDRON_TOKEN=//p' "$ENV_FILE" | head -1 | tr -d '"' | tr -d "'")"
|
|
export CLOUDRON_TOKEN
|
|
if [ -z "$CLOUDRON_TOKEN" ]; then
|
|
log "FATAL: CLOUDRON_TOKEN not found in $ENV_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
log "watcher started: polling $REPO_DIR every ${INTERVAL}s"
|
|
|
|
while true; do
|
|
if ! git fetch --quiet origin main 2>>"$LOG_FILE"; then
|
|
log "git fetch failed; will retry"
|
|
sleep "$INTERVAL"
|
|
continue
|
|
fi
|
|
|
|
REMOTE="$(git rev-parse origin/main 2>/dev/null || echo none)"
|
|
# Compare against the commit last DEPLOYED (not the clone's HEAD): a push
|
|
# made from this very clone would otherwise look like "no change".
|
|
LAST_DEPLOYED="$(cat "$STATE_FILE" 2>/dev/null || echo none)"
|
|
|
|
if [ "$LAST_DEPLOYED" != "$REMOTE" ]; then
|
|
log "main moved: ${LAST_DEPLOYED:0:12} -> ${REMOTE:0:12}; deploying"
|
|
# flock -n shares the receiver's lock: one deploy at a time, ever.
|
|
if flock -n "$LOCK_FILE" bash -c '
|
|
set -e
|
|
cd "$1"
|
|
git pull --ff-only origin main
|
|
bash publishing/build.sh
|
|
bash publishing/deploy.sh
|
|
' _ "$REPO_DIR" >>"$LOG_FILE" 2>&1; then
|
|
printf '%s\n' "$REMOTE" > "$STATE_FILE"
|
|
log "deploy finished for ${REMOTE:0:12}"
|
|
else
|
|
log "deploy FAILED for ${REMOTE:0:12} (see log above)"
|
|
fi
|
|
fi
|
|
|
|
sleep "$INTERVAL"
|
|
done
|