-
Notifications
You must be signed in to change notification settings - Fork 0
chore: sync workflow templates #316
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| ## Workflow Source | ||
|
|
||
| Started from: | ||
| - [ ] GitHub issue: # | ||
| - [ ] Direct PR / remote GitHub work | ||
| - [ ] Local Codex/user request | ||
| - [ ] Automation run | ||
| - [ ] Review follow-up from PR # | ||
| - [ ] Sync / maintenance campaign | ||
| - [ ] Dependabot or dependency update | ||
| - [ ] Do not automate | ||
|
|
||
| Automation intent: | ||
| - [ ] Verifier should review this | ||
| - [ ] Keepalive may manage this PR | ||
| - [ ] Human-only unless checks fail | ||
|
|
||
| Notes: | ||
| <!-- If there is no linked issue, briefly describe the source. Automation also accepts workflow source labels such as workflow:source-direct-pr. --> | ||
|
|
||
| ## Summary | ||
|
|
||
|
|
||
| ## Testing |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,10 @@ const fs = require('fs'); | |
| const os = require('os'); | ||
| const childProcess = require('child_process'); | ||
| const { ensureRateLimitWrapped } = require('./github-rate-limited-wrapper.js'); | ||
| const { | ||
| formatSourceContextForLog, | ||
| resolvePrSourceContext, | ||
| } = require('./source_context.js'); | ||
|
|
||
| class RateLimitError extends Error { | ||
| constructor(message, options = {}) { | ||
|
|
@@ -930,6 +934,66 @@ function isCampaignIssue(issue = {}) { | |
| return labels.has('campaign:sync-dependabot') || labels.has('campaign:active'); | ||
| } | ||
|
|
||
| function buildSourceContextRepairCommentBody(prNumber) { | ||
| return [ | ||
| '<!-- missing-issue-warning -->', | ||
| '### Workflow source needed', | ||
| '', | ||
| `PR #${prNumber} does not need a GitHub issue, but Workflows needs one valid source context before PR metadata automation can manage it safely.`, | ||
| '', | ||
| 'Please do one of:', | ||
| '', | ||
| '- Add `<!-- meta:issue:123 -->` or a normal `Closes #123` / `Related to #123` line.', | ||
| '- Check one `Workflow Source` option in the PR body.', | ||
| '- Add a hidden marker such as `<!-- workflow-source:local_request -->`, `<!-- workflow-source:manual_remote -->`, `<!-- workflow-source:review_followup -->`, `<!-- workflow-source:sync_campaign -->`, or `<!-- workflow-source:dependabot -->`.', | ||
| '- Add a workflow source label such as `workflow:source-direct-pr`, `workflow:source-local-request`, `workflow:source-review-followup`, `workflow:source-sync`, or `workflow:no-automation`.', | ||
| '', | ||
| 'Once a valid source is present, this warning will not be reposted.', | ||
| ].join('\n'); | ||
| } | ||
|
|
||
| function buildSourceContextResolvedCommentBody(prNumber, sourceContext) { | ||
| return [ | ||
| '<!-- missing-issue-warning -->', | ||
| '### Workflow source detected', | ||
| '', | ||
| `PR #${prNumber} now has valid workflow source context (${formatSourceContextForLog(sourceContext)}).`, | ||
| '', | ||
| 'No linked GitHub issue is required for this PR.', | ||
| ].join('\n'); | ||
| } | ||
|
|
||
| async function resolveSourceContextRepairComment({ | ||
| github, | ||
| owner, | ||
| repo, | ||
| prNumber, | ||
| comments, | ||
| sourceContext, | ||
| core, | ||
| }) { | ||
| const marker = '<!-- missing-issue-warning -->'; | ||
| const existingWarning = comments.find((c) => c.body && c.body.includes(marker)); | ||
| if (!existingWarning) { | ||
| return false; | ||
| } | ||
|
|
||
| const resolvedBody = buildSourceContextResolvedCommentBody(prNumber, sourceContext); | ||
| if (existingWarning.body === resolvedBody) { | ||
| core?.info?.(`Workflow source repair comment already resolved (id: ${existingWarning.id})`); | ||
| return false; | ||
| } | ||
|
|
||
| await github.rest.issues.updateComment({ | ||
| owner, | ||
| repo, | ||
| comment_id: existingWarning.id, | ||
| body: resolvedBody, | ||
| }); | ||
|
Comment on lines
+987
to
+992
|
||
| core?.info?.(`Resolved workflow source repair comment (id: ${existingWarning.id})`); | ||
| return true; | ||
| } | ||
|
|
||
| function buildPreamble(sections) { | ||
| const lines = ['<!-- pr-preamble:start -->']; | ||
|
|
||
|
|
@@ -1231,9 +1295,35 @@ async function run({github: rawGithub, context, core, inputs}) { | |
| } | ||
|
|
||
| const issueNumber = extractIssueNumberFromPull(pr); | ||
| const sourceContext = resolvePrSourceContext(pr); | ||
| if (!issueNumber) { | ||
| if (sourceContext.isValid && !sourceContext.requiresIssue) { | ||
| core.info( | ||
| `PR #${pr.number} has valid non-issue workflow source context (${formatSourceContextForLog(sourceContext)}); skipping issue-sourced body sync.`, | ||
| ); | ||
| try { | ||
| const comments = await github.paginate(github.rest.issues.listComments, { | ||
| owner, | ||
| repo, | ||
| issue_number: pr.number, | ||
| }); | ||
| await resolveSourceContextRepairComment({ | ||
| github, | ||
| owner, | ||
| repo, | ||
| prNumber: pr.number, | ||
| comments, | ||
| sourceContext, | ||
| core, | ||
| }); | ||
| } catch (error) { | ||
| core.warning(`Failed to resolve workflow source repair comment: ${error.message}`); | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| const marker = '<!-- missing-issue-warning -->'; | ||
| const warningMsg = `Unable to determine source issue for PR #${pr.number}. The PR title, branch name, or body must contain the issue number (e.g. #123, branch: issue-123, or the hidden marker <!-- meta:issue:123 -->).`; | ||
| const warningMsg = `Unable to determine workflow source context for PR #${pr.number}. Add a GitHub issue reference or another valid Workflow Source entry.`; | ||
| core.warning(warningMsg); | ||
|
|
||
| try { | ||
|
|
@@ -1244,11 +1334,20 @@ async function run({github: rawGithub, context, core, inputs}) { | |
| }); | ||
| // Find existing warning comment by marker to enable upsert pattern | ||
| const existingWarning = comments.find((c) => c.body && c.body.includes(marker)); | ||
| const commentBody = `${marker}\n⚠️ **Action Required**: ${warningMsg}`; | ||
| const commentBody = buildSourceContextRepairCommentBody(pr.number); | ||
|
|
||
| if (existingWarning) { | ||
| // Update existing comment (avoids duplicates from race conditions) | ||
| core.info(`Warning comment already exists (id: ${existingWarning.id}), skipping duplicate`); | ||
| if (existingWarning.body !== commentBody) { | ||
| await github.rest.issues.updateComment({ | ||
| owner, | ||
| repo, | ||
| comment_id: existingWarning.id, | ||
| body: commentBody, | ||
| }); | ||
|
Comment on lines
+1341
to
+1346
|
||
| core.info(`Updated workflow source repair comment (id: ${existingWarning.id})`); | ||
| } else { | ||
| core.info(`Workflow source repair comment already exists (id: ${existingWarning.id})`); | ||
| } | ||
| } else { | ||
| await github.rest.issues.createComment({ | ||
| owner, | ||
|
|
@@ -1435,6 +1534,9 @@ module.exports = { | |
| filterWorkflowRunsForStatus, | ||
| buildContextBlock, | ||
| buildPreamble, | ||
| buildSourceContextRepairCommentBody, | ||
| buildSourceContextResolvedCommentBody, | ||
| resolveSourceContextRepairComment, | ||
| isCampaignIssue, | ||
| buildStatusBlock, | ||
| withRetries, | ||
|
|
||
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 repair comment currently states “PR #X does not need a GitHub issue” but then instructs the user to add an issue reference; for PRs that do originate from an issue this reads contradictory. Reword the first sentence to reflect the actual requirement (“add a linked issue OR select a valid non-issue Workflow Source”) so the guidance is accurate for both cases.