-
Notifications
You must be signed in to change notification settings - Fork 371
feat: add label-triggered jobs (disable workflow, apply safe outputs) to maintenance workflow #29269
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
Merged
Merged
feat: add label-triggered jobs (disable workflow, apply safe outputs) to maintenance workflow #29269
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
ba26b50
feat: add disable_agentic_workflow label-triggered job to maintenance…
Copilot f932e1b
fix: address code review feedback - improve regex security and env is…
Copilot 574f10f
fix: contents read-only, create disable label, remove label after suc…
Copilot 3dc6fe8
feat: add disable_label_trigger config field to aw.json maintenance
Copilot ba82e06
feat: move disable label creation to disable_agentic_workflow and add…
Copilot 9b92f2f
fix: address code review feedback in disable_agentic_workflow.cjs
Copilot 09370b8
feat: rename disable_label_trigger to label_trigger_disable with defa…
Copilot 6660c5d
docs: clarify label_trigger_disable field and test assertion messages
Copilot fa01332
feat: rename to label_triggers, issues-only trigger, add label_apply_…
Copilot 17ab2ae
fix: improve comment wording in test files per code review
Copilot a6324c3
refactor: rename disable job to label_..., use REST API, extract shar…
Copilot 3b0b43a
Merge branch 'main' into copilot/update-agentic-maintenance-action
pelikhan 930050b
docs(adr): add draft ADR-29269 for label-triggered maintenance jobs
github-actions[bot] 41d5f81
fix: centralize workflow ID extraction, fix lockFileName normalizatio…
Copilot c7e9f58
Merge branch 'main' into copilot/update-agentic-maintenance-action
pelikhan 4929821
fix: add explicit permission gate on label-triggered operation steps
Copilot e3b1c8c
fix: make label_triggers opt-in (default false), enable in this repo'…
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| { | ||
| "maintenance": { | ||
| "action_failure_issue_expires": 12 | ||
| "action_failure_issue_expires": 12, | ||
| "label_triggers": true | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| // @ts-check | ||
| /// <reference types="@actions/github-script" /> | ||
|
|
||
| const { getErrorMessage } = require("./error_helpers.cjs"); | ||
| const { ERR_NOT_FOUND } = require("./error_codes.cjs"); | ||
| const { ensureLabelExists, validateLabeledIssueEvent, removeLabelSafely } = require("./label_trigger_helpers.cjs"); | ||
| const { extractWorkflowId, isValidWorkflowId } = require("./generate_footer.cjs"); | ||
|
|
||
| const DISABLE_LABEL = "agentic-workflows:disable"; | ||
| const DISABLE_LABEL_COLOR = "8250df"; // GitHub purple | ||
| const DISABLE_LABEL_DESCRIPTION = "Disable the agentic workflow that created this issue"; | ||
|
|
||
| /** | ||
| * Disable an agentic workflow when the "agentic-workflows:disable" label is applied to an issue. | ||
| * | ||
| * Reads the labeled issue body to extract the workflow_id from XML comment markers, | ||
| * disables the corresponding agentic workflow via the GitHub REST API, and posts a comment | ||
| * confirming the action. | ||
| * | ||
| * @returns {Promise<void>} | ||
| */ | ||
| async function main() { | ||
| const ctx = validateLabeledIssueEvent(DISABLE_LABEL); | ||
| if (!ctx) return; | ||
|
|
||
| const { owner, repo, issueNumber, body } = ctx; | ||
|
|
||
| // Ensure the disable label exists so it is available for future use | ||
| await ensureLabelExists(owner, repo, DISABLE_LABEL, DISABLE_LABEL_COLOR, DISABLE_LABEL_DESCRIPTION); | ||
|
|
||
| core.info(`Processing issue #${issueNumber} labeled with '${DISABLE_LABEL}'`); | ||
|
|
||
| // Extract workflow ID from body XML comment markers | ||
| const workflowId = extractWorkflowId(body); | ||
|
|
||
| if (!workflowId) { | ||
| core.warning(`Could not find workflow ID in issue #${issueNumber} body. Expected a <!-- gh-aw-workflow-id: ... --> marker.`); | ||
| await github.rest.issues.createComment({ | ||
| owner, | ||
| repo, | ||
| issue_number: issueNumber, | ||
| body: | ||
| `> [!WARNING]\n` + | ||
| `> **Could not disable agentic workflow**\n>\n` + | ||
| `> No workflow ID marker was found in this issue's body. ` + | ||
| `The \`${DISABLE_LABEL}\` label can only be used on issues that were created by an agentic workflow ` + | ||
| `(they contain a \`<!-- gh-aw-workflow-id: ... -->\` marker).\n>\n` + | ||
| `> To disable a workflow manually, trigger the maintenance workflow with the \`disable\` operation.`, | ||
| }); | ||
| core.setFailed(`${ERR_NOT_FOUND}: No workflow ID marker found in issue #${issueNumber}`); | ||
| return; | ||
| } | ||
|
|
||
| core.info(`Found workflow ID: ${workflowId}`); | ||
| core.info(`Disabling agentic workflow '${workflowId}'...`); | ||
|
|
||
| // Disable the workflow via the GitHub REST API using its compiled lock file name | ||
| const lockFileName = `${workflowId}.lock.yml`; | ||
| try { | ||
| await github.rest.actions.disableWorkflow({ owner, repo, workflow_id: lockFileName }); | ||
|
Comment on lines
+57
to
+60
|
||
| } catch (err) { | ||
| const msg = getErrorMessage(err); | ||
| core.error(`Failed to disable workflow '${workflowId}': ${msg}`); | ||
| await github.rest.issues.createComment({ | ||
| owner, | ||
| repo, | ||
| issue_number: issueNumber, | ||
| body: | ||
| `> [!WARNING]\n` + | ||
| `> **Failed to disable agentic workflow \`${workflowId}\`**\n>\n` + | ||
| `> ${msg}\n>\n` + | ||
| `> Please check the [workflow run logs](${process.env.GITHUB_SERVER_URL || "https://github.com"}/${owner}/${repo}/actions/runs/${process.env.GITHUB_RUN_ID || ""}) for details.`, | ||
| }); | ||
| core.setFailed(`Failed to disable workflow '${workflowId}': ${msg}`); | ||
| return; | ||
| } | ||
|
|
||
| core.info(`Successfully disabled workflow '${workflowId}'`); | ||
|
|
||
| // Post a success comment on the issue | ||
| await github.rest.issues.createComment({ | ||
| owner, | ||
| repo, | ||
| issue_number: issueNumber, | ||
| body: `The agentic workflow \`${workflowId}\` has been disabled.\n\n` + `To re-enable it, trigger the maintenance workflow with the \`enable\` operation.\n\n` + `<!-- gh-aw-comment-type: workflow-disabled -->`, | ||
| }); | ||
|
|
||
| core.info(`Posted disable confirmation comment on issue #${issueNumber}`); | ||
|
|
||
| // Remove the disable label now that the action is complete | ||
| await removeLabelSafely(owner, repo, issueNumber, DISABLE_LABEL); | ||
| } | ||
|
|
||
| module.exports = { main }; | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
@copilot make sure the member check is on a mode that fails the job.
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.
Done in 4929821. Added
id: check_permissionsto the permission check step andif: ${{ steps.check_permissions.outcome == 'success' }}to the operation step in bothlabel_disable_agentic_workflowandlabel_apply_safe_outputsjobs. This makes the gate explicit — the disable/apply step is skipped unless the member check step itself succeeds, regardless of anycontinue-on-errorsetting that might be applied in the future.