Skip to content

Bug: Cross-repo create-pull-request checkout uses hardcoded github.token instead of safe-outputs token #16426

@sohail-unity

Description

@sohail-unity

Summary

When create-pull-request is configured with target-repo and a custom github-token (PAT) in safe-outputs, the compiled safe_outputs job's checkout and git credential steps use the hardcoded ${{ github.token }} instead of the configured token. This causes Not Found errors because the default GITHUB_TOKEN is scoped to the source repository and cannot access the target repository.

This is a remaining bug from #15500, which fixed the repository: and REPO_NAME parameters but did not address the token used for authentication.

Reproduction

Workflow in org/source-repo targeting org/target-repo:

safe-outputs:
  github-token: ${{ secrets.CROSS_REPO_PAT }}
  create-pull-request:
    target-repo: "org/target-repo"
    base-branch: main
    draft: true

Result: The compiled .lock.yml produces:

- name: Checkout repository
  uses: actions/checkout@...
  with:
    repository: org/target-repo    # correct (fixed in #15500)
    token: ${{ github.token }}     # BUG: ignores safe-outputs github-token
    persist-credentials: false
    fetch-depth: 1

- name: Configure Git credentials
  env:
    REPO_NAME: "org/target-repo"   # correct (fixed in #15500)
    SERVER_URL: ${{ github.server_url }}
    GIT_TOKEN: ${{ github.token }} # BUG: same hardcoded token

The checkout fails with: Not Found - https://docs.github.com/rest/repos/repos#get-a-repository

Note: The PAT itself is valid — the same token successfully creates issues in the target repo via the create_issue safe-output fallback path, which correctly uses addSafeOutputGitHubTokenForConfig for token resolution.

Root Cause

In pkg/workflow/compiler_safe_outputs_steps.go, the buildSharedPRCheckoutSteps function (consolidated path) hardcodes ${{ github.token }} when GitHub App auth is not configured:

// Line 86-91 (current code)
} else {
    checkoutToken = "${{ github.token }}"
    gitRemoteToken = "${{ github.token }}"
}

This bypasses the token precedence chain that every other safe-output operation respects:

  1. Per-config github-token (e.g., create-pull-request.github-token)
  2. Safe-outputs level github-token
  3. Top-level github-token
  4. ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}

The same bug exists in the non-consolidated path in pkg/workflow/create_pull_request.go line 71:

gitToken := "${{ github.token }}"

Proposed Fix

Replace the hardcoded ${{ github.token }} with the existing getEffectiveSafeOutputGitHubToken chain, matching how addSafeOutputGitHubTokenForConfig resolves tokens for all other safe-output operations.

In compiler_safe_outputs_steps.go (buildSharedPRCheckoutSteps):

} else {
    var configToken string
    if data.SafeOutputs.CreatePullRequests != nil {
        configToken = data.SafeOutputs.CreatePullRequests.GitHubToken
    }
    var safeOutputsToken string
    if data.SafeOutputs != nil {
        safeOutputsToken = data.SafeOutputs.GitHubToken
    }
    effectiveToken := getEffectiveSafeOutputGitHubToken(configToken,
        getEffectiveSafeOutputGitHubToken(safeOutputsToken, data.GitHubToken))
    checkoutToken = effectiveToken
    gitRemoteToken = effectiveToken
}

In create_pull_request.go (buildCreateOutputPullRequestJob):

var safeOutputsToken string
if data.SafeOutputs != nil {
    safeOutputsToken = data.SafeOutputs.GitHubToken
}
gitToken := getEffectiveSafeOutputGitHubToken(
    data.SafeOutputs.CreatePullRequests.GitHubToken,
    getEffectiveSafeOutputGitHubToken(safeOutputsToken, data.GitHubToken))

Tests to add/update:

  • Update TestBuildSharedPRCheckoutSteps "create pull request only" case to expect ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} instead of ${{ github.token }}
  • Add cases: cross-repo with safe-outputs.github-token, with per-config token, with top-level token, without any custom token
  • Add integration tests: TestCreatePullRequestCrossRepoWithCustomToken and TestCreatePullRequestCrossRepoWithoutCustomToken
  • Add changeset: patch-fix-cross-repo-checkout-token.md

Environment

  • gh-aw CLI: v0.43.22
  • Compiler output at commit d00dc822f (current main)
  • Verified locally: all unit tests and integration tests pass with the proposed fix

Related

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions