Files
ThothII/scripts/compose-with-preflight.sh
Codex eba6148511 test: stabilize pre-deployment gates
Remove the redundant timing-dependent native Argon2 concurrency test while retaining native vector coverage and deterministic limiter coverage. Refresh stale deployment and browser contracts, make release scripts portable across Bash/macOS, and update production dependency locks for resolved security advisories.
2026-09-04 16:15:35 +02:00

132 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Validate operator-managed Compose inputs before delegating to Docker Compose.
set -euo pipefail
usage() {
echo "usage: $0 --env-file <operator.env> -f <compose.yaml> ... <docker-compose-command>" >&2
exit 2
}
trim() {
local value="$1"
value="${value#"${value%%[![:space:]]*}"}"
value="${value%"${value##*[![:space:]]}"}"
printf '%s' "$value"
}
is_safe_absolute_path() {
local value="$1" segment
local -a segments
[[ "$value" == /* && "$value" != *//* ]] || return 1
IFS=/ read -r -a segments <<<"$value"
for segment in "${segments[@]}"; do
[[ "$segment" != . && "$segment" != .. ]] || return 1
done
}
read_env_value() {
local source="$1" wanted="$2" line trimmed name value result=""
while IFS= read -r line || [[ -n "$line" ]]; do
trimmed="$(trim "$line")"
[[ -n "$trimmed" && "$trimmed" != \#* && "$trimmed" == *=* ]] || continue
name="$(trim "${trimmed%%=*}")"
[[ "$name" == "$wanted" ]] || continue
value="$(trim "${trimmed#*=}")"
value="$(trim "${value%%#*}")"
value="${value#\"}"; value="${value%\"}"
value="${value#\'}"; value="${value%\'}"
result="$value"
done <"$source"
printf '%s' "$result"
}
source_names() {
local source="$1" line trimmed name
{
while IFS= read -r line || [[ -n "$line" ]]; do
trimmed="$(trim "$line")"
[[ -n "$trimmed" && "$trimmed" != \#* && "$trimmed" == *=* ]] || continue
name="$(trim "${trimmed%%=*}")"
[[ "$name" =~ ^[A-Za-z_][A-Za-z0-9_]*_SOURCE$ ]] && printf '%s\n' "$name"
done <"$source"
while IFS= read -r line; do
name="${line%%=*}"
[[ "$name" =~ ^[A-Za-z_][A-Za-z0-9_]*_SOURCE$ ]] && printf '%s\n' "$name"
done < <(env)
} | sort -u
}
record_git_transport() {
local compose_file="$1" transport=""
[[ -f "$compose_file" ]] || return 0
transport="$(awk '
/^[[:space:]]*x-thoth-git-transport:[[:space:]]*/ {
value = $0
sub(/^[[:space:]]*x-thoth-git-transport:[[:space:]]*/, "", value)
sub(/[[:space:]]*#.*/, "", value)
print value
exit
}
' "$compose_file")"
case "$transport" in
ssh) ssh_override=1 ;;
https) https_override=1 ;;
"")
case "$(basename "$compose_file")" in
*git-ssh*.yaml|*git-ssh*.yml) ssh_override=1 ;;
*git-https*.yaml|*git-https*.yml) https_override=1 ;;
esac
;;
*) echo "invalid x-thoth-git-transport in $compose_file" >&2; exit 2 ;;
esac
}
env_file=""
ssh_override=0
https_override=0
arguments=("$@")
for ((index = 0; index < ${#arguments[@]}; index += 1)); do
argument="${arguments[index]}"
case "$argument" in
--env-file)
((index + 1 < ${#arguments[@]})) || usage
((index += 1))
env_file="${arguments[index]}"
;;
--env-file=*) env_file="${argument#--env-file=}" ;;
-f|--file)
((index + 1 < ${#arguments[@]})) || usage
((index += 1))
compose_file="${arguments[index]}"
record_git_transport "$compose_file"
;;
--file=*)
compose_file="${argument#--file=}"
record_git_transport "$compose_file"
;;
esac
done
[[ -n "$env_file" && -f "$env_file" ]] || { echo "Compose preflight requires an existing --env-file" >&2; exit 2; }
if ((ssh_override && https_override)); then
echo "SSH and HTTPS Git overrides are mutually exclusive" >&2
exit 2
fi
while IFS= read -r name; do
if [[ "$name" == *"_VECTOR_"* || "$name" == *"_EMBEDDING_"* || "$name" == THT_VECTOR_* ]]; then
echo "retired semantic source path is not supported: $name" >&2
exit 2
fi
value="$(read_env_value "$env_file" "$name")"
if declare -p "$name" >/dev/null 2>&1; then
value="${!name}"
fi
if [[ -n "$value" ]] && ! is_safe_absolute_path "$value"; then
echo "unsafe source path for $name in $env_file" >&2
exit 2
fi
done < <(source_names "$env_file")
exec docker compose "${arguments[@]}"