Skip to content

fix: False fork PR detection on same-repo PRs #24218

@lpcox

Description

@lpcox

Problem

detectForkPR() in actions/setup/js/pr_helpers.cjs incorrectly reports "Fork PR detected" for a same-repo PR:

Warning: ⚠️ Fork PR detected - gh pr checkout will fetch from fork repository

This causes the checkout strategy to fall through to gh pr checkout instead of the fast git fetch + git checkout path. Combined with #24217 (stale GH_HOST), this triggers the checkout failure.

Triggered by: https://github.com/fsprojects/FSharp.Control.AsyncSeq/actions/runs/23929188570/job/69792652319#step:13:93
PR in question: fsprojects/FSharp.Control.AsyncSeq#302 (same-repo PR, not a fork)

Root cause

detectForkPR() uses three checks:

function detectForkPR(pullRequest) {
  // 1. head.repo is null (deleted fork)
  // 2. GitHub's explicit fork flag
  else if (pullRequest.head.repo.fork === true) { isFork = true; }
  // 3. Different full_name
  else if (pullRequest.head.repo.full_name !== pullRequest.base?.repo?.full_name) { isFork = true; }
  return { isFork, reason };
}

One of these checks is returning a false positive. Possible causes:

  • Check 1: head.repo could be null for certain PR states (draft, reopened from deleted branch)
  • Check 2: The repo might have fork: true if it's itself a fork of another repo (common for OSS — fsprojects/FSharp.Control.AsyncSeq could be a fork)
  • Check 3: Name mismatch due to repo rename/transfer

Most likely: Check 2 — the repository itself (fsprojects/FSharp.Control.AsyncSeq) may be a GitHub fork of another repo. The fork flag on the repo object reflects whether the repo is a fork, not whether the PR is cross-repo. A same-repo PR in a forked repo would have head.repo.fork === true but isn't actually a cross-repo fork PR.

Proposed fix

Check 2 should be removed or refined. The fork flag on head.repo indicates that the repository itself is a fork of another repo — it does NOT mean the PR is from a different repository. The correct fork PR check is only check 3 (different full_name):

function detectForkPR(pullRequest) {
    return { isFork: true, reason: "head repository deleted (was likely a fork)" };
  }
  if (pullRequest.head.repo.full_name !== pullRequest.base?.repo?.full_name) {
    return { isFork: true, reason: "different repository names" };
  }
  return { isFork: false, reason: "same repository" };
}

Files to modify

  • actions/setup/js/pr_helpers.cjs — Remove or refine the head.repo.fork === true check
  • actions/setup/js/pr_helpers.test.cjs — Update tests

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    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