Skip to content

[WIP] Fix checkout PR branch fetch depth issue - #50378

Merged
pelikhan merged 5 commits into
mainfrom
copilot/fix-deep-fetch-issue
Aug 4, 2026
Merged

[WIP] Fix checkout PR branch fetch depth issue#50378
pelikhan merged 5 commits into
mainfrom
copilot/fix-deep-fetch-issue

Conversation

Copilot AI commented Aug 4, 2026

Copy link
Copy Markdown
Contributor
  • Skip --depth=N in checkout_pr_branch.cjs when the repo is not already shallow (preserves checkout: fetch-depth: 0)
  • Report a clear shallow-clone error when git merge-base fails in generate_git_patch.cjs full mode
  • Add unit tests for the non-shallow fetch paths

Run: https://github.com/github/gh-aw/actions/runs/30949820215

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 11.9 AIC · ⌖ 6.9 AIC · ⊞ 8.3K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.54 AIC · ⌖ 6.21 AIC · ⊞ 8.3K ·
Comment /souschef to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI requested a review from pelikhan August 4, 2026 19:54
@pelikhan
pelikhan marked this pull request as ready for review August 4, 2026 20:07
Copilot AI balanced review requested due to automatic review settings August 4, 2026 20:07
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #50378 does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100).

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Not ready to approve

The new shallow-clone diagnostic is swallowed by fallback handling and does not reliably reach callers.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

Prevents PR checkout from re-shallowing complete repositories and improves shallow-history diagnostics.

Changes:

  • Omits fetch depth for complete clones.
  • Adds coverage for both PR fetch paths.
  • Adds shallow merge-base error handling.
File summaries
File Description
actions/setup/js/checkout_pr_branch.cjs Preserves full history during PR fetches.
actions/setup/js/checkout_pr_branch.test.cjs Tests non-shallow fetch behavior.
actions/setup/js/generate_git_patch.cjs Adds shallow merge-base diagnostics.
Review details

Suppressed comments (1)

actions/setup/js/checkout_pr_branch.cjs:349

  • On the new non-shallow path, the preceding message still claims this refs/pull fetch has depth: N, even though depthArgs omits the option. Log the resolved fetch mode instead so the checkout diagnostics reflect the command that actually runs.
      await exec.exec("git", ["fetch", "origin", `+refs/pull/${prNumber}/head:refs/remotes/origin/pr-head`, ...(await depthArgs(fetchDepth))]);
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Balanced

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment on lines +261 to +267
if (fs.existsSync(path.join(cwd || process.cwd(), ".git", "shallow"))) {
throw new Error(
`${ERR_SYSTEM}: Could not compute merge-base between ${defaultBranchRef} and ${tipRef} because the repository is a shallow clone (.git/shallow exists). ` +
"Deepen the clone (checkout.fetch-depth: 0) so the common ancestor is reachable."
);
}
throw mergeBaseError;
Comment thread actions/setup/js/checkout_pr_branch.cjs Outdated

core.info(`Fetching branch: ${branchName} from origin (depth: ${fetchDepth} for ${commitCount} PR commit(s))`);
await exec.exec("git", ["fetch", "origin", branchName, `--depth=${fetchDepth}`]);
await exec.exec("git", ["fetch", "origin", branchName, ...(await depthArgs(fetchDepth))]);

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: Fix checkout PR branch fetch depth issue

The approach is correct and well-structured. One reliability concern worth addressing before merging:

isShallowRepository() fallback on Git < 2.15

git rev-parse --is-shallow-repository was added in Git 2.15. When it is not available the command exits non-zero, and isShallowRepository() returns false — silently skipping --depth on shallow clones and recreating the original bug. The existing generate_git_patch.cjs already handles this portably by checking fs.existsSync(".git/shallow"); using the same technique as a fallback here would make the fix robust across all runner git versions.

A memoisation cache is a nice-to-have (two fetches at most per run, each very fast) but the correctness issue is the more pressing concern.

Everything else looks good — test coverage is clear and the generate_git_patch.cjs error message is a genuine usability improvement.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 21.5 AIC · ⌖ 9.34 AIC · ⊞ 5.4K

* grafts history, silently undoing an explicit `checkout: fetch-depth: 0`. That
* breaks later `git merge-base` calls (e.g. patch generation for
* create_pull_request). We therefore only pass `--depth` when the repository is
* already shallow; a complete clone already has the objects we need.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

isShallowRepository() runs on every depthArgs() call with no memoization, and it silently falls back to false when git rev-parse --is-shallow-repository exits non-zero (i.e., Git < 2.15). On a genuinely shallow clone with an older git binary, --depth is therefore omitted, recreating the original bug.

Consider two improvements:

  1. Cache the result: memoize at module level so the git rev-parse subprocess runs at most once.
  2. Portable fallback: when exitCode !== 0, fall back to fs.existsSync(path.join(process.cwd(), ".git", "shallow")) — purely local, no credentials, and already used for this purpose in generate_git_patch.cjs.

@copilot please address this.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — requesting changes on two correctness/coverage issues.

📋 Key Themes & Highlights

Key Themes

  • Shallow detection inconsistency: generate_git_patch.cjs uses fs.existsSync('.git/shallow') while checkout_pr_branch.cjs uses git rev-parse --is-shallow-repository. These diverge in git worktrees and after --unshallow. A shared helper in git_helpers.cjs would make both paths consistent and testable.
  • Missing regression test for the new merge-base error path in generate_git_patch.cjs — the improved error message has no test guard.
  • Test isolation: second new test mutates mockContext.eventName without explicit teardown.

Positive Highlights

  • ✅ Clean abstraction: isShallowRepository() and depthArgs() are well-named and well-documented
  • ✅ Safe default: both helpers return false/[] on errors — correct fail-open for complete clones
  • ✅ Good coverage of both fetch paths (pull_request and pull_request_target events)
  • ✅ Informative core.info log when depth is omitted

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 40.5 AIC · ⌖ 8.26 AIC · ⊞ 7.1K
Comment /matt to run again

// otherwise complete clone) can make the merge-base unreachable.
// Surface that explicitly instead of the misleading "branch does not
// exist locally" message.
if (fs.existsSync(path.join(cwd || process.cwd(), ".git", "shallow"))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/diagnosing-bugs] Shallow detection here uses fs.existsSync('.git/shallow'), but checkout_pr_branch.cjs uses git rev-parse --is-shallow-repository — these diverge on edge cases: git worktrees have .git as a file (not a directory) so the path.join(cwd, '.git', 'shallow') join silently fails; also git fetch --unshallow does not always delete .git/shallow immediately, giving false positives.

💡 Suggested fix

Extract isShallowRepository() into a shared helper (e.g. git_helpers.cjs) and call it in both files:

const shallow = await isShallowRepository({ cwd });
if (shallow) {
  throw new Error(`${ERR_SYSTEM}: Could not compute merge-base ... shallow clone.`);
}
throw mergeBaseError;

This is also more testable — no real .git/shallow file needed.

@copilot please address this.

throw new Error(
`${ERR_SYSTEM}: Could not compute merge-base between ${defaultBranchRef} and ${tipRef} because the repository is a shallow clone (.git/shallow exists). ` +
"Deepen the clone (checkout.fetch-depth: 0) so the common ancestor is reachable."
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] No test covers the new merge-base error path in generate_git_patch.cjs. Without a regression test, future refactors can silently remove the improved error message and nobody will notice.

💡 Suggested test shape

In generate_git_patch.test.cjs, add a test that stubs execGitSync to throw on merge-base and asserts the resulting error message contains 'shallow clone' and ERR_SYSTEM:

it('reports shallow-clone error when merge-base fails and .git/shallow exists', async () => {
  mockExecGitSync.mockImplementationOnce((args) => {
    if (args[0] === 'merge-base') throw new Error('fatal: no merge base');
  });
  mockFsExistsSync.mockReturnValue(true); // simulate .git/shallow present
  await expect(generateGitPatch('branch', 'main', { mode: 'full' }))
    .rejects.toThrow(/shallow clone/);
});

@copilot please address this.

});

it("should omit --depth for refs/pull fetch when the repository is not shallow", async () => {
mockExec.getExecOutput.mockResolvedValue({ stdout: "false\n", stderr: "", exitCode: 0 });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] The second test modifies mockContext.eventName but relies on beforeEach/module cache reset (via vi.resetModules) to clean up. If the reset order changes, this mutation leaks into subsequent tests. Explicitly set mockContext.eventName back in the test or in afterEach to make the test self-contained.

💡 Minimal fix

At the top of the pull_request_target test, save and restore:

const originalEvent = mockContext.eventName;
mockContext.eventName = 'pull_request_target';
// ... assertions ...
mockContext.eventName = originalEvent;

Or confirm vi.resetModules() in beforeEach fully re-creates mockContext (add a comment stating this intent).

@copilot please address this.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 100/100 — Excellent

Analyzed 2 test(s): 2 design, 0 implementation, 0 violation(s).

📊 Metrics (2 tests)
Metric Value
Analyzed 2 (JavaScript/vitest)
✅ Design 2 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 2 (100%)
Duplicate clusters 0
Inflation No (0.55:1)
🚨 Violations 0
Test File Classification Issues
should omit --depth when the repository is not shallow actions/setup/js/checkout_pr_branch.test.cjs:243 Design test None — verifies core behavior change
should omit --depth for refs/pull fetch when the repository is not shallow actions/setup/js/checkout_pr_branch.test.cjs:254 Design test None — covers alternate fetch path

Quality Analysis

Both tests verify the core design invariant: conditional --depth flag based on repository shallowness.

Test 1: Shallow repo check (line 243)

  • Mocks getExecOutput to simulate non-shallow repo (stdout: "false\n")
  • Asserts fetch called without --depth=2
  • Verifies no errors

Test 2: Shallow repo check for refs/pull fetch (line 254)

  • Same mock setup + pull_request_target event
  • Asserts refs/pull fetch called without --depth argument
  • Covers alternate GitHub Actions event path

Production code alignment: Changes in checkout_pr_branch.cjs add isShallowRepository() and depthArgs() helper functions to conditionally omit --depth for complete clones. Tests directly verify this behavior via mock setup and assertion pairs.

Verdict

passed. 0% implementation tests (threshold: 30%). No violations detected.

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 19 AIC · ⌖ 5.89 AIC · ⊞ 8.6K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 100/100. 0% implementation tests (threshold: 30%).

@github-actions github-actions Bot mentioned this pull request Aug 4, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: no blocking issues found

The fetch-depth fix is sound and well-tested; two minor robustness gaps flagged inline are non-blocking.

💡 Themes
  • checkout_pr_branch.cjs: isShallowRepository() correctly distinguishes shallow vs. non-shallow clones and preserves fetch-depth: 0 semantics as intended; new unit tests cover both branches.
  • Minor: the non-exception failure path in isShallowRepository() doesn't log a warning, unlike the exception path — inconsistent diagnostics for similar failure classes (see inline comment).
  • generate_git_patch.cjs: the new shallow-clone error message is a good UX improvement over the previous misleading "branch does not exist locally" error, but the .git/shallow file-existence check is a proxy that can both false-positive and false-negative relative to the actual cause of a merge-base failure (see inline comment).
  • No correctness, concurrency, or security-relevant issues found in the diff.

🔎 Code quality review by PR Code Quality Reviewer · auto · 44.8 AIC · ⌖ 10 AIC · ⊞ 7.9K
Comment /review to run again

Comments that could not be inline-anchored

actions/setup/js/checkout_pr_branch.cjs:26

When git rev-parse exits non-zero (not an exception), the failure is swallowed silently and treated as "not shallow" with no diagnostic — unlike the catch block below which does warn.

<details><summary>💡 Details</summary>

If rev-parse --is-shallow-repository fails for a legitimate reason (e.g. detached worktree quirks, older git version, permissions), the function silently falls back to "non-shallow" behavior (omitting --depth), which changes fetch semantics with zero visibility for wh…

actions/setup/js/generate_git_patch.cjs:129

Detecting shallowness via fs.existsSync(&quot;.git/shallow&quot;) misdiagnoses the real failure: a merge-base can also be unreachable on a fully-fetched-but-still-shallow-graft repo, or fail for reasons unrelated to shallow history (e.g. missing ref), yet this always attributes it to shallowness when the file happens to exist.

<details><summary>💡 Details</summary>

The new fix in checkout_pr_branch.cjs explicitly tries to avoid ever creating .git/shallow when the repo started non-shallow, but any…

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the remaining review feedback on this PR, refresh the branch if GitHub allows it, and then run the pr-finisher skill before handing it back.

Open review feedback to close out (newest first):

  • github-actions changes requested: unify shallow-repository detection with the patch-generation path, add a regression test for the new merge-base error path, and clean up test isolation.
  • github-actions comment: make the fetch-depth diagnostics reflect whether --depth was actually omitted.
  • github-actions comment: add a robust fallback for git rev-parse --is-shallow-repository on older Git versions.

Generated by 👨🍳 PR Sous Chef

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 11.9 AIC · ⌖ 6.9 AIC · ⊞ 8.3K ·
Comment /souschef to run again

Copilot AI and others added 2 commits August 4, 2026 21:17
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the remaining review feedback on this PR, refresh the branch if GitHub allows it, and then run the pr-finisher skill before handing it back.

Open review feedback to close out (newest first):

  • github-actions changes requested: unify shallow-repository detection with the patch-generation path, add a regression test for the new merge-base error path, and clean up test isolation.
  • github-actions comment: the non-exception git rev-parse --is-shallow-repository failure path should emit a warning so diagnostics match the catch path.
  • copilot-pull-request-reviewer: the refs/pull fetch diagnostics should report the resolved fetch mode instead of always claiming a depth value.
  • github-actions comment: add a robust fallback for git rev-parse --is-shallow-repository on older Git versions.

Generated by 👨🍳 PR Sous Chef

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.54 AIC · ⌖ 6.21 AIC · ⊞ 8.3K ·
Comment /souschef to run again

Copilot AI requested a review from gh-aw-bot August 4, 2026 21:29
@pelikhan
pelikhan merged commit 10ccfef into main Aug 4, 2026
@pelikhan
pelikhan deleted the copilot/fix-deep-fetch-issue branch August 4, 2026 21:29
Copilot stopped work on behalf of gh-aw-bot due to an error August 4, 2026 21:29
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.

checkout_pr_branch's --depth=2 fetch re-shallows the repo, breaking create_pull_request patch generation despite checkout.fetch-depth: 0

4 participants