feat: move distribution builds to platform Docker builder
This commit is contained in:
@@ -40,6 +40,7 @@ const fallbackFragments = [
|
||||
async function main() {
|
||||
await mkdir(evidenceDir, { recursive: true });
|
||||
|
||||
const smokeSeed = await loadSmokeSeed();
|
||||
const session = await loginApi();
|
||||
const authHeaders = { Authorization: `Bearer ${session.sessionId}` };
|
||||
await ensureAiProvider(authHeaders);
|
||||
@@ -47,7 +48,7 @@ async function main() {
|
||||
const [instances, endpoints, jobs, plugins, marketplace, users, providers, logStreams, artifacts, usage] = await Promise.all([
|
||||
getJson("/server-instances", authHeaders),
|
||||
getJson("/run/endpoints?status=online", authHeaders),
|
||||
getJson("/jobs?serverInstanceId=server-local-debug", authHeaders),
|
||||
getJson(`/jobs?serverInstanceId=${encodeURIComponent(smokeSeed.serverLocalId)}`, authHeaders),
|
||||
getJson("/game-plugins", authHeaders),
|
||||
getJson("/plugin-marketplace/plugins", authHeaders),
|
||||
getJson("/users", authHeaders),
|
||||
@@ -57,15 +58,18 @@ async function main() {
|
||||
getJson("/metrics/platform", authHeaders)
|
||||
]);
|
||||
|
||||
const server = findRequired(instances.items, (item) => item.id === "server-local-debug", "server-local-debug instance");
|
||||
const runEndpoint = findRequired(endpoints.items, (item) => item.id === "run-local-debug", "run-local-debug endpoint");
|
||||
const server = findRequired(instances.items, (item) => item.id === smokeSeed.serverLocalId, `${smokeSeed.serverLocalId} instance`);
|
||||
const runEndpoint = findRequired(endpoints.items, (item) => item.id === server.runEndpointId, `${server.runEndpointId} generated endpoint`);
|
||||
const plugin = findRequired(plugins.items, (item) => item.id === "game.example", "game.example plugin");
|
||||
const marketplacePlugin = findRequired(marketplace.items, (item) => item.id === "game.example", "game.example marketplace plugin");
|
||||
const operator = findRequired(users.items, (item) => item.email === "operator.local@example.test", "operator local user");
|
||||
const aiProvider = findRequired(providers.items, (item) => item.id === "ai.openai" || item.apiKeyConfigured === true, "redacted AI provider");
|
||||
|
||||
assertEqual(server.pluginId, "game.example", "server is backed by game.example");
|
||||
assertEqual(server.runEndpointId, "run-local-debug", "server is assigned to run-local-debug");
|
||||
assertEqual(server.runEndpointId, smokeSeed.generatedRunEndpointId, "server is assigned to its generated Run");
|
||||
if (runEndpoint.capabilities.includes("distribution.build")) {
|
||||
throw new Error("generated Run unexpectedly advertises distribution.build");
|
||||
}
|
||||
assertIncludes(runEndpoint.capabilities, "process.install", "run endpoint exposes process.install");
|
||||
assertIncludes(runEndpoint.capabilities, "process.start", "run endpoint exposes process.start");
|
||||
assertIncludes(runEndpoint.capabilities, "process.stop", "run endpoint exposes process.stop");
|
||||
@@ -90,6 +94,7 @@ async function main() {
|
||||
platformUrl,
|
||||
webUrl,
|
||||
localDebugRoot,
|
||||
smokeSeed,
|
||||
seedEvidenceDir: path.join(localDebugRoot, "smoke"),
|
||||
session: {
|
||||
userId: session.user.id,
|
||||
@@ -169,7 +174,7 @@ async function main() {
|
||||
},
|
||||
{
|
||||
name: "服务器详情",
|
||||
hash: "#/servers/server-local-debug",
|
||||
hash: `#/servers/${encodeURIComponent(server.id)}`,
|
||||
markers: [
|
||||
server.name,
|
||||
`${server.id} · 插件 ${server.pluginId}@${server.pluginVersion} · 节点 ${server.runEndpointId}`,
|
||||
@@ -225,6 +230,28 @@ async function main() {
|
||||
console.log(`evidence file: ${evidencePath}`);
|
||||
}
|
||||
|
||||
async function loadSmokeSeed() {
|
||||
const configPath = path.join(localDebugRoot, "smoke", "run-build-config.env");
|
||||
const contents = await readFile(configPath, "utf8");
|
||||
const values = {};
|
||||
for (const line of contents.split(/\r?\n/)) {
|
||||
const separator = line.indexOf("=");
|
||||
if (separator <= 0) continue;
|
||||
values[line.slice(0, separator)] = line.slice(separator + 1);
|
||||
}
|
||||
for (const key of ["SMOKE_INVOCATION_ID", "SERVER_LOCAL_ID", "SCUM_ALPHA_ID", "SCUM_BETA_ID", "SCUM_DYNAMIC_ID", "GENERATED_RUN_ENDPOINT_ID"]) {
|
||||
if (!values[key]) throw new Error(`smoke seed configuration is missing ${key}`);
|
||||
}
|
||||
return {
|
||||
invocationId: values.SMOKE_INVOCATION_ID,
|
||||
serverLocalId: values.SERVER_LOCAL_ID,
|
||||
scumAlphaId: values.SCUM_ALPHA_ID,
|
||||
scumBetaId: values.SCUM_BETA_ID,
|
||||
scumDynamicId: values.SCUM_DYNAMIC_ID,
|
||||
generatedRunEndpointId: values.GENERATED_RUN_ENDPOINT_ID
|
||||
};
|
||||
}
|
||||
|
||||
async function loginApi() {
|
||||
const response = await postJson("/auth/login", {
|
||||
account: "operator.local@example.test",
|
||||
@@ -362,9 +389,9 @@ async function verifyResponsiveThemeWalkthroughs(chrome, routeChecks, server) {
|
||||
}
|
||||
}
|
||||
|
||||
await chrome.evaluate(() => {
|
||||
window.location.hash = "#/servers/server-local-debug";
|
||||
});
|
||||
await chrome.evaluate((serverID) => {
|
||||
window.location.hash = `#/servers/${encodeURIComponent(serverID)}`;
|
||||
}, server.id);
|
||||
await chrome.waitForText([server.name, "插件控制"], `${scenario.name} / server detail tabs`);
|
||||
const pluginControls = await clickAndVerify(chrome, "插件控制", ["生产生命周期", "Logs 桥接执行", "server.logs.read", "server.artifacts.read", "读取"]);
|
||||
const pluginLayout = await chrome.layoutSnapshot();
|
||||
@@ -438,7 +465,7 @@ async function clickAndVerify(chrome, buttonText, markers) {
|
||||
}
|
||||
|
||||
async function verifyServerQuickRuntimeMenu(chrome, label) {
|
||||
const markers = ["生成 run", "下载 run", "推送更新", "生成客户端", "依赖检查", "依赖安装", "实时日志", "历史日志"];
|
||||
const markers = ["生成 run", "下载 run", "更新 run", "生成客户端", "依赖检查", "依赖安装", "实时日志", "历史日志"];
|
||||
await chrome.evaluate(() => {
|
||||
const trigger = Array.from(document.querySelectorAll("button")).find((item) => item.textContent?.includes("运行操作"));
|
||||
if (!(trigger instanceof HTMLButtonElement)) {
|
||||
@@ -787,13 +814,13 @@ async function verifyLifecycleOperation(headers, server, chrome) {
|
||||
if (result.job.capability !== expectedCapability) {
|
||||
throw new Error(`lifecycle job used unexpected capability ${result.job.capability}`);
|
||||
}
|
||||
if (result.job.runEndpointId !== "run-local-debug") {
|
||||
if (result.job.runEndpointId !== currentServer.runEndpointId) {
|
||||
throw new Error(`lifecycle job used unexpected run endpoint ${result.job.runEndpointId}`);
|
||||
}
|
||||
|
||||
const job = await waitForJob(headers, currentServer.id, result.job.id);
|
||||
|
||||
await chrome.navigate(`${webUrl}/#/servers/server-local-debug`);
|
||||
await chrome.navigate(`${webUrl}/#/servers/${encodeURIComponent(currentServer.id)}`);
|
||||
await chrome.waitForText([currentServer.name, "操作历史"], "server detail after lifecycle operation");
|
||||
const historyState = await clickAndVerify(chrome, "操作历史", ["操作历史", "平台任务记录", "server-lifecycle", "process."]);
|
||||
|
||||
@@ -953,6 +980,8 @@ async function startChrome() {
|
||||
const clipped = intersection(rectFromDomRect(rect), clipForElement(element));
|
||||
const visibleWidth = Math.max(0, clipped.right - clipped.left);
|
||||
const visibleHeight = Math.max(0, clipped.bottom - clipped.top);
|
||||
const floatingMenu = element.closest(".runtime-action-popover");
|
||||
const floatingMenuRect = floatingMenu?.getBoundingClientRect();
|
||||
return {
|
||||
tag: element.tagName.toLowerCase(),
|
||||
text: (element.textContent || element.getAttribute("aria-label") || "").trim().slice(0, 60),
|
||||
@@ -961,7 +990,8 @@ async function startChrome() {
|
||||
right: Math.round(clipped.right),
|
||||
bottom: Math.round(clipped.bottom),
|
||||
width: Math.round(visibleWidth),
|
||||
height: Math.round(visibleHeight)
|
||||
height: Math.round(visibleHeight),
|
||||
boundedFloatingMenu: Boolean(floatingMenuRect && floatingMenuRect.width <= 320 && floatingMenuRect.height <= 320)
|
||||
};
|
||||
})
|
||||
.filter((control) => control.width > 0 && control.height > 0);
|
||||
@@ -969,6 +999,9 @@ async function startChrome() {
|
||||
const overlappingControls = [];
|
||||
for (let index = 0; index < controls.length; index += 1) {
|
||||
for (let otherIndex = index + 1; otherIndex < controls.length; otherIndex += 1) {
|
||||
if (controls[index].boundedFloatingMenu !== controls[otherIndex].boundedFloatingMenu && (controls[index].boundedFloatingMenu || controls[otherIndex].boundedFloatingMenu)) {
|
||||
continue;
|
||||
}
|
||||
const left = Math.max(controls[index].left, controls[otherIndex].left);
|
||||
const top = Math.max(controls[index].top, controls[otherIndex].top);
|
||||
const right = Math.min(controls[index].right, controls[otherIndex].right);
|
||||
|
||||
Reference in New Issue
Block a user