Files
yawn/server/deploy-docker.sh
Ampandheaust d71da85307 Fix Docker deployment inputs
Include all addon workspaces and vendored dependencies in image builds, and expose deploy time plus commit metadata on the home page.

Amp-Thread-ID: https://ampcode.com/threads/T-01a033d4-0e44-708e-af0e-6166283416ff
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
2026-08-24 18:30:45 +00:00

91 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
repository="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
expected_repository="$HOME/yawn"
state_directory="$HOME/.local/state/yawn"
deployed_revision_file="$state_directory/deployed-revision"
compose=(docker compose --project-name yawn --project-directory "$repository" --file "$repository/compose.yaml")
if [[ "$repository" != "$expected_repository" ]]; then
printf 'Expected the repository at %s, found %s\n' "$expected_repository" "$repository" >&2
exit 1
fi
for command in git docker flock; do
if ! command -v "$command" >/dev/null 2>&1; then
printf 'Missing required command: %s\n' "$command" >&2
exit 1
fi
done
if ! docker compose version >/dev/null 2>&1; then
printf 'Docker Compose v2 is required.\n' >&2
exit 1
fi
mkdir -p "$state_directory"
exec 9>"$state_directory/deploy.lock"
if ! flock -n 9; then
printf 'Another Yawn deployment is already running.\n'
exit 0
fi
cd "$repository"
if [[ "$(git branch --show-current)" != "main" ]]; then
printf 'Deployments must run from the main branch.\n' >&2
exit 1
fi
if [[ -n "$(git status --porcelain --untracked-files=normal)" ]]; then
printf 'Refusing to deploy a checkout with local changes.\n' >&2
exit 1
fi
printf 'Updating main...\n'
git fetch origin main
fetched="$(git rev-parse FETCH_HEAD)"
git merge --ff-only "$fetched"
if [[ "$(git rev-parse HEAD)" != "$fetched" ]]; then
printf 'HEAD does not match origin/main after updating.\n' >&2
exit 1
fi
deployed_at="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
commit_message="$(git log -1 --format=%s)"
printf 'Building the production image...\n'
"${compose[@]}" build --pull \
--build-arg "YAWN_DEPLOYED_AT=$deployed_at" \
--build-arg "YAWN_DEPLOY_COMMIT_MESSAGE=$commit_message" \
yawn
"${compose[@]}" up -d --remove-orphans yawn
container="$("${compose[@]}" ps -q yawn)"
if [[ -z "$container" ]]; then
printf 'Docker Compose did not create the Yawn container.\n' >&2
exit 1
fi
printf 'Waiting for Yawn to become healthy...\n'
for _ in {1..60}; do
status="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container")"
case "$status" in
healthy)
temporary_revision="$(mktemp "$state_directory/deployed-revision.XXXXXX")"
git rev-parse HEAD >"$temporary_revision"
mv -f -- "$temporary_revision" "$deployed_revision_file"
printf 'The Yawn container is healthy.\n'
exit 0
;;
unhealthy | exited | dead)
"${compose[@]}" logs --tail 50 yawn >&2
exit 1
;;
esac
sleep 2
done
printf 'Yawn did not become healthy before the timeout.\n' >&2
"${compose[@]}" logs --tail 50 yawn >&2
exit 1