-
Notifications
You must be signed in to change notification settings - Fork 528
Support temporary IDs for dispatched workflow runs #53572
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ const path = require("node:path"); | |
| const { isStagedMode } = require("./safe_output_helpers.cjs"); | ||
| const { logStagedPreviewInfo } = require("./staged_preview.cjs"); | ||
| const { checkFileProtectionPostApply } = require("./manifest_file_helpers.cjs"); | ||
| const { loadTemporaryIdMapFromResolved, resolveIssueNumber } = require("./temporary_id.cjs"); | ||
|
|
||
| /** @type {string} Safe output type handled by this module */ | ||
| const HANDLER_TYPE = "approve_workflow_run"; | ||
|
|
@@ -129,10 +130,17 @@ async function main(config = {}) { | |
|
|
||
| const githubClient = isStaged ? null : await createAuthenticatedGitHubClient(config); | ||
|
|
||
| return async function handleApproveWorkflowRun(message) { | ||
| const runId = parsePositiveInt(message.run_id); | ||
| return async function handleApproveWorkflowRun(message, resolvedTemporaryIds = {}) { | ||
| const resolvedRunId = resolveIssueNumber(message.run_id, loadTemporaryIdMapFromResolved(resolvedTemporaryIds)); | ||
| const runId = resolvedRunId.wasTemporaryId ? (resolvedRunId.resolved?.number ?? undefined) : parsePositiveInt(message.run_id); | ||
|
Comment on lines
+134
to
+135
|
||
| if (!runId) { | ||
| const error = "run_id must be a positive integer"; | ||
| const error = (resolvedRunId.wasTemporaryId ? resolvedRunId.errorMessage : null) || "run_id must be a positive integer or resolved temporary ID"; | ||
| core.warning(error); | ||
| return { success: false, error }; | ||
| } | ||
| const resolvedRepo = resolvedRunId.resolved?.repo; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/tdd] 💡 Suggested fix + regression testGuard before comparing: const resolvedRepo = resolvedRunId.resolved?.repo;
if (resolvedRunId.wasTemporaryId) {
if (!resolvedRepo) {
const error = `Temporary workflow run ID '${message.run_id}' does not contain a repository reference`;
core.warning(error);
return { success: false, error };
}
if (resolvedRepo !== `${context.repo.owner}/${context.repo.repo}`) {
const error = `Temporary workflow run ID '${message.run_id}' belongs to ${resolvedRepo}, not ${context.repo.owner}/${context.repo.repo}`;
core.warning(error);
return { success: false, error };
}
}And add a test: it("rejects a temporary ID with missing repo field", async () => {
const handler = await main(externalTokenConfig);
const result = await handler({ run_id: "aw_run123" }, { aw_run123: { number: 123 } });
expect(result.success).toBe(false);
expect(result.error).toContain("does not contain a repository reference");
});@copilot please address this. |
||
| if (resolvedRunId.wasTemporaryId && resolvedRepo !== `${context.repo.owner}/${context.repo.repo}`) { | ||
| const error = `Temporary workflow run ID '${message.run_id}' belongs to ${resolvedRepo}, not ${context.repo.owner}/${context.repo.repo}`; | ||
| core.warning(error); | ||
| return { success: false, error }; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new
approve_workflow_runpath trustsresolvedTemporaryIds[...].numberwithout re-validating it as a positive integer, so a malformed or fractional mapping can now flow straight intogetWorkflowRun/approval instead of being rejected like directrun_idinput is.💡 Why this needs fixing
resolveIssueNumber()convertsnumberwithNumber(...), but this call site never re-appliesparsePositiveInt()when the source was a temporary ID:That means values like
1.5,0,-1, orNaNcoming from the resolved map can bypass the existing integer validation path and get sent to the Actions API. At best this becomes a flaky runtime failure; at worst it weakens the contract thatapprove_workflow_runonly accepts positive integer run IDs.Please normalize the resolved temporary-ID value through the same positive-integer validator before using it, and add a test that rejects a temporary ID mapped to a non-integer/non-positive
number.