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

Merged
juliusmarminge merged 1 commit into
pingdotgg: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 into
pingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format

Conversation

@EfeDurmaz16

@EfeDurmaz16EfeDurmaz16 commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

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:

consthrefChannel=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:

constversionRelease=/\/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' (#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 #2181 currently
cannot update at all, so there is no update-path regression — only
forward progress.
Closes#2181
@coderabbitai

Copy link
Copy Markdown

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-actionsgithub-actionsBot 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

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.

@juliusmarmingejuliusmarminge left a comment

Copy link
Copy Markdown
Member

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:mainApr 19, 2026
10 of 11 checks passed
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 20, 2026
Upstream additions:
- fix(web): restore manual sort drag and keep per-group expand state (pingdotgg#2221)
- fix: Change right panel sheet to be below title bar / action bar (pingdotgg#2224)
- Refactor OpenCode lifecycle and structured output handling (pingdotgg#2218)
- effect-codex-app-server (pingdotgg#1942)
- Redesign model picker with favorites and search (pingdotgg#2153)
- fix(server): prevent probeClaudeCapabilities from wasting API requests (pingdotgg#2192)
- fix(server): handle OpenCode text response format in commit message gen (pingdotgg#2202)
- Devcontainer / IDE updates (pingdotgg#2208)
- Expand leading ~ in Codex home paths before exporting CODEX_HOME (pingdotgg#2210)
- fix(release): use v<semver> tag format for nightly releases (pingdotgg#2186)
Fork adaptations:
- Took upstream's redesigned model picker with favorites and search
- Removed deleted codexAppServerManager (replaced by effect-codex-app-server)
- Stubbed fetchCodexUsage (manager-based readout no longer available)
- Extended PROVIDER_ICON_BY_PROVIDER for all 8 fork providers
- Extended modelOptionsByProvider test fixtures for all 8 providers
- Inline ClaudeSlashCommand type (not yet re-exported from SDK)
- Updated SettingsPanels imports for new picker module structure
- Preserved fork's CI customizations (ubuntu-24.04 not Blacksmith)
fav-devs pushed a commit to fav-devs/fdcode that referenced this pull request Apr 21, 2026
MuneerAhmed03 pushed a commit to MuneerAhmed03/t3code that referenced this pull request Apr 26, 2026
Morphexe pushed a commit to Morphexe/t3code that referenced this pull request May 4, 2026
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S10-29 changed lines (additions + deletions).vouch:unvouchedPR 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

@EfeDurmaz16@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

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

Merged
juliusmarminge merged 1 commit into
pingdotgg: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 into
pingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format

Conversation

@EfeDurmaz16

@EfeDurmaz16EfeDurmaz16 commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

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:

consthrefChannel=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:

constversionRelease=/\/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' (#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 #2181 currently
cannot update at all, so there is no update-path regression — only
forward progress.
Closes#2181
@coderabbitai

Copy link
Copy Markdown

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-actionsgithub-actionsBot 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

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.

@juliusmarmingejuliusmarminge left a comment

Copy link
Copy Markdown
Member

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:mainApr 19, 2026
10 of 11 checks passed
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 20, 2026
Upstream additions:
- fix(web): restore manual sort drag and keep per-group expand state (pingdotgg#2221)
- fix: Change right panel sheet to be below title bar / action bar (pingdotgg#2224)
- Refactor OpenCode lifecycle and structured output handling (pingdotgg#2218)
- effect-codex-app-server (pingdotgg#1942)
- Redesign model picker with favorites and search (pingdotgg#2153)
- fix(server): prevent probeClaudeCapabilities from wasting API requests (pingdotgg#2192)
- fix(server): handle OpenCode text response format in commit message gen (pingdotgg#2202)
- Devcontainer / IDE updates (pingdotgg#2208)
- Expand leading ~ in Codex home paths before exporting CODEX_HOME (pingdotgg#2210)
- fix(release): use v<semver> tag format for nightly releases (pingdotgg#2186)
Fork adaptations:
- Took upstream's redesigned model picker with favorites and search
- Removed deleted codexAppServerManager (replaced by effect-codex-app-server)
- Stubbed fetchCodexUsage (manager-based readout no longer available)
- Extended PROVIDER_ICON_BY_PROVIDER for all 8 fork providers
- Extended modelOptionsByProvider test fixtures for all 8 providers
- Inline ClaudeSlashCommand type (not yet re-exported from SDK)
- Updated SettingsPanels imports for new picker module structure
- Preserved fork's CI customizations (ubuntu-24.04 not Blacksmith)
fav-devs pushed a commit to fav-devs/fdcode that referenced this pull request Apr 21, 2026
MuneerAhmed03 pushed a commit to MuneerAhmed03/t3code that referenced this pull request Apr 26, 2026
Morphexe pushed a commit to Morphexe/t3code that referenced this pull request May 4, 2026
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S10-29 changed lines (additions + deletions).vouch:unvouchedPR 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

@EfeDurmaz16@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Merged
juliusmarminge merged 1 commit into
pingdotgg: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 into
pingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format

Conversation

@EfeDurmaz16

@EfeDurmaz16EfeDurmaz16 commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

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:

consthrefChannel=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:

constversionRelease=/\/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' (#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 #2181 currently
cannot update at all, so there is no update-path regression — only
forward progress.
Closes#2181
@coderabbitai

Copy link
Copy Markdown

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-actionsgithub-actionsBot 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

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.

@juliusmarmingejuliusmarminge left a comment

Copy link
Copy Markdown
Member

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:mainApr 19, 2026
10 of 11 checks passed
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 20, 2026
Upstream additions:
- fix(web): restore manual sort drag and keep per-group expand state (pingdotgg#2221)
- fix: Change right panel sheet to be below title bar / action bar (pingdotgg#2224)
- Refactor OpenCode lifecycle and structured output handling (pingdotgg#2218)
- effect-codex-app-server (pingdotgg#1942)
- Redesign model picker with favorites and search (pingdotgg#2153)
- fix(server): prevent probeClaudeCapabilities from wasting API requests (pingdotgg#2192)
- fix(server): handle OpenCode text response format in commit message gen (pingdotgg#2202)
- Devcontainer / IDE updates (pingdotgg#2208)
- Expand leading ~ in Codex home paths before exporting CODEX_HOME (pingdotgg#2210)
- fix(release): use v<semver> tag format for nightly releases (pingdotgg#2186)
Fork adaptations:
- Took upstream's redesigned model picker with favorites and search
- Removed deleted codexAppServerManager (replaced by effect-codex-app-server)
- Stubbed fetchCodexUsage (manager-based readout no longer available)
- Extended PROVIDER_ICON_BY_PROVIDER for all 8 fork providers
- Extended modelOptionsByProvider test fixtures for all 8 providers
- Inline ClaudeSlashCommand type (not yet re-exported from SDK)
- Updated SettingsPanels imports for new picker module structure
- Preserved fork's CI customizations (ubuntu-24.04 not Blacksmith)
fav-devs pushed a commit to fav-devs/fdcode that referenced this pull request Apr 21, 2026
MuneerAhmed03 pushed a commit to MuneerAhmed03/t3code that referenced this pull request Apr 26, 2026
Morphexe pushed a commit to Morphexe/t3code that referenced this pull request May 4, 2026
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S10-29 changed lines (additions + deletions).vouch:unvouchedPR 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

@EfeDurmaz16@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Merged
juliusmarminge merged 1 commit into
pingdotgg: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 into
pingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format

Conversation

@EfeDurmaz16

@EfeDurmaz16EfeDurmaz16 commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

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:

consthrefChannel=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:

constversionRelease=/\/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' (#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 #2181 currently
cannot update at all, so there is no update-path regression — only
forward progress.
Closes#2181
@coderabbitai

Copy link
Copy Markdown

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-actionsgithub-actionsBot 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

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.

@juliusmarmingejuliusmarminge left a comment

Copy link
Copy Markdown
Member

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:mainApr 19, 2026
10 of 11 checks passed
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 20, 2026
Upstream additions:
- fix(web): restore manual sort drag and keep per-group expand state (pingdotgg#2221)
- fix: Change right panel sheet to be below title bar / action bar (pingdotgg#2224)
- Refactor OpenCode lifecycle and structured output handling (pingdotgg#2218)
- effect-codex-app-server (pingdotgg#1942)
- Redesign model picker with favorites and search (pingdotgg#2153)
- fix(server): prevent probeClaudeCapabilities from wasting API requests (pingdotgg#2192)
- fix(server): handle OpenCode text response format in commit message gen (pingdotgg#2202)
- Devcontainer / IDE updates (pingdotgg#2208)
- Expand leading ~ in Codex home paths before exporting CODEX_HOME (pingdotgg#2210)
- fix(release): use v<semver> tag format for nightly releases (pingdotgg#2186)
Fork adaptations:
- Took upstream's redesigned model picker with favorites and search
- Removed deleted codexAppServerManager (replaced by effect-codex-app-server)
- Stubbed fetchCodexUsage (manager-based readout no longer available)
- Extended PROVIDER_ICON_BY_PROVIDER for all 8 fork providers
- Extended modelOptionsByProvider test fixtures for all 8 providers
- Inline ClaudeSlashCommand type (not yet re-exported from SDK)
- Updated SettingsPanels imports for new picker module structure
- Preserved fork's CI customizations (ubuntu-24.04 not Blacksmith)
fav-devs pushed a commit to fav-devs/fdcode that referenced this pull request Apr 21, 2026
MuneerAhmed03 pushed a commit to MuneerAhmed03/t3code that referenced this pull request Apr 26, 2026
Morphexe pushed a commit to Morphexe/t3code that referenced this pull request May 4, 2026
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S10-29 changed lines (additions + deletions).vouch:unvouchedPR 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

@EfeDurmaz16@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

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

Merged
juliusmarminge merged 1 commit into
pingdotgg: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 into
pingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format

Conversation

@EfeDurmaz16

@EfeDurmaz16EfeDurmaz16 commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

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:

consthrefChannel=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:

constversionRelease=/\/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' (#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 #2181 currently
cannot update at all, so there is no update-path regression — only
forward progress.
Closes#2181
@coderabbitai

Copy link
Copy Markdown

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-actionsgithub-actionsBot 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

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.

@juliusmarmingejuliusmarminge left a comment

Copy link
Copy Markdown
Member

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:mainApr 19, 2026
10 of 11 checks passed
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 20, 2026
Upstream additions:
- fix(web): restore manual sort drag and keep per-group expand state (pingdotgg#2221)
- fix: Change right panel sheet to be below title bar / action bar (pingdotgg#2224)
- Refactor OpenCode lifecycle and structured output handling (pingdotgg#2218)
- effect-codex-app-server (pingdotgg#1942)
- Redesign model picker with favorites and search (pingdotgg#2153)
- fix(server): prevent probeClaudeCapabilities from wasting API requests (pingdotgg#2192)
- fix(server): handle OpenCode text response format in commit message gen (pingdotgg#2202)
- Devcontainer / IDE updates (pingdotgg#2208)
- Expand leading ~ in Codex home paths before exporting CODEX_HOME (pingdotgg#2210)
- fix(release): use v<semver> tag format for nightly releases (pingdotgg#2186)
Fork adaptations:
- Took upstream's redesigned model picker with favorites and search
- Removed deleted codexAppServerManager (replaced by effect-codex-app-server)
- Stubbed fetchCodexUsage (manager-based readout no longer available)
- Extended PROVIDER_ICON_BY_PROVIDER for all 8 fork providers
- Extended modelOptionsByProvider test fixtures for all 8 providers
- Inline ClaudeSlashCommand type (not yet re-exported from SDK)
- Updated SettingsPanels imports for new picker module structure
- Preserved fork's CI customizations (ubuntu-24.04 not Blacksmith)
fav-devs pushed a commit to fav-devs/fdcode that referenced this pull request Apr 21, 2026
MuneerAhmed03 pushed a commit to MuneerAhmed03/t3code that referenced this pull request Apr 26, 2026
Morphexe pushed a commit to Morphexe/t3code that referenced this pull request May 4, 2026
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S10-29 changed lines (additions + deletions).vouch:unvouchedPR 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

@EfeDurmaz16@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Merged
juliusmarminge merged 1 commit into
pingdotgg: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 into
pingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format

Conversation

@EfeDurmaz16

@EfeDurmaz16EfeDurmaz16 commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

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:

consthrefChannel=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:

constversionRelease=/\/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' (#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 #2181 currently
cannot update at all, so there is no update-path regression — only
forward progress.
Closes#2181
@coderabbitai

Copy link
Copy Markdown

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-actionsgithub-actionsBot 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

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.

@juliusmarmingejuliusmarminge left a comment

Copy link
Copy Markdown
Member

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:mainApr 19, 2026
10 of 11 checks passed
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 20, 2026
Upstream additions:
- fix(web): restore manual sort drag and keep per-group expand state (pingdotgg#2221)
- fix: Change right panel sheet to be below title bar / action bar (pingdotgg#2224)
- Refactor OpenCode lifecycle and structured output handling (pingdotgg#2218)
- effect-codex-app-server (pingdotgg#1942)
- Redesign model picker with favorites and search (pingdotgg#2153)
- fix(server): prevent probeClaudeCapabilities from wasting API requests (pingdotgg#2192)
- fix(server): handle OpenCode text response format in commit message gen (pingdotgg#2202)
- Devcontainer / IDE updates (pingdotgg#2208)
- Expand leading ~ in Codex home paths before exporting CODEX_HOME (pingdotgg#2210)
- fix(release): use v<semver> tag format for nightly releases (pingdotgg#2186)
Fork adaptations:
- Took upstream's redesigned model picker with favorites and search
- Removed deleted codexAppServerManager (replaced by effect-codex-app-server)
- Stubbed fetchCodexUsage (manager-based readout no longer available)
- Extended PROVIDER_ICON_BY_PROVIDER for all 8 fork providers
- Extended modelOptionsByProvider test fixtures for all 8 providers
- Inline ClaudeSlashCommand type (not yet re-exported from SDK)
- Updated SettingsPanels imports for new picker module structure
- Preserved fork's CI customizations (ubuntu-24.04 not Blacksmith)
fav-devs pushed a commit to fav-devs/fdcode that referenced this pull request Apr 21, 2026
MuneerAhmed03 pushed a commit to MuneerAhmed03/t3code that referenced this pull request Apr 26, 2026
Morphexe pushed a commit to Morphexe/t3code that referenced this pull request May 4, 2026
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S10-29 changed lines (additions + deletions).vouch:unvouchedPR 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

@EfeDurmaz16@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Merged
juliusmarminge merged 1 commit into
pingdotgg: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 into
pingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format

Conversation

@EfeDurmaz16

@EfeDurmaz16EfeDurmaz16 commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

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:

consthrefChannel=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:

constversionRelease=/\/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' (#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 #2181 currently
cannot update at all, so there is no update-path regression — only
forward progress.
Closes#2181
@coderabbitai

Copy link
Copy Markdown

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-actionsgithub-actionsBot 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

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.

@juliusmarmingejuliusmarminge left a comment

Copy link
Copy Markdown
Member

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:mainApr 19, 2026
10 of 11 checks passed
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 20, 2026
Upstream additions:
- fix(web): restore manual sort drag and keep per-group expand state (pingdotgg#2221)
- fix: Change right panel sheet to be below title bar / action bar (pingdotgg#2224)
- Refactor OpenCode lifecycle and structured output handling (pingdotgg#2218)
- effect-codex-app-server (pingdotgg#1942)
- Redesign model picker with favorites and search (pingdotgg#2153)
- fix(server): prevent probeClaudeCapabilities from wasting API requests (pingdotgg#2192)
- fix(server): handle OpenCode text response format in commit message gen (pingdotgg#2202)
- Devcontainer / IDE updates (pingdotgg#2208)
- Expand leading ~ in Codex home paths before exporting CODEX_HOME (pingdotgg#2210)
- fix(release): use v<semver> tag format for nightly releases (pingdotgg#2186)
Fork adaptations:
- Took upstream's redesigned model picker with favorites and search
- Removed deleted codexAppServerManager (replaced by effect-codex-app-server)
- Stubbed fetchCodexUsage (manager-based readout no longer available)
- Extended PROVIDER_ICON_BY_PROVIDER for all 8 fork providers
- Extended modelOptionsByProvider test fixtures for all 8 providers
- Inline ClaudeSlashCommand type (not yet re-exported from SDK)
- Updated SettingsPanels imports for new picker module structure
- Preserved fork's CI customizations (ubuntu-24.04 not Blacksmith)
fav-devs pushed a commit to fav-devs/fdcode that referenced this pull request Apr 21, 2026
MuneerAhmed03 pushed a commit to MuneerAhmed03/t3code that referenced this pull request Apr 26, 2026
Morphexe pushed a commit to Morphexe/t3code that referenced this pull request May 4, 2026
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S10-29 changed lines (additions + deletions).vouch:unvouchedPR 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

@EfeDurmaz16@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

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

Merged
juliusmarminge merged 1 commit into
pingdotgg: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 into
pingdotgg:mainfrom
EfeDurmaz16:fix/nightly-updater-tag-format

Conversation

@EfeDurmaz16

@EfeDurmaz16EfeDurmaz16 commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

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:

consthrefChannel=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:

constversionRelease=/\/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' (#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 #2181 currently
cannot update at all, so there is no update-path regression — only
forward progress.
Closes#2181
@coderabbitai

Copy link
Copy Markdown

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-actionsgithub-actionsBot 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

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.

@juliusmarmingejuliusmarminge left a comment

Copy link
Copy Markdown
Member

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:mainApr 19, 2026
10 of 11 checks passed
aaditagrawal added a commit to aaditagrawal/t3code that referenced this pull request Apr 20, 2026
Upstream additions:
- fix(web): restore manual sort drag and keep per-group expand state (pingdotgg#2221)
- fix: Change right panel sheet to be below title bar / action bar (pingdotgg#2224)
- Refactor OpenCode lifecycle and structured output handling (pingdotgg#2218)
- effect-codex-app-server (pingdotgg#1942)
- Redesign model picker with favorites and search (pingdotgg#2153)
- fix(server): prevent probeClaudeCapabilities from wasting API requests (pingdotgg#2192)
- fix(server): handle OpenCode text response format in commit message gen (pingdotgg#2202)
- Devcontainer / IDE updates (pingdotgg#2208)
- Expand leading ~ in Codex home paths before exporting CODEX_HOME (pingdotgg#2210)
- fix(release): use v<semver> tag format for nightly releases (pingdotgg#2186)
Fork adaptations:
- Took upstream's redesigned model picker with favorites and search
- Removed deleted codexAppServerManager (replaced by effect-codex-app-server)
- Stubbed fetchCodexUsage (manager-based readout no longer available)
- Extended PROVIDER_ICON_BY_PROVIDER for all 8 fork providers
- Extended modelOptionsByProvider test fixtures for all 8 providers
- Inline ClaudeSlashCommand type (not yet re-exported from SDK)
- Updated SettingsPanels imports for new picker module structure
- Preserved fork's CI customizations (ubuntu-24.04 not Blacksmith)
fav-devs pushed a commit to fav-devs/fdcode that referenced this pull request Apr 21, 2026
MuneerAhmed03 pushed a commit to MuneerAhmed03/t3code that referenced this pull request Apr 26, 2026
Morphexe pushed a commit to Morphexe/t3code that referenced this pull request May 4, 2026
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S10-29 changed lines (additions + deletions).vouch:unvouchedPR 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

@EfeDurmaz16@juliusmarminge