Skip to content

fix(compiler): use push-to-pull-request-branch target-repo for safe_outputs checkout#22244

Closed
Copilot wants to merge 5 commits intomainfrom
copilot/fix-smoke-update-cross-repo-pr
Closed

fix(compiler): use push-to-pull-request-branch target-repo for safe_outputs checkout#22244
Copilot wants to merge 5 commits intomainfrom
copilot/fix-smoke-update-cross-repo-pr

Conversation

Copy link
Contributor

Copilot AI commented Mar 22, 2026

smoke-update-cross-repo-pr has a 100% scheduled failure rate because the safe_outputs job checks out the wrong repository when only push-to-pull-request-branch (not create-pull-request) is configured with a target-repo.

Root cause

buildSharedPRCheckoutSteps only read CreatePullRequests.TargetRepoSlug when determining which repo to check out. With just push-to-pull-request-branch configured:

  • Checkout used github/gh-aw (the workflow repo, no repository: param)
  • Configure Git credentials set origingithub/gh-aw
  • push_to_pull_request_branch.cjs then did git fetch origin pr-branch and got exit code 128 — the branch only exists in githubnext/gh-aw-side-repo

Fix

Each PR safe output (create-pull-request, push-to-pull-request-branch) now independently registers its target-repo checkout requirement with a CheckoutManager. The manager deduplicates registrations that share the same (repository, path) key, so two outputs targeting the same cross-repo destination produce a single checkout step.

The generated safe_outputs job for smoke-update-cross-repo-pr now correctly emits:

- name: Checkout repository
  uses: actions/checkout@...
  with:
    repository: githubnext/gh-aw-side-repo   # was missing
    ...
- name: Configure Git credentials
  env:
    REPO_NAME: "githubnext/gh-aw-side-repo"  # was ${{ github.repository }}

Changes

  • pkg/workflow/compiler_safe_outputs_steps.gobuildSafeOutputsCheckoutManager replaces the old priority chain with independent per-safe-output registration; each output appends its CheckoutConfig directly; CheckoutManager handles deduplication
  • pkg/workflow/checkout_manager.go — added GetPrimaryTargetRepo() and GenerateSafeOutputsCheckoutStep() methods; buildSharedPRCheckoutSteps delegates checkout step generation and REPO_NAME resolution to the manager
  • pkg/workflow/compiler_safe_outputs_steps_test.go — added test cases: cross-repo checkout via push-to-pull-request-branch alone; same-repo deduplication when both outputs register the same target; different target-repos uses the first-registered (create-pr) repo
  • .github/workflows/smoke-update-cross-repo-pr.lock.yml — recompiled

[!WARNING]


💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

…utputs checkout

In buildSharedPRCheckoutSteps, only create-pull-request.target-repo was
used to determine the checkout repository. When only push-to-pull-request-branch
is configured with target-repo (as in smoke-update-cross-repo-pr), the safe_outputs
job checked out github/gh-aw and set origin to github/gh-aw. Then
push_to_pull_request_branch.cjs failed with exit code 128 trying to
git fetch origin pr-branch from the wrong repo.

Fix: add PushToPullRequestBranch.TargetRepoSlug as a fallback in the
checkout target resolution chain. Recompile smoke-update-cross-repo-pr.

Fixes #288 (smoke-update-cross-repo-pr 100% failure rate)

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/81b48fe1-e860-480a-a840-8bfe6a5acd08
Copilot AI changed the title [WIP] Fix smoke update cross-repo PR workflow outage fix(compiler): use push-to-pull-request-branch target-repo for safe_outputs checkout Mar 22, 2026
Copilot AI requested a review from pelikhan March 22, 2026 09:02
@pelikhan
Copy link
Contributor

@copilot use a checkout manager instance in the compiler to handle multiple checkouts as needed in safe-outputs

…target resolution

Add GetPrimaryTargetRepo() and GenerateSafeOutputsCheckoutStep() to CheckoutManager.
Add buildSafeOutputsCheckoutManager() to Compiler, which encapsulates the
target-repo priority chain (create-pr > push-to-pr-branch > trial > default)
using CheckoutManager. Refactor buildSharedPRCheckoutSteps to delegate checkout
step generation and REPO_NAME resolution to the manager instance.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/15ee0c87-aef0-49b2-a00d-5cb3779f77c3
Copy link
Contributor Author

Copilot AI commented Mar 22, 2026

@copilot use a checkout manager instance in the compiler to handle multiple checkouts as needed in safe-outputs

Done in f28614c. Refactored buildSharedPRCheckoutSteps to use a CheckoutManager instance:

  • Added GetPrimaryTargetRepo() and GenerateSafeOutputsCheckoutStep() to CheckoutManager
  • Added buildSafeOutputsCheckoutManager() on the Compiler — encapsulates the target-repo priority chain (create-pull-requestpush-to-pull-request-branch → trial mode → default) using NewCheckoutManager
  • buildSharedPRCheckoutSteps now delegates checkout step generation and REPO_NAME resolution to the manager, consistent with how the agent job uses CheckoutManager in compiler_yaml_main_job.go

@pelikhan
Copy link
Contributor

@copilot the fallback startegy does not make sense. Each safe output should register the checkout they need and let the checkout manager handle it.

…out registration

