This was generated by AI during triage.
Summary
Please add first-class safe-output support for creating a pull request whose head branch is pushed to an automation-owned fork while the base branch remains in the upstream repository.
Our motivating scenario is an agentic workflow for microsoft/vscode. For security and trust-boundary reasons, we want changes produced by the workflow to enter microsoft/vscode through the same fork-based path used by community contributors, rather than allowing the workflow to push branches directly into the upstream repository.
Desired workflow
Given:
- upstream repository:
microsoft/vscode
- automation-owned fork:
<automation-owner>/vscode
- upstream base branch:
main
The workflow should be able to:
- Start from the current upstream
microsoft/vscode@main state. The automation fork may be stale, so the workflow must explicitly synchronize or base its working branch on the upstream SHA at run time.
- Apply and commit the agent's changes.
- Push the generated feature branch only to
<automation-owner>/vscode.
- Create a PR in
microsoft/vscode with:
base: main
head: <automation-owner>:<generated-branch>
- Continue updating that fork-backed PR branch in later agentic workflow runs.
The fork's default branch does not necessarily need to be mutated. A safe implementation could check out the upstream base SHA, create the feature branch from that SHA, and push only the feature branch to the fork. If gh-aw prefers to synchronize the fork's default branch, we would also need a first-class, race-safe mechanism for doing that.
Current gap
safe-outputs.create-pull-request.target-repo currently identifies the repository where gh-aw applies the patch, pushes the branch, and opens the PR. The handler creates the PR with an unqualified head: branchName, so the head and base are in the same repository.
There does not appear to be a separate head-repo / source-repo setting that would let a workflow:
- push the branch to one repository,
- create the PR in another repository, and
- send an owner-qualified head such as
<automation-owner>:<branch> to GitHub.
Changing target-repo to the fork would instead target the PR at the fork itself. Supplying a different token does not change where the branch and PR are created.
Related work such as #21306 added cross-repository support for push_to_pull_request_branch, but the documented implementation still rejects actual fork PR branches because the workflow normally lacks write access to the contributor's fork. This request is specifically for a configured automation-owned fork to which the workflow has explicit write credentials.
Possible configuration shape
The exact schema is open for discussion, but conceptually we need separate upstream/base and fork/head configuration:
checkout:
- repository: microsoft/vscode
ref: main
current: true
safe-outputs:
create-pull-request:
target-repo: microsoft/vscode
head-repo: <automation-owner>/vscode
base-branch: main
allowed-repos:
- microsoft/vscode
- <automation-owner>/vscode
head-github-token: ${{ secrets.AUTOMATION_FORK_TOKEN }}
Equivalent names such as source-repo, push-repo, or a structured head: block would also work.
If the upstream and fork require different GitHub App installations or credentials, gh-aw may need distinct authentication configuration for:
- reading the upstream repository and creating the upstream PR,
- writing the branch to the fork, and
- updating the fork branch in follow-up runs.
Sync/base semantics
Please clarify or support one of these models:
Preferred: upstream-based ephemeral branch
- Resolve the current upstream base branch SHA.
- Check out that exact SHA.
- Apply the agent patch and create a feature branch.
- Push the feature branch to the configured fork.
This avoids mutating the fork's default branch and guarantees that the PR branch is based on the upstream state observed by the workflow.
Alternative: synchronize the fork first
- Synchronize
<automation-owner>/vscode@main from microsoft/vscode@main using the GitHub fork-sync API or an explicit fetch/reset/push flow.
- Create the feature branch from the synchronized fork branch.
If this model is supported, synchronization should be explicit, auditable, race-safe, and constrained to the configured upstream/fork pair.
Security requirements
The motivation is to strengthen the trust boundary, not merely change branch naming:
- The workflow must not require
contents: write on the upstream repository.
- The feature branch must be pushed only to the configured automation fork.
- The upstream credential should need only the permissions required to read metadata and create/manage the PR.
- The fork credential should be scoped only to the configured fork and branch operations.
- Both repositories should be allowlisted at compile time; the agent must not be able to choose an arbitrary fork or upstream repository at runtime.
- Base and head branch names should remain subject to existing branch validation and protected-file policies.
- Safe-output summaries and manifests should record the upstream repo, fork repo, base SHA, pushed head SHA, and credential role used for each operation.
- The resulting GitHub PR must be a real fork PR so downstream systems can classify it as fork-originated and apply their normal community-contributor isolation policies.
Follow-up update support
The initial PR is only part of the lifecycle. push-to-pull-request-branch or a successor safe output should support updating a configured automation-owned fork when:
- the PR head repository exactly matches the configured
head-repo, and
- the workflow has an explicitly configured write credential for that repository.
This should remain forbidden for arbitrary contributor forks.
Acceptance criteria
- A workflow can check out an upstream repository and create a feature branch based on the current upstream base SHA.
- Safe outputs push that branch to a separately configured automation fork.
- Safe outputs create a PR against the upstream repository using an owner-qualified fork head.
- The upstream repository does not grant the workflow
contents: write.
- Later safe-output runs can update that same configured fork branch without enabling writes to arbitrary contributor forks.
- Documentation explains upstream/fork synchronization, token/App installation requirements, least-privilege permissions, and security constraints.
Would the gh-aw team prefer extending create-pull-request and push-to-pull-request-branch, or introducing a dedicated fork-backed PR safe output for this trust-boundary use case?
Summary
Please add first-class safe-output support for creating a pull request whose head branch is pushed to an automation-owned fork while the base branch remains in the upstream repository.
Our motivating scenario is an agentic workflow for
microsoft/vscode. For security and trust-boundary reasons, we want changes produced by the workflow to entermicrosoft/vscodethrough the same fork-based path used by community contributors, rather than allowing the workflow to push branches directly into the upstream repository.Desired workflow
Given:
microsoft/vscode<automation-owner>/vscodemainThe workflow should be able to:
microsoft/vscode@mainstate. The automation fork may be stale, so the workflow must explicitly synchronize or base its working branch on the upstream SHA at run time.<automation-owner>/vscode.microsoft/vscodewith:base: mainhead: <automation-owner>:<generated-branch>The fork's default branch does not necessarily need to be mutated. A safe implementation could check out the upstream base SHA, create the feature branch from that SHA, and push only the feature branch to the fork. If gh-aw prefers to synchronize the fork's default branch, we would also need a first-class, race-safe mechanism for doing that.
Current gap
safe-outputs.create-pull-request.target-repocurrently identifies the repository where gh-aw applies the patch, pushes the branch, and opens the PR. The handler creates the PR with an unqualifiedhead: branchName, so the head and base are in the same repository.There does not appear to be a separate
head-repo/source-reposetting that would let a workflow:<automation-owner>:<branch>to GitHub.Changing
target-repoto the fork would instead target the PR at the fork itself. Supplying a different token does not change where the branch and PR are created.Related work such as #21306 added cross-repository support for
push_to_pull_request_branch, but the documented implementation still rejects actual fork PR branches because the workflow normally lacks write access to the contributor's fork. This request is specifically for a configured automation-owned fork to which the workflow has explicit write credentials.Possible configuration shape
The exact schema is open for discussion, but conceptually we need separate upstream/base and fork/head configuration:
Equivalent names such as
source-repo,push-repo, or a structuredhead:block would also work.If the upstream and fork require different GitHub App installations or credentials, gh-aw may need distinct authentication configuration for:
Sync/base semantics
Please clarify or support one of these models:
Preferred: upstream-based ephemeral branch
This avoids mutating the fork's default branch and guarantees that the PR branch is based on the upstream state observed by the workflow.
Alternative: synchronize the fork first
<automation-owner>/vscode@mainfrommicrosoft/vscode@mainusing the GitHub fork-sync API or an explicit fetch/reset/push flow.If this model is supported, synchronization should be explicit, auditable, race-safe, and constrained to the configured upstream/fork pair.
Security requirements
The motivation is to strengthen the trust boundary, not merely change branch naming:
contents: writeon the upstream repository.Follow-up update support
The initial PR is only part of the lifecycle.
push-to-pull-request-branchor a successor safe output should support updating a configured automation-owned fork when:head-repo, andThis should remain forbidden for arbitrary contributor forks.
Acceptance criteria
contents: write.Would the gh-aw team prefer extending
create-pull-requestandpush-to-pull-request-branch, or introducing a dedicated fork-backed PR safe output for this trust-boundary use case?