feat: 完整游戏运维功能

This commit is contained in:
npc0-hue
2026-07-18 09:04:01 +08:00
parent f3b14b7945
commit 48b8ad8d6c
187 changed files with 16607 additions and 1140 deletions
+4
View File
@@ -20,6 +20,10 @@ export PLATFORM_DATA_DIR="${PLATFORM_DATA_DIR:-$LOCAL_DEBUG_ROOT/platform}"
export PLATFORM_METADATA_PATH="${PLATFORM_METADATA_PATH:-$PLATFORM_DATA_DIR/metadata.json}"
export PLATFORM_LOG_BODY_BACKEND="${PLATFORM_LOG_BODY_BACKEND:-file}"
export PLATFORM_LOG_DIR="${PLATFORM_LOG_DIR:-$PLATFORM_DATA_DIR/logs}"
export PLATFORM_ARTIFACT_DIR="${PLATFORM_ARTIFACT_DIR:-$PLATFORM_DATA_DIR/artifacts}"
export PLATFORM_BOOTSTRAP_ADMIN_EMAIL="${PLATFORM_BOOTSTRAP_ADMIN_EMAIL:-operator.local@example.test}"
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 RUN_REPO_DIR="${RUN_REPO_DIR:-$LOCAL_DEBUG_ROOT_DIR/run}"
export RUN_MODE="${RUN_MODE:-worker}"
+76 -4
View File
@@ -38,7 +38,7 @@ wait_for_url() {
}
start_self_hosted_stack() {
mkdir -p "$LOCAL_DEBUG_LOG_DIR" "$LOCAL_DEBUG_PID_DIR" "$PLATFORM_DATA_DIR" "$PLATFORM_LOG_DIR" "$RUN_WORKSPACE_ROOT" "$RUN_SPOOL_ROOT" "$GOCACHE"
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" "$GOCACHE"
trap cleanup_self_started EXIT
printf 'self-starting platform for local debug smoke\n'
@@ -52,6 +52,10 @@ 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" \
go run ./cmd/platform
) >"$LOCAL_DEBUG_LOG_DIR/platform.log" 2>&1 &
SELF_STARTED_PIDS+=("$!")
@@ -103,8 +107,9 @@ json_post() {
local url="$1"
local body_file="$2"
local output_file="$3"
shift 3
local status
status="$(curl -sS -H 'Content-Type: application/json' --data-binary "@$body_file" "$url" -o "$output_file" -w '%{http_code}')"
status="$(curl -sS -H 'Content-Type: application/json' "$@" --data-binary "@$body_file" "$url" -o "$output_file" -w '%{http_code}')"
case "$status" in
2*)
return 0
@@ -152,6 +157,61 @@ json_id() {
node -e 'const fs=require("fs"); const data=JSON.parse(fs.readFileSync(process.argv[1],"utf8")); const id=data.instance?.id || data.serverInstance?.id || data.id || ((data.items||[])[0]||{}).id; if (!id) process.exit(2); process.stdout.write(id);' "$1"
}
wait_for_distribution_build() {
local distribution_file="$1"
local job_file="$2"
local artifact_file="$3"
local job_id
local artifact_id
job_id="$(node -e 'const fs=require("fs"); const data=JSON.parse(fs.readFileSync(process.argv[1],"utf8")); if (!data.buildJobId) process.exit(2); process.stdout.write(data.buildJobId);' "$distribution_file")"
artifact_id="$(node -e 'const fs=require("fs"); const data=JSON.parse(fs.readFileSync(process.argv[1],"utf8")); if (!data.artifactId) process.exit(2); process.stdout.write(data.artifactId);' "$distribution_file")"
rm -f "$job_file" "$artifact_file"
for _ in $(seq 1 60); do
json_get "$API_URL/jobs/$job_id" "$job_file" "${AUTH_HEADER[@]}" || true
if [[ ! -s "$job_file" ]]; then
sleep 1
continue
fi
if node - "$job_file" <<'NODE'; then
const fs = require("fs");
const job = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
process.exit(job.state === "succeeded" && job.resultRef ? 0 : 1);
NODE
break
fi
if node - "$job_file" <<'NODE'; then
const fs = require("fs");
const job = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
process.exit(job.state === "failed" || job.state === "cancelled" ? 0 : 1);
NODE
printf 'distribution build job reached terminal failure\n' >&2
sed -n '1,120p' "$job_file" >&2
exit 1
fi
sleep 1
done
json_get "$API_URL/jobs/$job_id" "$job_file" "${AUTH_HEADER[@]}"
json_get "$API_URL/artifacts/$artifact_id" "$artifact_file" "${AUTH_HEADER[@]}"
node - "$job_file" "$artifact_file" "$artifact_id" <<'NODE'
const fs = require("fs");
const job = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
const artifact = JSON.parse(fs.readFileSync(process.argv[3], "utf8"));
const artifactId = process.argv[4];
if (job.state !== "succeeded" || job.resultRef !== `artifact://${artifactId}`) {
console.error("expected distribution build job to succeed with artifact result");
console.error(JSON.stringify(job, null, 2));
process.exit(1);
}
if (artifact.id !== artifactId || artifact.state !== "available" || !/^sha256:/.test(artifact.checksum || "")) {
console.error("expected available distribution artifact with sha256 checksum");
console.error(JSON.stringify(artifact, null, 2));
process.exit(1);
}
NODE
}
printf 'checking platform health at %s\n' "$PLATFORM_URL"
json_get "$PLATFORM_URL/healthz" "$WORK_DIR/health.json"
require_file_contains "$WORK_DIR/health.json" '"status"[[:space:]]*:[[:space:]]*"ok"'
@@ -159,7 +219,7 @@ require_file_contains "$WORK_DIR/health.json" '"status"[[:space:]]*:[[:space:]]*
cat >"$WORK_DIR/login.request.json" <<'JSON'
{"account":"operator.local@example.test","password":"operator-local"}
JSON
json_post "$API_URL/auth/login" "$WORK_DIR/login.request.json" "$WORK_DIR/login.response.json"
json_post "$API_URL/auth/login" "$WORK_DIR/login.request.json" "$WORK_DIR/login.response.json" -H 'X-Auth-Token-Response: bearer'
SESSION_ID="$(session_token_from_login "$WORK_DIR/login.response.json")"
AUTH_HEADER=(-H "Authorization: Bearer $SESSION_ID")
require_file_contains "$WORK_DIR/login.response.json" '"status"[[:space:]]*:[[:space:]]*"active"'
@@ -356,7 +416,19 @@ curl -fsS -H 'Content-Type: application/json' "${AUTH_HEADER[@]}" --data-binary
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" '"checksum"[[:space:]]*:[[:space:]]*"sha256:'
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") {
console.error("expected run distribution to be building or available");
console.error(JSON.stringify(distribution, null, 2));
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"
printf 'checking jobs, logs, artifacts, and marketplace refs\n'
json_get "$API_URL/server-instances" "$WORK_DIR/server-instances.response.json" "${AUTH_HEADER[@]}"
+3
View File
@@ -130,6 +130,9 @@ 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" \
go run ./cmd/platform
wait_for_url platform "$(local_debug_platform_url)/healthz"