Skip to content

fix(linear-release-sync): pick previous tag by semver, not creation date#142

Merged
Piotr1215 merged 1 commit into
mainfrom
devops-874/fix-prev-tag-semver-order
May 11, 2026
Merged

fix(linear-release-sync): pick previous tag by semver, not creation date#142
Piotr1215 merged 1 commit into
mainfrom
devops-874/fix-prev-tag-semver-order

Conversation

@Piotr1215
Copy link
Copy Markdown
Contributor

Summary

Fixes DEVOPS-874 — the action posts spurious "Now available in stable release vX.Y.Z" comments on Linear issues that already shipped on an earlier patch of the same release line.

Root cause: LatestStableSemverRange paginated GitHub releases in CREATED_AT DESC order and returned the first release matching the semver constraint. For repos that maintain multiple stable lines in parallel (loft-sh/loft: 4.5.x / 4.6.x / 4.7.x / 4.8.x), a patch on an older minor cut shortly before a patch on a newer minor would win the lookup.

Concrete trigger from the loft release timeline:

  • v4.6.3 published 2026-04-28 22:03Z
  • v4.8.2 published 2026-04-28 22:05Z

LastStableReleaseBeforeTag(v4.8.2) returned v4.6.3 instead of v4.8.1. FetchAllPRsBetween(v4.6.3, v4.8.2) then included every commit unique to the 4.8 line — pulling in 4.8.0/4.8.1 PRs. ENGUI-494 (shipped in v4.8.0) was in that set, was already in Released state, had no "Now available in stable release v4.8.2" comment yet (dedup is per-tag), so the action posted one.

Strict-filtering does not mitigate this — the 4.8.0 PR was merged long before v4.8.2's PublishedAt, so it passes the time filter.

Key Changes

  • LatestStableSemverRange now collects every release matching the constraint across all pages and returns the highest by semver comparison, instead of returning the first creation-date match.
  • Added regression test TestLastStableReleaseBeforeTag_PrefersSemverOverCreationDate that pins the loft-sh/loft scenario (v4.6.3 ahead of v4.8.1 in CREATED_AT order, but v4.8.1 is the correct predecessor of v4.8.2).
  • Added TestLatestStableSemverRange_HighestSemverAcrossPages covering the case where the semver winner is on a later page than a non-winning match.

Dependencies

None. Existing tests continue to pass (TestLatestStableSemverRange_Pagination, TestLatestStableSemverRange_NoMatch, etc.).

TODO

  • Merge
  • Cut a new linear-release-sync/v1 binary (workflow_dispatch on release-linear-release-sync.yaml) so the loft release workflow picks up the fix on the next stable release
  • Decide separately whether to retroactively suppress / amend the wrongly posted comments from the v4.8.2 run (not in scope here)

Closes DEVOPS-874

LatestStableSemverRange iterates GitHub releases in CREATED_AT DESC order and
returned the first one matching the semver constraint. For loft-sh/loft —
which maintains 4.5.x, 4.6.x, 4.7.x, 4.8.x stable lines in parallel — a patch
on an older minor cut shortly before a patch on a newer minor wins the
lookup. v4.6.3 was tagged two minutes before v4.8.2 on 2026-04-28, so
LastStableReleaseBeforeTag(v4.8.2) returned v4.6.3. compare(v4.6.3..v4.8.2)
then spanned the wrong git ancestry and dragged 4.8.0/4.8.1 PRs into the
4.8.2 sync run, posting spurious "Now available in stable release v4.8.2"
comments on issues that already shipped one or more patches ago (ENGUI-494
was the trigger).

Collect every match across pagination and return the highest semver. The
per-tag dedup guard in MoveIssueToState stays as-is — once the compare range
is correct, no historical PRs reach it.

Closes DEVOPS-874
@Piotr1215 Piotr1215 merged commit 2931093 into main May 11, 2026
4 checks passed
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