ReviewOS

stacks/uplink

fix(release): four places carry the app version and two already disagree

#29
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Part of #6.

The download subline on the homepage is built from a committed JSON file that the release command writes but never commits, so the site advertises whatever version somebody last remembered to commit by hand. Today that is older than the version package.json says is being built, and nothing anywhere fails to say so.

What is there today

  • package.json#L4 is "0.1.1", bumped in 7f4d3cd. The only published release is v0.1.0, which is also the only tag in the repository.
  • resources/data/release.json#L2 is still "0.1.0". It was committed once, in 4667358, and no commit has touched it since.
  • The homepage imports that file at resources/views/index.stx#L47, builds the download subline from it at resources/views/index.stx#L50 (Version ${release.version}, macOS ${release.minimumMacOS} or later, ...), and renders it under the download button at resources/views/index.stx#L326. The page therefore says version 0.1.0.
  • app/Uplink/service.ts#L56 hardcodes <key>CFBundleShortVersionString</key><string>0.1.0</string> in the Info.plist that buildBundle writes at app/Uplink/service.ts#L98. infoPlist() at app/Uplink/service.ts#L46 takes no arguments, so no caller can pass a version in. That is the from-source bundle, so buddy uplink:install on a tree at 0.1.1 installs a bundle reporting 0.1.0.
  • Two places already do it correctly. app/Desktop/launcher.ts#L46 calls startDesktopAgent({ version: pkg.version }) from the import at app/Desktop/launcher.ts#L18, and app/Commands/Uplink.ts#L191 reads the version out of package.json and passes it to the DMG build as DESKTOP_APP_VERSION at app/Commands/Uplink.ts#L212.
  • The seam is the release path. app/Commands/Uplink.ts#L223 writes resources/data/release.json after the build and before gh release create at app/Commands/Uplink.ts#L229, and never commits it. The comment above it at app/Commands/Uplink.ts#L222 says to commit it, which is a note to the maintainer, not something the command does. The tagged commit never contains its own release metadata, and because release.json is a build input the homepage only changes after a follow up commit and the deploy that CI triggers for main (.github/workflows/deploy.yml#L11).
  • A grep for 0.1.0 across the repository finds exactly two live copies, app/Uplink/service.ts#L56 and resources/data/release.json#L2, both current on main while package.json says 0.1.1.

Proposal

  1. In app/Uplink/service.ts, import package.json the way app/Desktop/launcher.ts#L18 does and interpolate pkg.version into CFBundleShortVersionString at app/Uplink/service.ts#L56. infoPlist() keeps its empty signature, so app/Uplink/service.ts#L98 is unchanged.
  2. In app/Commands/Uplink.ts, stage and commit resources/data/release.json immediately after writing it at line 223, before gh release create at line 229. gh creates the tag from the remote tip, so the commit has to land and be pushed first for the tag to point at a commit whose release.json matches the DMG being uploaded.
  3. Add a check script that reads package.json and resources/data/release.json and exits non zero when the two versions differ. Wire it as a package.json script and run it as a step in the lint job of .github/workflows/ci.yml, which already installs dependencies at .github/workflows/ci.yml#L45 and runs bun buddy lint at .github/workflows/ci.yml#L50.

Requirements

  • package.json#L4 becomes the only version literal in the repository. resources/data/release.json stays committed, because the homepage imports it at build time (resources/views/index.stx#L47), but its version field is generated by the release command and never typed by hand.
  • The bump and the release travel in one commit. The check makes it impossible to bump package.json ahead of a release without regenerating release.json, which is exactly the state that produced today's disagreement. If a bump has to land before the release, the same commit updates release.json.
  • Do not touch the source bundle's identity. app/Uplink/service.ts#L21 keeps com.stacksjs.uplink.source deliberately distinct from the downloadable app's bundle id, for the Full Disk Access reason documented in the comment above it. Only CFBundleShortVersionString changes.
  • The check compares versions only. bytes at app/Commands/Uplink.ts#L225 is the size of the built DMG and cannot be verified in CI without building one, so leave it out of the assertion.
  • The check script is a new file in a directory that does not exist yet. package.json#L76 and package.json#L82 already invoke .github/scripts/check-declarations-fresh.ts and .github/scripts/check-lockfile-version.ts, but .github/scripts/ is absent from this repository, so the script cannot assume it is there.

Acceptance

  • A grep for the current version string across app/, resources/ and config/ finds package.json only.
  • buddy uplink:install on a tree at 0.1.1 produces storage/uplink/Uplink.app/Contents/Info.plist with CFBundleShortVersionString 0.1.1.
  • Editing resources/data/release.json to a version other than the one in package.json fails CI in the lint job, with a message naming both values.
  • After a buddy uplink:release run, the tag it created points at a commit that already contains the matching resources/data/release.json, and the homepage shows the new version on the next deploy with no extra commit.

Sign in to comment on this issue.