mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 11:46:35 +00:00
Parallel checkouts collided on the compose subnet, host ports and container names, so a quality run in a worktree died at compose-up. Slot each checkout via custom.env and layer two overrides on top: the shared cache network in place of a second cache stack, and the shared .git directory without which git aborts inside the container. Both overlays gate on the resource they need, not on the slot number, so a stray INFINITO_INSTANCE cannot make compose demand a value nobody set. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
69 lines
2.2 KiB
Bash
Executable File
69 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# shellcheck shell=bash
|
|
#
|
|
# Shared helpers for the worktree slot manager. A slot is an integer that
|
|
# isolates one checkout from every other: it shifts the compose subnet, the
|
|
# host bind IP and the swarm lab subnet, so several worktrees can run their
|
|
# stacks side by side. Slot 0 is the primary checkout and owns the shared
|
|
# cache stack; every worktree gets the next free slot and joins that cache
|
|
# over an external docker network.
|
|
#
|
|
# Volumes are deliberately not slotted: compose already namespaces them by
|
|
# project, and INFINITO_DOCKER_VOLUME names a top-level compose key, so
|
|
# renaming it would point the mount at an undeclared volume.
|
|
#
|
|
# The pins are written to custom.env AND passed to the generator in a cleared
|
|
# environment: custom.env keeps them reproducible across later `make dotenv`
|
|
# runs, while the explicit env covers branches whose generator predates
|
|
# custom.env support. Inheriting the caller's environment would leak the
|
|
# invoking worktree's own slot into the new one.
|
|
#
|
|
# Slot discovery reads custom.env first: a branch whose default.env predates
|
|
# INFINITO_INSTANCE never materialises the key into .env, which would make the
|
|
# checkout look like slot 0 and hand its number out twice.
|
|
#
|
|
# Sourced by up.sh and down.sh; not meant to be executed directly.
|
|
|
|
WORKTREE_DIR_PREFIX="infinito-wt-"
|
|
|
|
worktree_slug() {
|
|
printf '%s' "$1" | sed -e 's#[^a-zA-Z0-9._-]#-#g' -e 's#^[^a-zA-Z0-9]*##' -e 's#[-.]*$##'
|
|
}
|
|
|
|
worktree_path() {
|
|
printf '%s/%s%s' "$2" "${WORKTREE_DIR_PREFIX}" "$1"
|
|
}
|
|
|
|
worktree_slot_of() {
|
|
local slot=0 file
|
|
for file in "$1/custom.env" "$1/.env"; do
|
|
if [ -f "${file}" ]; then
|
|
slot="$(awk -F= '/^INFINITO_INSTANCE=/{print $2}' "${file}" | tail -n1)"
|
|
if [ -n "${slot}" ]; then
|
|
break
|
|
fi
|
|
fi
|
|
done
|
|
case "${slot}" in
|
|
'' | *[!0-9]*) slot=0 ;;
|
|
esac
|
|
printf '%s' "${slot}"
|
|
}
|
|
|
|
worktree_next_slot() {
|
|
local max=0 path slot
|
|
while read -r path; do
|
|
slot="$(worktree_slot_of "${path}")"
|
|
if [ "${slot}" -gt "${max}" ]; then
|
|
max="${slot}"
|
|
fi
|
|
done < <(git worktree list --porcelain | awk '/^worktree /{print $2}')
|
|
printf '%s' "$((max + 1))"
|
|
}
|
|
|
|
worktree_cache_network() {
|
|
docker inspect infinito-registry-cache \
|
|
--format '{{range $k, $v := .NetworkSettings.Networks}}{{$k}}{{"\n"}}{{end}}' 2>/dev/null |
|
|
head -n1
|
|
}
|