github / github/gh-aw

SideRepoOps: create_pull_request bases PR on repo default branch, not the checked-out ref (breaks non-default/release-branch checkouts)

Open
#39,407 2 comments 0 reactions 0 assignees View on GitHub
ai-inspected community
Dominant language
Go
Stars
5.1k
Forks
541
Avg merge
5h 46m
Merged PRs (30d)
760

Description

🤖 _This issue was investigated and filed by Claude Code._

## Summary

In a **SideRepoOps** workflow that checks out a target/side repository at a **non-default ref** (`checkout: [{ repository: …, ref: }]`), `create_pull_request` and `push_to_pull_request_branch` base the PR on the side repo's **default branch**, not on the **ref that was actually checked out**. The agent commits on top of ``, but the patch's merge-base is computed against the default branch — producing a PR with the wrong base (and a diff that drags in the entire release-branch divergence).

This is related to but distinct from the credential/404 failure in #39404. Here the concern is *which* branch is chosen as the base, even when resolution succeeds.

## Where the base branch comes from

For `create_pull_request`, `safe_outputs_handlers.cjs` resolves the base branch in this order:

```js
if (prConfig.base_branch) baseBranch = prConfig.base_branch; // ① explicit config
else if (manifestEntry && manifestEntry.default_branch) baseBranch = …; // ② checkout manifest
else baseBranch = await getBaseBranch(...); // ③ repos.get() default_branch
```

Both ② and ③ resolve to the **repository default branch**:

- The compiler-emitted *"Build checkout manifest for safe-outputs handlers"* step computes `default_branch` via `git symbolic-ref --short refs/remotes/origin/HEAD` (→ the repo's default) or `gh api repos/ --jq .default_branch` (→ the repo's default).
- `get_base_branch.cjs` falls back to `github.rest.repos.get().default_branch` (→ the repo's default).

Nothing in the chain consults the **`ref` the workflow checked out**. So when a workflow does:

```yaml
checkout:
- repository: /
ref: # e.g. a maintenance/release branch, NOT the default
path:
```

…the agent works on top of ``, but the PR ends up based on ``.

## Impact

- The PR targets the wrong base branch.
- `generate_git_patch` computes `merge-base(feature, origin/)`, which lies far behind ``; the resulting patch/diff includes the whole divergence between the release branch and the default branch, not just the agent's change.
- Only single-branch repos (where default == the checked-out ref) are unaffected, which masks the bug.

## Expected

When a checkout pins a non-default `ref`, that ref should be the default base for `create_pull_request` / `push_to_pull_request_branch` — i.e. the base should track the checked-out branch, not the repository's default branch. Concretely, the checkout manifest could record the checked-out ref (e.g. `git rev-parse --abbrev-ref HEAD` of the checkout) rather than `origin/HEAD`'s default, or the handler could prefer the checkout's upstream branch.

## Current workaround

Set `base_branch` explicitly (path ①) to the checked-out ref:

```yaml
safe-outputs:
create-pull-request:
base-branch: # must be kept in lockstep with checkout.ref
```

This works but duplicates the ref and is easy to let drift from `checkout.ref`. Deriving the base from the checkout would remove that footgun.

## Redaction note

Private repository names, branch names, and run URLs are replaced with placeholders (`/`, ``, ``). Related: #39404.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.