diff --git a/.github/workflows/dependabot-burner.lock.yml b/.github/workflows/dependabot-burner.lock.yml index 41e0f9de40..71bd6568a3 100644 --- a/.github/workflows/dependabot-burner.lock.yml +++ b/.github/workflows/dependabot-burner.lock.yml @@ -1306,7 +1306,6 @@ jobs: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"expires\":48,\"max\":5},\"create_project_status_update\":{\"max\":1},\"missing_data\":{},\"missing_tool\":{},\"update_project\":{\"max\":10,\"project\":\"https://github.com/orgs/githubnext/projects/144\"}}" GH_AW_PROJECT_URL: "https://github.com/orgs/githubnext/projects/144" - GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/github-mcp-tools-report.lock.yml b/.github/workflows/github-mcp-tools-report.lock.yml index 70225731c5..765b866e0f 100644 --- a/.github/workflows/github-mcp-tools-report.lock.yml +++ b/.github/workflows/github-mcp-tools-report.lock.yml @@ -183,7 +183,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'EOF' - {"create_discussion":{"expires":168,"max":1},"create_pull_request":{"expires":48},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"create_discussion":{"expires":168,"max":1},"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1}} EOF cat > /opt/gh-aw/safeoutputs/tools.json << 'EOF' [ @@ -214,7 +214,7 @@ jobs: "name": "create_discussion" }, { - "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[mcp-tools] \". Labels [documentation automation] will be automatically added. Reviewers [copilot] will be assigned.", + "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Reviewers [copilot] will be assigned.", "inputSchema": { "additionalProperties": false, "properties": { @@ -1265,7 +1265,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":168,\"max\":1},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"draft\":false,\"expires\":48,\"labels\":[\"documentation\",\"automation\"],\"max\":1,\"max_patch_size\":1024,\"title_prefix\":\"[mcp-tools] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":168,\"max\":1},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index 937e4b9dad..4291bad149 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -212,7 +212,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'EOF' - {"add_comment":{"max":3,"target":"*"},"add_labels":{"allowed":["poetry","creative","automation","ai-generated","epic","haiku","sonnet","limerick"],"max":5},"create_agent_session":{"max":1},"create_discussion":{"expires":168,"max":2},"create_issue":{"expires":48,"group":true,"max":2},"create_missing_tool_issue":{"max":1,"title_prefix":"[missing tool]"},"create_pull_request":{"expires":48},"create_pull_request_review_comment":{"max":2},"link_sub_issue":{"max":3},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_to_pull_request_branch":{"max":0},"update_issue":{"max":2},"upload_asset":{"max":0}} + {"add_comment":{"max":3,"target":"*"},"add_labels":{"allowed":["poetry","creative","automation","ai-generated","epic","haiku","sonnet","limerick"],"max":5},"create_agent_session":{"max":1},"create_discussion":{"expires":168,"max":2},"create_issue":{"expires":48,"group":true,"max":2},"create_missing_tool_issue":{"max":1,"title_prefix":"[missing tool]"},"create_pull_request":{},"create_pull_request_review_comment":{"max":2},"link_sub_issue":{"max":3},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_to_pull_request_branch":{"max":0},"update_issue":{"max":2},"upload_asset":{"max":0}} EOF cat > /opt/gh-aw/safeoutputs/tools.json << 'EOF' [ @@ -345,7 +345,7 @@ jobs: "name": "add_comment" }, { - "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[🎨 POETRY] \". Labels [poetry automation creative-writing] will be automatically added. Reviewers [copilot] will be assigned.", + "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Reviewers [copilot] will be assigned.", "inputSchema": { "additionalProperties": false, "properties": { @@ -1822,7 +1822,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":3,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"poetry\",\"creative\",\"automation\",\"ai-generated\",\"epic\",\"haiku\",\"sonnet\",\"limerick\"],\"max\":5},\"close_pull_request\":{\"max\":2,\"required_labels\":[\"poetry\",\"automation\"],\"required_title_prefix\":\"[🎨 POETRY]\",\"target\":\"*\"},\"create_discussion\":{\"category\":\"general\",\"close_older_discussions\":true,\"expires\":168,\"labels\":[\"poetry\",\"automation\",\"ai-generated\"],\"max\":2,\"title_prefix\":\"[📜 POETRY] \"},\"create_issue\":{\"expires\":48,\"group\":true,\"labels\":[\"poetry\",\"automation\",\"ai-generated\"],\"max\":2,\"title_prefix\":\"[🎭 POEM-BOT] \"},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"draft\":false,\"expires\":48,\"labels\":[\"poetry\",\"automation\",\"creative-writing\"],\"max\":1,\"max_patch_size\":1024,\"title_prefix\":\"[🎨 POETRY] \"},\"create_pull_request_review_comment\":{\"max\":2,\"side\":\"RIGHT\"},\"link_sub_issue\":{\"max\":3,\"parent_required_labels\":[\"poetry\",\"epic\"],\"parent_title_prefix\":\"[🎭 POEM-BOT]\",\"sub_required_labels\":[\"poetry\"],\"sub_title_prefix\":\"[🎭 POEM-BOT]\"},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"base_branch\":\"${{ github.ref_name }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024},\"update_issue\":{\"allow_body\":true,\"allow_status\":true,\"allow_title\":true,\"max\":2,\"target\":\"*\"}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":3,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"poetry\",\"creative\",\"automation\",\"ai-generated\",\"epic\",\"haiku\",\"sonnet\",\"limerick\"],\"max\":5},\"close_pull_request\":{\"max\":2,\"required_labels\":[\"poetry\",\"automation\"],\"required_title_prefix\":\"[🎨 POETRY]\",\"target\":\"*\"},\"create_discussion\":{\"category\":\"general\",\"close_older_discussions\":true,\"expires\":168,\"labels\":[\"poetry\",\"automation\",\"ai-generated\"],\"max\":2,\"title_prefix\":\"[📜 POETRY] \"},\"create_issue\":{\"expires\":48,\"group\":true,\"labels\":[\"poetry\",\"automation\",\"ai-generated\"],\"max\":2,\"title_prefix\":\"[🎭 POEM-BOT] \"},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"create_pull_request_review_comment\":{\"max\":2,\"side\":\"RIGHT\"},\"link_sub_issue\":{\"max\":3,\"parent_required_labels\":[\"poetry\",\"epic\"],\"parent_title_prefix\":\"[🎭 POEM-BOT]\",\"sub_required_labels\":[\"poetry\"],\"sub_title_prefix\":\"[🎭 POEM-BOT]\"},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"base_branch\":\"${{ github.ref_name }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024},\"update_issue\":{\"allow_body\":true,\"allow_status\":true,\"allow_title\":true,\"max\":2,\"target\":\"*\"}}" GH_AW_SAFE_OUTPUTS_STAGED: "true" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index 4a6ba88232..0f06def944 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -250,7 +250,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'EOF' - {"add_comment":{"max":1},"create_pull_request":{"expires":48},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"add_comment":{"max":1},"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1}} EOF cat > /opt/gh-aw/safeoutputs/tools.json << 'EOF' [ @@ -276,7 +276,7 @@ jobs: "name": "add_comment" }, { - "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[q] \". Labels [automation workflow-optimization] will be automatically added. Reviewers [copilot] will be assigned.", + "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Reviewers [copilot] will be assigned.", "inputSchema": { "additionalProperties": false, "properties": { @@ -1281,7 +1281,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"draft\":false,\"expires\":48,\"if_no_changes\":\"ignore\",\"labels\":[\"automation\",\"workflow-optimization\"],\"max\":1,\"max_patch_size\":1024,\"title_prefix\":\"[q] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/security-alert-burndown.lock.yml b/.github/workflows/security-alert-burndown.lock.yml index fe7941a469..c861667be2 100644 --- a/.github/workflows/security-alert-burndown.lock.yml +++ b/.github/workflows/security-alert-burndown.lock.yml @@ -1186,7 +1186,6 @@ jobs: GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"assignees\":[\"copilot\"],\"max\":1},\"missing_data\":{},\"missing_tool\":{},\"update_project\":{\"max\":100,\"project\":\"https://github.com/orgs/githubnext/projects/144\"}}" GH_AW_ASSIGN_COPILOT: "true" GH_AW_PROJECT_URL: "https://github.com/orgs/githubnext/projects/144" - GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }} with: github-token: ${{ secrets.GH_AW_AGENT_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/smoke-project.lock.yml b/.github/workflows/smoke-project.lock.yml index f29df99e4d..8a51548fa8 100644 --- a/.github/workflows/smoke-project.lock.yml +++ b/.github/workflows/smoke-project.lock.yml @@ -1420,7 +1420,6 @@ jobs: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_project_status_update\":{\"github-token\":\"${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }}\",\"max\":1,\"project\":\"https://github.com/orgs/githubnext/projects/146\"},\"missing_data\":{},\"missing_tool\":{},\"update_project\":{\"github-token\":\"${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }}\",\"max\":20,\"project\":\"https://github.com/orgs/githubnext/projects/146\",\"views\":[{\"name\":\"Smoke Test Board\",\"layout\":\"board\",\"filter\":\"is:open\"},{\"name\":\"Smoke Test Table\",\"layout\":\"table\"}]}}" GH_AW_PROJECT_URL: "https://github.com/orgs/githubnext/projects/146" - GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml index 32d751ee47..fa6a1cb56f 100644 --- a/.github/workflows/technical-doc-writer.lock.yml +++ b/.github/workflows/technical-doc-writer.lock.yml @@ -205,7 +205,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'EOF' - {"add_comment":{"max":1},"create_pull_request":{"expires":48},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} + {"add_comment":{"max":1},"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} EOF cat > /opt/gh-aw/safeoutputs/tools.json << 'EOF' [ @@ -231,7 +231,7 @@ jobs: "name": "add_comment" }, { - "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[docs] \". Labels [documentation] will be automatically added. Reviewers [copilot] will be assigned.", + "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Reviewers [copilot] will be assigned.", "inputSchema": { "additionalProperties": false, "properties": { @@ -1683,7 +1683,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"draft\":false,\"expires\":48,\"labels\":[\"documentation\"],\"max\":1,\"max_patch_size\":1024,\"title_prefix\":\"[docs] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/test-project-url-default.lock.yml b/.github/workflows/test-project-url-default.lock.yml index d55538441f..d8da718246 100644 --- a/.github/workflows/test-project-url-default.lock.yml +++ b/.github/workflows/test-project-url-default.lock.yml @@ -1189,7 +1189,6 @@ jobs: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_project_status_update\":{\"max\":1,\"project\":\"https://github.com/orgs/\\u003cORG\\u003e/projects/\\u003cNUMBER\\u003e\"},\"missing_data\":{},\"missing_tool\":{},\"update_project\":{\"max\":5,\"project\":\"https://github.com/orgs/\\u003cORG\\u003e/projects/\\u003cNUMBER\\u003e\"}}" GH_AW_PROJECT_URL: "https://github.com/orgs//projects/" - GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 3156eeabac..c5377d8f46 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -204,12 +204,12 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'EOF' - {"create_missing_tool_issue":{"max":1,"title_prefix":"[missing tool]"},"create_pull_request":{"expires":48},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_to_pull_request_branch":{"max":0}} + {"create_missing_tool_issue":{"max":1,"title_prefix":"[missing tool]"},"create_pull_request":{},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_to_pull_request_branch":{"max":0}} EOF cat > /opt/gh-aw/safeoutputs/tools.json << 'EOF' [ { - "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[tidy] \". Labels [automation maintenance] will be automatically added. Reviewers [copilot] will be assigned.", + "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Reviewers [copilot] will be assigned.", "inputSchema": { "additionalProperties": false, "properties": { @@ -1226,7 +1226,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"draft\":false,\"expires\":48,\"labels\":[\"automation\",\"maintenance\"],\"max\":1,\"max_patch_size\":1024,\"title_prefix\":\"[tidy] \"},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"base_branch\":\"${{ github.ref_name }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"base_branch\":\"${{ github.ref_name }}\",\"max\":1,\"max_patch_size\":1024},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"base_branch\":\"${{ github.ref_name }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/actions/setup/js/update_project.cjs b/actions/setup/js/update_project.cjs index 76bd361d63..c33dec19f5 100644 --- a/actions/setup/js/update_project.cjs +++ b/actions/setup/js/update_project.cjs @@ -406,6 +406,7 @@ async function updateProject(output, temporaryIdMap = new Map(), githubClient = const ownerType = repoResult.repository.owner.__typename; core.info(`✓ Repository: ${owner}/${repo} (${ownerType})`); + let viewerLogin; try { const viewerResult = await github.graphql(`query { viewer { @@ -413,12 +414,23 @@ async function updateProject(output, temporaryIdMap = new Map(), githubClient = } }`); if (viewerResult?.viewer?.login) { - core.info(`✓ Authenticated as: ${viewerResult.viewer.login}`); + viewerLogin = viewerResult.viewer.login; + core.info(`✓ Authenticated as: ${viewerLogin}`); } } catch (viewerError) { core.warning(`Could not resolve token identity (viewer.login): ${getErrorMessage(viewerError)}`); } + // Projects v2 GraphQL API does not work with the default GITHUB_TOKEN. + // If we are authenticated as github-actions[bot], fail fast with a clear error + // rather than attempting project resolution and falling back. + if (viewerLogin === "github-actions[bot]") { + throw new Error( + "GitHub Projects v2 operations require a PAT or GitHub App token with Projects access, but this run is authenticated as github-actions[bot] (default GITHUB_TOKEN). " + + "Fix: set secrets.GH_AW_PROJECT_GITHUB_TOKEN (or configure safe-outputs.update-project.github-token) so the safe-outputs step uses that token for github-script." + ); + } + let projectId; core.info(`[2/4] Resolving project from URL (scope=${projectInfo.scope}, login=${projectInfo.ownerLogin}, number=${projectNumberFromUrl})...`); let resolvedProjectNumber = projectNumberFromUrl; diff --git a/actions/setup/js/update_project.test.cjs b/actions/setup/js/update_project.test.cjs index da26c63598..50e8727db4 100644 --- a/actions/setup/js/update_project.test.cjs +++ b/actions/setup/js/update_project.test.cjs @@ -121,6 +121,39 @@ describe("update_project handler config: field_definitions", () => { }); }); +describe("update_project token guardrails", () => { + it("fails fast with a clear error when authenticated as github-actions[bot]", async () => { + delete process.env.GH_AW_PROJECT_GITHUB_TOKEN; + + const projectUrl = "https://github.com/orgs/githubnext/projects/146"; + + mockGithub.graphql.mockImplementation(async (query, vars) => { + const q = String(query); + + if (q.includes("repository(owner:") || q.includes("repository(owner:")) { + return repoResponse("Organization"); + } + if (q.includes("viewer") && !vars) { + return viewerResponse("github-actions[bot]"); + } + + throw new Error(`Unexpected graphql query in test (should fail fast before project resolution): ${q}`); + }); + + await expect( + updateProject( + { + project: projectUrl, + content_type: "issue", + content_number: 1, + }, + new Map(), + mockGithub + ) + ).rejects.toThrow(/Projects v2 operations require.*github-actions\[bot\].*GH_AW_PROJECT_GITHUB_TOKEN/i); + }); +}); + function clearMock(fn) { if (fn && typeof fn.mockClear === "function") { fn.mockClear(); diff --git a/pkg/workflow/compiler_safe_outputs_steps.go b/pkg/workflow/compiler_safe_outputs_steps.go index f1dbf9933b..95fb3fef9a 100644 --- a/pkg/workflow/compiler_safe_outputs_steps.go +++ b/pkg/workflow/compiler_safe_outputs_steps.go @@ -215,10 +215,17 @@ func (c *Compiler) buildHandlerManagerStep(data *WorkflowData) []string { } // With section for github-token - // Use the standard safe outputs token for all operations - // Project-specific handlers (create_project) will use custom tokens from their handler config + // Use the standard safe outputs token for all operations. + // If project operations are configured, prefer the project token for the github-script client. + // Rationale: update_project/create_project_status_update call the Projects v2 GraphQL API, which + // cannot be accessed with the default GITHUB_TOKEN. GH_AW_PROJECT_GITHUB_TOKEN is the required + // token for Projects v2 operations. steps = append(steps, " with:\n") - c.addSafeOutputGitHubTokenForConfig(&steps, data, "") + configToken := "" + if projectToken != "" { + configToken = projectToken + } + c.addSafeOutputGitHubTokenForConfig(&steps, data, configToken) steps = append(steps, " script: |\n") steps = append(steps, " const { setupGlobals } = require('"+SetupActionDestination+"/setup_globals.cjs');\n") diff --git a/pkg/workflow/safe_outputs_handler_manager_token_test.go b/pkg/workflow/safe_outputs_handler_manager_token_test.go index 3a1db954f6..f62f8f2c66 100644 --- a/pkg/workflow/safe_outputs_handler_manager_token_test.go +++ b/pkg/workflow/safe_outputs_handler_manager_token_test.go @@ -17,6 +17,7 @@ func TestHandlerManagerProjectGitHubTokenEnvVar(t *testing.T) { name string frontmatter map[string]any expectedEnvVarValue string + expectedWithToken string shouldHaveToken bool }{ { @@ -31,6 +32,7 @@ func TestHandlerManagerProjectGitHubTokenEnvVar(t *testing.T) { }, }, expectedEnvVarValue: "GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.PROJECTS_PAT }}", + expectedWithToken: "github-token: ${{ secrets.PROJECTS_PAT }}", shouldHaveToken: true, }, { @@ -44,6 +46,7 @@ func TestHandlerManagerProjectGitHubTokenEnvVar(t *testing.T) { }, }, expectedEnvVarValue: "GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }}", + expectedWithToken: "github-token: ${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }}", shouldHaveToken: true, }, { @@ -58,6 +61,7 @@ func TestHandlerManagerProjectGitHubTokenEnvVar(t *testing.T) { }, }, expectedEnvVarValue: "GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.CUSTOM_TOKEN }}", + expectedWithToken: "github-token: ${{ secrets.CUSTOM_TOKEN }}", shouldHaveToken: true, }, { @@ -72,6 +76,7 @@ func TestHandlerManagerProjectGitHubTokenEnvVar(t *testing.T) { }, }, expectedEnvVarValue: "GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.STATUS_PAT }}", + expectedWithToken: "github-token: ${{ secrets.STATUS_PAT }}", shouldHaveToken: true, }, { @@ -85,6 +90,7 @@ func TestHandlerManagerProjectGitHubTokenEnvVar(t *testing.T) { }, }, expectedEnvVarValue: "GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.CREATE_PAT }}", + expectedWithToken: "github-token: ${{ secrets.CREATE_PAT }}", shouldHaveToken: true, }, { @@ -106,6 +112,7 @@ func TestHandlerManagerProjectGitHubTokenEnvVar(t *testing.T) { }, }, expectedEnvVarValue: "GH_AW_PROJECT_GITHUB_TOKEN: ${{ secrets.UPDATE_PAT }}", + expectedWithToken: "github-token: ${{ secrets.UPDATE_PAT }}", shouldHaveToken: true, }, { @@ -146,6 +153,11 @@ func TestHandlerManagerProjectGitHubTokenEnvVar(t *testing.T) { assert.Contains(t, yamlStr, tt.expectedEnvVarValue, "Expected environment variable %q to be set in handler manager step", tt.expectedEnvVarValue) + + // Check that the github-script token matches the effective project token + assert.Contains(t, yamlStr, tt.expectedWithToken, + "Expected github-script token %q to be set in handler manager step", + tt.expectedWithToken) } else { // Check that GH_AW_PROJECT_GITHUB_TOKEN is NOT set assert.NotContains(t, yamlStr, "GH_AW_PROJECT_GITHUB_TOKEN",