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
58 lines
2.8 KiB
Bash
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
|