ci: deploy-container.sh — swap/rollback with dry-run tests
This commit is contained in:
Executable
+78
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env bash
|
||||
# deploy-container.sh — swap or rollback the flights-web container on the host.
|
||||
#
|
||||
# Usage: deploy-container.sh [--dry-run] <swap|rollback>
|
||||
#
|
||||
# `swap` — assumes the new image is tagged flights-web:${GITHUB_SHA}.
|
||||
# Tags :current → :previous, :sha → :current, restarts container.
|
||||
# `rollback` — runs flights-web:previous in place of :current, repoints :current.
|
||||
#
|
||||
# Env:
|
||||
# GITHUB_SHA (required for swap)
|
||||
# FLIGHTS_WEB_PORT (default 8081 — host port that nginx proxies to)
|
||||
# IMAGE_NAME (default flights-web — set this to point at a registry later)
|
||||
set -euo pipefail
|
||||
|
||||
DRY_RUN=0
|
||||
if [ "${1:-}" = "--dry-run" ]; then
|
||||
DRY_RUN=1
|
||||
shift
|
||||
fi
|
||||
|
||||
CMD="${1:-}"
|
||||
PORT="${FLIGHTS_WEB_PORT:-8081}"
|
||||
IMAGE="${IMAGE_NAME:-flights-web}"
|
||||
|
||||
run() {
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
printf 'docker %s\n' "$*"
|
||||
else
|
||||
docker "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
run_or_skip() {
|
||||
# Same as run, but doesn't fail in real mode if the docker call fails.
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
printf 'docker %s\n' "$*"
|
||||
else
|
||||
docker "$@" || true
|
||||
fi
|
||||
}
|
||||
|
||||
case "$CMD" in
|
||||
swap)
|
||||
: "${GITHUB_SHA:?GITHUB_SHA required for swap}"
|
||||
SHORT_SHA="${GITHUB_SHA:0:7}"
|
||||
# 1. Tag the currently-live image as :previous (skip if first deploy).
|
||||
if [ "$DRY_RUN" -eq 1 ] || docker image inspect "${IMAGE}:current" >/dev/null 2>&1; then
|
||||
run tag "${IMAGE}:current" "${IMAGE}:previous"
|
||||
fi
|
||||
# 2. Tag the new SHA as :current.
|
||||
run tag "${IMAGE}:${SHORT_SHA}" "${IMAGE}:current"
|
||||
# 3. Stop + remove existing container if present.
|
||||
run_or_skip stop flights-web
|
||||
run_or_skip rm flights-web
|
||||
# 4. Run new container.
|
||||
run run -d --name flights-web --restart unless-stopped \
|
||||
-p "127.0.0.1:${PORT}:8080" \
|
||||
"${IMAGE}:current"
|
||||
;;
|
||||
rollback)
|
||||
if [ "$DRY_RUN" -eq 0 ] && ! docker image inspect "${IMAGE}:previous" >/dev/null 2>&1; then
|
||||
echo "fatal: ${IMAGE}:previous not found — cannot rollback" >&2
|
||||
exit 1
|
||||
fi
|
||||
run_or_skip stop flights-web
|
||||
run_or_skip rm flights-web
|
||||
run run -d --name flights-web --restart unless-stopped \
|
||||
-p "127.0.0.1:${PORT}:8080" \
|
||||
"${IMAGE}:previous"
|
||||
# Repoint :current to :previous so subsequent swaps have a sane baseline.
|
||||
run tag "${IMAGE}:previous" "${IMAGE}:current"
|
||||
;;
|
||||
*)
|
||||
echo "usage: $0 [--dry-run] <swap|rollback>" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT="$(cd "$(dirname "$0")/../.." && pwd)/scripts/ci/deploy-container.sh"
|
||||
[ -x "$SCRIPT" ] || { echo "FAIL: $SCRIPT not executable"; exit 1; }
|
||||
|
||||
assert_contains() {
|
||||
local haystack="$1" needle="$2"
|
||||
case "$haystack" in
|
||||
*"$needle"*) ;;
|
||||
*) echo "FAIL: expected '$needle' in:"; echo "$haystack"; exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
assert_order() {
|
||||
local haystack="$1" first="$2" second="$3"
|
||||
local pos1 pos2
|
||||
pos1=$(printf '%s' "$haystack" | grep -nF "$first" | head -1 | cut -d: -f1)
|
||||
pos2=$(printf '%s' "$haystack" | grep -nF "$second" | head -1 | cut -d: -f1)
|
||||
if [ -z "$pos1" ] || [ -z "$pos2" ] || [ "$pos1" -ge "$pos2" ]; then
|
||||
echo "FAIL: expected '$first' (line $pos1) before '$second' (line $pos2)"
|
||||
echo "$haystack"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
export GITHUB_SHA=abcdef1234567890
|
||||
export FLIGHTS_WEB_PORT=8081
|
||||
|
||||
# --- swap ---
|
||||
out=$("$SCRIPT" --dry-run swap)
|
||||
# Order matters: tag previous before tagging current; remove old container before run new
|
||||
assert_order "$out" "tag flights-web:current flights-web:previous" "tag flights-web:abcdef1 flights-web:current"
|
||||
assert_contains "$out" "stop flights-web"
|
||||
assert_contains "$out" "rm flights-web"
|
||||
assert_order "$out" "rm flights-web" "run -d --name flights-web"
|
||||
assert_contains "$out" "127.0.0.1:8081:8080"
|
||||
assert_contains "$out" "flights-web:current"
|
||||
|
||||
# --- rollback ---
|
||||
out=$("$SCRIPT" --dry-run rollback)
|
||||
assert_contains "$out" "stop flights-web"
|
||||
assert_contains "$out" "rm flights-web"
|
||||
assert_contains "$out" "flights-web:previous"
|
||||
# After running previous, current alias should be repointed
|
||||
assert_order "$out" "run -d --name flights-web" "tag flights-web:previous flights-web:current"
|
||||
|
||||
# --- bad subcommand ---
|
||||
if "$SCRIPT" --dry-run foo 2>/dev/null; then
|
||||
echo "FAIL: expected unknown subcommand to error"; exit 1
|
||||
fi
|
||||
|
||||
echo "PASS: deploy-container.sh"
|
||||
Reference in New Issue
Block a user