Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/scripts/bug-server-manual.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ function context(env) {
// 复用既有 GitHub CI 公网入口;内网页面入口另由 bugserver 的 Host 白名单控制。
const host = env.BUG_SERVER_HOST || 'https://bug-server.zijieapi.com';
if (!new Set(['https://bug-server.zijieapi.com', 'https://bugserver.cn.goofy.app', 'https://g20b7465b2.gf-boe.bytedance.net']).has(host)) throw new Error('Unsupported Bug Server host');
return { env, host, runId };
const environment = env.BUG_SERVER_ENVIRONMENT || (host === 'https://g20b7465b2.gf-boe.bytedance.net' ? 'boe' : 'cn');
if (!['cn', 'boe', 'ppe'].includes(environment) || (environment === 'boe') !== (host === 'https://g20b7465b2.gf-boe.bytedance.net') ||
(environment === 'ppe' && host !== 'https://bug-server.zijieapi.com')) throw new Error('Unsupported Bug Server environment');
// PPE 固定复用 CN 公网入口,分流头仅发给 CI,不传给 GitHub 或产物地址。
const headers = environment === 'ppe' ? { 'x-use-ppe': '1', 'x-tt-env': 'ppe_bugserver_titan_auth' } : {};
return { env, host, runId, headers };
}

