Squash of Darkwing's 176a6bf4b..df65a3d4c on origin/darkwing/row190-r3, the 25 manifest paths, build-r3.patch efe898c2, manifest cc0ea9e8 (Filbert approve round 3, comment 29713). Design revision 3 in agents/darkwing/work/queue-190/DESIGN.md. Gate on based0bbc5c1cwith the patch: 15 package suites 2664 pass 0 fail, 10 scripts/test-*.sh suites 429 pass 0 fail (plus 156 node tests in the queue suite). Refactor moved to99a406ed3since, a window record touching no manifest path. Mutants 20 of 20 killed (BUILD.md, round 3). No live change: the stack runs from copy4429a104funtil a re-pin.
143 lines
6.7 KiB
Bash
143 lines
6.7 KiB
Bash
# Sourced, not run: stack instance selection for the shell entry points (row 190).
|
|
#
|
|
# instance_args "$@" take `--instance NAME` out of the arguments. Sets
|
|
# INSTANCE_FLAG (NAME, or empty) and INSTANCE_ARGS (the
|
|
# rest, in order). A second --instance or a missing
|
|
# NAME exits 4.
|
|
# instance_select run `mosaic-config.mjs instance [--instance NAME]`,
|
|
# which maps NAME to ~/.config/mosaic-NAME/config.json
|
|
# and checks the data root's instance.json claim, then
|
|
# set the names below. A refusal exits with the
|
|
# loader's code (3 claim or missing config, 4 name or
|
|
# mismatch) before the caller reads or writes anything.
|
|
#
|
|
# With no flag, every name is today's and MOSAIC_CONFIG is left as the caller
|
|
# had it. With --instance NAME (other than dev), MOSAIC_CONFIG is exported as
|
|
# NAME's config, so everything the entry point runs reads that config.
|
|
#
|
|
# BUS_TEMPLATE [email protected] | [email protected]
|
|
# BUS_GLOB 'mosaic-bus@*.service' | 'mosaic-bus-NAME@*.service'
|
|
# BUS_DROPIN_GLOBS unit-path globs whose .conf files can override the bus
|
|
# ExecStart: mosaic-bus@*.service.d for the default;
|
|
# mosaic-bus-NAME@*.service.d and the shared prefix
|
|
# mosaic-bus-.service.d for NAME; then mosaic-.service.d
|
|
# and service.d for both
|
|
# CONSOLE_UNIT mosaic-webui.service | mosaic-webui-NAME.service
|
|
# DISCORD_TEMPLATE [email protected] | [email protected]
|
|
# WRAPPER_NAME mosaic | mosaic-NAME
|
|
# SESSION_ENV %h/.config/mosaic-dev/secrets/claude-session.env
|
|
# | <config dir>/secrets/claude-session.env
|
|
# INSTANCE_FLAGS () or (--instance NAME), for the entry points this one runs
|
|
# INSTANCE_RESERVED ports a named instance's Console never takes: 7330 (the
|
|
# operator's bare Console), 7332 (the tunnel) and 7333
|
|
# (the default's tester); empty for the default
|
|
# INSTANCE_SED sed arguments that fill @CONFIG_ENV@ and @SESSION_ENV@
|
|
# in a unit template: the default deletes the
|
|
# @CONFIG_ENV@ line, so its render is byte-identical to
|
|
# the template before row 190; NAME gets a comment and
|
|
# Environment=MOSAIC_CONFIG=<config>, " [NAME]" after
|
|
# the Description, and the Console comment's "sets no
|
|
# MOSAIC_*" says it sets MOSAIC_CONFIG (Sage, N3)
|
|
#
|
|
# Also set: MOSAIC_INSTANCE (dev or NAME), MOSAIC_INSTANCE_CONFIG,
|
|
# MOSAIC_INSTANCE_CONFIG_DIR, MOSAIC_INSTANCE_DATA_ROOT (empty when no flag
|
|
# was given and the config is missing or invalid; the caller's own load
|
|
# refuses that as before) and MOSAIC_UNIT_SUFFIX (empty or -NAME).
|
|
|
|
INSTANCE_FLAG=""
|
|
INSTANCE_ARGS=()
|
|
INSTANCE_FLAGS=()
|
|
INSTANCE_RESERVED=()
|
|
|
|
instance_args() {
|
|
local seen=0
|
|
INSTANCE_FLAG=""
|
|
INSTANCE_ARGS=()
|
|
while [ $# -gt 0 ]; do
|
|
if [ "$1" = "--instance" ]; then
|
|
if [ "$seen" = 1 ] || [ $# -lt 2 ]; then
|
|
echo "instance: usage: --instance NAME, given once" >&2
|
|
exit 4
|
|
fi
|
|
INSTANCE_FLAG="$2"
|
|
seen=1
|
|
shift 2
|
|
else
|
|
INSTANCE_ARGS+=("$1")
|
|
shift
|
|
fi
|
|
done
|
|
}
|
|
|
|
instance_select() {
|
|
local here out
|
|
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
if [ -n "$INSTANCE_FLAG" ]; then
|
|
out="$(node "$here/mosaic-config.mjs" instance --instance "$INSTANCE_FLAG")" || exit $?
|
|
else
|
|
out="$(node "$here/mosaic-config.mjs" instance)" || exit $?
|
|
fi
|
|
eval "$out"
|
|
local s="$MOSAIC_UNIT_SUFFIX"
|
|
BUS_TEMPLATE="mosaic-bus$s@.service"
|
|
BUS_GLOB="mosaic-bus$s@*.service"
|
|
CONSOLE_UNIT="mosaic-webui$s.service"
|
|
DISCORD_TEMPLATE="mosaic-discord$s@.service"
|
|
WRAPPER_NAME="mosaic$s"
|
|
if [ -z "$s" ]; then
|
|
BUS_DROPIN_GLOBS=('mosaic-bus@*.service.d' 'mosaic-.service.d' 'service.d')
|
|
SESSION_ENV='%h/.config/mosaic-dev/secrets/claude-session.env'
|
|
INSTANCE_SED=(-e '/^@CONFIG_ENV@$/d' -e "s|@SESSION_ENV@|$SESSION_ENV|g")
|
|
return 0
|
|
fi
|
|
# systemd expands % and splits Environment= on spaces, and the sed
|
|
# expressions use |, so a named instance's paths keep to a plain set.
|
|
case "$MOSAIC_INSTANCE_CONFIG" in
|
|
*[!A-Za-z0-9/._+-]*)
|
|
echo "instance: config path contains a character a unit cannot carry: $MOSAIC_INSTANCE_CONFIG" >&2
|
|
exit 4 ;;
|
|
esac
|
|
export MOSAIC_CONFIG="${MOSAIC_CONFIG:-$MOSAIC_INSTANCE_CONFIG}"
|
|
INSTANCE_FLAGS=(--instance "$MOSAIC_INSTANCE")
|
|
INSTANCE_RESERVED=(7330 7332 7333)
|
|
BUS_DROPIN_GLOBS=("mosaic-bus$s@*.service.d" 'mosaic-bus-.service.d' 'mosaic-.service.d' 'service.d')
|
|
SESSION_ENV="$MOSAIC_INSTANCE_CONFIG_DIR/secrets/claude-session.env"
|
|
INSTANCE_SED=(
|
|
-e "s|^@CONFIG_ENV@\$|# Stack instance $MOSAIC_INSTANCE (row 190): the system config its processes read.\\nEnvironment=MOSAIC_CONFIG=$MOSAIC_INSTANCE_CONFIG|"
|
|
-e "s|@SESSION_ENV@|$SESSION_ENV|g"
|
|
-e "s|^\\(Description=.*\\)\$|\\1 [$MOSAIC_INSTANCE]|"
|
|
-e 's|The unit sets no MOSAIC_\*, CLAUDE\*, CODEX\* or PI_\* variable\.$|The unit sets MOSAIC_CONFIG and no other MOSAIC_*, CLAUDE*, CODEX* or PI_* variable.|'
|
|
)
|
|
}
|
|
|
|
# instance_port_holder DIR PORT: the installed Console unit in DIR, other than
|
|
# this instance's, whose ExecStart takes PORT as --port or --tester-port.
|
|
# A unit with no --port holds 7332, serve's default. Prints the unit and
|
|
# returns 0, or prints nothing and returns 1. Unit files are host
|
|
# configuration, so reading another instance's is not reading its state.
|
|
instance_port_holder() {
|
|
local dir="$1" want="$2" file unit line tok next port
|
|
want="$((10#$want))"
|
|
for file in "$dir"/mosaic-webui.service "$dir"/mosaic-webui-*.service; do
|
|
[ -f "$file" ] || continue
|
|
unit="${file##*/}"
|
|
[ "$unit" != "$CONSOLE_UNIT" ] || continue
|
|
line="$(sed -n 's/^ExecStart=//p' "$file" | tail -n 1)"
|
|
port=7332 next=""
|
|
local -a ports=() toks=()
|
|
read -r -a toks <<< "$line"
|
|
for tok in ${toks[@]+"${toks[@]}"}; do
|
|
case "$next" in
|
|
--port) [[ "$tok" =~ ^[0-9]{1,5}$ ]] && port="$((10#$tok))" ;;
|
|
--tester-port) [[ "$tok" =~ ^[0-9]{1,5}$ ]] && ports+=("$((10#$tok))") ;;
|
|
esac
|
|
next="$tok"
|
|
done
|
|
ports+=("$port")
|
|
for port in "${ports[@]}"; do
|
|
if [ "$port" = "$want" ]; then echo "$unit"; return 0; fi
|
|
done
|
|
done
|
|
return 1
|
|
}
|