Deploys from unpushed branches were being reverted by the next deploy from main, and in-place vault edits could overwrite each other. - deploy-guard.yml (imported by site.yml and dns.yml) refuses real runs unless the checkout is clean and exactly origin/main; --check is fine. - bin/deploy holds a lock so only one deploy runs at a time. - bin/vault-run edits the vault under a lock with an atomic swap. - bin/worktree starts a task in a fresh worktree from origin/main. - CLAUDE.md explains the workflow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
41 lines
1.6 KiB
YAML
41 lines
1.6 KiB
YAML
---
|
|
# Imported at the top of site.yml and dns.yml.
|
|
#
|
|
# Several agents work on this repo at once. If one deploys from an unpushed
|
|
# branch, the next deploy from main quietly puts the old config back. So a
|
|
# real run only goes ahead when this checkout is exactly origin/main:
|
|
# land your commit on main first, then deploy that commit.
|
|
#
|
|
# --check runs are always allowed. -e allow_unpushed=true skips the guard
|
|
# for emergencies; push the fix to main straight after.
|
|
- name: Only deploy what's on origin/main
|
|
hosts: localhost
|
|
gather_facts: false
|
|
tags: always
|
|
tasks:
|
|
- name: Check this checkout matches origin/main
|
|
ansible.builtin.shell: |
|
|
set -eu
|
|
git fetch -q origin main
|
|
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
|
|
echo "This checkout has uncommitted changes. Commit them, land them on main, then deploy."
|
|
exit 1
|
|
fi
|
|
head=$(git rev-parse HEAD); main=$(git rev-parse origin/main)
|
|
if [ "$head" != "$main" ]; then
|
|
echo "HEAD $(git rev-parse --short HEAD) isn't origin/main ($(git rev-parse --short origin/main))."
|
|
if git merge-base --is-ancestor "$main" "$head"; then
|
|
echo "Your commits aren't on main yet: rebase, push to main, then deploy."
|
|
else
|
|
echo "main has moved on: rebase onto origin/main first, or other agents' changes get reverted."
|
|
fi
|
|
exit 1
|
|
fi
|
|
args:
|
|
chdir: "{{ playbook_dir }}"
|
|
changed_when: false
|
|
check_mode: false
|
|
when:
|
|
- not ansible_check_mode
|
|
- not (allow_unpushed | default(false) | bool)
|