Skip to content

Correctly set base sha when multiple releases are in progress#63

Open
RomainCscn wants to merge 3 commits intoromain/lin-69346-github-release-action-misses-issues-merged-into-releasefrom
romain/lin-69484-ci-release-sync-can-pick-a-wrong-base-sha-when-multiple
Open

Correctly set base sha when multiple releases are in progress#63
RomainCscn wants to merge 3 commits intoromain/lin-69346-github-release-action-misses-issues-merged-into-releasefrom
romain/lin-69484-ci-release-sync-can-pick-a-wrong-base-sha-when-multiple

Conversation

@RomainCscn
Copy link
Copy Markdown
Collaborator

@RomainCscn RomainCscn commented May 7, 2026

Summary

On every sync, the CLI picks a "starting point" SHA from the API and uses it as the base for git log <base>..<HEAD>. Today the CLI trusts whatever the API returns, even when that SHA isn't on the build commit's branch ; leading to wrong ranges and re-attached issues. This PR has the CLI walk a list of recent release candidates and pick the first one that's actually an ancestor of HEAD.

Before

When a pipeline has multiple in-progress releases (concurrent trains, hotfixes, freshly-created rows), the API can't tell which release CI is asking about. It returns one based on a SQL heuristic. When that pick is wrong, the CLI scans a nonsensical commit range and either re-attaches issues that already shipped via a different release, or under-covers commits that should belong to the new release.

The fix

  • API (must ship first): https://github.com/linear/linear-app/pull/73464 adds recentReleasesByAccessKey returning a list of recent releases, ordered by the same heuristic.
  • CLI (this PR): replaces "trust the API's first answer" with "walk the list and ask git which one is actually reachable from HEAD." First ancestor from the API wins; otherwise fall back to scanning only the current commit.

Examples of bugs fixed by this + what doesn't change

1. Hotfix on a side branch

main:     A ─ B ─ C(1.71.0) ─ D   ← CI building 1.72.0
              ╲
hotfix:        H1 ─ H2(1.70.1)

API picks 1.70.1 (most recent createdAt). Its SHA H2 is on the side branch. CLI walks H2..D → scans B, C, D — everything 1.71.0 already shipped. Already-shipped issues re-attached to 1.72.0.

2. Mirror — CI on the hotfix branch

Same topology, CI now building 1.70.2 from the hotfix branch tip. API picks 1.71.0; its SHA is on main, not on the hotfix branch. CLI walks main-SHA..hotfix-HEAD → scans every commit on the hotfix branch. Issues already shipped via 1.70.1 re-attached.

3. Stale or orphaned commitSha

A release's stored SHA no longer exists on any branch (force-pushed trunk, manual edit, etc.). API still returns it. CLI walks from an orphan SHA → wrong range or error.

4. Newly created release with commitSha = null

User clicks "Create release" in the UI. Row exists with no SHA yet. API returns it as latest. CLI sees null, falls through to "scan current commit only." Misses everything between the previous release and HEAD.

What doesn't change

Situation Behavior
Single train, no concurrency identical to today
First-ever sync (empty pipeline) identical to today
Incremental re-sync at a newer commit identical to today

The walk only adds an is-ancestor check. A check can reject wrong answers; it can't turn a right answer into a wrong one.


Verification

  • Unit tests cover all four cases plus baseline + first-sync (src/base-sha.test.ts, 8 scenarios) plus an integration test that runs findBaseShagetCommitContextsBetweenShasscanCommits against a real git topology.
  • End-to-end: ran the production-built CLI binary against a real local Linear API instance, four scenarios on main vs the fix branch — three bugs reproduced on main, all fixed, baseline unchanged.

Stacked on #62.

@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 7, 2026

LIN-69484

@RomainCscn RomainCscn requested a review from axelniklasson May 7, 2026 15:29
RomainCscn added 3 commits May 7, 2026 16:57
Wraps `git merge-base --is-ancestor` for the upcoming base-SHA walk.
A candidate SHA on a side branch isn't reachable from the main-train
HEAD, so the walk needs this primitive to skip it.
Pure helper that picks a base SHA from a list of candidate releases by
asking git which one is reachable from HEAD. Tests cover the four bug
shapes (concurrent trains, mirror, all-non-ancestors, null commitSha)
plus baseline + first-sync, and an end-to-end pairing with
getCommitContextsBetweenShas that turns the LIN-69430 bug into a
concrete reproduction.
Replace `getLatestRelease` + verbatim-trust logic with
`recentReleasesByAccessKey` (limit pinned at 20 via a GraphQL variable)
and let findBaseSha pick the first ancestor of HEAD. Falls back to the
existing first-sync boundary when no candidate matches; surface that
fall-through at warn level when the candidate list was non-empty so the
case shows up in CI logs.
@RomainCscn RomainCscn force-pushed the romain/lin-69484-ci-release-sync-can-pick-a-wrong-base-sha-when-multiple branch from 7130412 to 85f286b Compare May 7, 2026 16:01
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.

1 participant