From a047531217d74bd9923ae512978234fef4033cc2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Dec 2025 20:59:52 +0000 Subject: [PATCH 1/3] Initial plan From 0d7cdaef28672f1c395305dd0868635584846f44 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Dec 2025 21:04:27 +0000 Subject: [PATCH 2/3] Plan: Remove project-to-repository linking in update-project safe output Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com> --- .github/workflows/issue-classifier.lock.yml | 2 +- .github/workflows/release.lock.yml | 6 +++--- .github/workflows/stale-repo-identifier.lock.yml | 2 +- .github/workflows/super-linter.lock.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index 3be5ab9acd8..4f4a69a3e57 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -2241,7 +2241,7 @@ jobs: path: /tmp/gh-aw/aw_info.json if-no-files-found: warn - name: Run AI Inference - uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v2.0.4 + uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v1 env: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml index ce61da11ec3..8433f151f17 100644 --- a/.github/workflows/release.lock.yml +++ b/.github/workflows/release.lock.yml @@ -6056,13 +6056,13 @@ jobs: - name: Download Go modules run: go mod download - name: Generate SBOM (SPDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 with: artifact-name: sbom.spdx.json format: spdx-json output-file: sbom.spdx.json - name: Generate SBOM (CycloneDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 with: artifact-name: sbom.cdx.json format: cyclonedx-json @@ -6261,7 +6261,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Release with gh-extension-precompile - uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2.1.0 + uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2 with: build_script_override: scripts/build-release.sh go_version_file: go.mod diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index 21caadf4297..a8cd91dcd02 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -176,7 +176,7 @@ jobs: ORGANIZATION: ${{ env.ORGANIZATION }} id: stale-repos name: Run stale_repos tool - uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3.0.2 + uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3 - env: INACTIVE_REPOS: ${{ steps.stale-repos.outputs.inactiveRepos }} name: Save stale repos output diff --git a/.github/workflows/super-linter.lock.yml b/.github/workflows/super-linter.lock.yml index 4c2fde522cd..b15660af2fb 100644 --- a/.github/workflows/super-linter.lock.yml +++ b/.github/workflows/super-linter.lock.yml @@ -6189,7 +6189,7 @@ jobs: persist-credentials: false - name: Super-linter id: super-linter - uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.3.1 + uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.2.1 env: CREATE_LOG_FILE: "true" DEFAULT_BRANCH: main From 49716850c78dc609b6d4aab5430c4ad7e408f070 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Dec 2025 21:16:09 +0000 Subject: [PATCH 3/3] Remove project-to-repository linking in update-project safe output Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com> --- pkg/workflow/js/update_project.cjs | 15 +++--------- pkg/workflow/js/update_project.test.cjs | 32 ++++++++++--------------- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/pkg/workflow/js/update_project.cjs b/pkg/workflow/js/update_project.cjs index 65496f51e3a..21939dd7abb 100644 --- a/pkg/workflow/js/update_project.cjs +++ b/pkg/workflow/js/update_project.cjs @@ -128,7 +128,7 @@ async function updateProject(output) { campaignId = output.campaign_id; try { let repoResult; - (core.info(`Looking up project #${projectNumberFromUrl} from URL: ${output.project}`), core.info("[1/5] Fetching repository information...")); + (core.info(`Looking up project #${projectNumberFromUrl} from URL: ${output.project}`), core.info("[1/4] Fetching repository information...")); try { repoResult = await github.graphql( "query($owner: String!, $repo: String!) {\n repository(owner: $owner, name: $repo) {\n id\n owner {\n id\n __typename\n }\n }\n }", @@ -147,7 +147,7 @@ async function updateProject(output) { core.warning(`Could not resolve token identity (viewer.login): ${viewerError.message}`); } let projectId; - core.info(`[2/5] Resolving project from URL (scope=${projectInfo.scope}, login=${projectInfo.ownerLogin}, number=${projectNumberFromUrl})...`); + core.info(`[2/4] Resolving project from URL (scope=${projectInfo.scope}, login=${projectInfo.ownerLogin}, number=${projectNumberFromUrl})...`); let resolvedProjectNumber = projectNumberFromUrl; try { const projectNumberInt = parseInt(projectNumberFromUrl, 10); @@ -157,16 +157,7 @@ async function updateProject(output) { } catch (error) { throw (logGraphQLError(error, "Resolving project from URL"), error); } - core.info("[3/5] Linking project to repository..."); - try { - await github.graphql( - "mutation($projectId: ID!, $repositoryId: ID!) {\n linkProjectV2ToRepository(input: {\n projectId: $projectId,\n repositoryId: $repositoryId\n }) {\n repository {\n id\n }\n }\n }", - { projectId, repositoryId } - ); - } catch (linkError) { - (linkError.message && linkError.message.includes("already linked")) || (logGraphQLError(linkError, "Linking project to repository"), core.warning(`Could not link project: ${linkError.message}`)); - } - (core.info("✓ Project linked to repository"), core.info("[4/5] Processing content (issue/PR/draft) if specified...")); + core.info("[3/4] Processing content (issue/PR/draft) if specified..."); const hasContentNumber = void 0 !== output.content_number && null !== output.content_number, hasIssue = void 0 !== output.issue && null !== output.issue, hasPullRequest = void 0 !== output.pull_request && null !== output.pull_request, diff --git a/pkg/workflow/js/update_project.test.cjs b/pkg/workflow/js/update_project.test.cjs index 36cf68442ff..676470a492b 100644 --- a/pkg/workflow/js/update_project.test.cjs +++ b/pkg/workflow/js/update_project.test.cjs @@ -132,8 +132,6 @@ const userProjectV2Response = (url, number = 60, id = "project123", userLogin = const orgProjectNullResponse = () => ({ organization: { projectV2: null } }); const userProjectNullResponse = () => ({ user: { projectV2: null } }); -const linkResponse = { linkProjectV2ToRepository: { repository: { id: "repo123" } } }; - const issueResponse = id => ({ repository: { issue: { id } } }); const pullRequestResponse = id => ({ repository: { pullRequest: { id } } }); @@ -232,7 +230,7 @@ describe("updateProject", () => { content_number: 42, }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project456"), linkResponse, issueResponse("issue-id-42"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "item-custom" } } }]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project456"), issueResponse("issue-id-42"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "item-custom" } } }]); await updateProject(output); @@ -245,7 +243,7 @@ describe("updateProject", () => { const projectUrl = "https://github.com/orgs/testowner/projects/60"; const output = { type: "update_project", project: projectUrl, content_type: "issue", content_number: 42 }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project123"), linkResponse, issueResponse("issue-id-42"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "item123" } } }]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project123"), issueResponse("issue-id-42"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "item123" } } }]); await updateProject(output); @@ -258,7 +256,7 @@ describe("updateProject", () => { const projectUrl = "https://github.com/orgs/testowner/projects/60"; const output = { type: "update_project", project: projectUrl, content_type: "issue", content_number: 42, campaign_id: "my-campaign" }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project123"), linkResponse, issueResponse("issue-id-42"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "item123" } } }]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project123"), issueResponse("issue-id-42"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "item123" } } }]); await updateProject(output); @@ -284,7 +282,7 @@ describe("updateProject", () => { draft_body: "Draft body", }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-draft"), linkResponse, addDraftIssueResponse("draft-item-1")]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-draft"), addDraftIssueResponse("draft-item-1")]); await updateProject(output); @@ -302,7 +300,7 @@ describe("updateProject", () => { draft_title: " ", }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-draft"), linkResponse]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-draft")]); await expect(updateProject(output)).rejects.toThrow(/draft_title/); }); @@ -311,7 +309,7 @@ describe("updateProject", () => { const projectUrl = "https://github.com/orgs/testowner/projects/60"; const output = { type: "update_project", project: projectUrl, content_type: "issue", content_number: 99 }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project123"), linkResponse, issueResponse("issue-id-99"), existingItemResponse("issue-id-99", "item-existing")]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project123"), issueResponse("issue-id-99"), existingItemResponse("issue-id-99", "item-existing")]); await updateProject(output); @@ -324,7 +322,7 @@ describe("updateProject", () => { const projectUrl = "https://github.com/orgs/testowner/projects/60"; const output = { type: "update_project", project: projectUrl, content_type: "pull_request", content_number: 17 }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-pr"), linkResponse, pullRequestResponse("pr-id-17"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "pr-item" } } }]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-pr"), pullRequestResponse("pr-id-17"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "pr-item" } } }]); await updateProject(output); @@ -336,7 +334,7 @@ describe("updateProject", () => { const projectUrl = "https://github.com/orgs/testowner/projects/60"; const output = { type: "update_project", project: projectUrl, issue: "101" }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "legacy-project"), linkResponse, issueResponse("issue-id-101"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "legacy-item" } } }]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "legacy-project"), issueResponse("issue-id-101"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "legacy-item" } } }]); await updateProject(output); @@ -351,7 +349,7 @@ describe("updateProject", () => { const projectUrl = "https://github.com/orgs/testowner/projects/60"; const output = { type: "update_project", project: projectUrl, content_number: "ABC" }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "invalid-project"), linkResponse]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "invalid-project")]); await expect(updateProject(output)).rejects.toThrow(/Invalid content number/); }); @@ -370,7 +368,6 @@ describe("updateProject", () => { repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-field"), - linkResponse, issueResponse("issue-id-10"), existingItemResponse("issue-id-10", "item-field"), fieldsResponse([{ id: "field-status", name: "Status" }]), @@ -398,7 +395,6 @@ describe("updateProject", () => { repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-draft-fields"), - linkResponse, addDraftIssueResponse("draft-item-fields"), fieldsResponse([{ id: "field-status", name: "Status" }]), updateFieldValueResponse(), @@ -426,7 +422,6 @@ describe("updateProject", () => { repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-priority"), - linkResponse, issueResponse("issue-id-15"), existingItemResponse("issue-id-15", "item-priority"), fieldsResponse([ @@ -462,7 +457,6 @@ describe("updateProject", () => { repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-status"), - linkResponse, issueResponse("issue-id-16"), existingItemResponse("issue-id-16", "item-status"), fieldsResponse([ @@ -525,7 +519,7 @@ describe("updateProject", () => { fields: { NonExistentField: "Some Value" }, }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-test"), linkResponse, issueResponse("issue-id-20"), existingItemResponse("issue-id-20", "item-test"), fieldsResponse([])]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-test"), issueResponse("issue-id-20"), existingItemResponse("issue-id-20", "item-test"), fieldsResponse([])]); mockGithub.graphql.mockRejectedValueOnce(new Error("Failed to create field")); @@ -538,7 +532,7 @@ describe("updateProject", () => { const projectUrl = "https://github.com/orgs/testowner/projects/60"; const output = { type: "update_project", project: projectUrl, content_type: "issue", content_number: 50, campaign_id: "test-campaign" }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-label"), linkResponse, issueResponse("issue-id-50"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "item-label" } } }]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-label"), issueResponse("issue-id-50"), emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "item-label" } } }]); mockGithub.rest.issues.addLabels.mockRejectedValueOnce(new Error("Labels disabled")); @@ -560,7 +554,7 @@ describe("updateProject", () => { campaign_id: "my-campaign-123", }; - queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project123"), linkResponse]); + queueResponses([repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project123")]); await updateProject(output); @@ -594,7 +588,6 @@ describe("updateProject", () => { repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-override"), - linkResponse, issueWithTimestamps, emptyItemsResponse(), { addProjectV2ItemById: { item: { id: "item-override" } } }, @@ -634,7 +627,6 @@ describe("updateProject", () => { repoResponse(), viewerResponse(), orgProjectV2Response(projectUrl, 60, "project-date-field"), - linkResponse, issueResponse("issue-id-75"), existingItemResponse("issue-id-75", "item-date-field"), // DATE field with dataType explicitly set to "DATE"