From f49c903342d54fd316c5aba2a48a70e4c1439309 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:11:16 +0000 Subject: [PATCH 1/3] Initial plan From 5690346c0051628345939123cff09e1917f6111b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:18:47 +0000 Subject: [PATCH 2/3] fix: send agent_assignment object in assignAgentToIssue REST request Build and include agent_assignment in the POST assignees payload when model, customAgent, customInstructions, baseBranch, or pullRequestRepoSlug are provided, so the Copilot coding agent receives custom instructions and agent configuration. Closes #46799" Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/assign_agent_helpers.cjs | 7 ++ .../setup/js/assign_agent_helpers.test.cjs | 88 +++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/actions/setup/js/assign_agent_helpers.cjs b/actions/setup/js/assign_agent_helpers.cjs index af5676d9840..61de9031e44 100644 --- a/actions/setup/js/assign_agent_helpers.cjs +++ b/actions/setup/js/assign_agent_helpers.cjs @@ -403,6 +403,13 @@ async function assignAgentToIssue( issue_number: issueNumber, assignees: [assignee], }; + const agentAssignment = {}; + if (pullRequestRepoSlug) agentAssignment.target_repo = pullRequestRepoSlug; + if (baseBranch) agentAssignment.base_branch = baseBranch; + if (customInstructions) agentAssignment.custom_instructions = customInstructions; + if (customAgent) agentAssignment.custom_agent = customAgent; + if (model) agentAssignment.model = model; + if (Object.keys(agentAssignment).length > 0) assignParams.agent_assignment = agentAssignment; await githubClient.request("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", assignParams); return true; } catch (error) { diff --git a/actions/setup/js/assign_agent_helpers.test.cjs b/actions/setup/js/assign_agent_helpers.test.cjs index f161106b9e5..b9c5a152da4 100644 --- a/actions/setup/js/assign_agent_helpers.test.cjs +++ b/actions/setup/js/assign_agent_helpers.test.cjs @@ -456,6 +456,94 @@ describe("assign_agent_helpers.cjs", () => { expect(mockCore.error).toHaveBeenCalledWith(expect.stringContaining("GH_AW_AGENT_TOKEN")); expect(mockCore.info).toHaveBeenCalledWith(expect.stringContaining("github.github.com/gh-aw/reference/copilot-cloud-agent/#authentication")); }); + + it("should not include agent_assignment when all optional fields are null", async () => { + const mockRequest = vi.fn().mockResolvedValue({ status: 201 }); + const restClient = { request: mockRequest }; + + await assignAgentToIssue("id", "copilot-swe-agent[bot]", [], "copilot", null, null, null, null, null, restClient, taskContext); + + expect(mockRequest).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", { + owner: "myorg", + repo: "myrepo", + issue_number: 42, + assignees: ["copilot-swe-agent[bot]"], + }); + }); + + it("should include agent_assignment with all fields when all are provided", async () => { + const mockRequest = vi.fn().mockResolvedValue({ status: 201 }); + const restClient = { request: mockRequest }; + + await assignAgentToIssue( + "id", + "copilot-swe-agent[bot]", + [], + "copilot", + null, + "claude-opus-4.6", + "my-agent", + "Follow the coding guidelines.", + "feature-branch", + restClient, + taskContext, + "otherorg/otherrepo" + ); + + expect(mockRequest).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", { + owner: "myorg", + repo: "myrepo", + issue_number: 42, + assignees: ["copilot-swe-agent[bot]"], + agent_assignment: { + target_repo: "otherorg/otherrepo", + base_branch: "feature-branch", + custom_instructions: "Follow the coding guidelines.", + custom_agent: "my-agent", + model: "claude-opus-4.6", + }, + }); + }); + + it("should include agent_assignment with only the provided fields", async () => { + const mockRequest = vi.fn().mockResolvedValue({ status: 201 }); + const restClient = { request: mockRequest }; + + await assignAgentToIssue( + "id", + "copilot-swe-agent[bot]", + [], + "copilot", + null, + null, + null, + "Always write tests.", + null, + restClient, + taskContext + ); + + expect(mockRequest).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", { + owner: "myorg", + repo: "myrepo", + issue_number: 42, + assignees: ["copilot-swe-agent[bot]"], + agent_assignment: { + custom_instructions: "Always write tests.", + }, + }); + }); + + it("should include agent_assignment with target_repo when pullRequestRepoSlug is provided", async () => { + const mockRequest = vi.fn().mockResolvedValue({ status: 201 }); + const restClient = { request: mockRequest }; + + await assignAgentToIssue("id", "copilot-swe-agent[bot]", [], "copilot", null, null, null, null, null, restClient, taskContext, "otherorg/otherrepo"); + + expect(mockRequest).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", expect.objectContaining({ + agent_assignment: { target_repo: "otherorg/otherrepo" }, + })); + }); }); describe("generatePermissionErrorSummary", () => { From b20e323c4cc87ed4249da9a1bec6ee3f9fbf7ce2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:59:15 +0000 Subject: [PATCH 3/3] fix: preserve explicit agent assignment values Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- actions/setup/js/assign_agent_helpers.cjs | 10 +-- .../setup/js/assign_agent_helpers.test.cjs | 62 ++++++++++--------- actions/setup/js/assign_to_agent.cjs | 8 ++- actions/setup/js/assign_to_agent.test.cjs | 13 +++- 4 files changed, 53 insertions(+), 40 deletions(-) diff --git a/actions/setup/js/assign_agent_helpers.cjs b/actions/setup/js/assign_agent_helpers.cjs index 61de9031e44..dcf2c838275 100644 --- a/actions/setup/js/assign_agent_helpers.cjs +++ b/actions/setup/js/assign_agent_helpers.cjs @@ -404,11 +404,11 @@ async function assignAgentToIssue( assignees: [assignee], }; const agentAssignment = {}; - if (pullRequestRepoSlug) agentAssignment.target_repo = pullRequestRepoSlug; - if (baseBranch) agentAssignment.base_branch = baseBranch; - if (customInstructions) agentAssignment.custom_instructions = customInstructions; - if (customAgent) agentAssignment.custom_agent = customAgent; - if (model) agentAssignment.model = model; + if (pullRequestRepoSlug != null) agentAssignment.target_repo = pullRequestRepoSlug; + if (baseBranch != null) agentAssignment.base_branch = baseBranch; + if (customInstructions != null) agentAssignment.custom_instructions = customInstructions; + if (customAgent != null) agentAssignment.custom_agent = customAgent; + if (model != null) agentAssignment.model = model; if (Object.keys(agentAssignment).length > 0) assignParams.agent_assignment = agentAssignment; await githubClient.request("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", assignParams); return true; diff --git a/actions/setup/js/assign_agent_helpers.test.cjs b/actions/setup/js/assign_agent_helpers.test.cjs index b9c5a152da4..84c5784092f 100644 --- a/actions/setup/js/assign_agent_helpers.test.cjs +++ b/actions/setup/js/assign_agent_helpers.test.cjs @@ -475,20 +475,7 @@ describe("assign_agent_helpers.cjs", () => { const mockRequest = vi.fn().mockResolvedValue({ status: 201 }); const restClient = { request: mockRequest }; - await assignAgentToIssue( - "id", - "copilot-swe-agent[bot]", - [], - "copilot", - null, - "claude-opus-4.6", - "my-agent", - "Follow the coding guidelines.", - "feature-branch", - restClient, - taskContext, - "otherorg/otherrepo" - ); + await assignAgentToIssue("id", "copilot-swe-agent[bot]", [], "copilot", null, "claude-opus-4.6", "my-agent", "Follow the coding guidelines.", "feature-branch", restClient, taskContext, "otherorg/otherrepo"); expect(mockRequest).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", { owner: "myorg", @@ -509,19 +496,7 @@ describe("assign_agent_helpers.cjs", () => { const mockRequest = vi.fn().mockResolvedValue({ status: 201 }); const restClient = { request: mockRequest }; - await assignAgentToIssue( - "id", - "copilot-swe-agent[bot]", - [], - "copilot", - null, - null, - null, - "Always write tests.", - null, - restClient, - taskContext - ); + await assignAgentToIssue("id", "copilot-swe-agent[bot]", [], "copilot", null, null, null, "Always write tests.", null, restClient, taskContext); expect(mockRequest).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", { owner: "myorg", @@ -540,9 +515,36 @@ describe("assign_agent_helpers.cjs", () => { await assignAgentToIssue("id", "copilot-swe-agent[bot]", [], "copilot", null, null, null, null, null, restClient, taskContext, "otherorg/otherrepo"); - expect(mockRequest).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", expect.objectContaining({ - agent_assignment: { target_repo: "otherorg/otherrepo" }, - })); + expect(mockRequest).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", { + owner: "myorg", + repo: "myrepo", + issue_number: 42, + assignees: ["copilot-swe-agent[bot]"], + agent_assignment: { + target_repo: "otherorg/otherrepo", + }, + }); + }); + + it("should include empty-string agent_assignment fields when explicitly provided", async () => { + const mockRequest = vi.fn().mockResolvedValue({ status: 201 }); + const restClient = { request: mockRequest }; + + await assignAgentToIssue("id", "copilot-swe-agent[bot]", [], "copilot", null, "", "", "", "", restClient, taskContext, ""); + + expect(mockRequest).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", { + owner: "myorg", + repo: "myrepo", + issue_number: 42, + assignees: ["copilot-swe-agent[bot]"], + agent_assignment: { + target_repo: "", + base_branch: "", + custom_instructions: "", + custom_agent: "", + model: "", + }, + }); }); }); diff --git a/actions/setup/js/assign_to_agent.cjs b/actions/setup/js/assign_to_agent.cjs index 064a7fab4e2..21868685ce5 100644 --- a/actions/setup/js/assign_to_agent.cjs +++ b/actions/setup/js/assign_to_agent.cjs @@ -244,6 +244,7 @@ async function main(config = {}) { // Handle per-item pull_request_repo override let effectivePullRequestRepoSlug = basePullRequestRepoSlug; + let effectivePullRequestBaseBranch = effectiveBaseBranch; let hasValidatedPerItemPullRequestRepoOverride = false; const hasPullRequestRepoOverrideField = message.pull_request_repo != null; const trimmedPullRequestRepoOverride = typeof message.pull_request_repo === "string" ? message.pull_request_repo.trim() : ""; @@ -260,8 +261,9 @@ async function main(config = {}) { return { success: false, error }; } try { - await resolvePullRequestRepo(githubClient, pullRequestRepoParts[0], pullRequestRepoParts[1], configuredBaseBranch); + const resolvedPullRequestRepo = await resolvePullRequestRepo(githubClient, pullRequestRepoParts[0], pullRequestRepoParts[1], configuredBaseBranch); effectivePullRequestRepoSlug = itemPullRequestRepo; + effectivePullRequestBaseBranch = resolvedPullRequestRepo.effectiveBaseBranch; hasValidatedPerItemPullRequestRepoOverride = true; core.info(`Using per-item pull request repository: ${itemPullRequestRepo}`); } catch (error) { @@ -389,7 +391,7 @@ async function main(config = {}) { if (model) core.info(`Using model: ${model}`); if (customAgent) core.info(`Using custom agent: ${customAgent}`); if (customInstructions) core.info(`Using custom instructions: ${customInstructions.substring(0, 100)}${customInstructions.length > 100 ? "..." : ""}`); - if (effectiveBaseBranch) core.info(`Using base branch: ${effectiveBaseBranch}`); + if (effectivePullRequestBaseBranch) core.info(`Using base branch: ${effectivePullRequestBaseBranch}`); const success = await assignAgentToIssue( assignableId, @@ -400,7 +402,7 @@ async function main(config = {}) { model, customAgent, customInstructions, - effectiveBaseBranch, + effectivePullRequestBaseBranch, githubClient, taskContext, effectivePullRequestRepoSlug, diff --git a/actions/setup/js/assign_to_agent.test.cjs b/actions/setup/js/assign_to_agent.test.cjs index fd9832bcff6..d2b4731824a 100644 --- a/actions/setup/js/assign_to_agent.test.cjs +++ b/actions/setup/js/assign_to_agent.test.cjs @@ -1496,7 +1496,7 @@ describe("assign_to_agent", () => { // Get global PR repository ID and default branch (for default-pr-repo) mockGithub.rest.repos.get.mockResolvedValueOnce({ data: { node_id: "default-pr-repo-id", default_branch: "main" } }); // Get item PR repository - mockGithub.rest.repos.get.mockResolvedValueOnce({ data: { node_id: "item-pull-request-repo-id", default_branch: "main" } }); + mockGithub.rest.repos.get.mockResolvedValueOnce({ data: { node_id: "item-pull-request-repo-id", default_branch: "develop" } }); // Find agent mockGithub.rest.issues.checkUserCanBeAssigned.mockResolvedValueOnce({}); mockGithub.rest.users.getByUsername.mockResolvedValueOnce({ data: { id: 99999 } }); @@ -1511,7 +1511,16 @@ describe("assign_to_agent", () => { expect(mockCore.info).toHaveBeenCalledWith(expect.stringContaining("Using per-item pull request repository: test-owner/item-pull-request-repo")); - expect(mockGithub.request).toHaveBeenCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", expect.objectContaining({ owner: "test-owner", repo: "test-repo", issue_number: 42 })); + expect(mockGithub.request).toHaveBeenLastCalledWith("POST /repos/{owner}/{repo}/issues/{issue_number}/assignees", { + owner: "test-owner", + repo: "test-repo", + issue_number: 42, + assignees: ["copilot-swe-agent[bot]"], + agent_assignment: { + target_repo: "test-owner/item-pull-request-repo", + base_branch: "develop", + }, + }); }); it("should reject per-item pull_request_repo not in allowed list", async () => {