fix(ci): restore backups through remote Docker API
quality / changes (push) Successful in 7s
quality / commitlint (push) Skipped
quality / openapi (push) Successful in 27s
quality / web (push) Successful in 48s
quality / api (push) Successful in 1m13s
quality / linux-agent-smoke (push) Successful in 22s
quality / docker-check (push) Successful in 4m43s
CD / quality (push) Successful in 7m42s
CD / publish (push) Successful in 5m17s

This commit is contained in:
Denozordec committed 2026-10-26 14:28:36 +07:00
1 parent 57b7652d4d
commit ce90fa9701
6 files changed
+85 -7

No files matched your search

+1 -1
View File
@@ -18,7 +18,7 @@ marker_name="$id-persistence"
tmp="$(mktemp -d)"
cleanup() {
result=$?
docker logs "$container" >>"$tmp/container.log" 2>&1 || true
if docker inspect "$container" >/dev/null 2>&1; then docker logs "$container" >>"$tmp/container.log" 2>&1 || true; fi
if [ "$result" -ne 0 ]; then cat "$tmp/container.log" >&2; fi
docker rm -f "$container" >/dev/null 2>&1 || true
docker volume rm "$volume" "$restore_volume" >/dev/null 2>&1 || true
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env sh
# No Docker daemon: verify actual restore transport, guards and exit propagation.
set -eu
wrapper="$(pwd)/deploy/docker/restore.sh"
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT HUP INT TERM
mkdir "$tmp/bin"
backup="$tmp/input backup.db"
printf 'synthetic backup' >"$backup"
cat >"$tmp/bin/docker" <<'DOCKER'
#!/usr/bin/env sh
set -eu
printf '%s\n' "$*" >>"$FAKE_LOG"
case "$1" in
volume) [ "$2" = inspect ]; exit 0 ;;
ps)
count=0; [ ! -f "$FAKE_COUNT" ] || count="$(cat "$FAKE_COUNT")"
count=$((count + 1)); printf '%s' "$count" >"$FAKE_COUNT"
if [ "$FAKE_CASE" = ps-initial-failure ] || { [ "$FAKE_CASE" = ps-later-failure ] && [ "$count" = 2 ]; }; then exit 29; fi
if [ "$FAKE_CASE" = live-initial ] || { [ "$FAKE_CASE" = live-later ] && [ "$count" = 2 ]; }; then printf 'other-writer\n'; fi ;;
create) printf 'helper-id\n' ;;
cp) [ "$2" = "$FAKE_BACKUP" ]; [ "$FAKE_CASE" != cp-failure ] || exit 17 ;;
start) [ "$FAKE_CASE" != start-failure ] || exit 19 ;;
wait) if [ "$FAKE_CASE" = restore-failure ]; then printf '23\n'; else printf '0\n'; fi ;;
rm) exit 0 ;;
*) echo 'Unexpected Docker operation in restore' >&2; exit 98 ;;
esac
DOCKER
chmod +x "$tmp/bin/docker"
for scenario in success cp-failure start-failure restore-failure live-initial live-later ps-initial-failure ps-later-failure; do
log="$tmp/$scenario.log"
if PATH="$tmp/bin:$PATH" FAKE_LOG="$log" FAKE_COUNT="$tmp/$scenario.count" FAKE_CASE="$scenario" FAKE_BACKUP="$backup" sh "$wrapper" image:immutable target-named-volume "$backup"; then actual=0; else actual=$?; fi
case "$scenario" in success) expected=0;; cp-failure) expected=17;; start-failure) expected=19;; restore-failure) expected=23;; ps-*-failure) expected=29;; *) expected=1;; esac
[ "$actual" = "$expected" ] || { echo "Unexpected status for $scenario: $actual" >&2; exit 1; }
grep -F 'volume inspect target-named-volume' "$log" >/dev/null
if grep -E -- '(type=bind|--privileged|--network host|docker.sock|^volume rm)' "$log" >/dev/null; then echo 'Restore must not use a host bind or remove the target volume' >&2; exit 1; fi
if [ "$scenario" = live-initial ] || [ "$scenario" = ps-initial-failure ]; then
if grep -E '^(create|cp|start) ' "$log" >/dev/null; then echo 'Active target must fail before helper creation' >&2; exit 1; fi
continue
fi
grep -E '^create --name evofw-restore-[^ ]+ --network none --cap-drop ALL --security-opt no-new-privileges:true --mount type=volume,src=target-named-volume,dst=/data --entrypoint node image:immutable tools/sqlite-backup.mjs restore /tmp/evofw-restore-input.db /data/app.db --offline$' "$log" >/dev/null
grep -E '^cp .*input backup.db evofw-restore-[^ ]+:/tmp/evofw-restore-input.db$' "$log" >/dev/null
grep -E '^rm -fv evofw-restore-' "$log" >/dev/null
if [ "$scenario" = cp-failure ] || [ "$scenario" = live-later ] || [ "$scenario" = ps-later-failure ]; then
if grep -E '^start ' "$log" >/dev/null; then echo 'Incomplete input or newly active target must never start restore' >&2; exit 1; fi
elif [ "$scenario" != start-failure ]; then
grep -E '^wait evofw-restore-' "$log" >/dev/null
[ "$(cat "$tmp/$scenario.count")" = 2 ]
fi
done
echo 'Restore wrapper regression passed (remote copy, offline guards, failures, cleanup)'