Files
probably-rendering-one-more…/scripts/preview/init.sh
T
codex-bot fe26f03cf4
Unified application CI and deployment / static-checks (push) Successful in 5s
Remote development preview source sync / sync-source (push) Failing after 4m54s
Unified application CI and deployment / static-checks (pull_request) Successful in 5s
python CI and deployment / static-checks (pull_request) Successful in 3s
Unified application CI and deployment / verify-and-release (push) Has been skipped
Unified application CI and deployment / verify-and-release (pull_request) Has been skipped
python CI and deployment / verify-and-deploy (pull_request) Has been skipped
Use numeric container ownership during preview setup
2026-11-04 14:25:41 +08:00

58 lines
2.8 KiB
Bash

#!/usr/bin/env bash
set -Eeuo pipefail
SOURCE=$(realpath "${1:?checkout directory required}")
IMAGE=${2:?verified integration image required}
PORT=${PREVIEW_PORT:-18136}
[[ "$IMAGE" =~ ^waterfall-wiki-tests:[0-9a-f]{40}$ ]] || exit 2
[[ "$PORT" =~ ^[0-9]+$ ]] && (( PORT >= 18136 && PORT <= 65535 )) || exit 2
command -v rsync >/dev/null
command -v ss >/dev/null
docker image inspect "$IMAGE" >/dev/null
ROOT=/opt/prompt-preview
exec 7>/var/lock/prompt-preview-init.lock
flock -w 30 7
if [ -s "$ROOT/fingerprint" ]; then echo 'Already initialized; use sync.sh, or perform an explicit manual refresh' >&2; exit 1; fi
if ss -H -ltn "sport = :$PORT" | grep -q .; then echo "Preview port $PORT is occupied; choose another PREVIEW_PORT" >&2; exit 1; fi
# The prebuilt tooling image must match dependency, startup and schema inputs.
expected=$(node "$SOURCE/scripts/preview/fingerprint.mjs" "$SOURCE")
actual=$(docker run --rm --entrypoint node \
--mount "type=bind,src=$SOURCE/scripts/preview/fingerprint.mjs,dst=/tmp/preview-fingerprint.mjs,readonly" \
"$IMAGE" /tmp/preview-fingerprint.mjs /repo)
[[ "$actual" == "$expected" ]] || { echo 'Tooling image does not match preview dependencies/configuration/schema' >&2; exit 1; }
install -d -m 0700 "$ROOT"
install -d -m 0755 "$ROOT/source" "$ROOT/status"
chown 1000:1000 "$ROOT/source" "$ROOT/status"
# Create independent preview credentials only once, never copy production secrets.
if [ ! -s "$ROOT/env" ]; then
ROOT="$ROOT" IMAGE="$IMAGE" PORT="$PORT" python3 - <<'PY'
import os,secrets,pathlib
p=pathlib.Path(os.environ['ROOT'])/'env'
with p.open('x') as f:
os.chmod(p,0o600)
f.write('PREVIEW_TOOL_IMAGE='+os.environ['IMAGE']+'\nPREVIEW_PORT='+os.environ['PORT']+'\n')
for key in ['POSTGRES_PASSWORD','S3_ACCESS_KEY','S3_SECRET_KEY']:f.write(key+'='+secrets.token_hex(24)+'\n')
PY
fi
rsync -a --delete --numeric-ids --chown=1000:1000 \
--exclude='.git' --exclude='node_modules' --exclude='.next' --exclude='dist' \
--exclude='*.tsbuildinfo' --exclude='.env' --exclude='.env.*' --exclude='.gitea' \
"$SOURCE/" "$ROOT/source/"
install -m 0644 "$SOURCE/scripts/preview/compose.yml" "$ROOT/compose.yml"
compose(){ docker compose -p prompt-preview --env-file "$ROOT/env" -f "$ROOT/compose.yml" "$@"; }
compose up -d --no-build --no-recreate --wait --wait-timeout 120 postgres objects
compose run --rm --no-deps prepare-tools
compose run --rm --no-deps auth-admin
compose run --rm --no-deps migrate
# The dependency volume is seeded from the already-verified image, no npm install.
compose up -d --no-build --no-recreate --no-deps waterfall-wiki
printf '%s\n' "$expected" > "$ROOT/fingerprint"
for attempt in {1..90}; do
if curl -fsS --max-time 5 "http://127.0.0.1:$PORT/api/health" >/dev/null; then
echo "Preview initialized on port $PORT; pnpm dev remains running"
exit 0
fi
sleep 2
done
compose logs --tail 60 waterfall-wiki
exit 1