Deploy workflow: commit-id image tags, guarded deploy.sh, opt-in prune
- Makefile builds from 'git archive HEAD' (stale-remote-HEAD impossible): tags registry.tanshu.com/mozimo:<short-commit> + :main; build-check target verifies both architectures without pushing - deploy.sh: refuses dirty tracked tree / HEAD != origin/main (--force to bypass), ff-only pull, passes the commit as image_tag to ansible, --prune flag for opt-in image cleanup - ansible: docker_image uses image_tag extra-var (falls back to tag), prune task keeps the 3 newest mozimo images, mozimo-repo only
This commit is contained in:
@@ -1,8 +1,19 @@
|
|||||||
|
COMMIT ?= $(shell git rev-parse --short HEAD)
|
||||||
|
|
||||||
.PHONY: build-production
|
.PHONY: build-production
|
||||||
build-production: ## Build the production docker image.
|
build-production: ## Multi-arch build from HEAD; tags registry.tanshu.com/mozimo:<commit> + :main
|
||||||
@docker buildx build \
|
@git archive --format=tar HEAD | docker buildx build \
|
||||||
--platform linux/amd64,linux/arm64 \
|
--platform linux/amd64,linux/arm64 \
|
||||||
--tag registry.tanshu.com/mozimo:staging \
|
--tag registry.tanshu.com/mozimo:$(COMMIT) \
|
||||||
$(if $(TAG),--tag registry.tanshu.com/mozimo:$(TAG)) \
|
--tag registry.tanshu.com/mozimo:main \
|
||||||
--push \
|
--push \
|
||||||
git@git.tanshu.com:tanshu/mozimo.in.git
|
-
|
||||||
|
|
||||||
|
.PHONY: build-check
|
||||||
|
build-check: ## Multi-arch compile check from HEAD, nothing pushed
|
||||||
|
@git archive --format=tar HEAD | docker buildx build \
|
||||||
|
--platform linux/amd64,linux/arm64 \
|
||||||
|
--tag mozimo:check \
|
||||||
|
--pull \
|
||||||
|
--progress=plain \
|
||||||
|
-
|
||||||
|
|||||||
@@ -31,3 +31,10 @@
|
|||||||
- "{{ host_directory }}/pb_data:/app/pb_data"
|
- "{{ host_directory }}/pb_data:/app/pb_data"
|
||||||
networks:
|
networks:
|
||||||
- name: "{{ docker_network }}"
|
- name: "{{ docker_network }}"
|
||||||
|
|
||||||
|
- name: Prune old mozimo images, keep newest 3 (opt-in via ./deploy.sh --prune)
|
||||||
|
ansible.builtin.shell: >
|
||||||
|
docker images "registry.tanshu.com/mozimo" --format "{{.ID}}" | tail -n +4 | xargs -r docker rmi
|
||||||
|
when: mozimo_image_prune | default(false) | bool
|
||||||
|
failed_when: false
|
||||||
|
changed_when: true
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ host: "staging.mozimo.in"
|
|||||||
|
|
||||||
docker_network: "{{ title }}_net"
|
docker_network: "{{ title }}_net"
|
||||||
|
|
||||||
docker_image: "{{ registry }}/{{ title }}:{{ tag }}"
|
# image tag: deploy.sh passes -e image_tag=<commit>; "tag" is the fallback
|
||||||
|
# when running the playbook by hand — rollback = -e image_tag=<older-commit>
|
||||||
|
docker_image: "{{ registry }}/{{ title }}:{{ image_tag | default(tag) }}"
|
||||||
docker_container: "{{ title }}-staging"
|
docker_container: "{{ title }}-staging"
|
||||||
docker_port: 3000
|
docker_port: 3000
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,51 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Mozimo deploy — build the exact commit at origin/main, tag it with its
|
||||||
|
# commit id, and hand that tag to ansible. Guards make it impossible to
|
||||||
|
# deploy anything other than what git knows about.
|
||||||
|
#
|
||||||
|
# ./deploy.sh deploy HEAD (must be pushed, tree must be clean)
|
||||||
|
# ./deploy.sh --prune also drop old mozimo images on the server (keep 3)
|
||||||
|
# ./deploy.sh --force skip the guards (know what you are doing)
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd -P )
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||||
cd "$parent_path" || exit
|
|
||||||
git pull
|
FORCE=false
|
||||||
if [ 1 -eq "$#" ]
|
PRUNE=false
|
||||||
then
|
for arg in "$@"; do
|
||||||
make build-production TAG="$1"
|
case "$arg" in
|
||||||
else
|
--force) FORCE=true ;;
|
||||||
make build-production
|
--prune) PRUNE=true ;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 [--force] [--prune]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# guards: only tracked-file state matters (untracked files never enter a
|
||||||
|
# `git archive HEAD` build); HEAD must equal origin/main
|
||||||
|
if [ "$FORCE" != true ]; then
|
||||||
|
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
|
||||||
|
echo "✗ 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/main)" ]; then
|
||||||
|
echo "✗ HEAD != origin/main — push or pull first (or --force)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$parent_path/ansible" || exit
|
git pull --ff-only
|
||||||
ansible-playbook playbook.yml
|
TAG=$(git rev-parse --short HEAD)
|
||||||
|
echo "▶ deploying commit $TAG"
|
||||||
|
make build-production TAG="$TAG"
|
||||||
|
|
||||||
|
PRUNE_FLAG=""
|
||||||
|
if [ "$PRUNE" = true ]; then
|
||||||
|
PRUNE_FLAG="-e mozimo_image_prune=true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ansible
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
ansible-playbook playbook.yml -e "image_tag=$TAG" $PRUNE_FLAG
|
||||||
|
|||||||
Reference in New Issue
Block a user