Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180#!/bin/sh# starts the localinfra stack the way e2e needs it, with the web as a production build.# --check says whether it is up and its web build is current: 0 yes, 1 not up, 2 web out of date# a live pc stack wins over compose, so this check has to come firstset -euhere="$(cd "$(dirname "$0")" && pwd)"cd "$here/.."
E2E_WEB_SRC="$(node "$here/harness/web-hash.ts")"export E2E_WEB_SRC
pcdir="$PWD/localinfra/pc"state="$(here="$pcdir" && . "$pcdir/bin/env.sh" && echo "$TNGL_STATE")"sock="$state/run/pc.sock"pc() { curl -sf --unix-socket "$sock" "$@"; }pc_running() { pc http://localhost/live >/dev/null 2>&1; }
stack="${E2E_STACK:-}"if [ -z "$stack" ]; then if pc_running; then stack=pc elif command -v podman >/dev/null 2>&1 || command -v docker >/dev/null 2>&1; then stack=compose else stack=pc fifi
if [ "${1:-}" = "--stack" ]; then echo "$stack" exitfi
# only the browser knows these names, so curl needs --resolve to reach caddyalice_resolves() { curl -sf --cacert localinfra/certs/root.crt --resolve pds.tngl.boltless.dev:443:127.0.0.1 \ "https://pds.tngl.boltless.dev/xrpc/com.atproto.identity.resolveHandle?handle=alice.pds.tngl.boltless.dev" >/dev/null}
if [ "$stack" = pc ]; then log="$state/up.log" launcher=0 # a live stack only rebuilds the web. its other services have to come from this tree backend="$(git log -1 --format=%H -- . ':(exclude)web' ':(exclude)e2e')" # setup writes the source hash first, then the env checksum built="$(cut -d ' ' -f 1 "$state/data/web/built" 2>/dev/null || true)"
if [ "${1:-}" = "--check" ]; then pc_running || exit 1 [ "$built" = "$E2E_WEB_SRC" ] || exit 2 exit fi
if pc_running; then if [ "$(cat "$state/backend" 2>/dev/null)" != "$backend" ]; then echo "the running stack's services are not from this tree, stop it with: curl --unix-socket $sock -X POST http://localhost/project/stop" >&2 exit 1 fi if [ "$built" != "$E2E_WEB_SRC" ]; then (here="$pcdir" && . "$pcdir/bin/env.sh" && sh "$pcdir/services/web/setup") pc -X POST http://localhost/process/restart/web >/dev/null # a restart keeps reporting the old exit code until the new process is up, so poll for ready tries=0 until pc http://localhost/process/web | grep -q '"is_ready":"Ready"'; do tries=$((tries + 1)) [ "$tries" -lt 300 ] || { echo "the web did not come back after its restart" >&2; exit 1; } sleep 1 done fi else mkdir -p "$state" echo "$backend" >"$state/backend" # pipeline specs need a spindle, and compose always runs one. the sites specs need the worker and sitesd for profile in spindle sites; do case ",${TNGL_PROFILES:-}," in *,"$profile",*) ;; *) TNGL_PROFILES=${TNGL_PROFILES:+$TNGL_PROFILES,}$profile ;; esac done export TNGL_PROFILES # not -D, linux port forwarders and slirp die with the foreground process # own session, so a caller killing its process group doesn't take the stack down own_session() { if command -v setsid >/dev/null 2>&1; then exec setsid "$@"; fi exec perl -MPOSIX -e 'POSIX::setsid(); exec @ARGV' "$@" } if command -v nix >/dev/null 2>&1; then own_session nix run .#localinfra -- -t=false >"$log" 2>&1 & else own_session "$pcdir/bin/up" -t=false >"$log" 2>&1 & fi launcher=$! fi
node -e ' const http = require("node:http"); const list = () => new Promise((resolve, reject) => http .get({ socketPath: process.argv[1], path: "/processes" }, (res) => { let body = ""; res.on("data", (chunk) => (body += chunk)); res.on("end", () => resolve(JSON.parse(body).data)); }) .on("error", reject) ); const failed = (p) => p.status === "Error" || (p.status === "Completed" && p.exit_code !== 0); const launcher = Number(process.argv[2]); const deadline = Date.now() + Number(process.argv[3]) * 1000; const launcherGone = () => { if (!launcher) return false; try { process.kill(launcher, 0); return false; } catch { return true; } }; (async () => { for (;;) { const all = await list().catch(() => []); const bad = all.find(failed); if (bad) { console.error(`${bad.name} failed, its log is in the stack`); process.exit(1); } if (all.length && all.every((p) => p.status === "Completed" || p.is_ready === "Ready")) return; if (launcherGone() || Date.now() > deadline) { console.error("the stack did not come up"); process.exit(1); } await new Promise((resolve) => setTimeout(resolve, 2000)); } })(); ' "$sock" "$launcher" "${E2E_UP_TIMEOUT:-3600}" || { [ "$launcher" = 0 ] || tail -n 30 "$log" >&2 exit 1 }
if ! alice_resolves; then echo "alice doesn't resolve, the stack's init-data hasn't run" >&2 exit 1 fi exitfi
# the web is a production build here, so no page waits on a module compiling when it is first asked forweb="-f localinfra/docker-compose.web-build.yml"if command -v podman >/dev/null 2>&1; then engine=podman compose="podman compose -f docker-compose.yml $web"else # docker doesn't publish ports from an internal network, which caddy sits on engine=docker compose="docker compose -f docker-compose.yml -f localinfra/docker-compose.docker.yml $web"fi
if [ "${1:-}" = "--check" ]; then id=$($compose ps --status running -q web 2>/dev/null || true) [ -n "$id" ] || exit 1 # the dev server answers too, but every first page waits on it compiling $engine inspect --format '{{join .Config.Cmd " "}}' "$id" | grep -q "vite build" || exit 1 built="$($engine inspect --format '{{index .Config.Labels "e2e.web-src"}}' "$id")" [ "$built" = "$E2E_WEB_SRC" ] || exit 2 exitfi
if [ ! -f localinfra/certs/root.crt ]; then echo "no dev ca yet, run ./localinfra/scripts/make-certs.sh and trust localinfra/certs/root.crt" >&2 exit 1fi
# compose only recreates the web when this label value changes$compose up -d --wait
if ! alice_resolves; then echo "alice doesn't resolve, the stack's init-data hasn't run" >&2 exit 1fi