Skip to content

fix(release): use v<semver> tag format for nightly releases#2186

Merged
juliusmarminge merged 1 commit intopingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format
Apr 19, 2026
Merged

fix(release): use v<semver> tag format for nightly releases#2186
juliusmarminge merged 1 commit intopingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format

Conversation

@EfeDurmaz16
Copy link
Copy Markdown
Contributor

@EfeDurmaz16 EfeDurmaz16 commented Apr 18, 2026

Closes #2181

What

Drop the nightly- prefix from nightly release tags so they become valid semver that electron-updater can parse.

  • Before: nightly-v0.0.21-nightly.20260417.58
  • After: v0.0.21-nightly.20260417.58

Stable tags (v<semver>) are unchanged. Existing nightly-v* tags stay in the repo as inert history — no retagging.

Why

The nightly update track has never actually worked. #2181 reports it, and you can reproduce it on 0.0.20: switch to the Nightly channel → "Check for updates" → Error: No published versions on GitHub.

Root cause is in electron-updater's GitHubProvider, which uses the semver package to parse tags from releases.atom. Two places, same problem:

1. Channel matchingproviders/GitHubProvider.js:68:

const hrefChannel = semver.prerelease(hrefTag)?.[0] || null;

With autoUpdater.channel = 'nightly' and allowPrerelease = true, a release is selected only when hrefChannel === 'nightly'. For that to hold, the tag must be valid semver with a prerelease identifier nightly.

  • semver.prerelease('v0.0.21-nightly.20260417.58')['nightly', '20260417', 58]
  • semver.prerelease('nightly-v0.0.21-nightly.20260417.58')null ❌ (the leading nightly-v breaks semver's grammar, which requires either a digit or an optional v + digit)

So no entry in the atom feed matches and the loop exits with tag == null, throwing No published versions on GitHub.

2. Release notes computationproviders/GitHubProvider.js:189:

const versionRelease = /\/tag\/v?([^/]+)$/.exec(...)[1];
if (semver.valid(versionRelease) && semver.lt(currentVersion, versionRelease)) { ... }

The optional v? strip doesn't help either — the remainder (nightly-v0.0.21-...) still isn't semver.valid(), so nightlies never show up in release notes either.

Fix

The minimal, library-aligned fix: make the tag valid semver. Dropping the nightly- prefix yields v<base>-nightly.<date>.<run>, which:

  • Is semver.valid()
  • Has prerelease identifier nightly — matches autoUpdater.channel = 'nightly'
  • Is ordered correctly relative to stable (0.0.21-nightly.20260417.58 < 0.0.21 < 0.0.22) ✅

Changes

  • scripts/resolve-nightly-release.ts — emit v<version> instead of nightly-v<version>.
  • scripts/resolve-nightly-release.test.ts, scripts/release-smoke.ts — fixtures updated for the new tag.
  • scripts/resolve-previous-release-tag.ts:
    • parseStableTag now rejects tags whose first prerelease identifier is nightly (the new nightly tags also start with v, so the stable resolver has to skip them explicitly).
    • parseNightlyTag accepts both the new v<version> format and the legacy nightly-v<version> format so the "previous nightly" release-note diff keeps working across the transition.
  • .github/workflows/release.yml:
    • last_nightly_tag lookup matches v*-nightly.* in addition to legacy nightly-v*.
    • push.tags trigger excludes v*-nightly.* so creating a new nightly tag doesn't accidentally re-trigger the stable release path.

No runtime code (apps/desktop/*) is touched. No library patches, no workarounds — just aligning the tag we publish with the format electron-updater already expects.

Why not a runtime workaround in main.ts?

I considered a desktop-side workaround (fetch recent releases via GitHub API, pick the latest nightly ourselves, point autoUpdater.setFeedURL at that release as a generic provider). Decided against it because:

  • It creates two parallel update-resolution paths (stable uses GitHubProvider, nightly uses custom logic) that need to stay in sync forever.
  • It commits us to the oddball nightly-v* tag format indefinitely, with client-side logic whose only job is to work around that format.
  • The tag format was introduced 3 days ago in Nightly release channel #2012 and has never worked end-to-end, so "don't break existing behavior" doesn't really apply here.

The tag-format change is 5 files, 15 insertions, 6 deletions — all in release tooling, none in runtime.

Testing

  • bun fmt, bun lint, bun typecheck, bun run test all pass.
  • scripts/resolve-nightly-release.test.ts asserts the new tag shape.
  • Manually ran node scripts/resolve-nightly-release.ts and node scripts/resolve-previous-release-tag.ts for both channels against the current repo tags — previous_tag resolution correctly finds v0.0.19 for stable and the last nightly-v* legacy tag for nightly.
  • End-to-end verification (installing the resulting build and updating) requires the CI pipeline to publish — happy to iterate if you want additional coverage before merge.

Risks / compatibility

  • Old nightly-v* tags: untouched, no rename. They remain in git history and on the Releases page.
  • Users currently on a nightly-v* build: they cannot update today anyway (that's the bug). After this PR the next nightly will be v<semver>, semver.gt picks it up correctly, and they transition forward. No "stuck user" scenario.
  • Stable release flow: unchanged. Stable tags are still v<semver> without a -nightly.* prerelease.
  • push.tags trigger: the added !v*-nightly.* exclusion prevents the stable path from firing when the nightly job creates the new-format tag.

Note

Fix nightly release tag format to use v<semver>-nightly.<date>.<run>

  • Changes resolveNightlyReleaseMetadata in resolve-nightly-release.ts to generate tags as v<semver>-nightly.<date>.<run> instead of nightly-v<semver>-nightly.<date>.<run>.
  • Updates parseNightlyTag in resolve-previous-release-tag.ts to accept both the new v*-nightly.* format and the legacy nightly-v* format.
  • Fixes parseStableTag to exclude nightly-tagged versions from being treated as stable releases.
  • Updates the release workflow to exclude v*-nightly.* tags from triggering the stable release job, and to search both tag formats when finding the last nightly.
  • Behavioral Change: nightly tags created going forward will use the new v*-nightly.* format; old nightly-v* tags remain recognized for backward compatibility.

Macroscope summarized 5a0162d.

Nightly releases were being tagged as 'nightly-v<version>' (e.g.
'nightly-v0.0.21-nightly.20260417.58'). This tag is not valid semver
because the 'nightly-v' prefix does not match semver's leading
(optional 'v' + digit) grammar.

electron-updater's GitHubProvider relies on the 'semver' package in
two places when resolving updates from the releases.atom feed:

  1. Channel matching (providers/GitHubProvider.js:68):
       const hrefChannel = semver.prerelease(hrefTag)?.[0] || null;
     With 'channel = nightly' and allowPrerelease = true, a release is
     only picked when its tag parses as a semver prerelease whose first
     identifier equals 'nightly'. semver.prerelease('nightly-v...') is
     null, so no nightly release ever matches and the updater throws
     'No published versions on GitHub' (pingdotgg#2181).

  2. Release notes (providers/GitHubProvider.js:189):
       const versionRelease = /\/tag\/v?([^/]+)$/.exec(...)[1];
       if (semver.valid(versionRelease) && ...) { ... }
     Same reason: the remainder after stripping an optional 'v' must
     be valid semver, which 'nightly-v...' is not.

Dropping the 'nightly-' prefix yields 'v<base>-nightly.<date>.<run>',
which IS valid semver with prerelease identifier 'nightly' — exactly
the format electron-updater expects for a custom channel. Stable
tags remain 'v<semver>' and are unaffected.

Changes:
- scripts/resolve-nightly-release.ts: emit 'v<version>' instead of
  'nightly-v<version>'.
- scripts/resolve-nightly-release.test.ts,
  scripts/release-smoke.ts: update fixtures for the new tag.
- scripts/resolve-previous-release-tag.ts:
  - parseStableTag now rejects tags whose first prerelease identifier
    is 'nightly' (new nightly tags also start with 'v', so the stable
    resolver has to exclude them explicitly).
  - parseNightlyTag accepts both the new 'v<version>' format and the
    legacy 'nightly-v<version>' format so release-note diffs against
    the last published nightly keep working across the transition.
- .github/workflows/release.yml:
  - last_nightly_tag lookup now matches 'v*-nightly.*' in addition to
    legacy 'nightly-v*'.
  - The push-tags trigger excludes 'v*-nightly.*' so the new nightly
    tags don't accidentally re-trigger the stable release path.

Existing 'nightly-v*' tags stay in the repo as inert history; no
retagging is performed. Nightly users affected by pingdotgg#2181 currently
cannot update at all, so there is no update-path regression — only
forward progress.

Closes pingdotgg#2181
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 18, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2dbcbdef-e22f-40d1-9df4-e2783ac5c7e0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Apr 18, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 18, 2026

Approvability

Verdict: Approved

This PR changes the nightly release tag format from nightly-v<semver> to v<semver>-nightly.* and updates related scripts to handle both formats. The changes are limited to CI/CD release scripts and workflows with no production runtime impact, and include corresponding test updates.

You can customize Macroscope's approvability policy. Learn more.

Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge left a comment

Choose a reason for hiding this comment

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

Thanks

@juliusmarminge juliusmarminge merged commit c83bc5d into pingdotgg:main Apr 19, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Nightly update track not working

2 participants