Chrome has no update channel for an unpacked extension, so every pull left one manual step: click reload on its card. The dashboard now publishes the version its own checkout ships at /api/autobuyer/status, and the extension reloads itself when it is behind — chrome.runtime.reload() re-reads the folder from disk, which the update check has already pulled into. It only ever runs code that is on disk, so a reload that changes nothing is reported and waited out rather than repeated; a dashboard that is behind is ignored. Also adds the deploy stack for running the dashboard on the droplet, next to the autotrader one: it joins that nginx's network and renders a server block into its conf.d rather than standing up a second ingress. AUTOFIRMER_DB moves the SQLite file onto a volume, since the working directory in a container is replaced on every deploy. And waitFor gained `hidden`: an absent gate matched on DOM presence only, so a modal that closes by going display:none could never satisfy it. The extension grew a visibility probe for this — locate cannot answer it, because absent and hidden are both errors there and a wait gate has to tell them apart. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
57 lines
2.2 KiB
Bash
Executable File
57 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Rebuild the dashboard image, restart the container, point the shared nginx at
|
|
# it. Safe to re-run any time — this is the normal "ship a change" command.
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
|
|
log() { printf '\n\033[1;34m==> %s\033[0m\n' "$1"; }
|
|
fail() { printf '\n\033[1;31mERROR: %s\033[0m\n' "$1" >&2; exit 1; }
|
|
|
|
[ -f .env ] || fail "no .env — copy .env.example to .env and fill it in"
|
|
set -a; . ./.env; set +a
|
|
: "${FIRMER_HOST:?set FIRMER_HOST in .env}"
|
|
SHARED_STACK="${SHARED_STACK:-/opt/autotrader/deploy}"
|
|
|
|
command -v envsubst >/dev/null || fail "envsubst missing — apt-get install -y gettext-base"
|
|
[ -d "$SHARED_STACK/nginx/conf.d" ] || fail "no nginx/conf.d under $SHARED_STACK"
|
|
|
|
log "Building and starting"
|
|
docker compose up -d --build
|
|
|
|
log "Waiting for the container to report healthy"
|
|
for _ in $(seq 1 30); do
|
|
state=$(docker inspect autofirmer --format '{{.State.Health.Status}}' 2>/dev/null || echo missing)
|
|
[ "$state" = healthy ] && break
|
|
sleep 2
|
|
done
|
|
[ "${state:-}" = healthy ] || fail "autofirmer is $state — check: docker logs autofirmer"
|
|
|
|
# Rendered into the *other* stack's conf.d, because that is the directory its
|
|
# nginx has mounted. The file is untracked there, and survives that stack's
|
|
# deploys and pulls; only its bootstrap-tls.sh wipes conf.d, and re-running this
|
|
# script puts it back.
|
|
#
|
|
# Held back until the certificate exists: nginx refuses to load a server block
|
|
# whose ssl_certificate is missing, and a broken file in that directory would
|
|
# also abort the autotrader deploys that reload the same nginx.
|
|
if docker run --rm -v autotrader-vps_letsencrypt:/le alpine \
|
|
test -f "/le/live/$FIRMER_HOST/fullchain.pem" 2>/dev/null; then
|
|
template=nginx/firmer.conf.template
|
|
else
|
|
log "No certificate for $FIRMER_HOST yet — rendering the HTTP-only config"
|
|
log "Run ./bootstrap-tls.sh once DNS points here, then this script again"
|
|
template=nginx/firmer-acme.conf.template
|
|
fi
|
|
|
|
log "Rendering $template"
|
|
# Named explicitly so envsubst leaves nginx's own $host, $remote_addr and the
|
|
# rest alone.
|
|
envsubst '${FIRMER_HOST}' < "$template" > "$SHARED_STACK/nginx/conf.d/firmer.conf"
|
|
|
|
log "Reloading the shared nginx"
|
|
docker exec nginx nginx -t
|
|
docker exec nginx nginx -s reload
|
|
|
|
log "Status"
|
|
docker compose ps
|