From 4fd433c4ee868b74e08f88ef688eb4fb5539731a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 16:18:45 +0000 Subject: [PATCH 1/4] Initial plan From 1d2226dfeff5cd2686f0782c98908d180d48cde4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 16:23:39 +0000 Subject: [PATCH 2/4] chore: plan for removing announcement-capable category limitation Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/mcp-inspector.lock.yml | 2 +- pkg/workflow/data/action_pins.json | 27 ++++++------------------ 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml index b924918d3f..6aacc72bf4 100644 --- a/.github/workflows/mcp-inspector.lock.yml +++ b/.github/workflows/mcp-inspector.lock.yml @@ -390,7 +390,7 @@ jobs: with: python-version: '3.12' - name: Setup uv - uses: astral-sh/setup-uv@6ee6290f1cbc4156c0bdd66691b2c144ef8df19a # v7.4.0 + uses: astral-sh/setup-uv@e06108dd0aef18192324c70427afc47652e63a82 # v7.5.0 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh # Cache memory file share configuration from frontmatter processed below diff --git a/pkg/workflow/data/action_pins.json b/pkg/workflow/data/action_pins.json index a98a9f788a..e4dac97476 100644 --- a/pkg/workflow/data/action_pins.json +++ b/pkg/workflow/data/action_pins.json @@ -10,21 +10,11 @@ "version": "v4.1.0", "sha": "a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32" }, - "actions/cache/restore@v4": { - "repo": "actions/cache/restore", - "version": "v4", - "sha": "0057852bfaa89a56745cba8c7296529d2fc39830" - }, "actions/cache/restore@v5.0.3": { "repo": "actions/cache/restore", "version": "v5.0.3", "sha": "cdf6c1fa76f9f475f3d7449005a359c84ca0f306" }, - "actions/cache/save@v4": { - "repo": "actions/cache/save", - "version": "v4", - "sha": "0057852bfaa89a56745cba8c7296529d2fc39830" - }, "actions/cache/save@v5.0.3": { "repo": "actions/cache/save", "version": "v5.0.3", @@ -40,10 +30,10 @@ "version": "v6.0.2", "sha": "de0fac2e4500dabe0009e67214ff5f5447ce83dd" }, - "actions/create-github-app-token@v3.0.0-beta.2": { + "actions/create-github-app-token@v3.0.0-beta.4": { "repo": "actions/create-github-app-token", - "version": "v3.0.0-beta.2", - "sha": "bf559f85448f9380bcfa2899dbdc01eb5b37be3a" + "version": "v3.0.0-beta.4", + "sha": "a7f885bf4560200d03183ed941cb6fb072e4b343" }, "actions/download-artifact@v8.0.1": { "repo": "actions/download-artifact", @@ -70,11 +60,6 @@ "version": "v5.2.0", "sha": "be666c2fcd27ec809703dec50e508c2fdc7f6654" }, - "actions/setup-node@v4": { - "repo": "actions/setup-node", - "version": "v4", - "sha": "49933ea5288caeca8642d1e84afbd3f7d6820020" - }, "actions/setup-node@v6.3.0": { "repo": "actions/setup-node", "version": "v6.3.0", @@ -95,10 +80,10 @@ "version": "v0.23.1", "sha": "57aae528053a48a3f6235f2d9461b05fbcb7366d" }, - "astral-sh/setup-uv@v7.4.0": { + "astral-sh/setup-uv@v7.5.0": { "repo": "astral-sh/setup-uv", - "version": "v7.4.0", - "sha": "6ee6290f1cbc4156c0bdd66691b2c144ef8df19a" + "version": "v7.5.0", + "sha": "e06108dd0aef18192324c70427afc47652e63a82" }, "cli/gh-extension-precompile@v2.1.0": { "repo": "cli/gh-extension-precompile", From b5e1470fd9ab75b7cb63f1ec4da8d2f7a33bb439 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 16:28:36 +0000 Subject: [PATCH 3/4] fix: remove announcement-capable category limitation for discussion creation Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/create_discussion.cjs | 17 ++--------------- ...e_discussion_category_normalization.test.cjs | 16 ++++++++-------- docs/src/content/docs/agent-factory-status.mdx | 1 + docs/src/content/docs/reference/faq.md | 12 ++++++------ docs/src/content/docs/reference/safe-outputs.md | 5 +---- 5 files changed, 18 insertions(+), 33 deletions(-) diff --git a/actions/setup/js/create_discussion.cjs b/actions/setup/js/create_discussion.cjs index fa6545c82b..c80c803eb8 100644 --- a/actions/setup/js/create_discussion.cjs +++ b/actions/setup/js/create_discussion.cjs @@ -99,21 +99,8 @@ function resolveCategoryId(categoryConfig, itemCategory, categories) { } } - // Fall back to announcement-capable category if available, otherwise first category + // Fall back to first available category if (categories.length > 0) { - // Try to find an "Announcements" category (case-insensitive) - const announcementCategory = categories.find(cat => cat.name.toLowerCase() === "announcements" || cat.slug.toLowerCase() === "announcements"); - - if (announcementCategory) { - return { - id: announcementCategory.id, - matchType: "fallback-announcement", - name: announcementCategory.name, - requestedCategory: categoryToMatch, - }; - } - - // Otherwise use first category return { id: categories[0].id, matchType: "fallback", @@ -261,7 +248,7 @@ function isPermissionsError(errorMessage) { async function handleFallbackToIssue(createIssueHandler, item, qualifiedItemRepo, resolvedTemporaryIds, contextMessage) { try { // Prepare issue message with a note about the fallback - const fallbackNote = `\n\n---\n\n> [!WARNING]\n> This was intended to be a discussion, but discussions could not be created due to permissions issues. This issue was created as a fallback.\n>\n> Discussion creation may fail if the specified category is not announcement-capable. Consider using the "Announcements" category or another announcement-capable category in your workflow configuration.\n`; + const fallbackNote = `\n\n---\n\n> [!WARNING]\n> This was intended to be a discussion, but discussions could not be created due to permissions issues. This issue was created as a fallback.\n`; const issueMessage = { ...item, body: (item.body || "") + fallbackNote, diff --git a/actions/setup/js/create_discussion_category_normalization.test.cjs b/actions/setup/js/create_discussion_category_normalization.test.cjs index a1ae88da50..8da93ab8db 100644 --- a/actions/setup/js/create_discussion_category_normalization.test.cjs +++ b/actions/setup/js/create_discussion_category_normalization.test.cjs @@ -277,8 +277,8 @@ describe("create_discussion category normalization", () => { expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn1"); // General (first) }); - it("should prefer Announcements category when no category specified", async () => { - // Mock categories with Announcements available + it("should fallback to first category when no category specified and Announcements available", async () => { + // Mock categories with Announcements available - but it should NOT be preferred mockGithub.graphql = vi.fn().mockImplementation((query, variables) => { if (query.includes("discussionCategories")) { return Promise.resolve({ @@ -340,14 +340,14 @@ describe("create_discussion category normalization", () => { expect(result.success).toBe(true); expect(result.number).toBe(42); - // Verify Announcements category was used (not General which is first) + // Verify first category (General) was used, not Announcements const createMutationCall = mockGithub.graphql.mock.calls.find(call => call[0].includes("createDiscussion")); expect(createMutationCall).toBeDefined(); - expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn4"); // Announcements + expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn1"); // General (first) }); - it("should prefer Announcements category when non-existent category specified", async () => { - // Mock categories with Announcements available + it("should fallback to first category when non-existent category specified", async () => { + // Mock categories with Announcements available - but first category should be used as fallback mockGithub.graphql = vi.fn().mockImplementation((query, variables) => { if (query.includes("discussionCategories")) { return Promise.resolve({ @@ -403,9 +403,9 @@ describe("create_discussion category normalization", () => { expect(result.success).toBe(true); expect(result.number).toBe(42); - // Verify Announcements category was used (not General which is first) + // Verify first category (General) was used as fallback, not Announcements const createMutationCall = mockGithub.graphql.mock.calls.find(call => call[0].includes("createDiscussion")); expect(createMutationCall).toBeDefined(); - expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn4"); // Announcements + expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn1"); // General (first) }); }); diff --git a/docs/src/content/docs/agent-factory-status.mdx b/docs/src/content/docs/agent-factory-status.mdx index 91412544dc..af5e5655ce 100644 --- a/docs/src/content/docs/agent-factory-status.mdx +++ b/docs/src/content/docs/agent-factory-status.mdx @@ -60,6 +60,7 @@ These are experimental agentic workflows used by the GitHub Next team to learn, | [Daily Fact About gh-aw](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-fact.md) | codex | [![Daily Fact About gh-aw](https://github.com/github/gh-aw/actions/workflows/daily-fact.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-fact.lock.yml) | `0 11 * * 1-5` | - | | [Daily File Diet](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-file-diet.md) | copilot | [![Daily File Diet](https://github.com/github/gh-aw/actions/workflows/daily-file-diet.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-file-diet.lock.yml) | `0 13 * * 1-5` | - | | [Daily Firewall Logs Collector and Reporter](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-firewall-report.md) | copilot | [![Daily Firewall Logs Collector and Reporter](https://github.com/github/gh-aw/actions/workflows/daily-firewall-report.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-firewall-report.lock.yml) | - | - | +| [Daily Go Function Namer](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-function-namer.md) | claude | [![Daily Go Function Namer](https://github.com/github/gh-aw/actions/workflows/daily-function-namer.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-function-namer.lock.yml) | - | - | | [Daily Issues Report Generator](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-issues-report.md) | codex | [![Daily Issues Report Generator](https://github.com/github/gh-aw/actions/workflows/daily-issues-report.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-issues-report.lock.yml) | - | - | | [Daily Malicious Code Scan Agent](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-malicious-code-scan.md) | copilot | [![Daily Malicious Code Scan Agent](https://github.com/github/gh-aw/actions/workflows/daily-malicious-code-scan.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-malicious-code-scan.lock.yml) | - | - | | [Daily MCP Tool Concurrency Analysis](https://github.com/github/gh-aw/blob/main/.github/workflows/daily-mcp-concurrency-analysis.md) | copilot | [![Daily MCP Tool Concurrency Analysis](https://github.com/github/gh-aw/actions/workflows/daily-mcp-concurrency-analysis.lock.yml/badge.svg)](https://github.com/github/gh-aw/actions/workflows/daily-mcp-concurrency-analysis.lock.yml) | `0 9 * * 1-5` | - | diff --git a/docs/src/content/docs/reference/faq.md b/docs/src/content/docs/reference/faq.md index beaafa83c9..c599dbc754 100644 --- a/docs/src/content/docs/reference/faq.md +++ b/docs/src/content/docs/reference/faq.md @@ -246,16 +246,16 @@ Yes! Use [TrialOps](/gh-aw/patterns/trial-ops/) to test workflows in isolated tr See [Common Issues](/gh-aw/troubleshooting/common-issues/) for detailed troubleshooting guidance including workflow failures, debugging strategies, permission issues, and network problems. -### Why is my create-discussion workflow failing with integration-forbidden? - -Discussion creation requires announcement-capable categories. If your workflow fails with an `integration-forbidden` error, ensure the `category` field in your configuration specifies a category that has announcement capabilities enabled in your repository's discussion settings. +### Why is my create-discussion workflow failing? Common issues: -- **Non-announcement categories**: Only categories configured to support announcements can be used for automated discussion creation. Check your repository's discussion settings to verify which categories have announcement capabilities. -- **Category name typos**: Verify the category name spelling in your workflow configuration matches exactly with your repository's discussion categories. Category names are case-sensitive. + +- **Category name typos**: Verify the category name spelling in your workflow configuration matches your repository's discussion categories. Category names are matched case-insensitively, but check for typos. - **Category slugs**: Use lowercase category slugs (e.g., `general`, `announcements`) rather than display names for better reliability. +- **Discussions not enabled**: Ensure discussions are enabled for your repository in **Settings → Features → Discussions**. +- **Insufficient permissions**: The workflow requires `discussions: write` permission. -If discussions are not enabled or the category lacks announcement capabilities, consider using `fallback-to-issue: true` (the default) to automatically create an issue instead. See [Discussion Creation](/gh-aw/reference/safe-outputs/#discussion-creation-create-discussion) for configuration details. +If discussions are not enabled or the workflow lacks permissions, consider using `fallback-to-issue: true` (the default) to automatically create an issue instead. See [Discussion Creation](/gh-aw/reference/safe-outputs/#discussion-creation-create-discussion) for configuration details. ### Why is my create-pull-request workflow failing with "GitHub Actions is not permitted to create or approve pull requests"? diff --git a/docs/src/content/docs/reference/safe-outputs.md b/docs/src/content/docs/reference/safe-outputs.md index 9b44af4391..f5529da3c0 100644 --- a/docs/src/content/docs/reference/safe-outputs.md +++ b/docs/src/content/docs/reference/safe-outputs.md @@ -945,14 +945,11 @@ Creates discussions with optional `category` (slug, name, or ID; defaults to fir **Category Naming Standard**: Use lowercase, plural category names (e.g., `audits`, `general`, `reports`) for consistency and better searchability. GitHub Discussion category IDs (starting with `DIC_`) are also supported. -> [!WARNING] -> Only announcement-capable category succeeds; all non-announcement categories fail with integration-forbidden. - ```yaml wrap safe-outputs: create-discussion: title-prefix: "[ai] " # prefix for titles - category: "announcements" # category slug, name, or ID (use lowercase, prefer announcement-capable) + category: "general" # category slug, name, or ID (use lowercase) expires: 3 # auto-close after 3 days (or false to disable) max: 3 # max discussions (default: 1) target-repo: "owner/repo" # cross-repository From d1d7492dd6aa578d5df966e2e10e31e0ffdce2cd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:12:04 +0000 Subject: [PATCH 4/4] fix: restore Announcements category preference as fallback default Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/create_discussion.cjs | 15 ++++++++++++++- ...te_discussion_category_normalization.test.cjs | 16 ++++++++-------- docs/src/content/docs/reference/safe-outputs.md | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/actions/setup/js/create_discussion.cjs b/actions/setup/js/create_discussion.cjs index c80c803eb8..de2a382380 100644 --- a/actions/setup/js/create_discussion.cjs +++ b/actions/setup/js/create_discussion.cjs @@ -99,8 +99,21 @@ function resolveCategoryId(categoryConfig, itemCategory, categories) { } } - // Fall back to first available category + // Fall back to "Announcements" category if available, otherwise first category if (categories.length > 0) { + // Try to find an "Announcements" category (case-insensitive) + const announcementCategory = categories.find(cat => cat.name.toLowerCase() === "announcements" || cat.slug.toLowerCase() === "announcements"); + + if (announcementCategory) { + return { + id: announcementCategory.id, + matchType: "fallback-announcement", + name: announcementCategory.name, + requestedCategory: categoryToMatch, + }; + } + + // Otherwise use first category return { id: categories[0].id, matchType: "fallback", diff --git a/actions/setup/js/create_discussion_category_normalization.test.cjs b/actions/setup/js/create_discussion_category_normalization.test.cjs index 8da93ab8db..a1ae88da50 100644 --- a/actions/setup/js/create_discussion_category_normalization.test.cjs +++ b/actions/setup/js/create_discussion_category_normalization.test.cjs @@ -277,8 +277,8 @@ describe("create_discussion category normalization", () => { expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn1"); // General (first) }); - it("should fallback to first category when no category specified and Announcements available", async () => { - // Mock categories with Announcements available - but it should NOT be preferred + it("should prefer Announcements category when no category specified", async () => { + // Mock categories with Announcements available mockGithub.graphql = vi.fn().mockImplementation((query, variables) => { if (query.includes("discussionCategories")) { return Promise.resolve({ @@ -340,14 +340,14 @@ describe("create_discussion category normalization", () => { expect(result.success).toBe(true); expect(result.number).toBe(42); - // Verify first category (General) was used, not Announcements + // Verify Announcements category was used (not General which is first) const createMutationCall = mockGithub.graphql.mock.calls.find(call => call[0].includes("createDiscussion")); expect(createMutationCall).toBeDefined(); - expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn1"); // General (first) + expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn4"); // Announcements }); - it("should fallback to first category when non-existent category specified", async () => { - // Mock categories with Announcements available - but first category should be used as fallback + it("should prefer Announcements category when non-existent category specified", async () => { + // Mock categories with Announcements available mockGithub.graphql = vi.fn().mockImplementation((query, variables) => { if (query.includes("discussionCategories")) { return Promise.resolve({ @@ -403,9 +403,9 @@ describe("create_discussion category normalization", () => { expect(result.success).toBe(true); expect(result.number).toBe(42); - // Verify first category (General) was used as fallback, not Announcements + // Verify Announcements category was used (not General which is first) const createMutationCall = mockGithub.graphql.mock.calls.find(call => call[0].includes("createDiscussion")); expect(createMutationCall).toBeDefined(); - expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn1"); // General (first) + expect(createMutationCall[1].categoryId).toBe("DIC_kwDOGFsHUM4BsUn4"); // Announcements }); }); diff --git a/docs/src/content/docs/reference/safe-outputs.md b/docs/src/content/docs/reference/safe-outputs.md index f5529da3c0..61582a6ad5 100644 --- a/docs/src/content/docs/reference/safe-outputs.md +++ b/docs/src/content/docs/reference/safe-outputs.md @@ -949,7 +949,7 @@ Creates discussions with optional `category` (slug, name, or ID; defaults to fir safe-outputs: create-discussion: title-prefix: "[ai] " # prefix for titles - category: "general" # category slug, name, or ID (use lowercase) + category: "announcements" # category slug, name, or ID (use lowercase) expires: 3 # auto-close after 3 days (or false to disable) max: 3 # max discussions (default: 1) target-repo: "owner/repo" # cross-repository