Skip to content

compiler: buildSharedPRCheckoutSteps ignores push-to-pull-request-branch.target-repo (and update-pull-request.target-repo) when create-pull-request is not configured #30472

@bryanchen-d

Description

@bryanchen-d

Bug

When a workflow configures safe-outputs.push-to-pull-request-branch.target-repo without also configuring safe-outputs.create-pull-request, the compiler-emitted safe_outputs job checks out the workflow repo instead of the target repo. The handler's git ls-remote --exit-code --heads origin <pr-branch> then fails with exit code 2 because origin points at the wrong repository.

This is the exact gap PR #22244 set out to fix. That PR was closed without merge on 2026-03-22; PR #28388 (which closed tracking issue #21306) only fixed the JS handler's directory handling, not the Go compiler step generation. As a result, the regression is still present on main (verified at HEAD of pkg/workflow/compiler_safe_outputs_steps.go) and against gh-aw extension v0.71.5.

Repro

Workflow config (abbreviated, real workflow at microsoft/vscode-engineering/.github/workflows/errors-fix-driver.md):

on:
  workflow_dispatch:
    inputs:
      pr_number: { type: string, required: true }

safe-outputs:
  github-token: ${{ steps.safe-outputs-app-token.outputs.token }}
  push-to-pull-request-branch:
    target-repo: "microsoft/vscode"
  update-pull-request:
    target-repo: "microsoft/vscode"
  # NOTE: no create-pull-request configured

tools:
  github:
    github-token: ${{ steps.safe-outputs-app-token.outputs.token }}

# checkout block puts target repo at workspace root
# (workflow repo is at ./workflow-repo)

The compiled safe_outputs job emits:

- name: Checkout repository
  if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')
  uses: actions/checkout@...
  with:
    ref: ${{ github.base_ref || ... }}
    token: ${{ steps.safe-outputs-app-token.outputs.token }}
    persist-credentials: false
    fetch-depth: 1
    # <-- repository: missing
- name: Configure Git credentials
  env:
    REPO_NAME: ${{ github.repository }}   # <-- wrong repo (vscode-engineering, not vscode)
    ...
  run: |
    git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"

The handler actions/setup/js/push_to_pull_request_branch.cjs then runs:

git ls-remote --exit-code --heads origin fix/listview-null-row-guard-314134-...

against origin = microsoft/vscode-engineering, exits with code 2, and fails the job.

Root cause (source)

pkg/workflow/compiler_safe_outputs_steps.go::buildSharedPRCheckoutSteps only consults CreatePullRequests.TargetRepoSlug when picking targetRepoSlug:

// Priority: create-pull-request target-repo > trialLogicalRepoSlug > default (source repo)
var targetRepoSlug string
if data.SafeOutputs.CreatePullRequests != nil &&
    data.SafeOutputs.CreatePullRequests.TargetRepoSlug != "" {
    targetRepoSlug = data.SafeOutputs.CreatePullRequests.TargetRepoSlug
} else if c.trialMode && c.trialLogicalRepoSlug != "" {
    targetRepoSlug = c.trialLogicalRepoSlug
}
// missing: PushToPullRequestBranch.TargetRepoSlug fallback

REPO_NAME and repository: are then both elided from the emitted YAML. The same is true for UpdatePullRequest.TargetRepoSlug, which has identical semantics for cross-repo updates.

Expected

When any of the following are set (and create-pull-request is not), the safe_outputs job should check out the configured target repo and set REPO_NAME accordingly:

  • push-to-pull-request-branch.target-repo
  • update-pull-request.target-repo (same problem class)

PR #22244's CheckoutManager-based design (each safe output independently registers its checkout requirement, manager dedupes) is the right shape; that PR just never landed.

Workaround

Add a no-op create-pull-request to safe-outputs purely to trick the compiler — undesirable because it changes runtime guards/permissions and risks accidental PR creation.

Affected versions

  • gh-aw extension v0.71.1 → v0.71.5 (current). Compiler main HEAD as of 2026-05-05 still has the gap.

Related

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions