- Makefile: podman build/push from the committed tree (git archive HEAD), tagged :<commit> + :latest; PLATFORM defaults to linux/arm64 for emily. - deploy.sh: push the commit first, refuse a dirty tracked tree or HEAD != origin/main, then build and deploy that exact commit via -e image_tag (rollback = an older commit). - ansible: target emily with no become. The register role writes hops.network (NetworkName=hops_net) plus the caddy.container.d drop-in; the hops role installs ~/podman-data/hops and hops.container under systemctl --user with a podman healthcheck gate; the caddy role appends the site blocks to the shared Caddyfile and reloads. - Drop the Docker-era network role, community.docker requirements, ansible/files templates and docker-compose.yml. - .containerignore replaces .dockerignore. - README: Podman build, rootless Quadlet deploy on emily.
73 lines
2.5 KiB
Bash
Executable File
73 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Hops n Grains deploy — push the current commit, build it with podman, and
|
|
# install the Quadlet unit on emily with ansible.
|
|
#
|
|
# The image is built from the committed tree (`git archive HEAD`) and tagged
|
|
# with its commit id, so what runs on the host is exactly what git knows about.
|
|
#
|
|
# ./deploy.sh deploy HEAD (tracked tree must be clean and pushed)
|
|
# ./deploy.sh --force skip the guards (know what you are doing)
|
|
# ./deploy.sh --no-push skip the push, if you already pushed
|
|
#
|
|
# Log in to the registry once beforehand: podman login registry.tanshu.com
|
|
set -euo pipefail
|
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
|
|
|
BRANCH="${BRANCH:-main}"
|
|
|
|
FORCE=false
|
|
NO_PUSH=false
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--force) FORCE=true ;;
|
|
--no-push) NO_PUSH=true ;;
|
|
*)
|
|
echo "Usage: $0 [--force] [--no-push]" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# The build takes HEAD, so push first: otherwise the registry collects an image
|
|
# for a commit that exists only on this machine.
|
|
if [ "$NO_PUSH" != true ]; then
|
|
echo "==> pushing"
|
|
git push
|
|
fi
|
|
|
|
# Guards. Only tracked-file state matters — untracked and ignored files never
|
|
# enter a `git archive HEAD` build. HEAD must match origin/$BRANCH so the commit
|
|
# the image is tagged with is one the remote actually has.
|
|
if [ "$FORCE" != true ]; then
|
|
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
|
|
echo "x tracked files modified - commit or stash first (or --force)" >&2
|
|
exit 1
|
|
fi
|
|
git fetch origin --quiet
|
|
if [ "$(git rev-parse HEAD)" != "$(git rev-parse "origin/$BRANCH")" ]; then
|
|
echo "x HEAD != origin/$BRANCH - push or pull first (or --force)" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
TAG=$(git rev-parse --short HEAD)
|
|
echo "==> deploying commit $TAG"
|
|
|
|
echo "========================================================"
|
|
echo " Building & Uploading Container Image (Podman)"
|
|
echo "========================================================"
|
|
make build-production COMMIT="$TAG"
|
|
|
|
echo ""
|
|
echo "========================================================"
|
|
echo " Executing Ansible Deployment"
|
|
echo "========================================================"
|
|
# The play configures rootless Podman Quadlet units that belong to the
|
|
# connecting user, so it must connect as that user and must NOT become root.
|
|
# `-u` is the account that owns ~/.config/containers/systemd on the target.
|
|
deploy_user="${ANSIBLE_USER:-tanshu}"
|
|
cd ansible || exit
|
|
# image_tag pins the exact commit; rollback is -e image_tag=<older-commit>.
|
|
ansible-playbook -u "$deploy_user" playbook.yml -e "image_tag=$TAG"
|