Skip to content

🤖 fix: restore ${os} token in release artifact names - #3927

Open
matifali wants to merge 2 commits into
mainfrom
fix/artifact-name-os-token
Open

🤖 fix: restore ${os} token in release artifact names#3927
matifali wants to merge 2 commits into
mainfrom
fix/artifact-name-os-token

Conversation

@matifali

@matifali matifali commented Aug 22, 2026

Copy link
Copy Markdown
Member

Summary

Restores the ${os} token in build.{mac,linux,win}.artifactName so every published release asset carries a mac/linux/win token in its filename, and updates every in-repo consumer of the old names. Without the token, installers that select release assets by operating system cannot find any xum asset at all.

Background

electron-builder's default artifact pattern is ${productName}-${version}-${arch}-${os}.${ext} (app-builder-lib/out/targets/ArchiveTarget.js). Our override exists to get the lowercase xum- slug instead of the Xum productName, but it also dropped -${os}.

The result is that v0.28.2 published mux-0.28.2-arm64.dmg, mux-0.28.2-arm64.zip, mux-0.28.2-x64.exe, and mux-0.28.2-x86_64.AppImage — not one of which says which OS it is for.

Asset-matching installers filter on an OS token before anything else, so they reject the entire asset list. Concretely, with mise:

$ mise install ubi:coder/xum
could not find a release asset for this OS (macos) from builder-debug.yml,
latest-linux.yml, latest-mac.yml, latest.yml, mux-0.1.0.vsix,
mux-0.28.2-arm64.AppImage, mux-0.28.2-arm64.dmg, mux-0.28.2-arm64.zip, ...

Worse is the silent failure mode: mise install github:coder/xum reports success. The only asset whose name contains an OS-ish token is latest-mac.yml, so mise installs that 785-byte electron-updater manifest and exits 0. The user gets a tool directory containing one YAML file, no binary, and no error. The same class of failure applies to Homebrew and asdf.

Implementation

xum-${version}-${arch}.${ext}xum-${version}-${arch}-${os}.${ext} for all three platforms. ${os} expands to mac/linux/win from platform.buildConfigurationKey, and all targets (ArchiveTarget, DmgTarget, NsisTarget, AppImageTarget) route through the same expandArtifactNamePattern, so dmg/zip/exe/AppImage all pick it up.

The rename has in-repo consumers that hardcode the old suffixes; all are updated here:

