Deploy script for remote installations; move-server: --exclude, quoted .env values

scripts/deploy.sh rolls a published image out to an installation set up with
move-server.sh (DEPLOY_TARGET in .env): checks the image for the target's
architecture, waits until no agent or terminal runs (--force skips), pulls and
recreates, runs the smoke test and goes back to the previous version on failure.

move-server.sh: --exclude leaves paths out of the workspace copy; values in .env
may be quoted (WORKSPACE='/home/...').

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-09 19:46:16 +01:00
1 parent 4244b9370c
commit 0241f6031b
2 files changed
+127 -5

No files matched your search

+10 -5
View File
@@ -37,12 +37,15 @@
# --source-container C container to stop here (default codecraft)
# --source-volume V data volume here (default codecraft-data)
# --source-workspace D project folder here (default: WORKSPACE of .env)
# --exclude PATTERN leave this out of the workspace copy (rsync pattern, relative to the
# workspace, e.g. /old-project/ or /app/target/); repeatable
# --no-stop do not stop the source (only for tests – the copy may be inconsistent)
# --dry-run show the steps only
set -euo pipefail
target="" ws_target="" tools_dir="" docker_sock=0 uid="" gid="" port="" bind="" name="codecraft"
src_container="codecraft" src_volume="codecraft-data" ws_source="" stop=1 dry=0
excludes=()
while (($#)); do
case "$1" in
--workspace) ws_target="$2"; shift ;;
@@ -56,9 +59,10 @@ while (($#)); do
--source-container) src_container="$2"; shift ;;
--source-volume) src_volume="$2"; shift ;;
--source-workspace) ws_source="$2"; shift ;;
--exclude) excludes+=(--exclude "$2"); shift ;;
--no-stop) stop=0 ;;
--dry-run) dry=1 ;;
-h|--help) sed -n '2,36p' "$0"; exit 0 ;;
-h|--help) sed -n '2,38p' "$0"; exit 0 ;;
-*) echo "unknown option $1" >&2; exit 2 ;;
*) target="$1" ;;
esac
@@ -68,7 +72,8 @@ done
cd "$(git rev-parse --show-toplevel)"
[[ -f .env ]] || { echo "no .env in $(pwd)" >&2; exit 1; }
env_get() { sed -n "s/^$1=//p" .env | tail -1; }
# Value of a .env variable, without surrounding quotes.
env_get() { sed -n "s/^$1=//p" .env | tail -1 | sed -E "s/^'(.*)'\$/\1/; s/^\"(.*)\"\$/\1/"; }
host="${target%%:*}"
dir="${target#*:}"
@@ -93,9 +98,9 @@ remote() {
}
q() { printf '%q' "$1"; }
sync_workspace() {
if (( dry )); then echo "[dry-run] rsync $ws_source/ -> $host:$ws_target/"; return; fi
if [[ "$host" == local ]]; then rsync -a --numeric-ids "$ws_source/" "$ws_target/"
else rsync -a --numeric-ids -e "ssh -o BatchMode=yes" "$ws_source/" "$host:$ws_target/"; fi
if (( dry )); then echo "[dry-run] rsync ${excludes[*]} $ws_source/ -> $host:$ws_target/"; return; fi
if [[ "$host" == local ]]; then rsync -a --numeric-ids "${excludes[@]}" "$ws_source/" "$ws_target/"
else rsync -a --numeric-ids "${excludes[@]}" -e "ssh -o BatchMode=yes" "$ws_source/" "$host:$ws_target/"; fi
}
put_file() { # put_file <remote path> < content
if (( dry )); then echo "[dry-run] write $host:$1"; cat >/dev/null; return; fi