refactor: use one safe deployment path

Always stop, back up, migrate and check readiness instead of
maintaining image/config hash detection and selective updates.

Keep file locking, key preservation and interrupted recovery.
Repeated and frontend-only deployments may cause brief API downtime.
This commit was merged in pull request #3.
This commit is contained in:
2026-10-03 11:38:08 +03:00
parent 2f8163e53d
commit a56ed85230
3 changed files with 36 additions and 71 deletions
+19 -42
View File
@@ -166,49 +166,26 @@ quiet compose run --rm --no-deps -T --entrypoint node backend -e '
process.exit(1);
' || die 'Image preflight failed: check data permissions, CA certificate and keys'
matches() {
local id=$1 service=$2 image=$3 name hash
[[ -n $id && -s $state/current ]] || return 1
read -r name hash <<< "$(compose config --hash "$service")"
[[ $name == "$service" && $hash =~ ^[0-9a-f]{64}$ ]] || return 1
[[ $(inspect "$id" '{{index .Config.Labels "com.docker.compose.config-hash"}}') == "$hash" && \
$(inspect "$id" '{{.Image}}') == "$(dock image inspect --format '{{.Id}}' "$image")" && \
$(inspect "$id" '{{.State.Running}} {{if .State.Health}}{{.State.Health.Status}}{{end}}') == 'true healthy' ]]
}
change_backend=yes change_frontend=yes
if matches "$backend" backend "$backend_image"; then change_backend=no; fi
if matches "$frontend" frontend "$frontend_image"; then change_frontend=no; fi
if [[ $change_backend == no && $change_frontend == no ]]; then
stage=ready
record > "$state/current.tmp"; mv -- "$state/current.tmp" "$state/current"
printf 'Already running the selected images and configuration; no update needed.\n'
exit
fi
if [[ $change_backend == yes ]]; then
mark stop
quiet compose stop backend
[[ -z $backend || $(inspect "$backend" '{{.State.Running}}') == false ]] || die 'Backend did not stop'
migration=$(container migration)
[[ -z $migration || $(inspect "$migration" '{{.State.Running}}') == false ]] || die 'A migration writer appeared; backup was not started'
if [[ $initialize != yes ]]; then
mark backup
mkdir -p -- "$backups"
partial=$(mktemp -d "$backups/.partial-$(date -u +%Y%m%dT%H%M%SZ).XXXXXXXX")
quiet cp -a -- "$data" "$partial/data" || die 'Backup failed; partial copy is NOT usable; backend remains stopped'
backup="$backups/$(basename -- "$partial" | sed 's/^\.partial-//')"
mv -- "$partial" "$backup"
printf 'Backup: %s\n' "$backup"
fi
mark migration
quiet compose up --no-deps --force-recreate --abort-on-container-exit --exit-code-from migration migration
mark backend-start
quiet compose up -d --no-deps --wait --wait-timeout 120 backend
fi
if [[ $change_frontend == yes ]]; then
mark frontend-start
quiet compose up -d --no-deps --wait --wait-timeout 120 frontend
mark stop
quiet compose stop backend
[[ -z $backend || $(inspect "$backend" '{{.State.Running}}') == false ]] || die 'Backend did not stop'
migration=$(container migration)
[[ -z $migration || $(inspect "$migration" '{{.State.Running}}') == false ]] || die 'A migration writer appeared; backup was not started'
if [[ $initialize != yes ]]; then
mark backup
mkdir -p -- "$backups"
partial=$(mktemp -d "$backups/.partial-$(date -u +%Y%m%dT%H%M%SZ).XXXXXXXX")
quiet cp -a -- "$data" "$partial/data" || die 'Backup failed; partial copy is NOT usable; backend remains stopped'
backup="$backups/$(basename -- "$partial" | sed 's/^\.partial-//')"
mv -- "$partial" "$backup"
printf 'Backup: %s\n' "$backup"
fi
mark migration
quiet compose up --no-deps --force-recreate --abort-on-container-exit --exit-code-from migration migration
mark backend-start
quiet compose up -d --no-deps --wait --wait-timeout 120 backend
mark frontend-start
quiet compose up -d --no-deps --wait --wait-timeout 120 frontend
stage=ready
record > "$state/current.tmp"; mv -- "$state/current.tmp" "$state/current"
rm -- "$state/pending"