safe-outputs: Apply labels when creating discussions#15597
Conversation
- Add fetchLabelIds() to fetch label node IDs from repository - Add applyLabelsToDiscussion() to apply labels via GraphQL - Build discussionLabels array with sanitization and deduplication - Apply labels after discussion creation - Handle errors gracefully (log warnings, continue if label application fails) - Add comprehensive tests for label functionality Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot update smoke codex to create a discussion in announcements category titled "codex was here" and with label "codex-was-here". Update prompt to make it one of the agent goals |
- Add create-discussion to safe-outputs with announcements category - Configure codex-was-here label for discussions - Add test requirement #7 for discussion creation testing - Update output section to include discussion creation test result Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Updated smoke-codex workflow in commit 4b150b4:
The workflow will now test the label application functionality for discussions. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot create-didcussion in smoke-codex should expire in 1d and close-older-discussions |
…ussions - Set expires: 1d for create-discussion (24 hours) - Enable close-older-discussions: true to clean up old discussions Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Updated in commit 6e4234c:
The smoke-codex workflow will now create discussions that expire in 1 day and automatically close older discussions with the same workflow-id marker. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
❌ Changeset Generator failed. Please review the logs for details. |
|
🧪 Smoke Temporary ID is now testing temporary ID functionality... |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation... |
|
🧪 Smoke Project is now testing project operations... |
|
✅ Smoke Project completed successfully. All project operations validated. |
- Change create-discussion label from copilot-was-here to ai-generated - Update test requirement #9 to reflect the new label - Recompile workflow Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Updated in commit 977949a:
smoke-copilot now tests discussion creation with the Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
|
🧪 Smoke Temporary ID is now testing temporary ID functionality... |
|
🧪 Smoke Project is now testing project operations... |
|
🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation... |
|
❌ Changeset Generator failed. Please review the logs for details. |
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
✅ Smoke Temporary ID completed successfully. Temporary ID validation passed. |
|
✅ Smoke Project completed successfully. All project operations validated. |
Agent Container Tool Check ✅
Result: 12/12 tools available ✅ All required development tools are present and functional in the agent container environment.
|
🚀 Smoke Test ResultsPR Titles:
Test Results:
Overall: PARTIAL PASS (9/11 tests, 81.8%) cc: @pelikhan
|
There was a problem hiding this comment.
Smoke Test Review
Added create_discussion safe-output to smoke-copilot workflow with 24-hour expiration. Changes look good - proper integration of discussion creation testing.
📰 BREAKING: Report filed by Smoke Copilot for issue #15597
| mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs | ||
| cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' | ||
| {"add_comment":{"allowed_repos":["github/gh-aw"],"max":2},"add_labels":{"allowed":["smoke-copilot"],"allowed_repos":["github/gh-aw"],"max":3},"create_issue":{"expires":2,"group":true,"max":1},"create_pull_request_review_comment":{"max":5},"dispatch_workflow":{"max":1,"workflow_files":{"haiku-printer":".yml"},"workflows":["haiku-printer"]},"missing_data":{},"missing_tool":{},"noop":{"max":1},"remove_labels":{"allowed":["smoke"],"max":3},"send-slack-message":{"description":"Send a message to Slack (stub for testing)","inputs":{"message":{"default":null,"description":"The message to send","required":true,"type":"string"}},"output":"Slack message stub executed!"},"submit_pull_request_review":{"max":1}} | ||
| {"add_comment":{"allowed_repos":["github/gh-aw"],"max":2},"add_labels":{"allowed":["smoke-copilot"],"allowed_repos":["github/gh-aw"],"max":3},"create_discussion":{"expires":24,"max":1},"create_issue":{"expires":2,"group":true,"max":1},"create_pull_request_review_comment":{"max":5},"dispatch_workflow":{"max":1,"workflow_files":{"haiku-printer":".yml"},"workflows":["haiku-printer"]},"missing_data":{},"missing_tool":{},"noop":{"max":1},"remove_labels":{"allowed":["smoke"],"max":3},"send-slack-message":{"description":"Send a message to Slack (stub for testing)","inputs":{"message":{"default":null,"description":"The message to send","required":true,"type":"string"}},"output":"Slack message stub executed!"},"submit_pull_request_review":{"max":1}} |
There was a problem hiding this comment.
✅ Good addition: create_discussion config now includes expires: 24 (hours) to automatically clean up test discussions after 1 day.
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug where discussion labels configured in safe-outputs.create-discussion.labels were parsed but never applied to created discussions. The fix implements a two-step GraphQL approach: fetching label node IDs via query, then applying them using the addLabelsToLabelable mutation after discussion creation.
Changes:
- Implemented label fetching and application functionality for discussions using GraphQL
- Added comprehensive test coverage for label operations (merging, sanitization, deduplication, error handling)
- Updated smoke-copilot workflow to test discussion creation with labels, expiration, and cleanup features
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| actions/setup/js/create_discussion.cjs | Added fetchLabelIds() and applyLabelsToDiscussion() functions; integrated label merging, sanitization, and application into discussion creation flow |
| actions/setup/js/create_discussion_labels.test.cjs | Added comprehensive test suite covering label application scenarios: config labels, per-message labels, merging, sanitization, missing labels, and graceful error handling |
| .github/workflows/smoke-copilot.md | Added test requirement #9 for discussion creation with labels; configured discussion with announcements category, ai-generated label, 1d expiration, and close-older-discussions |
| .github/workflows/smoke-copilot.lock.yml | Generated lock file reflecting workflow changes with proper configuration for create_discussion including labels, expiration, and cleanup settings |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| if (unmatchedLabels.length > 0) { | ||
| core.warning(`Could not find label IDs for: ${unmatchedLabels.join(", ")}`); | ||
| core.info(`These labels may not exist in the repository. Available labels: ${repoLabels.map(l => l.name).join(", ")}`); |
There was a problem hiding this comment.
Line 166 logs all available repository labels when requested labels are not found. For repositories with many labels (up to the 100 label query limit), this could result in very long log messages. Consider truncating the list or limiting the number of labels shown in the informational message (e.g., showing only the first 10 labels and adding "... and N more" for the rest) to improve log readability.
| core.info(`These labels may not exist in the repository. Available labels: ${repoLabels.map(l => l.name).join(", ")}`); | |
| const availableLabelNames = repoLabels.map((l) => l.name); | |
| const maxLabelsToShow = 10; | |
| const displayedLabels = availableLabelNames.slice(0, maxLabelsToShow); | |
| let infoMessage = `These labels may not exist in the repository. Available labels: ${displayedLabels.join(", ")}`; | |
| if (availableLabelNames.length > maxLabelsToShow) { | |
| const remainingCount = availableLabelNames.length - maxLabelsToShow; | |
| infoMessage += ` ... and ${remainingCount} more`; | |
| } | |
| core.info(infoMessage); |
| if (labelsApplied) { | ||
| core.info(`✓ Applied labels: ${labelIdsData.map(l => l.name).join(", ")}`); | ||
| } | ||
| } else if (discussionLabels.length > 0) { |
There was a problem hiding this comment.
The condition discussionLabels.length > 0 is redundant in this else-if block. This code is already within the outer if (discussionLabels.length > 0) block (line 561), and the else-if only executes when labelIdsData.length === 0. The redundant check can be simplified to just else without the condition.
| } else if (discussionLabels.length > 0) { | |
| } else { |
| let callCount = 0; | ||
| mockGithub.graphql.mockImplementation(async (query, variables) => { | ||
| callCount++; | ||
|
|
There was a problem hiding this comment.
The callCount variable is declared and incremented but never used in the mock implementation. This appears to be dead code that can be removed to improve code clarity.
| let callCount = 0; | |
| mockGithub.graphql.mockImplementation(async (query, variables) => { | |
| callCount++; | |
| mockGithub.graphql.mockImplementation(async (query, variables) => { |
safe-outputs.create-discussion.labelswere parsed from config but never applied to created discussions. ThecreateDiscussionGraphQL mutation doesn't accept labels, and no follow-up step existed to add them.Changes
Label Application Flow
fetchLabelIds(): Query repository labels, match requested labels case-insensitively, return node IDsapplyLabelsToDiscussion(): Apply labels viaaddLabelsToLabelableGraphQL mutation after discussion creationcreate_issuebehavior)Smoke Test Updates
smoke-copilotworkflow to test discussion creation with labelsclose-older-discussions: trueTechnical Note
Discussions require GraphQL
addLabelsToLabelable(label node IDs) rather than RESTissues.addLabels(label names) used by issues/PRs.Example
Discussions will now receive both labels (if they exist in the repository), expire after 1 day, and automatically close older discussions with the same workflow-id marker.
Warning
<issue_title>safe-outputs create-discussion does not apply configured labels</issue_title>
<issue_description>## Summary
safe-outputs.create-discussion.labelsappears to be accepted in config but not applied to newly created discussions.What I observed
The
create_discussionhandler parsesconfig.labels, but those labels are never used when creating the discussion.Expected behavior
When
safe-outputs.create-discussion.labelsis configured, created discussions should receive those labels.Actual behavior
Discussion is created successfully, but no labels are applied.
Reproduction
create-discussionandlabels:create_discussionoutput item.Code evidence
create_discussionparses labels from config, but does not use them later:actions/setup/js/create_discussion.cjs:196repositoryId,categoryId,title, andbody:actions/setup/js/create_discussion.cjs:405create_issuebuilds and passes labels to API create call:actions/setup/js/create_issue.cjs:376actions/setup/js/create_issue.cjs:469pkg/parser/schemas/main_workflow_schema.json:4364pkg/workflow/create_discussion.go:18Likely root cause
The discussion creation path lacks a label-attachment step (either during
createDiscussioninput if supported, or a follow-up mutation to apply labels after creation).Suggested fix
After discussion creation, resolve label IDs for configured labels and apply them to the created discussion node (or include label IDs directly if supported by the create mutation input).
Impact
Workflows depending on discussion labels for triage, filtering, and close-older-discussions matching do not behave as configured.
</issue_description>
Comments on the Issue (you are @copilot in this section)
<issue_title>safe-outputs create-discussion does not apply configured labels</issue_title>
<issue_title>safe-outputs create-discussion does not apply configured labels</issue_title>
<issue_title>safe-outputs create-discussion does not apply configured labels</issue_title>
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.