Add base-branch support to assign-to-agent safe output
Problem
When using assign-to-agent with pull-request-repo targeting a different repository, the Copilot coding agent branches off main regardless of the target repository's actual default branch. If the target repo's default branch is develop (or any non-main branch), the agent creates a PR against main — which is incorrect.
The create-pull-request safe output already supports base-branch to control this, but assign-to-agent does not, despite supporting pull-request-repo for cross-repo PR creation.
Root Cause Analysis
1. gh-aw never resolves the target repo's default branch:
In actions/setup/js/assign_to_agent.cjs, the GraphQL query for the target repo only fetches id:
query($owner: String!, $name: String!) {
repository(owner: $owner, name: $name) { id }
}
It should also fetch defaultBranchRef { name } and pass it through.
2. The GraphQL mutation has no baseBranch parameter:
The replaceActorsForAssignable mutation's agentAssignment input only accepts:
targetRepositoryId
model
customAgent
customInstructions
There is no baseBranch field in agentAssignment.
3. AssignToAgentConfig has no BaseBranch field:
Compare with CreatePullRequestsConfig which has:
BaseBranch string `yaml:"base-branch,omitempty"`
The AssignToAgentConfig struct has no equivalent field.
Expected Behavior
safe-outputs:
assign-to-agent:
target: "*"
pull-request-repo: "owner/code-repo"
base-branch: "develop" # New field
github-token: ${{ secrets.TOKEN }}
When base-branch is not specified, the agent should use the target repository's actual default branch (not hardcode main).
Implementation Plan
Please implement the following changes:
1. Update Config Struct (pkg/workflow/assign_to_agent.go)
Add BaseBranch field to AssignToAgentConfig:
BaseBranch string `yaml:"base-branch,omitempty"` // Base branch for PR creation in target repo
This mirrors the existing pattern in CreatePullRequestsConfig.
2. Update Compiler (pkg/workflow/compiler_safe_outputs_specialized.go)
In buildAssignToAgentStepConfig, pass the configured base branch as an env var:
if cfg.BaseBranch != "" {
customEnvVars = append(customEnvVars, fmt.Sprintf(" GH_AW_AGENT_BASE_BRANCH: %q\n", cfg.BaseBranch))
}
3. Update JSON Schema (pkg/parser/schemas/main_workflow_schema.json)
Add base-branch to the assign-to-agent section of the schema:
"base-branch": {
"type": "string",
"description": "Base branch for pull request creation in the target repository. Defaults to the target repo's default branch."
}
4. Update JS Handler — Resolve Default Branch (actions/setup/js/assign_to_agent.cjs)
Update the GraphQL query to also fetch the default branch:
query($owner: String!, $name: String!) {
repository(owner: $owner, name: $name) {
id
defaultBranchRef { name }
}
}
Read GH_AW_AGENT_BASE_BRANCH from environment. When resolving the target repo:
- If
base-branch is configured, use that
- Otherwise, use the fetched
defaultBranchRef.name from the target repo
5. Pass Branch to Agent Assignment (actions/setup/js/assign_agent_helpers.cjs)
This depends on whether the replaceActorsForAssignable mutation supports a baseBranch parameter in agentAssignment. Two approaches:
Option A (if GraphQL API is updated): Add baseBranch to the mutation variables:
agentAssignment: {
targetRepositoryId: $targetRepoId
baseBranch: $baseBranch
model: $model
}
Option B (if GraphQL API cannot be changed): Include the base branch in customInstructions as a workaround:
if (baseBranch && baseBranch !== defaultBranch) {
const branchInstruction = `IMPORTANT: Create your branch from the '${baseBranch}' branch, NOT from 'main'.`;
customInstructions = customInstructions
? `${branchInstruction}\n\n${customInstructions}`
: branchInstruction;
}
Note: Option A requires a corresponding GitHub API change. The agent should coordinate with the GitHub Copilot team if needed.
6. Update Tool Description Enhancer (pkg/workflow/tool_description_enhancer.go)
In the assign_to_agent case, add base branch constraint:
if config.BaseBranch != "" {
constraints = append(constraints, fmt.Sprintf("Pull requests will target the %q branch.", config.BaseBranch))
}
7. Add Tests
pkg/workflow/assign_to_agent_test.go (or equivalent):
- Test
AssignToAgentConfig parsing with base-branch field
- Test compiler includes
GH_AW_AGENT_BASE_BRANCH env var when configured
- Test backward compatibility when
base-branch is not set
actions/setup/js/assign_to_agent.test.cjs:
- Test with
GH_AW_AGENT_BASE_BRANCH env var set
- Test default branch resolution from target repo's
defaultBranchRef
- Test that unset
base-branch still works (backward compatibility)
8. Update Documentation (docs/src/content/docs/reference/safe-outputs.md)
Add base-branch to the assign-to-agent configuration example:
safe-outputs:
assign-to-agent:
target: "*"
pull-request-repo: "owner/code-repo"
base-branch: "develop" # New: target branch for PR (default: target repo's default branch)
github-token: ${{ secrets.TOKEN }}
Document:
base-branch specifies which branch in the target repo the PR should target
- When omitted, uses the target repository's actual default branch
- Only relevant when
pull-request-repo is configured
9. Follow Guidelines
- Use error message format: "[what's wrong]. [what's expected]. [example]"
- Use console formatting from
pkg/console for CLI output
- Run
make agent-finish before completing
Additional Context
- The
create-pull-request safe output already implements base-branch via GH_AW_BASE_BRANCH env var — this is the reference pattern
- The
replaceActorsForAssignable GraphQL mutation may need an upstream API change to properly support baseBranch in agentAssignment
- As a minimum viable fix, resolving
defaultBranchRef from the target repo (step 4) would fix the most common case where the default branch isn't main
Add
base-branchsupport toassign-to-agentsafe outputProblem
When using
assign-to-agentwithpull-request-repotargeting a different repository, the Copilot coding agent branches offmainregardless of the target repository's actual default branch. If the target repo's default branch isdevelop(or any non-mainbranch), the agent creates a PR againstmain— which is incorrect.The
create-pull-requestsafe output already supportsbase-branchto control this, butassign-to-agentdoes not, despite supportingpull-request-repofor cross-repo PR creation.Root Cause Analysis
1. gh-aw never resolves the target repo's default branch:
In
actions/setup/js/assign_to_agent.cjs, the GraphQL query for the target repo only fetchesid:It should also fetch
defaultBranchRef { name }and pass it through.2. The GraphQL mutation has no
baseBranchparameter:The
replaceActorsForAssignablemutation'sagentAssignmentinput only accepts:targetRepositoryIdmodelcustomAgentcustomInstructionsThere is no
baseBranchfield inagentAssignment.3.
AssignToAgentConfighas noBaseBranchfield:Compare with
CreatePullRequestsConfigwhich has:The
AssignToAgentConfigstruct has no equivalent field.Expected Behavior
When
base-branchis not specified, the agent should use the target repository's actual default branch (not hardcodemain).Implementation Plan
Please implement the following changes:
1. Update Config Struct (
pkg/workflow/assign_to_agent.go)Add
BaseBranchfield toAssignToAgentConfig:This mirrors the existing pattern in
CreatePullRequestsConfig.2. Update Compiler (
pkg/workflow/compiler_safe_outputs_specialized.go)In
buildAssignToAgentStepConfig, pass the configured base branch as an env var:3. Update JSON Schema (
pkg/parser/schemas/main_workflow_schema.json)Add
base-branchto theassign-to-agentsection of the schema:4. Update JS Handler — Resolve Default Branch (
actions/setup/js/assign_to_agent.cjs)Update the GraphQL query to also fetch the default branch:
Read
GH_AW_AGENT_BASE_BRANCHfrom environment. When resolving the target repo:base-branchis configured, use thatdefaultBranchRef.namefrom the target repo5. Pass Branch to Agent Assignment (
actions/setup/js/assign_agent_helpers.cjs)This depends on whether the
replaceActorsForAssignablemutation supports abaseBranchparameter inagentAssignment. Two approaches:Option A (if GraphQL API is updated): Add
baseBranchto the mutation variables:Option B (if GraphQL API cannot be changed): Include the base branch in
customInstructionsas a workaround:Note: Option A requires a corresponding GitHub API change. The agent should coordinate with the GitHub Copilot team if needed.
6. Update Tool Description Enhancer (
pkg/workflow/tool_description_enhancer.go)In the
assign_to_agentcase, add base branch constraint:7. Add Tests
pkg/workflow/assign_to_agent_test.go(or equivalent):AssignToAgentConfigparsing withbase-branchfieldGH_AW_AGENT_BASE_BRANCHenv var when configuredbase-branchis not setactions/setup/js/assign_to_agent.test.cjs:GH_AW_AGENT_BASE_BRANCHenv var setdefaultBranchRefbase-branchstill works (backward compatibility)8. Update Documentation (
docs/src/content/docs/reference/safe-outputs.md)Add
base-branchto theassign-to-agentconfiguration example:Document:
base-branchspecifies which branch in the target repo the PR should targetpull-request-repois configured9. Follow Guidelines
pkg/consolefor CLI outputmake agent-finishbefore completingAdditional Context
create-pull-requestsafe output already implementsbase-branchviaGH_AW_BASE_BRANCHenv var — this is the reference patternreplaceActorsForAssignableGraphQL mutation may need an upstream API change to properly supportbaseBranchinagentAssignmentdefaultBranchReffrom the target repo (step 4) would fix the most common case where the default branch isn'tmain