/** 每次重新构造 multipart;服务端 checkpoint 保证重试不重复创建 SCM/截图批次。 */
Expand All @@ -30,7 +35,7 @@ async function call(ctx, triggerType, fields = {}, filePath) {
form.append(key, String(value));
}
if (filePath) form.append('bundleFile', new Blob([await readFile(filePath)], { type: 'text/javascript' }), 'index.js');
const response = await fetch(`${ctx.host}/api/ci/trigger`, { method: 'POST', body: form,
const response = await fetch(`${ctx.host}/api/ci/trigger`, { method: 'POST', body: form, headers: ctx.headers,
signal: AbortSignal.timeout(75000), redirect: 'error' });
const result = await response.json();
if (!response.ok || result.code !== 0) {
Expand Down
17 changes: 14 additions & 3 deletions .github/scripts/bug-server-manual.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ const env = { GITHUB_REPOSITORY: 'VisActor/VChart', GITHUB_RUN_ID: '99', TASK_ID

test('控制脚本拒绝任意仓库、入口、任务编号和 run ID', () => {
for (const patch of [{ GITHUB_REPOSITORY: 'evil/VChart' }, { TASK_ID: `${taskId}\nreused=true` },
{ GITHUB_RUN_ID: '0' }, { BUG_SERVER_TOKEN: '' }, { BUG_SERVER_HOST: 'https://evil.example' }]) assert.throws(() => context({ ...env, ...patch }));
{ GITHUB_RUN_ID: '0' }, { BUG_SERVER_TOKEN: '' }, { BUG_SERVER_HOST: 'https://evil.example' },
{ BUG_SERVER_ENVIRONMENT: 'ppe_other' }, { BUG_SERVER_ENVIRONMENT: 'boe' },
{ BUG_SERVER_ENVIRONMENT: 'ppe', BUG_SERVER_HOST: 'https://g20b7465b2.gf-boe.bytedance.net' }]) assert.throws(() => context({ ...env, ...patch }));
});

test('BOE 控制请求只发送到固定 BOE 地址,保留任务与服务 token 校验', async t => {
Expand All @@ -22,6 +24,7 @@ test('BOE 控制请求只发送到固定 BOE 地址,保留任务与服务 toke
assert.equal(options.redirect, 'error');
assert.equal(options.body.get('token'), 'test-project-token');
assert.equal(options.body.get('workflowRunId'), '123');
assert.deepEqual(options.headers, {});
return new Response(JSON.stringify({ code: 0, data: {} }));
};
await run('complete', { ...env, TASK_ID: undefined, REPORTED_RUN_ID: '123', BUG_SERVER_HOST: 'https://g20b7465b2.gf-boe.bytedance.net' });
Expand All @@ -35,8 +38,10 @@ test('prepare 使用服务端冻结 SHA,下载复用失败会退回构建', as
t.after(() => rm(directory, { recursive: true, force: true }));
const previousFetch = global.fetch;
t.after(() => { global.fetch = previousFetch; });
let ppe = false;
global.fetch = async (url, options) => {
if (new URL(url).origin === 'https://api.github.com') return new Response('{}', { status: 404 });
assert.deepEqual(options.headers, ppe ? { 'x-use-ppe': '1', 'x-tt-env': 'ppe_bugserver_titan_auth' } : {});
assert.equal(options.body.get('triggerType'), 'manual-info');
assert.equal(options.body.get('manualTaskId'), taskId);
assert.equal(options.body.get('workflowRunId'), '99');
Expand All @@ -45,6 +50,8 @@ test('prepare 使用服务端冻结 SHA,下载复用失败会退回构建', as
};
await run('prepare', { ...env, RUNNER_TEMP: directory, GITHUB_OUTPUT: join(directory, 'outputs') });
assert.equal(await readFile(join(directory, 'outputs'), 'utf8'), `head_sha=${'a'.repeat(40)}\nhead_repository=contributor/VChart\nreused=false\n`);
ppe = true;
await run('prepare', { ...env, BUG_SERVER_ENVIRONMENT: 'ppe', RUNNER_TEMP: directory, GITHUB_OUTPUT: join(directory, 'ppe-outputs') });
});

test('submit 把可执行 JS 只当作上传数据,沿用 SCM/截图链路并保留差异结论', async t => {
Expand All @@ -62,13 +69,16 @@ test('submit 把可执行 JS 只当作上传数据,沿用 SCM/截图链路并
if (new URL(address).origin === 'https://api.github.com') {
assert.equal(options.headers.Authorization, 'Bearer test-github-token');
assert.equal(options.redirect, 'manual');
assert.equal(options.headers['x-tt-env'], undefined);
return new Response(null, { status: 302, headers: { location: 'https://artifact.example/signed.zip' } });
}
if (new URL(address).origin === 'https://artifact.example') {
assert.equal(options.headers, undefined); // 签名 URL 请求不能携带 GitHub token。
return new Response(bytes);
}
assert.equal(options.redirect, 'error');
assert.equal(address, 'https://bug-server.zijieapi.com/api/ci/trigger');
assert.deepEqual(options.headers, { 'x-use-ppe': '1', 'x-tt-env': 'ppe_bugserver_titan_auth' });
const form = options.body, type = form.get('triggerType');
operations.push(type);
assert.equal(form.get('token'), 'test-project-token');
Expand All @@ -83,7 +93,7 @@ test('submit 把可执行 JS 只当作上传数据,沿用 SCM/截图链路并
assert.ok(data, `Unexpected operation ${type}`);
return new Response(JSON.stringify({ code: 0, data }));
};
assert.equal(await run('submit', env), 1);
assert.equal(await run('submit', { ...env, BUG_SERVER_ENVIRONMENT: 'ppe' }), 1);
assert.deepEqual(operations, ['manual-artifact', 'upload-file', 'scm-build', 'scm-version-info', 'photo-test', 'photo-result', 'manual-finish']);
assert.ok(!operations.includes('performance-test'));
});
Expand All @@ -95,9 +105,10 @@ test('独立完成回报只提供源 run ID,不从事件 payload 猜测被测
assert.equal(options.body.get('workflowRunId'), '123');
assert.equal(options.body.get('manualTaskId'), null);
assert.equal(options.body.get('outcome'), null);
assert.deepEqual(options.headers, { 'x-use-ppe': '1', 'x-tt-env': 'ppe_bugserver_titan_auth' });
return new Response(JSON.stringify({ code: 0, data: { outcome: 'cancelled' } }));
};
assert.equal(await run('complete', { ...env, TASK_ID: undefined, REPORTED_RUN_ID: '123' }), 0);
assert.equal(await run('complete', { ...env, TASK_ID: undefined, REPORTED_RUN_ID: '123', BUG_SERVER_ENVIRONMENT: 'ppe' }), 0);
});

test('可信上传前检查拒绝文件及父目录符号链接、空文件和超限文件', async t => {
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/bug-server-manual-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
env:
# 只从源 run 的固定环境后缀选择回报地址,不接受任意 URL。
BUG_SERVER_HOST: ${{ endsWith(github.event.workflow_run.display_title, ':boe') && 'https://g20b7465b2.gf-boe.bytedance.net' || 'https://bug-server.zijieapi.com' }}
BUG_SERVER_ENVIRONMENT: ${{ endsWith(github.event.workflow_run.display_title, ':boe') && 'boe' || endsWith(github.event.workflow_run.display_title, ':ppe') && 'ppe' || 'cn' }}
REPORTED_RUN_ID: ${{ github.event.workflow_run.id }}
BUG_SERVER_TOKEN: ${{ secrets.BUG_SERVER_TOKEN }}
run: node .github/scripts/bug-server-manual.cjs complete
6 changes: 4 additions & 2 deletions .github/workflows/bug-server-manual.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Bug Server Manual PR
run-name: bugserver-manual:${{ inputs.task_id }}${{ inputs.environment == 'boe' && ':boe' || '' }}
run-name: bugserver-manual:${{ inputs.task_id }}${{ inputs.environment == 'boe' && ':boe' || inputs.environment == 'ppe' && ':ppe' || '' }}

on:
workflow_dispatch:
Expand All @@ -13,7 +13,7 @@ on:
required: false
default: cn
type: choice
options: [cn, boe]
options: [cn, boe, ppe]

permissions:
contents: read
Expand Down Expand Up @@ -45,6 +45,7 @@ jobs:
env:
TASK_ID: ${{ inputs.task_id }}
BUG_SERVER_HOST: ${{ inputs.environment == 'boe' && 'https://g20b7465b2.gf-boe.bytedance.net' || 'https://bug-server.zijieapi.com' }}
BUG_SERVER_ENVIRONMENT: ${{ inputs.environment }}
GH_TOKEN: ${{ github.token }}
BUG_SERVER_TOKEN: ${{ secrets.BUG_SERVER_TOKEN }}
run: node .github/scripts/bug-server-manual.cjs prepare
Expand Down Expand Up @@ -124,6 +125,7 @@ jobs:
env:
TASK_ID: ${{ inputs.task_id }}
BUG_SERVER_HOST: ${{ inputs.environment == 'boe' && 'https://g20b7465b2.gf-boe.bytedance.net' || 'https://bug-server.zijieapi.com' }}
BUG_SERVER_ENVIRONMENT: ${{ inputs.environment }}
GH_TOKEN: ${{ github.token }}
BUG_SERVER_TOKEN: ${{ secrets.BUG_SERVER_TOKEN }}
run: node .github/scripts/bug-server-manual.cjs submit
Loading