init deploy.sh

This commit is contained in:
boxi committed 2026-07-12 20:32:47 +02:00
1 parent 7ccf9e1bc3
commit c23836e5fe
2 files changed
+184

No files matched your search

+5
View File
@@ -23,3 +23,8 @@ ELASTIC_PASSWORD=
# --- Backend ---
# Keycloak client id (resource) the bearer-only backend expects.
KEYCLOAK_RESOURCE=
# --- Gitea registry (used by deploy.sh to download config.tar.gz) ---
# User + access token with package read scope for gitea.tail276105.ts.net.
GITEA_USER=
GITEA_TOKEN=
+179
View File
@@ -0,0 +1,179 @@
#!/usr/bin/env bash
#
# Boxit/Remsly prod deployment helper.
#
# One script, two modes:
# * Bootstrap (`deploy <version>`): downloads config-<version>.tar.gz from the
# Gitea generic package registry into ./config, extracts it to a staging dir
# and re-executes the deploy.sh *from the tarball* in install mode. The install
# logic therefore always comes from the deployed version (self-updating), which
# is what lets a release carry its own migration/special steps.
# * Install (`__install`, internal): syncs the staged config into the deploy
# directory (never touching .env or ./config) and runs docker compose.
#
# The deploy directory is the folder this script lives in; it also holds .env
# (secrets, host-only) and docker-compose.yml. Ship this script once to the host,
# afterwards every deploy refreshes it from the tarball.
#
# Usage:
# ./deploy.sh <version> deploy a specific version (e.g. 2026.07-A0-6)
# ./deploy.sh deploy <version> same, explicit
# ./deploy.sh list-remote [n] list the last n versions in the registry (default 10)
# ./deploy.sh list-local list downloaded config archives
# ./deploy.sh help
#
set -euo pipefail
# --- Constants ---------------------------------------------------------------
GITEA_HOST="gitea.tail276105.ts.net"
OWNER="remsly"
PKG="prod-config"
DEPLOY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_DIR="${DEPLOY_DIR}/config"
INSTALLED_FILE="${DEPLOY_DIR}/.installed-version"
# --- Helpers -----------------------------------------------------------------
die() { echo "ERROR: $*" >&2; exit 1; }
# Read a single key from .env without sourcing it (values are unquoted KEY=value).
read_env() {
local key="$1" val
[ -f "${DEPLOY_DIR}/.env" ] || return 1
val="$(grep -E "^${key}=" "${DEPLOY_DIR}/.env" | head -n1 | cut -d= -f2-)" || return 1
# strip trailing CR (CRLF files) and surrounding quotes
val="${val%$'\r'}"; val="${val%\"}"; val="${val#\"}"; val="${val%\'}"; val="${val#\'}"
printf '%s' "$val"
}
# Basic-auth curl against Gitea, using GITEA_USER/GITEA_TOKEN from .env.
gitea_curl() {
local user token
user="$(read_env GITEA_USER || true)"
token="$(read_env GITEA_TOKEN || true)"
[ -n "$user" ] && [ -n "$token" ] || die "GITEA_USER/GITEA_TOKEN missing in ${DEPLOY_DIR}/.env"
curl -fsSL --user "${user}:${token}" "$@"
}
# Resolve the docker compose command (v2 plugin preferred, v1 fallback).
compose() {
if docker compose version >/dev/null 2>&1; then
docker compose "$@"
elif command -v docker-compose >/dev/null 2>&1; then
docker-compose "$@"
else
die "neither 'docker compose' nor 'docker-compose' found"
fi
}
tarball_url() { printf 'https://%s/api/packages/%s/generic/%s/%s/config.tar.gz' "$GITEA_HOST" "$OWNER" "$PKG" "$1"; }
# --- Commands ----------------------------------------------------------------
cmd_list_remote() {
local n="${1:-10}"
echo "Last ${n} remote version(s) of ${PKG}:"
gitea_curl "https://${GITEA_HOST}/api/v1/packages/${OWNER}?type=generic&q=${PKG}" \
| grep -o '"version":"[^"]*"' | cut -d'"' -f4 \
| sort -Vr | head -n "$n" \
| sed 's/^/ /'
}
cmd_list_local() {
local current="" f v
[ -f "$INSTALLED_FILE" ] && current="$(cat "$INSTALLED_FILE")"
echo "Local config archives in ${CONFIG_DIR}:"
if ! ls "${CONFIG_DIR}"/config-*.tar.gz >/dev/null 2>&1; then
echo " (none)"
return 0
fi
for f in "${CONFIG_DIR}"/config-*.tar.gz; do
v="$(basename "$f")"; v="${v#config-}"; v="${v%.tar.gz}"
if [ "$v" = "$current" ]; then
echo " ${v} <- installed"
else
echo " ${v}"
fi
done | sort -Vr
}
cmd_deploy() {
local version="${1:-}"
[ -n "$version" ] || die "version required (e.g. ${0##*/} 2026.07-A0-6)"
mkdir -p "$CONFIG_DIR"
local archive="${CONFIG_DIR}/config-${version}.tar.gz"
if [ -f "$archive" ]; then
echo "Using cached ${archive}"
else
echo "Downloading ${version} ..."
gitea_curl -o "$archive" "$(tarball_url "$version")" \
|| { rm -f "$archive"; die "download of ${version} failed"; }
fi
local stage
stage="$(mktemp -d)"
tar -xzf "$archive" -C "$stage"
[ -f "${stage}/deploy.sh" ] || die "tarball has no deploy.sh"
# Hand off to the deploy.sh shipped in this version (self-updating install logic).
# The running host copy is not overwritten because we exec the staged copy.
exec bash "${stage}/deploy.sh" __install "$version" "$DEPLOY_DIR" "$stage"
}
cmd_install() {
local version="$1" deploydir="$2" stage="$3"
echo "Installing ${version} into ${deploydir} ..."
# Sync staged config into the deploy dir; never clobber secrets or downloads.
if command -v rsync >/dev/null 2>&1; then
rsync -a --exclude='.env' --exclude='config/' "${stage}/" "${deploydir}/"
else
# cp fallback: copy everything except .env / config (tarball has neither, but be safe)
( cd "$stage" && find . -mindepth 1 -maxdepth 1 \
! -name '.env' ! -name 'config' \
-exec cp -a {} "${deploydir}/" \; )
fi
( cd "$deploydir" && compose pull && compose up -d )
# Optional per-version migration/special-task hook shipped inside the tarball.
if [ -f "${deploydir}/post-deploy.sh" ]; then
echo "Running post-deploy.sh hook ..."
bash "${deploydir}/post-deploy.sh" "$version"
fi
printf '%s\n' "$version" > "${deploydir}/.installed-version"
rm -rf "$stage"
echo "Deployed ${version}."
}
usage() {
local me="${0##*/}"
cat <<EOF
${me} - Boxit/Remsly prod deployment helper
Usage:
${me} <version> deploy a specific version (e.g. 2026.07-A0-6)
${me} deploy <version> same, explicit
${me} list-remote [n] list the last n versions in the registry (default 10)
${me} list-local list downloaded config archives under ./config
${me} help
Requires GITEA_USER/GITEA_TOKEN in ./.env for registry access.
EOF
}
# --- Dispatch ----------------------------------------------------------------
main() {
local cmd="${1:-help}"
case "$cmd" in
list-remote) shift; cmd_list_remote "$@" ;;
list-local) cmd_list_local ;;
deploy) shift; cmd_deploy "$@" ;;
__install) shift; cmd_install "$@" ;;
help|-h|--help) usage ;;
*) cmd_deploy "$cmd" ;; # bare version shorthand
esac
}
main "$@"
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.