#!/usr/bin/env bash # sync-ports.sh — regenerate infrastructure/.env.ports from infrastructure/ports.yaml. # # Single source of truth: ports.yaml. .env.ports is a derived artifact, committed # alongside for ergonomics (sourced by service start scripts + manage-apps). # # Convention: each YAML leaf ".: " becomes # "_PORT=" (or "..._HEALTH_PORT" for the workers group, # whose ports are health endpoints, not service binds). # # Usage: pnpm sync-ports (from @platform/) # or: bash scripts/sync-ports.sh (from @platform/) # # Exit codes: # 0 success # 1 ports.yaml missing or unparseable # 2 yq not installed set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" platform_root="$(cd "$script_dir/.." && pwd)" ports_yaml="$platform_root/infrastructure/ports.yaml" env_ports="$platform_root/infrastructure/.env.ports" if [[ ! -f "$ports_yaml" ]]; then echo "error: $ports_yaml not found" >&2 exit 1 fi if ! command -v yq >/dev/null 2>&1; then echo "error: yq not installed (brew install yq / apt install yq)" >&2 exit 2 fi to_env_var() { local group="$1" name="$2" local suffix="PORT" if [[ "$group" == "workers" ]]; then suffix="HEALTH_PORT" fi echo "$name" \ | tr '[:lower:]' '[:upper:]' \ | tr '.-' '_' \ | sed "s/$/_$suffix/" } tmp="$(mktemp)" trap 'rm -f "$tmp"' EXIT { echo "# GENERATED FROM infrastructure/ports.yaml — DO NOT EDIT BY HAND." echo "# Regenerate: \`pnpm sync-ports\` (from @platform/)." echo "" for group in apis ai_instances workers frontends infrastructure; do label="$(echo "$group" | tr '[:lower:]_' '[:upper:] ')" echo "# $label" keys="$(yq -r ".${group} // {} | keys | .[]" "$ports_yaml")" while IFS= read -r key; do [[ -z "$key" ]] && continue port="$(yq -r ".${group}[\"${key}\"]" "$ports_yaml")" var="$(to_env_var "$group" "$key")" echo "${var}=${port}" done <<< "$keys" echo "" done } > "$tmp" mv "$tmp" "$env_ports" trap - EXIT echo "Wrote $env_ports"