Each safe output (create-pull-request, push-to-pull-request-branch) now
independently registers its checkout requirement with CheckoutManager.
CheckoutManager deduplicates registrations with the same (repository, path)
key, so two outputs targeting the same cross-repo destination produce one
checkout step. Trial-mode fallback only applies when no safe output has
registered a cross-repo checkout.

Add test for same-repo deduplication case. Rename existing "takes precedence"
test to reflect the registration-order semantics.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/793077a6-1487-47a3-8a4a-a7ec33d2ff4c
Copy link
Contributor Author

Copilot AI commented Mar 22, 2026

@copilot the fallback startegy does not make sense. Each safe output should register the checkout they need and let the checkout manager handle it.

Done in 1ba7f8a. Replaced the if/else if priority chain with independent per-safe-output registration:

  • create-pull-request and push-to-pull-request-branch each call append(configs, &CheckoutConfig{Repository: ...}) independently
  • NewCheckoutManager deduplicates entries with the same (repository, path) key — when both outputs target the same cross-repo destination, only one checkout step is emitted
  • Added a test case that verifies same-repo deduplication
  • The trial-mode fallback only fires when no safe output has registered a cross-repo checkout

@pelikhan pelikhan marked this pull request as ready for review March 22, 2026 16:09
Copilot AI review requested due to automatic review settings March 22, 2026 16:09
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes safe_outputs cross-repo failures by ensuring the checkout step uses the correct target-repo when only push-to-pull-request-branch is configured, via a shared CheckoutManager that deduplicates checkout requirements.

Changes:

  • Add buildSafeOutputsCheckoutManager to register per-safe-output checkout requirements and drive shared PR checkout/git-remote behavior.
  • Extend CheckoutManager with GetPrimaryTargetRepo() and GenerateSafeOutputsCheckoutStep() and delegate safe-outputs checkout generation to it.
  • Add/extend tests for push-to-pull-request-branch cross-repo checkout and same/different-target registration behavior; recompile the smoke workflow lockfile.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
pkg/workflow/compiler_safe_outputs_steps.go Builds a CheckoutManager from safe-output configs and delegates safe_outputs checkout + REPO_NAME selection to it.
pkg/workflow/checkout_manager.go Adds helper methods to select the primary target repo and generate the safe_outputs checkout YAML step.
pkg/workflow/compiler_safe_outputs_steps_test.go Adds test cases for cross-repo checkout via push-to-pull-request-branch and target repo selection behavior.
.github/workflows/smoke-update-cross-repo-pr.lock.yml Regenerated workflow output showing correct repository: and REPO_NAME for the cross-repo case.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +301 to +305
checkContains: []string{
// Deduplication: same repo registered by both outputs → exactly one checkout
"repository: githubnext/gh-aw-side-repo",
`REPO_NAME: "githubnext/gh-aw-side-repo"`,
},
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new "deduplicated to one checkout" case only asserts that the generated YAML contains the repository/REPO_NAME strings, but it doesn’t verify that only one checkout step (or only one repository: line) was emitted. As written, it would still pass if two identical checkout steps were generated. Consider asserting the count (e.g., strings.Count(stepsContent, "- name: Checkout repository") == 1 or counting repository: githubnext/gh-aw-side-repo).

Copilot uses AI. Check for mistakes.
Comment on lines +73 to +74
// CheckoutManager deduplicates registrations that share the same repository,
// so two outputs targeting the same repo result in a single checkout step.
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc comment mismatch: buildSafeOutputsCheckoutManager says the manager “deduplicates registrations that share the same repository”, but CheckoutManager deduplication is keyed on (repository, path). Updating the comment to reflect (repository, path) (and that safe_outputs registrations currently always use the workspace root path) would avoid confusion for future readers.

Suggested change
// CheckoutManager deduplicates registrations that share the same repository,
// so two outputs targeting the same repo result in a single checkout step.
// CheckoutManager deduplicates registrations that share the same (repository, path)
// pair, and safe_outputs currently always use the workspace root path as the
// checkout path. As a result, two outputs targeting the same repo result in a
// single checkout step.

Copilot uses AI. Check for mistakes.
@pelikhan
Copy link
Contributor

@copilot review changes for consistency, clarity,

…nt assertion

- Update buildSafeOutputsCheckoutManager doc comment: "same repository" →
  "(repository, path) pair" to match CheckoutManager's actual deduplication key
- Add checkCounts field to TestBuildSharedPRCheckoutSteps struct so tests can
  assert exact occurrence counts, not just presence
- Use checkCounts in the same-target-repo deduplication test to verify exactly
  one "repository:" line is emitted when both outputs register the same repo

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/02c6726f-1025-4e71-901b-03950a7e296b
Copy link
Contributor Author

Copilot AI commented Mar 22, 2026

@copilot review changes for consistency, clarity,

Done in 55e39e1. Two consistency/clarity fixes:

  • Doc comment (compiler_safe_outputs_steps.go:73): Updated "same repository" → "(repository, path) pair" to accurately match CheckoutManager's deduplication key, and noted that safe_outputs always registers the workspace root path
  • Test assertion (compiler_safe_outputs_steps_test.go): Added a checkCounts map[string]int field to the test struct and used it in the deduplication test to assert "repository: githubnext/gh-aw-side-repo" appears exactly once — previously the test only checked presence, not count

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[health] Smoke Update Cross-Repo PR: 100% failure rate on schedule (6/6 consecutive failures)

3 participants