chore(ci): Implement /query-regression command handling and admission workflow (#8975)

* Implement `/query-regression` command handling and admission workflow

- Add `query-regression-slash.py` script for processing `/query-regression` commands in PR comments, validating case arguments, and checking permissions.
- Update `checks.yml` to include tests for the new slash command functionality.
- Modify `query-regression-comment.yml` to trigger on the new `Query Regression Command` workflow.
- Create `query-regression-slash.yml` to handle the dispatched command, validate allowlist and permissions, and initiate the regression workflow.
- Enhance `query-regression.yml` to support additional inputs for PR admission and SHA verification.
- Introduce `slash-command-dispatch.yml` to parse and dispatch commands from PR comments.
- Document the new command admission process in `AGENTS.md` and `README.md`.
- Add unit tests in `test_query_regression_slash.py` to cover command parsing and admission logic.

* refactor: enhance query-regression command handling with comment validation and identity checks

* feat: implement admission identity handling for query regression workflows

* refactor: update PR admission logic in query regression workflow

* refactor: update token usage in slash command dispatch and README for clarity

* test: add cases for handling re-run failed jobs and stale runner artifacts

* refactor: improve repository metadata handling in query regression scripts

* chore: enable overwrite for artifact uploads to handle re-run failed jobs

* chore: enable overwrite for query regression admission uploads

* feat: enhance query-regression admission with HMAC signing and verification

- Introduced HMAC signing for admission markers in query-regression workflows to ensure integrity and authenticity.
- Updated `query-regression-comment.test.cjs` to include tests for signing and verifying admission markers.
- Modified `query-regression-slash.py` to handle admission marker signing and verification, including checks for dispatch sender and head SHA consistency.
- Enhanced workflows to securely manage admission markers and HMAC secrets, ensuring they are not exposed to untrusted contexts.
- Improved documentation to clarify the admission process and the role of HMAC in securing the workflow.

* test: add case to find newly posted marker among newer comments

* test: add case to verify multiline output handling in write_outputs function
This commit is contained in:
localhost
2026-09-07 07:23:05 +00:00
committed by GitHub
parent f9df4def74
commit 4d65e8984a
12 changed files with 2515 additions and 193 deletions
+790 -18
View File
@@ -5,7 +5,16 @@ const test = require('node:test');
const assert = require('node:assert/strict');
const handler = require('./query-regression-comment.cjs');
const { collectReportRows, renderSummaryTable } = handler._test;
const {
collectReportRows,
renderSummaryTable,
admissionMac,
verifyAdmissionMac,
formatAdmissionMarker,
parseAdmissionMarker,
} = handler._test;
const HMAC_SECRET = 'test-admission-hmac';
function report(name, measurements, thresholds = []) {
return {
@@ -19,10 +28,41 @@ function report(name, measurements, thresholds = []) {
};
}
function markerComment(identity, { id = 1, secret = HMAC_SECRET } = {}) {
const payload = { ...identity, mac: admissionMac(secret, identity) };
return { id, body: formatAdmissionMarker(payload) };
}
function githubApi({ identity, pull, comments }) {
return {
rest: {
issues: {
listComments: async () => ({ data: comments ?? [markerComment(identity)] }),
},
pulls: {
get: async () => ({
data: pull ?? {
state: 'open',
base: { repo: { full_name: identity.base_repo } },
head: { repo: { full_name: identity.head_repo }, sha: identity.head_sha },
},
}),
},
},
};
}
test('keeps the default export callable and exposes only the test seam', () => {
assert.equal(typeof handler, 'function');
assert.equal(handler.constructor.name, 'AsyncFunction');
assert.deepEqual(Object.keys(handler._test).sort(), ['collectReportRows', 'renderSummaryTable']);
assert.deepEqual(Object.keys(handler._test).sort(), [
'admissionMac',
'collectReportRows',
'formatAdmissionMarker',
'parseAdmissionMarker',
'renderSummaryTable',
'verifyAdmissionMac',
]);
});
test('renders every case in one summary table without per-case separators', () => {
@@ -305,18 +345,87 @@ test('escapes Markdown table content, including bare carriage returns', () => {
assert.doesNotMatch(table, /hidden|comment|drop|\r/);
});
test('writes the explicit no-report summary without an empty table', async () => {
test('posts a comment-command report without treating workflow_run as the PR head', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const originalHmac = process.env.QUERY_REGRESSION_ADMISSION_HMAC;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
try {
fs.mkdirSync(artifactDir);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify({
run_id: 101,
const metadata = {
run_id: 202,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
head_sha: 'pr-head-sha',
head_repo: 'fork/repo',
built_base_sha: 'base-sha',
event_base_sha: 'event-base-sha',
candidate_sha: 'merge-sha',
base_sha: 'event-base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(metadata),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify(metadata));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '202';
process.env.WORKFLOW_RUN_ATTEMPT = '1';
process.env.QUERY_REGRESSION_ADMISSION_HMAC = HMAC_SECRET;
await handler({
core: {
info() {},
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: githubApi({ identity: metadata }),
});
assert.equal(outputs.get('should_post'), 'true');
assert.equal(outputs.get('pr_number'), '42');
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
if (originalHmac === undefined) delete process.env.QUERY_REGRESSION_ADMISSION_HMAC;
else process.env.QUERY_REGRESSION_ADMISSION_HMAC = originalHmac;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('skips reports produced by a pull_request workflow_run', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
const infos = [];
try {
fs.mkdirSync(artifactDir);
const metadata = {
run_id: 303,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
@@ -325,14 +434,21 @@ test('writes the explicit no-report summary without an empty table', async () =>
built_base_sha: 'base-sha',
event_base_sha: 'event-base-sha',
candidate_sha: 'candidate-sha',
}));
base_sha: 'event-base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(metadata),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify(metadata));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '101';
process.env.WORKFLOW_RUN_ID = '303';
process.env.WORKFLOW_RUN_ATTEMPT = '1';
await handler({
core: {
info() {},
info(message) { infos.push(message); },
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
@@ -347,19 +463,73 @@ test('writes the explicit no-report summary without an empty table', async () =>
},
},
},
github: {
rest: {
pulls: {
get: async () => ({
data: {
state: 'open',
base: { repo: { full_name: 'owner/repo' } },
head: { repo: { full_name: 'fork/repo' }, sha: 'head-sha' },
},
}),
github: { rest: { pulls: { get: async () => { throw new Error('should not fetch PR'); } } } },
});
assert.equal(outputs.get('should_post'), 'false');
assert.match(infos.join('\n'), /not repository_dispatch/);
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('writes the explicit no-report summary without an empty table', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const originalHmac = process.env.QUERY_REGRESSION_ADMISSION_HMAC;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
try {
fs.mkdirSync(artifactDir);
const metadata = {
run_id: 101,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
head_sha: 'head-sha',
head_repo: 'fork/repo',
built_base_sha: 'base-sha',
event_base_sha: 'event-base-sha',
candidate_sha: 'candidate-sha',
base_sha: 'event-base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(metadata),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify(metadata));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '101';
process.env.WORKFLOW_RUN_ATTEMPT = '1';
process.env.QUERY_REGRESSION_ADMISSION_HMAC = HMAC_SECRET;
await handler({
core: {
info() {},
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: githubApi({ identity: metadata }),
});
const summary = fs.readFileSync(path.join(artifactDir, 'query-regression-summary.md'), 'utf8');
@@ -372,6 +542,608 @@ test('writes the explicit no-report summary without an empty table', async () =>
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
if (originalHmac === undefined) delete process.env.QUERY_REGRESSION_ADMISSION_HMAC;
else process.env.QUERY_REGRESSION_ADMISSION_HMAC = originalHmac;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('skips when the runner artifact forges a different PR number', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
const infos = [];
try {
fs.mkdirSync(artifactDir);
const admission = {
run_id: 404,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
head_sha: 'head-sha',
head_repo: 'fork/repo',
candidate_sha: 'merge-sha',
base_sha: 'base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(admission),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify({
...admission,
pr_number: 99,
}));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '404';
process.env.WORKFLOW_RUN_ATTEMPT = '1';
await handler({
core: {
info(message) { infos.push(message); },
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: { rest: { pulls: { get: async () => { throw new Error('should not fetch PR'); } } } },
});
assert.equal(outputs.get('should_post'), 'false');
assert.match(infos.join('\n'), /does not match admission artifact/);
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('posts after Re-run failed jobs when admission stays on attempt 1', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const originalHmac = process.env.QUERY_REGRESSION_ADMISSION_HMAC;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
try {
fs.mkdirSync(artifactDir);
const admission = {
run_id: 505,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
head_sha: 'pr-head-sha',
head_repo: 'fork/repo',
candidate_sha: 'merge-sha',
base_sha: 'base-sha',
};
const metadata = {
...admission,
run_attempt: 2,
built_base_sha: 'base-sha',
event_base_sha: 'base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(admission),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify(metadata));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '505';
process.env.WORKFLOW_RUN_ATTEMPT = '2';
process.env.QUERY_REGRESSION_ADMISSION_HMAC = HMAC_SECRET;
await handler({
core: {
info() {},
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: githubApi({ identity: admission }),
});
assert.equal(outputs.get('should_post'), 'true');
assert.equal(outputs.get('pr_number'), '42');
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
if (originalHmac === undefined) delete process.env.QUERY_REGRESSION_ADMISSION_HMAC;
else process.env.QUERY_REGRESSION_ADMISSION_HMAC = originalHmac;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('skips a stale runner artifact from a previous attempt', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
const infos = [];
try {
fs.mkdirSync(artifactDir);
const admission = {
run_id: 606,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
head_sha: 'pr-head-sha',
head_repo: 'fork/repo',
candidate_sha: 'merge-sha',
base_sha: 'base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(admission),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify({
...admission,
built_base_sha: 'base-sha',
event_base_sha: 'base-sha',
}));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '606';
process.env.WORKFLOW_RUN_ATTEMPT = '2';
await handler({
core: {
info(message) { infos.push(message); },
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: { rest: { pulls: { get: async () => { throw new Error('should not fetch PR'); } } } },
});
assert.equal(outputs.get('should_post'), 'false');
assert.match(infos.join('\n'), /does not match this workflow_run attempt/);
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('skips when the current PR head repository is missing', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const originalHmac = process.env.QUERY_REGRESSION_ADMISSION_HMAC;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
const infos = [];
try {
fs.mkdirSync(artifactDir);
const metadata = {
run_id: 707,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
head_sha: 'pr-head-sha',
head_repo: 'fork/repo',
built_base_sha: 'base-sha',
event_base_sha: 'base-sha',
candidate_sha: 'merge-sha',
base_sha: 'base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(metadata),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify(metadata));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '707';
process.env.WORKFLOW_RUN_ATTEMPT = '1';
process.env.QUERY_REGRESSION_ADMISSION_HMAC = HMAC_SECRET;
await handler({
core: {
info(message) { infos.push(message); },
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: githubApi({
identity: metadata,
pull: {
state: 'open',
base: { repo: { full_name: 'owner/repo' } },
head: { repo: null, sha: 'pr-head-sha' },
},
}),
});
assert.equal(outputs.get('should_post'), 'false');
assert.match(infos.join('\n'), /does not match trusted admission/);
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
if (originalHmac === undefined) delete process.env.QUERY_REGRESSION_ADMISSION_HMAC;
else process.env.QUERY_REGRESSION_ADMISSION_HMAC = originalHmac;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('signs and verifies admission markers', () => {
const identity = {
run_id: 808,
pr_number: 42,
head_sha: 'HEADSHA',
head_repo: 'fork/repo',
base_repo: 'owner/repo',
candidate_sha: 'MERGESHA',
base_sha: 'BASESHA',
};
const mac = admissionMac(HMAC_SECRET, identity);
assert.equal(verifyAdmissionMac(HMAC_SECRET, identity, mac), true);
assert.equal(verifyAdmissionMac('other', identity, mac), false);
assert.equal(verifyAdmissionMac(HMAC_SECRET, { ...identity, pr_number: 99 }, mac), false);
const parsed = parseAdmissionMarker(`noise\n${formatAdmissionMarker({ ...identity, mac })}\n`);
assert.equal(parsed.pr_number, 42);
assert.equal(verifyAdmissionMac(HMAC_SECRET, parsed, parsed.mac), true);
});
test('skips when the HMAC secret is unset', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const originalHmac = process.env.QUERY_REGRESSION_ADMISSION_HMAC;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
const infos = [];
try {
fs.mkdirSync(artifactDir);
const metadata = {
run_id: 808,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
head_sha: 'pr-head-sha',
head_repo: 'fork/repo',
candidate_sha: 'merge-sha',
base_sha: 'base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(metadata),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify(metadata));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '808';
process.env.WORKFLOW_RUN_ATTEMPT = '1';
delete process.env.QUERY_REGRESSION_ADMISSION_HMAC;
await handler({
core: {
info(message) { infos.push(message); },
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: githubApi({ identity: metadata }),
});
assert.equal(outputs.get('should_post'), 'false');
assert.match(infos.join('\n'), /QUERY_REGRESSION_ADMISSION_HMAC is unset/);
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
if (originalHmac === undefined) delete process.env.QUERY_REGRESSION_ADMISSION_HMAC;
else process.env.QUERY_REGRESSION_ADMISSION_HMAC = originalHmac;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('skips when the hinted PR has no signed marker for this run', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const originalHmac = process.env.QUERY_REGRESSION_ADMISSION_HMAC;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
const infos = [];
try {
fs.mkdirSync(artifactDir);
const metadata = {
run_id: 909,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 99,
head_sha: 'pr-head-sha',
head_repo: 'fork/repo',
candidate_sha: 'merge-sha',
base_sha: 'base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(metadata),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify(metadata));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '909';
process.env.WORKFLOW_RUN_ATTEMPT = '1';
process.env.QUERY_REGRESSION_ADMISSION_HMAC = HMAC_SECRET;
await handler({
core: {
info(message) { infos.push(message); },
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: githubApi({ identity: metadata, comments: [{ id: 1, body: 'unrelated' }] }),
});
assert.equal(outputs.get('should_post'), 'false');
assert.match(infos.join('\n'), /No signed admission marker/);
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
if (originalHmac === undefined) delete process.env.QUERY_REGRESSION_ADMISSION_HMAC;
else process.env.QUERY_REGRESSION_ADMISSION_HMAC = originalHmac;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('skips a marker whose HMAC does not match', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const originalHmac = process.env.QUERY_REGRESSION_ADMISSION_HMAC;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
const infos = [];
try {
fs.mkdirSync(artifactDir);
const metadata = {
run_id: 910,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
head_sha: 'pr-head-sha',
head_repo: 'fork/repo',
candidate_sha: 'merge-sha',
base_sha: 'base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(metadata),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify(metadata));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '910';
process.env.WORKFLOW_RUN_ATTEMPT = '1';
process.env.QUERY_REGRESSION_ADMISSION_HMAC = HMAC_SECRET;
await handler({
core: {
info(message) { infos.push(message); },
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: githubApi({
identity: metadata,
comments: [markerComment(metadata, { secret: 'forged-secret' })],
}),
});
assert.equal(outputs.get('should_post'), 'false');
assert.match(infos.join('\n'), /No signed admission marker/);
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
if (originalHmac === undefined) delete process.env.QUERY_REGRESSION_ADMISSION_HMAC;
else process.env.QUERY_REGRESSION_ADMISSION_HMAC = originalHmac;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});
test('finds a newly posted marker after a full page of newer comments', async () => {
const originalCwd = process.cwd();
const originalRunId = process.env.WORKFLOW_RUN_ID;
const originalRunAttempt = process.env.WORKFLOW_RUN_ATTEMPT;
const originalHmac = process.env.QUERY_REGRESSION_ADMISSION_HMAC;
const temporaryDir = fs.mkdtempSync(path.join(os.tmpdir(), 'query-regression-comment-'));
const artifactDir = path.join(temporaryDir, 'query-regression-comment');
const outputs = new Map();
const pages = [];
try {
fs.mkdirSync(artifactDir);
const metadata = {
run_id: 911,
run_attempt: 1,
base_repo: 'owner/repo',
pr_number: 42,
head_sha: 'pr-head-sha',
head_repo: 'fork/repo',
candidate_sha: 'merge-sha',
base_sha: 'base-sha',
};
fs.mkdirSync(path.join(temporaryDir, 'query-regression-admission'));
fs.writeFileSync(
path.join(temporaryDir, 'query-regression-admission', 'query-regression-admission.json'),
JSON.stringify(metadata),
);
fs.writeFileSync(path.join(artifactDir, 'query-regression-pr.json'), JSON.stringify(metadata));
process.chdir(temporaryDir);
process.env.WORKFLOW_RUN_ID = '911';
process.env.WORKFLOW_RUN_ATTEMPT = '1';
process.env.QUERY_REGRESSION_ADMISSION_HMAC = HMAC_SECRET;
await handler({
core: {
info() {},
warning() {},
setOutput(name, value) { outputs.set(name, value); },
},
context: {
repo: { owner: 'owner', repo: 'repo' },
payload: {
workflow_run: {
event: 'repository_dispatch',
head_sha: 'default-branch-sha',
head_repository: { full_name: 'owner/repo' },
pull_requests: [],
},
},
},
github: {
rest: {
issues: {
listComments: async ({ page, direction }) => {
pages.push({ page, direction });
if (page === 1) {
return {
data: Array.from({ length: 100 }, (_, index) => ({
id: 10_000 - index,
body: 'unrelated',
})),
};
}
return { data: [markerComment(metadata, { id: 50 })] };
},
},
pulls: {
get: async () => ({
data: {
state: 'open',
base: { repo: { full_name: 'owner/repo' } },
head: { repo: { full_name: 'fork/repo' }, sha: 'pr-head-sha' },
},
}),
},
},
},
});
assert.equal(outputs.get('should_post'), 'true');
assert.deepEqual(pages, [
{ page: 1, direction: 'desc' },
{ page: 2, direction: 'desc' },
]);
} finally {
process.chdir(originalCwd);
if (originalRunId === undefined) delete process.env.WORKFLOW_RUN_ID;
else process.env.WORKFLOW_RUN_ID = originalRunId;
if (originalRunAttempt === undefined) delete process.env.WORKFLOW_RUN_ATTEMPT;
else process.env.WORKFLOW_RUN_ATTEMPT = originalRunAttempt;
if (originalHmac === undefined) delete process.env.QUERY_REGRESSION_ADMISSION_HMAC;
else process.env.QUERY_REGRESSION_ADMISSION_HMAC = originalHmac;
fs.rmSync(temporaryDir, { recursive: true, force: true });
}
});