89 lines
3.8 KiB
Bash
Executable File
89 lines
3.8 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
# Stage a committed source archive, build commit-labelled immutable images and promote
|
|
# them without overlaying source files or reseeding persisted data.
|
|
archive="${1:-}"
|
|
expected_checksum="${2:-}"
|
|
revision="${3:-}"
|
|
root="${MOBILITYOPS_DEPLOY_ROOT:-/mnt/user/appdata/mobilityops}"
|
|
project="${COMPOSE_PROJECT_NAME:-mobilityops}"
|
|
|
|
[ "${#revision}" -eq 40 ] || { echo "Revision must be a full Git SHA" >&2; exit 1; }
|
|
case "$revision" in *[!0-9a-f]*) echo "Revision must be lowercase hexadecimal" >&2; exit 1;; esac
|
|
[ -f "$archive" ] || { echo "Archive not found: $archive" >&2; exit 1; }
|
|
[ -n "$expected_checksum" ] || { echo "Expected SHA-256 is required" >&2; exit 1; }
|
|
[ -f "$root/.env" ] || { echo "Production .env is missing" >&2; exit 1; }
|
|
|
|
actual_checksum="$(sha256sum "$archive" | awk '{print $1}')"
|
|
[ "$actual_checksum" = "$expected_checksum" ] || {
|
|
echo "Archive checksum mismatch" >&2
|
|
exit 1
|
|
}
|
|
|
|
release_root="$root/.deploy/releases"
|
|
release_dir="$release_root/$revision"
|
|
mkdir -p "$release_root"
|
|
if [ -e "$release_dir" ]; then
|
|
echo "Release directory already exists; refusing to overwrite: $release_dir" >&2
|
|
exit 1
|
|
fi
|
|
mkdir "$release_dir"
|
|
tar -xzf "$archive" -C "$release_dir"
|
|
|
|
short_revision="$(printf '%s' "$revision" | cut -c1-12)"
|
|
build_date="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
api_image="mobilityops-api:$short_revision"
|
|
web_image="mobilityops-web:$short_revision"
|
|
|
|
docker build --target runtime --build-arg "VCS_REF=$revision" --build-arg "BUILD_DATE=$build_date" \
|
|
--tag "$api_image" --file "$release_dir/backend/Dockerfile" "$release_dir"
|
|
docker build --build-arg "VCS_REF=$revision" --build-arg "BUILD_DATE=$build_date" \
|
|
--tag "$web_image" "$release_dir/frontend"
|
|
|
|
for image in "$api_image" "$web_image"; do
|
|
labelled_revision="$(docker image inspect --format '{{index .Config.Labels "org.opencontainers.image.revision"}}' "$image")"
|
|
[ "$labelled_revision" = "$revision" ] || {
|
|
echo "Image revision label mismatch for $image" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
|
|
compose="docker compose --env-file $root/.env -p $project -f $release_dir/compose.yaml -f $release_dir/compose.unraid.yaml -f $release_dir/compose.observability.yaml -f $release_dir/compose.release.yaml --profile observability"
|
|
old_api_id="$(docker inspect --format '{{.Image}}' "$project-api-1" 2>/dev/null || true)"
|
|
old_web_id="$(docker inspect --format '{{.Image}}' "$project-web-1" 2>/dev/null || true)"
|
|
export MOBILITYOPS_API_IMAGE="$api_image" MOBILITYOPS_WEB_IMAGE="$web_image"
|
|
$compose up --no-build -d api web backup prometheus alertmanager grafana
|
|
|
|
attempt=0
|
|
until curl -fsS http://127.0.0.1:1236/health/ready > /dev/null; do
|
|
attempt=$((attempt + 1))
|
|
if [ "$attempt" -ge 30 ]; then
|
|
if [ -n "$old_api_id" ] && [ -n "$old_web_id" ]; then
|
|
rollback_api="mobilityops-api:rollback-$short_revision"
|
|
rollback_web="mobilityops-web:rollback-$short_revision"
|
|
docker tag "$old_api_id" "$rollback_api"
|
|
docker tag "$old_web_id" "$rollback_web"
|
|
export MOBILITYOPS_API_IMAGE="$rollback_api" MOBILITYOPS_WEB_IMAGE="$rollback_web"
|
|
$compose up --no-build -d api web || true
|
|
fi
|
|
echo "Release failed readiness; source revision was not promoted" >&2
|
|
exit 1
|
|
fi
|
|
sleep 2
|
|
done
|
|
$compose exec -T api alembic current
|
|
for service in backup prometheus alertmanager grafana; do
|
|
attempt=0
|
|
until status="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$project-$service-1" 2>/dev/null)" \
|
|
&& { [ "$status" = "healthy" ] || [ "$status" = "running" ]; }; do
|
|
attempt=$((attempt + 1))
|
|
[ "$attempt" -lt 60 ] || { echo "$service did not become healthy" >&2; exit 1; }
|
|
sleep 5
|
|
done
|
|
done
|
|
printf '%s\n' "$revision" > "$root/.deploy/source-revision"
|
|
printf '%s %s %s %s\n' "$revision" "$api_image" "$web_image" "$expected_checksum" \
|
|
>> "$root/.deploy/release-history.log"
|
|
echo "Promoted Fleet Ops release $revision"
|