#!/usr/bin/env bash # Break-glass manual deploy. The normal path is a push to main # (.tangled/workflows/deploy-microvm.yml); this does the same two things by # hand: build the amd64 image and push it to ghcr, then kick the droplet's pull # timer rather than waiting up to a minute for its next poll. Nothing is built # on the droplet and no source is shipped there. Run from the repo root. # # Cross-building amd64 from an arm Mac works because the Dockerfile's build # stage sets +JMsingle; see the comment there. set -euo pipefail droplet="${CRATE_DROPLET:-root@206.189.15.37}" img="ghcr.io/nmokkenstorm/crate" # Transitional: the droplet still runs the pre-rename image name and unit # names; drop the legacy tags and the SSH block at droplet teardown. legacy_img="ghcr.io/nmokkenstorm/at-record" builder="crate" tag="$(git rev-parse --short HEAD)" # buildx builds the working tree, not HEAD, so a dirty tree would ship changes # under a tag naming a commit that does not contain them. if [ -n "$(git status --porcelain --untracked-files=no)" ] && [ -z "${CRATE_ALLOW_DIRTY:-}" ]; then echo "refusing: working tree is dirty, but the image would be tagged $tag" >&2 echo "commit first, or set CRATE_ALLOW_DIRTY=1 to override" >&2 exit 1 fi # The default "docker" driver has no registry exporter, so --push needs a # docker-container builder. Created once, reused after that. docker buildx inspect "$builder" >/dev/null 2>&1 \ || docker buildx create --name "$builder" --driver docker-container >/dev/null echo "building $img:$tag for linux/amd64" docker buildx build \ --builder "$builder" \ --platform linux/amd64 \ -t "$img:$tag" -t "$img:latest" \ -t "$legacy_img:$tag" -t "$legacy_img:latest" \ --push . echo "rolling the droplet onto $tag" ssh -o ConnectTimeout=20 "$droplet" " set -e systemctl start crate-pull.service cd /opt/crate && docker compose ps " echo "published $tag; verify:" echo " curl -sf https://crate.mokkenstorm.dev/healthz"