Location Was Why it breaks
_desktop-release.yml arm64 AppImage upload release/xum-*-arm64.AppImage unmatched glob fails gh release upload
_desktop-release.yml Linux checksum job --pattern "xum-*-x86_64.AppImage" etc. gh release download errors no assets match the file pattern, before checksums publish
nightly.yml REQUIRED_ASSETS xum-${RELEASE_VERSION}-arm64.AppImage etc. a complete nightly reads as incomplete, gets deleted and rebuilt
pr.yml macOS dmg uploads release/*-x64.dmg, release/*-arm64.dmg if-no-files-found: error fails every macOS CI build after packaging
docs/install.mdx (+ generated skill copy) xum-x.x.x-x64.exe documents a filename that will no longer exist

scripts/create-legacy-mux-artifact-aliases.sh needs no change — it rewrites the xum-/Xum- prefix and passes the remainder through untouched, so mux- aliases keep tracking canonical names. Its test fixtures are updated to realistic post-rename filenames so they actually demonstrate that.

expandArtifactName in productIdentity.test.ts now calls electron-builder's own expandMacro rather than reimplementing the substitution rules, so the test exercises the builder instead of comparing two copies of the same string.

Validation

Verified the fix actually solves the problem end-to-end, rather than assuming it would. I published a scratch GitHub release carrying the post-fix asset names (xum-0.29.0-arm64-mac.zip plus the full set of dmg/blockmap/exe/AppImage/yml siblings, the zip containing only an Xum.app bundle) and pointed mise at it:

$ mise install github:matifali/xum@0.29.0
✓ installed
$ mise x github:matifali/xum@0.29.0 -- xum
xum 0.29.0 (scratch)

mise strips the .app wrapper, installs Contents/MacOS/xum, and the shim runs. No consumer-side options needed — "github:coder/xum" = "latest" is enough. Two things worth recording from that test:

  • The rename alone is what unblocks it. Before adding the OS token, the same install either picks the wrong asset or fails.
  • An .app-only archive is otherwise a hazard for these installers: without a resolvable executable they abort with Is a directory (os error 21). Our bundle layout happens to resolve cleanly.

Confirmed the rewritten test is not tautological — expandMacro throws when the macro is absent, so the assertion has teeth:

cannot expand pattern "xum-${version}-${arch}-${os}.${ext}": macro os is not defined

Locally: bun test src/common/compat src/desktop/updater.test.ts green, make typecheck clean, actionlint clean on all three modified workflows. Grepped for residual old-pattern references and found none.

What this unblocks for users

After this lands, installing xum's CLI via mise is one config line — no asset patterns, no per-user workarounds:

# ~/.config/mise/config.toml
[tools]
"github:coder/xum" = "latest"

mise install, mise up, and version pinning all work from there, and the same applies to any installer that matches release assets by OS token.

To be precise about scope: this gives users the CLI on PATH, not a Finder/Spotlight-registered application. mise installs under ~/.local/share/mise — a hidden directory macOS does not index — and has no concept of an .app bundle; it unpacks ours to bare Contents/MacOS/xum. Anyone wanting the desktop app should still use the dmg. This PR is about making the assets discoverable by tooling, not about making mise a supported install path for the GUI.

Today, with no OS token, neither is possible — github:coder/xum silently installs a YAML manifest and reports success.

Risks

Low, but it touches the release path, so worth being explicit.

Auto-update is unaffected. src/desktop/updater.ts is stock electron-updater with the GitHub provider and never reconstructs asset filenames from a pattern — it reads them out of latest-mac.yml, which electron-builder regenerates with the new names. A client on 0.28.2 reads the new manifest and downloads the new filename. I checked for hardcoded name-building specifically because that would have made this a coordinated change instead of a config one.

Download links change. Anything pinning an exact asset URL for a future release needs updating; already-published assets are untouched.

The residual risk is a hardcoded asset name outside this repo (website, install script, package manifest) that I can't see from here — worth a second pair of eyes. The first review round showed this rename has more consumers than a grep for the obvious prefix turns up.

Note: Pixel / Review fails on this PR and equally on unrelated PR #3926; this change touches no UI.


Generated with Claude Code • Model: claude-opus-5

electron-builder's default artifact pattern includes ${os}; our override
dropped it, so no published asset carries a mac/win/linux token. Installers
that match release assets by OS (mise/ubi, Homebrew, asdf) reject every
asset as a result.

Also update the arm64 AppImage upload glob, which anchored on the old
"-arm64.AppImage" suffix.
@matifali

Copy link
Copy Markdown
Member Author

@codex review

Config-only change to build.{mac,linux,win}.artifactName, restoring the ${os} token that electron-builder includes by default. Worth focusing on:

  • Any hardcoded release-asset filename I missed. I checked the upload globs in _desktop-release.yml, scripts/create-legacy-mux-artifact-aliases.sh (prefix-based, unaffected), and src/desktop/updater.ts (stock electron-updater, reads names from latest-mac.yml).
  • Whether the arm64 AppImage glob change (xum-*-arm64.AppImage -> xum-*-arm64-linux.AppImage) is the right anchor, or whether it should be loosened.
  • Auto-update continuity for clients on 0.28.2 upgrading across the rename.

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7520768a0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread package.json
Comment thread src/common/compat/productIdentity.test.ts
Comment thread package.json
Comment thread package.json
Codex review caught four consumers of the old names that my first grep
missed (it required a `release/` prefix and an `xum-` prefix, so bare
`*-x64.dmg` style globs slipped through):

- _desktop-release.yml: `gh release download --pattern` for the Linux
  checksum job; an unmatched pattern errors out before checksums publish.
- nightly.yml: REQUIRED_ASSETS sentinel list, which would treat a complete
  nightly as incomplete and rebuild it.
- pr.yml: macOS dmg upload globs, which set `if-no-files-found: error`.
- docs/install.mdx (and its generated built-in skill copy): documented
  Windows installer filename.

Also address the tautological-test finding: expandArtifactName now routes
through electron-builder's own expandMacro instead of reimplementing the
substitution rules, so it throws ERR_ELECTRON_BUILDER_MACRO_NOT_DEFINED if
${os} ever stops resolving. Verified it does throw when the macro is absent.

Alias-script fixtures updated to realistic post-rename filenames so they
prove mux-* aliasing still works with the new names.
@matifali

Copy link
Copy Markdown
Member Author

@codex review

Addressed all four findings in 35c0b30 — thanks, the Linux and macOS consumer catches were real misses. My original grep required both a release/ prefix and an xum- prefix, so bare *-x64.dmg style globs never showed up.

  • Linux asset consumers_desktop-release.yml checksum job now downloads *-x86_64-linux.AppImage / *-arm64-linux.AppImage (and the mux- aliases), and nightly.yml REQUIRED_ASSETS carries -linux.
  • macOS CI globspr.yml uploads release/*-x64-mac.dmg and release/*-arm64-mac.dmg.
  • Windows docsdocs/install.mdx and the regenerated builtInSkillContent.generated.ts both say xum-x.x.x-x64-win.exe.
  • Tautological testexpandArtifactName now calls electron-builder's expandMacro instead of reimplementing the substitution. Confirmed it has teeth: dropping the os extra produces cannot expand pattern "xum-${version}-${arch}-${os}.${ext}": macro os is not defined.

Also updated the create-legacy-mux-artifact-aliases fixtures to realistic post-rename filenames, so they demonstrate that prefix-rewriting still produces correct mux- aliases for the new names.

Re-grepped for residual old-pattern references across workflows, scripts, and docs and found none — but given this round, another look for consumers I've still missed would be welcome.

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant