Skip to content

fix(core): read a commit's parents from the object, not the shallow graft - #375

Closed
gregberge wants to merge 1 commit into
mainfrom
fix/test-merge-parents-on-shallow-clone
Closed

gregberge wants to merge 1 commit into
mainfrom
fix/test-merge-parents-on-shallow-clone

Conversation

@gregberge

@gregberge gregberge commented Sep 7, 2026

Copy link
Copy Markdown
Member

Description

getCommitParents() read the parents with git rev-list --parents, which honours the shallow graft: on the shallow clones CI uses, every commit at the boundary of the fetched history is reported as parentless. That is exactly the commit we ask about — the test-merge commit HEAD sits on — so the answer came from a git fetch --depth=2 origin <sha> instead: once per build, over the network, for a commit the remote has to still be willing to serve.

rev-list --parents  →  751bad91                    (parents hidden by the graft)
cat-file commit     →  parent 46f42167 / 569a5f52  (both there)

The object carries the parent SHAs whatever the graft says, so reading it answers locally. Only the SHAs come back this way — the parent objects can still be absent — which is all the one caller needs, and is now written down in the JSDoc.

With the fetch gone the function is synchronous, and the deepening path it existed for is unreachable anyway: getTestMergeBaseCommitSha only calls it after establishing the commit is HEAD, so its object is always present. An explicit maxBuffer replaces the bound the old command got for free from printing nothing but SHAs.

Reading the object and failing to read it are now reported apart. Both used to log is not a merge commit, which blames the commit's shape for a commit we never managed to look at.

The existing tests build a full local repository, where the parents are readable whatever git is asked, so none of them covered the shallow checkout CI actually uses. The new one does, with the remote pointed at a path that does not exist; it fails without the change.

This is a robustness fix, not the fix for the "older baseline" reports. See below.

Type of changes

bug

Checklist

  • I have read the CONTRIBUTING doc
  • The commits message follows the Conventional Commits' policy
  • Lint and unit tests pass locally
  • I have added tests if needed

Further comments

A console.warn was here and has been dropped

An earlier revision warned when a run on a merge ref could not identify its test merge. A review of it found the trigger was wrong in a way that made it net-negative, so it is gone:

  • checkRunsOnMergeRef inspected GITHUB_REF, which the runner sets from the trigger, not from what actions/checkout checked out. On a pull_request event that is always refs/pull/<n>/merge, so the predicate reduced to GITHUB_EVENT_NAME === "pull_request" and fired on two fallbacks this file documents as correct: a ref: ${{ github.event.pull_request.head.sha }} checkout, and a configured referenceBranch. The existing tests at github-actions.test.ts:103 and :123 assert those configs are right; they only stayed silent because createContext leaves GITHUB_REF unset, an env real Actions never produces.
  • It was written to stderr while ora owns stderr in cli/src/commands/upload.ts, so it was partially overwritten by the next spinner frame.
  • It printed once per build name (playwright/src/reporter.ts loops upload()), so three times for a three-browser matrix.

The diagnostic intent survives in the debug channel, which is where the per-guard detail already lives. Doing this properly means giving Service.getMergeBaseCommitSha a way to say "this answer is a guess" — its Promise<string | null> cannot — and warning once centrally, which also covers the shared git.ts path that degrades worse (no baseline at all) and silently. That touches types.ts and seven services, so it belongs in its own change.

What the investigation ruled out

Chasing a reported build on a light-app project (GitHub Actions, 24 build names in one monorepo, a push to master every ~2 minutes), against the production database and real runners in argos-ci/argos-test-repository#22:

  • "The closest base branch builds were still running when /baseline was called." No — they had concluded more than five minutes before.
  • "A base-branch push orphans the test-merge commit." No — GitHub does not recompute refs/pull/<n>/merge when the base branch moves. main was advanced and the merge ref was unchanged 15 minutes later.
  • "…and then the SHA can no longer be fetched." No — moving the pull request head does recompute the ref, but GitHub keeps serving the orphaned merge commit: git fetch --depth=2 origin $GITHUB_SHA returned 0 and the resolver still resolved correctly at fetch-depth: 1. fetch-depth is a red herring.
  • Version skew across packages. No — all 23 jobs of the failing run reported @argos-ci/core@6.8.3, with identical baseBranch and baseBranchResolvedFrom.
  • Eligibility flapping. No — zero build_reviews rows on any of the skipped baselines.

The baseline walk is correct: run 34122664365 is textbook, with design-system-kit — the one build name without a build at the nearer commit — correctly falling back further.

The one thing that would settle it

In the failing run, two jobs resolved 400f4496/0344ca3e and the other 21 resolved 65ec16f2, 85 minutes older. Whether that is a bug turns on a single fact the database cannot answer:

git merge-base --is-ancestor a59619df 400f4496
  • Ancestor → those 21 build names had a nearer eligible baseline in their candidate list and should have used it, so getMergeBase() is returning different values for identical inputs in one run.
  • Not an ancestor65ec16f2 was the correct answer, and the complaint is really that in a monorepo a package untouched for 90 minutes legitimately gets a 90-minute-old baseline.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
argos-js-sdk-reference Ready Ready Preview Sep 7, 2026 6:30pm UTC

Request Review

@gregberge gregberge changed the title fix(core): warn instead of silently baselining against the fork point fix(core): read a commit's parents from the object, not the shallow graft Sep 7, 2026
@gregberge
gregberge force-pushed the fix/test-merge-parents-on-shallow-clone branch from 33e19b1 to 30bad01 Compare September 7, 2026 17:18
@gregberge
gregberge requested a review from jsfez September 7, 2026 18:23
…raft

getCommitParents() read the parents with "git rev-list --parents", which honours
the shallow graft: on the shallow clones CI uses, every commit at the boundary
of the fetched history is reported as having no parent. That is exactly the
commit we ask about - the test-merge commit HEAD sits on - so the answer came
from a "git fetch --depth=2 origin <sha>" instead, once per build, over the
network, for a commit the remote has to still be willing to serve.

The commit object carries its parent SHAs whatever the graft says, so reading
the object answers locally and cannot fail on the network, on lock contention,
or on a remote that has stopped advertising the commit. Only the SHAs come back
this way - the parent objects can still be absent - which is all the one caller
needs, and is now written down.

With the fetch gone the function is synchronous, and the deepening path it
existed for is unreachable: getTestMergeBaseCommitSha only calls it after
establishing that the commit is HEAD, so its object is always present. An
explicit maxBuffer replaces the bound the old command got for free from
printing nothing but SHAs.

Reading the object and failing to read it are also reported apart now. Both used
to log "is not a merge commit", which blames the commit's shape for a commit we
never managed to look at.

The existing tests build a full local repository, where the parents are readable
whatever git is asked, so none of them covered the shallow checkout CI actually
uses. The new one does, with the remote pointed at a path that does not exist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gregberge

Copy link
Copy Markdown
Member Author

For the record: the "older baseline" report that started this was not caused by anything in the CLI — see argos-ci/argos#2586. The server sorted baseline candidates by position as text ("10" < "2"), which is invisible below ten candidates and is why every local-git hypothesis here was falsified on real runners.

This PR's change is still worth having on its own terms: reading parents from the commit object removes a per-build network fetch and the graft dependency, and the shallow-checkout path finally has a test. But it should be reviewed as a cleanup, not as a fix for that report — the description already says so, and this confirms it.

@gregberge gregberge closed this Sep 7, 2026
@gregberge
gregberge deleted the fix/test-merge-parents-on-shallow-clone branch September 7, 2026 20:22

This branch was successfully deployed

1 active deployment
Preview 2d598f81 Deployed Sep 7, 2026 by vercel[bot]
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.

2 participants