feat: move distribution builds to platform Docker builder

This commit is contained in:
npc0-hue
2026-07-30 19:25:50 +08:00
parent 1e004dc9ec
commit e614a17fe3
45 changed files with 4492 additions and 294 deletions
+25 -1
View File
@@ -25,11 +25,12 @@ export PLATFORM_BOOTSTRAP_ADMIN_EMAIL="${PLATFORM_BOOTSTRAP_ADMIN_EMAIL:-operato
export PLATFORM_BOOTSTRAP_ADMIN_PASSWORD="${PLATFORM_BOOTSTRAP_ADMIN_PASSWORD:-operator-local}"
export PLATFORM_SECRET_ENVELOPE_KEY="${PLATFORM_SECRET_ENVELOPE_KEY:-local-debug-secret-envelope-key-change-me}"
export PLATFORM_AI_PROVIDER_MODE="${PLATFORM_AI_PROVIDER_MODE:-mock}"
export PLATFORM_RUN_RELEASE_URL="${PLATFORM_RUN_RELEASE_URL:-http://127.0.0.1:$LOCAL_DEBUG_PLATFORM_PORT}"
export RUN_SOURCE_DIR="${RUN_SOURCE_DIR:-${RUN_REPO_DIR:-$LOCAL_DEBUG_ROOT_DIR/run}}"
export RUN_REPO_DIR="$RUN_SOURCE_DIR"
export RUN_MODE="${RUN_MODE:-worker}"
export RUN_PLATFORM_URL="${RUN_PLATFORM_URL:-https://scum.npc0.com:$LOCAL_DEBUG_PLATFORM_PORT}"
export RUN_PLATFORM_URL="${RUN_PLATFORM_URL:-http://127.0.0.1:$LOCAL_DEBUG_PLATFORM_PORT}"
export RUN_ENDPOINT_ID="${RUN_ENDPOINT_ID:-run-local-debug}"
export RUN_DISPLAY_NAME="${RUN_DISPLAY_NAME:-Local Debug Run}"
export RUN_VERSION="${RUN_VERSION:-0.1.0-local-debug}"
@@ -38,6 +39,11 @@ export RUN_WORKSPACE_ROOT="${RUN_WORKSPACE_ROOT:-$LOCAL_DEBUG_ROOT/run/workspace
export RUN_BUILD_BUCKET_ROOT="${RUN_BUILD_BUCKET_ROOT:-$LOCAL_DEBUG_ROOT/run/build-buckets}"
export RUN_BUILD_SOURCE_ROOT="${RUN_BUILD_SOURCE_ROOT:-$RUN_BUILD_BUCKET_ROOT/source/current}"
export RUN_BOOTSTRAP_BIN="${RUN_BOOTSTRAP_BIN:-$RUN_BUILD_BUCKET_ROOT/bootstrap/bin/run}"
export PLATFORM_BUILDER_DOCKER_BINARY="${PLATFORM_BUILDER_DOCKER_BINARY:-docker}"
export PLATFORM_BUILDER_IMAGE="${PLATFORM_BUILDER_IMAGE:-browser-platform-distribution-builder:1.0.0}"
export PLATFORM_BUILDER_SOURCE_DIR="${PLATFORM_BUILDER_SOURCE_DIR:-$RUN_BUILD_SOURCE_ROOT}"
export PLATFORM_BUILDER_WORKSPACE_DIR="${PLATFORM_BUILDER_WORKSPACE_DIR:-$PLATFORM_DATA_DIR/distribution-builds}"
export PLATFORM_BUILDER_TIMEOUT_SECONDS="${PLATFORM_BUILDER_TIMEOUT_SECONDS:-1800}"
export RUN_SPOOL_ROOT="${RUN_SPOOL_ROOT:-$LOCAL_DEBUG_ROOT/run/spool}"
export RUN_MAX_JOBS="${RUN_MAX_JOBS:-1}"
export RUN_HEARTBEAT_INTERVAL_MS="${RUN_HEARTBEAT_INTERVAL_MS:-2000}"
@@ -162,6 +168,24 @@ local_debug_prepare_run_build_source() {
EOF
}
local_debug_prepare_distribution_builder() {
local_debug_prepare_run_build_source
if ! command -v "$PLATFORM_BUILDER_DOCKER_BINARY" >/dev/null 2>&1; then
printf 'platform distribution builder requires %s\n' "$PLATFORM_BUILDER_DOCKER_BINARY" >&2
return 1
fi
if [[ "$PLATFORM_BUILDER_IMAGE" == "browser-platform-distribution-builder:1.0.0" ]]; then
"$PLATFORM_BUILDER_DOCKER_BINARY" build \
-t "$PLATFORM_BUILDER_IMAGE" \
"$LOCAL_DEBUG_ROOT_DIR/platform/distribution-builder"
return
fi
if ! "$PLATFORM_BUILDER_DOCKER_BINARY" image inspect "$PLATFORM_BUILDER_IMAGE" >/dev/null 2>&1; then
printf 'configured platform builder image is not present: %s\n' "$PLATFORM_BUILDER_IMAGE" >&2
return 1
fi
}
local_debug_build_bootstrap_run() {
local_debug_prepare_run_build_source
mkdir -p "$(dirname "$RUN_BOOTSTRAP_BIN")"
+388 -64
View File
@@ -8,14 +8,35 @@ source "$ROOT_DIR/scripts/local-debug/env.sh"
PLATFORM_URL="$(local_debug_platform_url)"
API_URL="$PLATFORM_URL/api/v1"
WORK_DIR="$LOCAL_DEBUG_ROOT/smoke"
SMOKE_INVOCATION_ID="${SMOKE_INVOCATION_ID:-$(date -u +%Y%m%d%H%M%S)-$$}"
SERVER_LOCAL_ID="server-local-debug-$SMOKE_INVOCATION_ID"
SCUM_ALPHA_ID="scum-alpha-$SMOKE_INVOCATION_ID"
SCUM_BETA_ID="scum-beta-$SMOKE_INVOCATION_ID"
SCUM_DYNAMIC_ID="scum-dynamic-$SMOKE_INVOCATION_ID"
GENERATED_RUN_ENDPOINT_ID="server-run-$SERVER_LOCAL_ID"
GENERATED_RUN_BIN="$WORK_DIR/generated-$SERVER_LOCAL_ID-run"
GENERATED_RUN_LOG="$LOCAL_DEBUG_LOG_DIR/generated-$SERVER_LOCAL_ID-run.log"
GENERATED_RUN_PID_FILE="$LOCAL_DEBUG_PID_DIR/generated-$SERVER_LOCAL_ID-run.pid"
mkdir -p "$WORK_DIR"
cat >"$WORK_DIR/run-build-config.env" <<EOF
SMOKE_INVOCATION_ID=$SMOKE_INVOCATION_ID
SERVER_LOCAL_ID=$SERVER_LOCAL_ID
SCUM_ALPHA_ID=$SCUM_ALPHA_ID
SCUM_BETA_ID=$SCUM_BETA_ID
SCUM_DYNAMIC_ID=$SCUM_DYNAMIC_ID
GENERATED_RUN_ENDPOINT_ID=$GENERATED_RUN_ENDPOINT_ID
PLATFORM_RUN_RELEASE_URL=$PLATFORM_RUN_RELEASE_URL
RUN_SOURCE_DIR=$RUN_SOURCE_DIR
RUN_REPO_DIR=$RUN_REPO_DIR
RUN_BUILD_BUCKET_ROOT=$RUN_BUILD_BUCKET_ROOT
RUN_BUILD_SOURCE_ROOT=$RUN_BUILD_SOURCE_ROOT
RUN_BOOTSTRAP_BIN=$RUN_BOOTSTRAP_BIN
PLATFORM_BUILDER_DOCKER_BINARY=$PLATFORM_BUILDER_DOCKER_BINARY
PLATFORM_BUILDER_IMAGE=$PLATFORM_BUILDER_IMAGE
PLATFORM_BUILDER_SOURCE_DIR=$PLATFORM_BUILDER_SOURCE_DIR
PLATFORM_BUILDER_WORKSPACE_DIR=$PLATFORM_BUILDER_WORKSPACE_DIR
PLATFORM_BUILDER_TIMEOUT_SECONDS=$PLATFORM_BUILDER_TIMEOUT_SECONDS
RUN_WORKSPACE_ROOT=$RUN_WORKSPACE_ROOT
RUN_SPOOL_ROOT=$RUN_SPOOL_ROOT
RUN_MAX_JOBS=$RUN_MAX_JOBS
@@ -23,10 +44,10 @@ EOF
prepare_run_workspace() {
local_debug_prepare_run_lifecycle_templates
local_debug_seed_server_lifecycle_workspace server-local-debug game.example run-local
local_debug_seed_server_lifecycle_workspace scum-alpha game.scum run-local
local_debug_seed_server_lifecycle_workspace scum-beta game.scum run-local
local_debug_seed_server_lifecycle_workspace scum-dynamic game.scum run-local
local_debug_seed_server_lifecycle_workspace "$SERVER_LOCAL_ID" game.example run-local
local_debug_seed_server_lifecycle_workspace "$SCUM_ALPHA_ID" game.scum run-local
local_debug_seed_server_lifecycle_workspace "$SCUM_BETA_ID" game.scum run-local
local_debug_seed_server_lifecycle_workspace "$SCUM_DYNAMIC_ID" game.scum run-local
}
prepare_run_workspace
@@ -58,8 +79,55 @@ wait_for_url() {
return 1
}
assert_no_active_run_session() {
local endpoint_file="$WORK_DIR/bootstrap-run-endpoint.response.json"
local endpoint_url="${RUN_PLATFORM_URL%/}/api/v1/run/endpoints/$RUN_ENDPOINT_ID"
local status
status="$(curl -sS -o "$endpoint_file" -w '%{http_code}' "$endpoint_url" || true)"
case "$status" in
404)
return 0
;;
200)
if node - "$endpoint_file" <<'NODE'
const fs = require("fs");
const endpoint = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
const heartbeat = endpoint.lastHeartbeatAt || endpoint.LastHeartbeatAt;
const ageMilliseconds = heartbeat ? Date.now() - Date.parse(heartbeat) : Number.POSITIVE_INFINITY;
process.exit(endpoint.status === "online" && Number.isFinite(ageMilliseconds) && ageMilliseconds >= 0 && ageMilliseconds < 30_000 ? 0 : 1);
NODE
then
printf 'refusing to self-start Run endpoint %s: an active session already exists at %s\n' "$RUN_ENDPOINT_ID" "$RUN_PLATFORM_URL" >&2
printf 'run the smoke against that existing stack, or stop the existing Run before using LOCAL_DEBUG_SELF_START=true\n' >&2
return 1
fi
return 0
;;
*)
printf 'refusing to self-start Run endpoint %s: could not verify its session state at %s (HTTP %s)\n' "$RUN_ENDPOINT_ID" "$RUN_PLATFORM_URL" "$status" >&2
return 1
;;
esac
}
assert_no_managed_run_process() {
local run_pid_file="$LOCAL_DEBUG_PID_DIR/run.pid"
if [[ ! -f "$run_pid_file" ]]; then
return 0
fi
local pid
pid="$(<"$run_pid_file")"
if [[ "$pid" =~ ^[0-9]+$ ]] && kill -0 "$pid" 2>/dev/null; then
printf 'refusing to self-start a second Run while managed Run pid %s is active\n' "$pid" >&2
printf 'run the smoke against that existing stack, or stop it before using LOCAL_DEBUG_SELF_START=true\n' >&2
return 1
fi
rm -f "$run_pid_file"
}
start_self_hosted_stack() {
mkdir -p "$LOCAL_DEBUG_LOG_DIR" "$LOCAL_DEBUG_PID_DIR" "$PLATFORM_DATA_DIR" "$PLATFORM_LOG_DIR" "$PLATFORM_ARTIFACT_DIR" "$RUN_WORKSPACE_ROOT" "$RUN_SPOOL_ROOT" "$RUN_BUILD_BUCKET_ROOT" "$GOCACHE"
local_debug_prepare_distribution_builder
trap cleanup_self_started EXIT
printf 'self-starting platform for local debug smoke\n'
@@ -73,10 +141,16 @@ start_self_hosted_stack() {
PLATFORM_METADATA_PATH="$PLATFORM_METADATA_PATH" \
PLATFORM_LOG_BODY_BACKEND="$PLATFORM_LOG_BODY_BACKEND" \
PLATFORM_LOG_DIR="$PLATFORM_LOG_DIR" \
PLATFORM_ARTIFACT_DIR="$PLATFORM_ARTIFACT_DIR" \
PLATFORM_BOOTSTRAP_ADMIN_EMAIL="$PLATFORM_BOOTSTRAP_ADMIN_EMAIL" \
PLATFORM_BOOTSTRAP_ADMIN_PASSWORD="$PLATFORM_BOOTSTRAP_ADMIN_PASSWORD" \
PLATFORM_SECRET_ENVELOPE_KEY="$PLATFORM_SECRET_ENVELOPE_KEY" \
PLATFORM_ARTIFACT_DIR="$PLATFORM_ARTIFACT_DIR" \
PLATFORM_BOOTSTRAP_ADMIN_EMAIL="$PLATFORM_BOOTSTRAP_ADMIN_EMAIL" \
PLATFORM_BOOTSTRAP_ADMIN_PASSWORD="$PLATFORM_BOOTSTRAP_ADMIN_PASSWORD" \
PLATFORM_SECRET_ENVELOPE_KEY="$PLATFORM_SECRET_ENVELOPE_KEY" \
PLATFORM_RUN_RELEASE_URL="$PLATFORM_RUN_RELEASE_URL" \
PLATFORM_BUILDER_DOCKER_BINARY="$PLATFORM_BUILDER_DOCKER_BINARY" \
PLATFORM_BUILDER_IMAGE="$PLATFORM_BUILDER_IMAGE" \
PLATFORM_BUILDER_SOURCE_DIR="$PLATFORM_BUILDER_SOURCE_DIR" \
PLATFORM_BUILDER_WORKSPACE_DIR="$PLATFORM_BUILDER_WORKSPACE_DIR" \
PLATFORM_BUILDER_TIMEOUT_SECONDS="$PLATFORM_BUILDER_TIMEOUT_SECONDS" \
go run ./cmd/platform
) >"$LOCAL_DEBUG_LOG_DIR/platform.log" 2>&1 &
SELF_STARTED_PIDS+=("$!")
@@ -402,6 +476,108 @@ if (reference.artifactId !== artifactId || reference.checksum !== checksum || pa
NODE
}
local_debug_host_target() {
local os_name
local arch_name
case "$(uname -s)" in
Darwin) os_name="darwin" ;;
Linux) os_name="linux" ;;
*) printf 'unsupported local-debug generated Run host OS: %s\n' "$(uname -s)" >&2; return 1 ;;
esac
case "$(uname -m)" in
arm64 | aarch64) arch_name="arm64" ;;
x86_64 | amd64) arch_name="amd64" ;;
*) printf 'unsupported local-debug generated Run host architecture: %s\n' "$(uname -m)" >&2; return 1 ;;
esac
printf '%s/%s' "$os_name" "$arch_name"
}
launch_generated_run() {
local payload_file="$1"
mkdir -p "$LOCAL_DEBUG_LOG_DIR" "$LOCAL_DEBUG_PID_DIR" "$(dirname "$GENERATED_RUN_BIN")" "$RUN_SPOOL_ROOT/$GENERATED_RUN_ENDPOINT_ID"
cp "$payload_file" "$GENERATED_RUN_BIN"
chmod 700 "$GENERATED_RUN_BIN"
(
unset RUN_PLATFORM_URL RUN_ENDPOINT_ID RUN_DISPLAY_NAME RUN_VERSION RUN_REGISTRATION_TOKEN
unset RUN_SERVER_INSTANCE_ID RUN_PLUGIN_ID RUN_COMPONENT_KIND RUN_COMPONENT_KEY RUN_KEY_GENERATION RUN_PACKAGE_CONFIG
exec env \
GOCACHE="$GOCACHE" \
RUN_MODE=worker \
RUN_WORKSPACE_ROOT="$RUN_WORKSPACE_ROOT" \
RUN_BUILD_SOURCE_ROOT="$RUN_BUILD_SOURCE_ROOT" \
RUN_SPOOL_ROOT="$RUN_SPOOL_ROOT/$GENERATED_RUN_ENDPOINT_ID" \
RUN_MAX_JOBS="$RUN_MAX_JOBS" \
RUN_HEARTBEAT_INTERVAL_MS="$RUN_HEARTBEAT_INTERVAL_MS" \
RUN_POLL_INTERVAL_MS="$RUN_POLL_INTERVAL_MS" \
RUN_RETRY_BACKOFF_MS="$RUN_RETRY_BACKOFF_MS" \
"$GENERATED_RUN_BIN"
) >"$GENERATED_RUN_LOG" 2>&1 &
local generated_pid="$!"
printf '%s' "$generated_pid" >"$GENERATED_RUN_PID_FILE"
if [[ "${LOCAL_DEBUG_SELF_START:-false}" == "true" ]]; then
SELF_STARTED_PIDS+=("$generated_pid")
fi
}
wait_for_generated_run_registration_and_heartbeat() {
local registration_file="$WORK_DIR/generated-run-registration.response.json"
local heartbeat_file="$WORK_DIR/generated-run-heartbeat.response.json"
local first_heartbeat=""
rm -f "$registration_file" "$heartbeat_file"
printf 'waiting for generated Run endpoint %s registration\n' "$GENERATED_RUN_ENDPOINT_ID"
for _ in $(seq 1 45); do
if [[ -f "$GENERATED_RUN_PID_FILE" ]] && ! kill -0 "$(<"$GENERATED_RUN_PID_FILE")" 2>/dev/null; then
printf 'generated Run exited before registration; see %s\n' "$GENERATED_RUN_LOG" >&2
return 1
fi
if json_get "$API_URL/run/endpoints/$GENERATED_RUN_ENDPOINT_ID" "$registration_file" "${AUTH_HEADER[@]}" 2>/dev/null; then
if first_heartbeat="$(node - "$registration_file" "$GENERATED_RUN_ENDPOINT_ID" <<'NODE'
const fs = require("fs");
const endpoint = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
const expectedID = process.argv[3];
const heartbeat = endpoint.lastHeartbeatAt || endpoint.LastHeartbeatAt || "";
const capabilities = endpoint.capabilities || endpoint.Capabilities || [];
if (endpoint.id !== expectedID || endpoint.status !== "online" || !heartbeat || capabilities.includes("distribution.build")) {
process.exit(1);
}
process.stdout.write(heartbeat);
NODE
)"; then
break
fi
fi
sleep 1
done
if [[ -z "$first_heartbeat" ]]; then
printf 'generated Run endpoint %s did not register with a safe capability report\n' "$GENERATED_RUN_ENDPOINT_ID" >&2
[[ -f "$GENERATED_RUN_LOG" ]] && sed -n '1,160p' "$GENERATED_RUN_LOG" >&2
return 1
fi
reject_forbidden_fragments "$registration_file"
printf 'waiting for generated Run endpoint %s heartbeat\n' "$GENERATED_RUN_ENDPOINT_ID"
for _ in $(seq 1 45); do
if json_get "$API_URL/run/endpoints/$GENERATED_RUN_ENDPOINT_ID" "$heartbeat_file" "${AUTH_HEADER[@]}" 2>/dev/null && node - "$heartbeat_file" "$GENERATED_RUN_ENDPOINT_ID" "$first_heartbeat" <<'NODE'
const fs = require("fs");
const endpoint = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
const expectedID = process.argv[3];
const firstHeartbeat = Date.parse(process.argv[4]);
const heartbeat = Date.parse(endpoint.lastHeartbeatAt || endpoint.LastHeartbeatAt || "");
const capabilities = endpoint.capabilities || endpoint.Capabilities || [];
process.exit(endpoint.id === expectedID && endpoint.status === "online" && Number.isFinite(heartbeat) && heartbeat > firstHeartbeat && !capabilities.includes("distribution.build") ? 0 : 1);
NODE
then
reject_forbidden_fragments "$heartbeat_file"
return 0
fi
sleep 1
done
printf 'generated Run endpoint %s did not report a subsequent heartbeat\n' "$GENERATED_RUN_ENDPOINT_ID" >&2
[[ -f "$GENERATED_RUN_LOG" ]] && sed -n '1,160p' "$GENERATED_RUN_LOG" >&2
return 1
}
wait_for_lifecycle_install_success() {
local server_id="$1"
local output_file="$2"
@@ -476,7 +652,7 @@ const manifest = {
createFormSchema: source.server.createFormSchema
},
capabilities: ["process.install", "process.start", "process.stop", "config.write"],
permissions: ["server.read", "server.lifecycle", "server.logs.read", "server.artifacts.read", "ai.invoke"],
permissions: ["server.read", "server.lifecycle", "server.run.distribution", "server.logs.read", "server.artifacts.read", "ai.invoke"],
actions: {
install: source.actions.install,
start: source.actions.start,
@@ -488,11 +664,11 @@ const manifest = {
key: "logs",
title: "Logs",
path: "/logs",
permissions: ["server.read", "server.lifecycle", "server.logs.read", "server.artifacts.read", "ai.invoke"],
bridgeActions: ["server.instances.read", "jobs.dispatch", "logs.query", "artifacts.open", "plugin-lifecycle.request", "ai.invoke"]
permissions: ["server.read", "server.lifecycle", "server.run.distribution", "server.logs.read", "server.artifacts.read", "ai.invoke"],
bridgeActions: ["server.instances.read", "jobs.dispatch", "logs.query", "artifacts.open", "run.distribution.request", "plugin-lifecycle.request", "ai.invoke"]
}
],
bridge: { actions: ["server.instances.read", "jobs.dispatch", "logs.query", "artifacts.open", "plugin-lifecycle.request", "ai.invoke"] },
bridge: { actions: ["server.instances.read", "jobs.dispatch", "logs.query", "artifacts.open", "run.distribution.request", "plugin-lifecycle.request", "ai.invoke"] },
ai: source.ai,
productionLifecycle: source.productionLifecycle,
runtimeProfiles: {
@@ -595,25 +771,45 @@ done
require_file_contains "$WORK_DIR/run-endpoints.response.json" "$RUN_ENDPOINT_ID"
reject_forbidden_fragments "$WORK_DIR/run-endpoints.response.json"
GENERATED_RUN_TARGET="$(local_debug_host_target)"
IFS=/ read -r GENERATED_RUN_TARGET_OS GENERATED_RUN_TARGET_ARCH <<<"$GENERATED_RUN_TARGET"
printf 'GENERATED_RUN_TARGET_OS=%s\nGENERATED_RUN_TARGET_ARCH=%s\n' "$GENERATED_RUN_TARGET_OS" "$GENERATED_RUN_TARGET_ARCH" >>"$WORK_DIR/run-build-config.env"
cat >"$WORK_DIR/create-server.request.json" <<JSON
{
"id": "server-local-debug",
"id": "$SERVER_LOCAL_ID",
"pluginId": "game.example",
"runEndpointId": "$RUN_ENDPOINT_ID",
"name": "Local Debug Example Server",
"idempotencyKey": "local-debug-create",
"name": "Local Debug Example Server $SMOKE_INVOCATION_ID",
"idempotencyKey": "local-debug-create-$SMOKE_INVOCATION_ID"
}
JSON
cat >"$WORK_DIR/server-runtime-binding.request.json" <<JSON
{
"profileKey": "run-local",
"bindings": {}
}
JSON
cat >"$WORK_DIR/server-run-generate.request.json" <<JSON
{
"targetOs": "$GENERATED_RUN_TARGET_OS",
"targetArch": "$GENERATED_RUN_TARGET_ARCH",
"idempotencyKey": "local-debug-server-run-generate-$SMOKE_INVOCATION_ID"
}
JSON
cat >"$WORK_DIR/create-scum-alpha.request.json" <<JSON
{
"id": "scum-alpha",
"id": "$SCUM_ALPHA_ID",
"pluginId": "game.scum",
"runEndpointId": "$RUN_ENDPOINT_ID",
"name": "SCUM Alpha",
"idempotencyKey": "local-debug-scum-alpha-create",
"name": "SCUM Alpha $SMOKE_INVOCATION_ID",
"idempotencyKey": "local-debug-scum-alpha-create-$SMOKE_INVOCATION_ID"
}
JSON
cat >"$WORK_DIR/scum-alpha-runtime-binding.request.json" <<JSON
{
"profileKey": "run-local",
"bindings": {}
}
@@ -621,11 +817,11 @@ JSON
cat >"$WORK_DIR/create-scum-beta.request.json" <<JSON
{
"id": "scum-beta",
"id": "$SCUM_BETA_ID",
"pluginId": "game.scum",
"runEndpointId": "$RUN_ENDPOINT_ID",
"name": "SCUM Beta",
"idempotencyKey": "local-debug-scum-beta-create",
"name": "SCUM Beta $SMOKE_INVOCATION_ID",
"idempotencyKey": "local-debug-scum-beta-create-$SMOKE_INVOCATION_ID",
"profileKey": "run-local",
"bindings": {}
}
@@ -633,11 +829,11 @@ JSON
cat >"$WORK_DIR/create-scum-dynamic.request.json" <<JSON
{
"id": "scum-dynamic",
"id": "$SCUM_DYNAMIC_ID",
"pluginId": "game.scum",
"runEndpointId": "$RUN_ENDPOINT_ID",
"name": "SCUM Dynamic",
"idempotencyKey": "local-debug-scum-dynamic-create",
"name": "SCUM Dynamic $SMOKE_INVOCATION_ID",
"idempotencyKey": "local-debug-scum-dynamic-create-$SMOKE_INVOCATION_ID",
"profileKey": "run-local",
"bindings": {}
}
@@ -645,20 +841,20 @@ JSON
cat >"$WORK_DIR/scum-alpha-run-generate.request.json" <<JSON
{
"targetOs": "windows",
"targetOs": "linux",
"targetArch": "amd64",
"idempotencyKey": "local-debug-scum-alpha-run-generate"
"idempotencyKey": "local-debug-scum-alpha-run-generate-$SMOKE_INVOCATION_ID"
}
JSON
printf 'creating server lifecycle workflow through platform API\n'
create_server_workflow "dev" "server-local-debug" "$WORK_DIR/create-server.request.json" "$WORK_DIR/create-server.response.json"
create_server_workflow "dev" "$SERVER_LOCAL_ID" "$WORK_DIR/create-server.request.json" "$WORK_DIR/create-server.response.json"
reject_forbidden_fragments "$WORK_DIR/create-server.response.json"
printf 'creating SCUM server lifecycle workflows through platform API\n'
create_server_workflow "SCUM alpha" "scum-alpha" "$WORK_DIR/create-scum-alpha.request.json" "$WORK_DIR/create-scum-alpha.response.json"
create_server_workflow "SCUM beta" "scum-beta" "$WORK_DIR/create-scum-beta.request.json" "$WORK_DIR/create-scum-beta.response.json"
create_server_workflow "SCUM dynamic" "scum-dynamic" "$WORK_DIR/create-scum-dynamic.request.json" "$WORK_DIR/create-scum-dynamic.response.json"
create_server_workflow "SCUM alpha" "$SCUM_ALPHA_ID" "$WORK_DIR/create-scum-alpha.request.json" "$WORK_DIR/create-scum-alpha.response.json"
create_server_workflow "SCUM beta" "$SCUM_BETA_ID" "$WORK_DIR/create-scum-beta.request.json" "$WORK_DIR/create-scum-beta.response.json"
create_server_workflow "SCUM dynamic" "$SCUM_DYNAMIC_ID" "$WORK_DIR/create-scum-dynamic.request.json" "$WORK_DIR/create-scum-dynamic.response.json"
reject_forbidden_fragments "$WORK_DIR/create-scum-alpha.response.json"
reject_forbidden_fragments "$WORK_DIR/create-scum-beta.response.json"
reject_forbidden_fragments "$WORK_DIR/create-scum-dynamic.response.json"
@@ -667,9 +863,114 @@ require_file_contains "$WORK_DIR/create-scum-beta.response.json" '"pluginId"[[:s
require_file_contains "$WORK_DIR/create-scum-dynamic.response.json" '"pluginId"[[:space:]]*:[[:space:]]*"game.scum"'
SERVER_ID="$(json_id "$WORK_DIR/create-server.response.json")"
SCUM_ALPHA_ID="$(json_id "$WORK_DIR/create-scum-alpha.response.json")"
SCUM_BETA_ID="$(json_id "$WORK_DIR/create-scum-beta.response.json")"
SCUM_DYNAMIC_ID="$(json_id "$WORK_DIR/create-scum-dynamic.response.json")"
CREATED_SCUM_ALPHA_ID="$(json_id "$WORK_DIR/create-scum-alpha.response.json")"
CREATED_SCUM_BETA_ID="$(json_id "$WORK_DIR/create-scum-beta.response.json")"
CREATED_SCUM_DYNAMIC_ID="$(json_id "$WORK_DIR/create-scum-dynamic.response.json")"
if [[ "$SERVER_ID" != "$SERVER_LOCAL_ID" || "$CREATED_SCUM_ALPHA_ID" != "$SCUM_ALPHA_ID" || "$CREATED_SCUM_BETA_ID" != "$SCUM_BETA_ID" || "$CREATED_SCUM_DYNAMIC_ID" != "$SCUM_DYNAMIC_ID" ]]; then
printf 'created server IDs do not match invocation-scoped workspace IDs\n' >&2
exit 1
fi
node - "$WORK_DIR/create-server.request.json" <<'NODE'
const fs = require("fs");
const request = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
for (const forbidden of ["deploymentTargetId", "runEndpointId", "profileKey", "bindings", "deployment"]) {
if (Object.hasOwn(request, forbidden)) {
console.error(`minimal server creation unexpectedly included ${forbidden}`);
process.exit(1);
}
}
if (!request.pluginId || !request.name) {
console.error("minimal server creation omitted pluginId or name");
process.exit(1);
}
NODE
printf 'configuring example server runtime binding after minimal creation\n'
curl -fsS -X PUT -H 'Content-Type: application/json' "${AUTH_HEADER[@]}" \
--data-binary "@$WORK_DIR/server-runtime-binding.request.json" \
"$API_URL/server-instances/$SERVER_ID/runtime-binding" >"$WORK_DIR/server-runtime-binding.response.json"
reject_forbidden_fragments "$WORK_DIR/server-runtime-binding.response.json"
require_file_contains "$WORK_DIR/server-runtime-binding.response.json" '"status"[[:space:]]*:[[:space:]]*"complete"'
printf 'checking example server platform-builder action\n'
json_get "$API_URL/server-instances/$SERVER_ID/runtime/actions" "$WORK_DIR/server-runtime-actions.response.json" "${AUTH_HEADER[@]}"
node - "$WORK_DIR/server-runtime-actions.response.json" <<'NODE'
const fs = require("fs");
const response = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
const action = (response.actions || []).find((candidate) => candidate.key === "generate-run");
if (!action || action.available !== true || (action.reason || "").includes("run endpoint")) {
console.error("expected minimal example server to generate through the ready platform builder");
console.error(JSON.stringify(response, null, 2));
process.exit(1);
}
NODE
reject_forbidden_fragments "$WORK_DIR/server-runtime-actions.response.json"
printf 'generating host-native example Run through platform Docker builder\n'
curl -fsS -H 'Content-Type: application/json' "${AUTH_HEADER[@]}" --data-binary "@$WORK_DIR/server-run-generate.request.json" "$API_URL/server-instances/$SERVER_ID/run/generate" >"$WORK_DIR/server-run-generate.response.json"
reject_forbidden_fragments "$WORK_DIR/server-run-generate.response.json"
node - "$WORK_DIR/server-run-generate.response.json" "$SERVER_ID" "$GENERATED_RUN_ENDPOINT_ID" "$GENERATED_RUN_TARGET_OS" "$GENERATED_RUN_TARGET_ARCH" <<'NODE'
const fs = require("fs");
const distribution = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
const [serverID, endpointID, targetOS, targetArch] = process.argv.slice(3);
if (distribution.serverInstanceId !== serverID || distribution.runEndpointId !== endpointID || distribution.targetOs !== targetOS || distribution.targetArch !== targetArch || !distribution.buildJobId || !distribution.artifactId) {
console.error("host-native Run distribution identity did not match the minimal server");
console.error(JSON.stringify(distribution, null, 2));
process.exit(1);
}
NODE
wait_for_distribution_build "$WORK_DIR/server-run-generate.response.json" "$WORK_DIR/server-run-build-job.response.json" "$WORK_DIR/server-run-build-artifact.response.json"
node - "$WORK_DIR/server-run-build-job.response.json" <<'NODE'
const fs = require("fs");
const job = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
if (job.runEndpointId !== "platform-distribution-builder" || job.capability !== "distribution.build" || job.state !== "succeeded") {
console.error("host-native Run was not completed by the platform distribution builder");
console.error(JSON.stringify(job, null, 2));
process.exit(1);
}
NODE
reject_forbidden_fragments "$WORK_DIR/server-run-build-job.response.json"
reject_forbidden_fragments "$WORK_DIR/server-run-build-artifact.response.json"
read_latest_run_download_content "$SERVER_ID" "$WORK_DIR/server-run-download.response.json" "$WORK_DIR/server-run-download-content.bin" "$WORK_DIR/server-run-download-chunks"
launch_generated_run "$WORK_DIR/server-run-download-content.bin"
wait_for_generated_run_registration_and_heartbeat
cat >"$WORK_DIR/server-deployment.request.json" <<JSON
{
"runEndpointId": "$GENERATED_RUN_ENDPOINT_ID",
"mode": "custom-command",
"profileKey": "run-local",
"createInputs": {},
"serverRoot": "$RUN_WORKSPACE_ROOT/$SERVER_ID",
"startCommand": "/usr/bin/true"
}
JSON
printf 'saving optional deployment settings after generated Run registration\n'
curl -fsS -X PUT -H 'Content-Type: application/json' "${AUTH_HEADER[@]}" \
--data-binary "@$WORK_DIR/server-deployment.request.json" \
"$API_URL/server-instances/$SERVER_ID/deployment" >"$WORK_DIR/server-deployment.response.json"
reject_forbidden_fragments "$WORK_DIR/server-deployment.response.json"
json_get "$API_URL/server-instances/$SERVER_ID" "$WORK_DIR/server-before-deploy.response.json" "${AUTH_HEADER[@]}"
SERVER_CONFIG_VERSION="$(node -e 'const fs=require("fs"); const value=JSON.parse(fs.readFileSync(process.argv[1], "utf8")).configVersion; if (!Number.isInteger(value) || value < 1) process.exit(2); process.stdout.write(String(value));' "$WORK_DIR/server-before-deploy.response.json")"
cat >"$WORK_DIR/server-deploy.request.json" <<JSON
{
"expectedConfigVersion": $SERVER_CONFIG_VERSION,
"idempotencyKey": "local-debug-server-deploy-$SMOKE_INVOCATION_ID"
}
JSON
json_post "$API_URL/server-instances/$SERVER_ID/deploy" "$WORK_DIR/server-deploy.request.json" "$WORK_DIR/server-deploy.response.json" "${AUTH_HEADER[@]}"
reject_forbidden_fragments "$WORK_DIR/server-deploy.response.json"
require_file_contains "$WORK_DIR/server-deploy.response.json" "\"runEndpointId\"[[:space:]]*:[[:space:]]*\"$GENERATED_RUN_ENDPOINT_ID\""
wait_for_lifecycle_install_success "$SERVER_ID" "$WORK_DIR/jobs.response.json"
printf 'configuring SCUM alpha runtime binding after minimal creation\n'
curl -fsS -X PUT -H 'Content-Type: application/json' "${AUTH_HEADER[@]}" \
--data-binary "@$WORK_DIR/scum-alpha-runtime-binding.request.json" \
"$API_URL/server-instances/$SCUM_ALPHA_ID/runtime-binding" >"$WORK_DIR/scum-alpha-runtime-binding.response.json"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-runtime-binding.response.json"
require_file_contains "$WORK_DIR/scum-alpha-runtime-binding.response.json" '"status"[[:space:]]*:[[:space:]]*"complete"'
wait_for_lifecycle_install_success "$SCUM_DYNAMIC_ID" "$WORK_DIR/scum-dynamic-jobs.response.json"
@@ -677,27 +978,29 @@ printf 'checking SCUM runtime distribution action\n'
json_get "$API_URL/server-instances/$SCUM_ALPHA_ID/runtime/actions" "$WORK_DIR/scum-alpha-runtime-actions.response.json" "${AUTH_HEADER[@]}"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-runtime-actions.response.json"
require_file_contains "$WORK_DIR/scum-alpha-runtime-actions.response.json" '"key"[[:space:]]*:[[:space:]]*"generate-run"'
SCUM_BUILD_AVAILABLE="$(node - "$WORK_DIR/scum-alpha-runtime-actions.response.json" <<'NODE'
node - "$WORK_DIR/scum-alpha-runtime-actions.response.json" <<'NODE'
const fs = require("fs");
const response = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
const action = (response.actions || []).find((candidate) => candidate.key === "generate-run");
if (!action || (action.available !== true && action.reason !== "run endpoint cannot build distributions")) {
console.error("expected SCUM generate-run action to match the Run capability report");
if (!action || action.available !== true) {
console.error("expected SCUM generate-run action to use the ready platform builder");
console.error(JSON.stringify(response, null, 2));
process.exit(1);
}
process.stdout.write(action.available === true ? "true" : "false");
if ((action.reason || "").includes("run endpoint")) {
console.error("platform build availability must not reference a Run endpoint capability");
console.error(JSON.stringify(action, null, 2));
process.exit(1);
}
NODE
)"
if [[ "$SCUM_BUILD_AVAILABLE" == "true" ]]; then
printf 'generating SCUM run package through platform API\n'
curl -fsS -H 'Content-Type: application/json' "${AUTH_HEADER[@]}" --data-binary "@$WORK_DIR/scum-alpha-run-generate.request.json" "$API_URL/server-instances/$SCUM_ALPHA_ID/run/generate" >"$WORK_DIR/scum-alpha-run-generate.response.json"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-run-generate.response.json"
require_file_contains "$WORK_DIR/scum-alpha-run-generate.response.json" '"serverInstanceId"[[:space:]]*:[[:space:]]*"scum-alpha"'
require_file_contains "$WORK_DIR/scum-alpha-run-generate.response.json" '"artifactId"[[:space:]]*:[[:space:]]*"artifact-run-dist-scum-alpha'
require_file_contains "$WORK_DIR/scum-alpha-run-generate.response.json" '"buildJobId"[[:space:]]*:[[:space:]]*"job-distribution-build'
node - "$WORK_DIR/scum-alpha-run-generate.response.json" <<'NODE'
printf 'generating SCUM run package through platform API\n'
curl -fsS -H 'Content-Type: application/json' "${AUTH_HEADER[@]}" --data-binary "@$WORK_DIR/scum-alpha-run-generate.request.json" "$API_URL/server-instances/$SCUM_ALPHA_ID/run/generate" >"$WORK_DIR/scum-alpha-run-generate.response.json"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-run-generate.response.json"
require_file_contains "$WORK_DIR/scum-alpha-run-generate.response.json" "\"serverInstanceId\"[[:space:]]*:[[:space:]]*\"$SCUM_ALPHA_ID\""
require_file_contains "$WORK_DIR/scum-alpha-run-generate.response.json" "\"artifactId\"[[:space:]]*:[[:space:]]*\"artifact-run-dist-$SCUM_ALPHA_ID"
require_file_contains "$WORK_DIR/scum-alpha-run-generate.response.json" '"buildJobId"[[:space:]]*:[[:space:]]*"job-distribution-build'
node - "$WORK_DIR/scum-alpha-run-generate.response.json" <<'NODE'
const fs = require("fs");
const distribution = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
if (distribution.status !== "building" && distribution.status !== "available") {
@@ -706,14 +1009,11 @@ if (distribution.status !== "building" && distribution.status !== "available") {
process.exit(1);
}
NODE
wait_for_distribution_build "$WORK_DIR/scum-alpha-run-generate.response.json" "$WORK_DIR/scum-alpha-run-build-job.response.json" "$WORK_DIR/scum-alpha-run-build-artifact.response.json"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-run-build-job.response.json"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-run-build-artifact.response.json"
read_latest_run_download_content "$SCUM_ALPHA_ID" "$WORK_DIR/scum-alpha-run-download.response.json" "$WORK_DIR/scum-alpha-run-download-content.bin" "$WORK_DIR/scum-alpha-run-download-chunks"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-run-download.response.json"
else
printf 'SCUM run package build is unavailable because Run did not advertise distribution.build; verified without fake success\n'
fi
wait_for_distribution_build "$WORK_DIR/scum-alpha-run-generate.response.json" "$WORK_DIR/scum-alpha-run-build-job.response.json" "$WORK_DIR/scum-alpha-run-build-artifact.response.json"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-run-build-job.response.json"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-run-build-artifact.response.json"
read_latest_run_download_content "$SCUM_ALPHA_ID" "$WORK_DIR/scum-alpha-run-download.response.json" "$WORK_DIR/scum-alpha-run-download-content.bin" "$WORK_DIR/scum-alpha-run-download-chunks"
reject_forbidden_fragments "$WORK_DIR/scum-alpha-run-download.response.json"
printf 'checking jobs, logs, artifacts, and marketplace refs\n'
json_get "$API_URL/server-instances" "$WORK_DIR/server-instances.response.json" "${AUTH_HEADER[@]}"
@@ -726,14 +1026,34 @@ json_get "$API_URL/artifacts" "$WORK_DIR/artifacts.response.json" "${AUTH_HEADER
json_get "$API_URL/plugin-marketplace/plugins" "$WORK_DIR/marketplace.response.json" "${AUTH_HEADER[@]}"
json_get "$API_URL/plugin-marketplace/plugins?serverType=scum&keyword=scum" "$WORK_DIR/scum-marketplace.response.json" "${AUTH_HEADER[@]}"
require_file_contains "$WORK_DIR/scum-marketplace.response.json" '"id"[[:space:]]*:[[:space:]]*"game.scum"'
if [[ "$SCUM_BUILD_AVAILABLE" == "true" ]]; then
require_file_contains "$WORK_DIR/artifacts.response.json" '"id"[[:space:]]*:[[:space:]]*"artifact-run-dist-scum-alpha'
fi
require_file_contains "$WORK_DIR/scum-alpha-jobs.response.json" '"serverInstanceId"[[:space:]]*:[[:space:]]*"scum-alpha"'
require_file_contains "$WORK_DIR/scum-beta-jobs.response.json" '"serverInstanceId"[[:space:]]*:[[:space:]]*"scum-beta"'
require_file_contains "$WORK_DIR/artifacts.response.json" "\"id\"[[:space:]]*:[[:space:]]*\"artifact-run-dist-$SCUM_ALPHA_ID"
require_file_contains "$WORK_DIR/scum-alpha-jobs.response.json" "\"serverInstanceId\"[[:space:]]*:[[:space:]]*\"$SCUM_ALPHA_ID\""
require_file_contains "$WORK_DIR/scum-beta-jobs.response.json" "\"serverInstanceId\"[[:space:]]*:[[:space:]]*\"$SCUM_BETA_ID\""
require_file_contains "$WORK_DIR/scum-dynamic-jobs.response.json" '"state"[[:space:]]*:[[:space:]]*"succeeded"'
for file in "$WORK_DIR"/server-instances.response.json "$WORK_DIR"/jobs.response.json "$WORK_DIR"/scum-alpha-jobs.response.json "$WORK_DIR"/scum-beta-jobs.response.json "$WORK_DIR"/scum-dynamic-jobs.response.json "$WORK_DIR"/log-streams.response.json "$WORK_DIR"/artifacts.response.json "$WORK_DIR"/marketplace.response.json "$WORK_DIR"/scum-marketplace.response.json "$WORK_DIR"/scum-alpha-runtime-actions.response.json "$WORK_DIR"/scum-alpha-run-generate.response.json "$WORK_DIR"/scum-alpha-run-download.response.json; do
for file in \
"$WORK_DIR"/server-instances.response.json \
"$WORK_DIR"/jobs.response.json \
"$WORK_DIR"/server-runtime-binding.response.json \
"$WORK_DIR"/server-runtime-actions.response.json \
"$WORK_DIR"/server-run-generate.response.json \
"$WORK_DIR"/server-run-build-job.response.json \
"$WORK_DIR"/server-run-build-artifact.response.json \
"$WORK_DIR"/server-run-download.response.json \
"$WORK_DIR"/generated-run-registration.response.json \
"$WORK_DIR"/generated-run-heartbeat.response.json \
"$WORK_DIR"/server-deployment.response.json \
"$WORK_DIR"/server-deploy.response.json \
"$WORK_DIR"/scum-alpha-jobs.response.json \
"$WORK_DIR"/scum-beta-jobs.response.json \
"$WORK_DIR"/scum-dynamic-jobs.response.json \
"$WORK_DIR"/log-streams.response.json \
"$WORK_DIR"/artifacts.response.json \
"$WORK_DIR"/marketplace.response.json \
"$WORK_DIR"/scum-marketplace.response.json \
"$WORK_DIR"/scum-alpha-runtime-actions.response.json \
"$WORK_DIR"/scum-alpha-run-generate.response.json \
"$WORK_DIR"/scum-alpha-run-download.response.json; do
if [[ -f "$file" ]]; then
reject_forbidden_fragments "$file"
fi
@@ -743,6 +1063,10 @@ if [[ "$VITE_PLATFORM_API_BASE_URL" != "/api/v1" ]]; then
printf 'VITE_PLATFORM_API_BASE_URL must be /api/v1, got %s\n' "$VITE_PLATFORM_API_BASE_URL" >&2
exit 1
fi
if [[ "$PLATFORM_RUN_RELEASE_URL" != "$PLATFORM_URL" ]]; then
printf 'PLATFORM_RUN_RELEASE_URL must be %s for executable local Run proof, got %s\n' "$PLATFORM_URL" "$PLATFORM_RUN_RELEASE_URL" >&2
exit 1
fi
if [[ "$PLATFORM_API_PROXY" != "$PLATFORM_URL" ]]; then
printf 'PLATFORM_API_PROXY must be %s, got %s\n' "$PLATFORM_URL" "$PLATFORM_API_PROXY" >&2
exit 1
@@ -759,8 +1083,8 @@ cat >"$WORK_DIR/local-ui-checklist.md" <<EOF
- Login with operator.local@example.test / operator-local.
- Confirm the login path is API-backed and no local fallback banner or fallback workspace appears.
- Visit 首页, 服务器管理, 插件市场, 用户管理, AI 提供商管理.
- Open server-local-debug detail and inspect lifecycle history, plugin controls, logs, and artifact references.
- Confirm 插件市场 can find SCUM Server / game.scum, then open scum-alpha, scum-beta, and scum-dynamic from 服务器管理.
- Open $SERVER_ID detail and inspect lifecycle history, plugin controls, logs, and artifact references.
- Confirm 插件市场 can find SCUM Server / game.scum, then open $SCUM_ALPHA_ID, $SCUM_BETA_ID, and $SCUM_DYNAMIC_ID from 服务器管理.
- Confirm all SCUM servers are backed by game.scum and have separate lifecycle install jobs and operation history.
- Search visible text for forbidden fragments: /Users/, /private/, unix://, tcp://, Bearer , sk-, password=, apiKeyRef, rawApiKey, run session tokens, direct run URLs, plugin-owned transport details.
- Acceptance requires platform routes, logical IDs, job refs, log refs, artifact refs, and safe metadata only.
+13 -3
View File
@@ -8,6 +8,7 @@ source "$ROOT_DIR/scripts/local-debug/env.sh"
mkdir -p "$LOCAL_DEBUG_LOG_DIR" "$LOCAL_DEBUG_PID_DIR" "$PLATFORM_DATA_DIR" "$PLATFORM_LOG_DIR" "$RUN_WORKSPACE_ROOT" "$RUN_SPOOL_ROOT" "$RUN_BUILD_BUCKET_ROOT"
mkdir -p "$GOCACHE"
local_debug_prepare_run_lifecycle_templates
local_debug_prepare_distribution_builder
managed_pid_running() {
local pid_file="$1"
@@ -188,6 +189,8 @@ printf 'run source: %s\n' "$RUN_SOURCE_DIR"
printf 'run build bucket: %s\n' "$RUN_BUILD_BUCKET_ROOT"
printf 'run build source snapshot: %s\n' "$RUN_BUILD_SOURCE_ROOT"
printf 'run bootstrap binary: %s\n' "$RUN_BOOTSTRAP_BIN"
printf 'platform builder image: %s\n' "$PLATFORM_BUILDER_IMAGE"
printf 'platform builder workspace: %s\n' "$PLATFORM_BUILDER_WORKSPACE_DIR"
printf 'platform log: %s\n' "$LOCAL_DEBUG_LOG_DIR/platform.log"
printf 'run log: %s\n' "$LOCAL_DEBUG_LOG_DIR/run.log"
printf 'platform_web log: %s\n' "$LOCAL_DEBUG_LOG_DIR/platform_web.log"
@@ -203,9 +206,16 @@ start_service platform "$ROOT_DIR/platform" env \
PLATFORM_METADATA_PATH="$PLATFORM_METADATA_PATH" \
PLATFORM_LOG_BODY_BACKEND="$PLATFORM_LOG_BODY_BACKEND" \
PLATFORM_LOG_DIR="$PLATFORM_LOG_DIR" \
PLATFORM_BOOTSTRAP_ADMIN_EMAIL="$PLATFORM_BOOTSTRAP_ADMIN_EMAIL" \
PLATFORM_BOOTSTRAP_ADMIN_PASSWORD="$PLATFORM_BOOTSTRAP_ADMIN_PASSWORD" \
PLATFORM_SECRET_ENVELOPE_KEY="$PLATFORM_SECRET_ENVELOPE_KEY" \
PLATFORM_ARTIFACT_DIR="$PLATFORM_ARTIFACT_DIR" \
PLATFORM_BOOTSTRAP_ADMIN_EMAIL="$PLATFORM_BOOTSTRAP_ADMIN_EMAIL" \
PLATFORM_BOOTSTRAP_ADMIN_PASSWORD="$PLATFORM_BOOTSTRAP_ADMIN_PASSWORD" \
PLATFORM_SECRET_ENVELOPE_KEY="$PLATFORM_SECRET_ENVELOPE_KEY" \
PLATFORM_RUN_RELEASE_URL="$PLATFORM_RUN_RELEASE_URL" \
PLATFORM_BUILDER_DOCKER_BINARY="$PLATFORM_BUILDER_DOCKER_BINARY" \
PLATFORM_BUILDER_IMAGE="$PLATFORM_BUILDER_IMAGE" \
PLATFORM_BUILDER_SOURCE_DIR="$PLATFORM_BUILDER_SOURCE_DIR" \
PLATFORM_BUILDER_WORKSPACE_DIR="$PLATFORM_BUILDER_WORKSPACE_DIR" \
PLATFORM_BUILDER_TIMEOUT_SECONDS="$PLATFORM_BUILDER_TIMEOUT_SECONDS" \
go run ./cmd/platform
wait_for_url platform "$(local_debug_platform_url)/healthz"
+9 -3
View File
@@ -8,12 +8,18 @@ source "$ROOT_DIR/scripts/local-debug/env.sh"
if [[ ! -d "$LOCAL_DEBUG_PID_DIR" ]]; then
printf 'no local debug pid directory at %s\n' "$LOCAL_DEBUG_PID_DIR"
else
for name in platform_web run platform; do
pid_file="$LOCAL_DEBUG_PID_DIR/$name.pid"
pid_files=("$LOCAL_DEBUG_PID_DIR/platform_web.pid" "$LOCAL_DEBUG_PID_DIR/run.pid" "$LOCAL_DEBUG_PID_DIR/platform.pid")
for generated_pid_file in "$LOCAL_DEBUG_PID_DIR"/generated-*-run.pid; do
if [[ -f "$generated_pid_file" ]]; then
pid_files+=("$generated_pid_file")
fi
done
for pid_file in "${pid_files[@]}"; do
if [[ ! -f "$pid_file" ]]; then
continue
fi
pid="$(cat "$pid_file")"
name="$(basename "$pid_file" .pid)"
pid="$(<"$pid_file")"
if kill -0 "$pid" 2>/dev/null; then
printf 'stopping %s pid %s\n' "$name" "$pid"
kill "$pid" 2>/dev/null || true