also looking at this
fix(release): derive the app version instead of copying it
#53
5 files
+73
-2
| @@ -0,0 +1,44 @@ | ||
| 1 | #!/usr/bin/env bun | |
| 2 | import process from 'node:process' | |
| 3 | import { infoPlist } from '../../app/Uplink/service' | |
| 4 | import pkg from '../../package.json' | |
| 5 | import release from '../../resources/data/release.json' | |
| 6 | ||
| 7 | /** | |
| 8 | * The version lives in package.json. Everything else derives it, and this says | |
| 9 | * so out loud in CI. | |
| 10 | * | |
| 11 | * It used to live in four places. Two of them drifted: the homepage advertised | |
| 12 | * 0.1.0 while the tree built 0.1.1, and the bundle `uplink:install` writes | |
| 13 | * reported 0.1.0 whatever it was built from. Nothing failed, because nothing | |
| 14 | * compared them (#29). | |
| 15 | * | |
| 16 | * `release.json` is written and committed by `buddy uplink:release`, so if this | |
| 17 | * fails the usual cause is a version bumped without a release. The homepage is | |
| 18 | * advertising the previous build until one happens, which is worth knowing. | |
| 19 | */ | |
| 20 | ||
| 21 | const problems: string[] = [] | |
| 22 | ||
| 23 | if (release.version !== pkg.version) { | |
| 24 | problems.push( | |
| 25 | `resources/data/release.json says ${release.version}, package.json says ${pkg.version}.`, | |
| 26 | ' The homepage download button reads release.json, so it is advertising a different build.', | |
| 27 | ' `buddy uplink:release` writes and commits that file: run a release, or put the version back.', | |
| 28 | ) | |
| 29 | } | |
| 30 | ||
| 31 | if (!infoPlist().includes(`<string>${pkg.version}</string>`)) { | |
| 32 | problems.push( | |
| 33 | `The Info.plist in app/Uplink/service.ts does not carry ${pkg.version}.`, | |
| 34 | ' It should interpolate pkg.version rather than naming a version of its own.', | |
| 35 | ) | |
| 36 | } | |
| 37 | ||
| 38 | if (problems.length > 0) { | |
| 39 | console.error('The app version is not consistent:\n') | |
| 40 | console.error(problems.join('\n')) | |
| 41 | process.exit(1) | |
| 42 | } | |
| 43 | ||
| 44 | console.log(`Version ${pkg.version} agrees across package.json, release.json and the Info.plist.`) | |
| @@ -50,6 +50,11 @@ jobs: | ||
| 50 | 50 | - name: Lint |
| 51 | 51 | run: bun buddy lint |
| 52 | 52 | |
| 53 | # The version lives in package.json; everything else derives it. Two | |
| 54 | # copies had already drifted before anything compared them (#29). | |
| 55 | - name: Check the app version is consistent | |
| 56 | run: bun run release:check | |
| 57 | ||
| 53 | 58 | typecheck: |
| 54 | 59 | runs-on: ${{ matrix.os }} |
| 55 | 60 | |
| @@ -234,13 +234,27 @@ export default defineCommand((cli) => { | ||
| 234 | 234 | const built = `${appDir}/storage/framework/desktop-dmg/Uplink-${version}.dmg` |
| 235 | 235 | const stable = `${appDir}/storage/framework/desktop-dmg/Uplink.dmg` |
| 236 | 236 | copyFileSync(built, stable) |
| 237 | // The homepage's download button states the version and size; commit this. | |
| 237 | // What the homepage's download button reads. | |
| 238 | 238 | await Bun.write(`${appDir}/resources/data/release.json`, `${JSON.stringify({ |
| 239 | 239 | version, |
| 240 | 240 | bytes: Bun.file(built).size, |
| 241 | 241 | minimumMacOS: '13', |
| 242 | 242 | url: 'https://github.com/stacksjs/uplink/releases/latest/download/Uplink.dmg', |
| 243 | 243 | }, null, 2)}\n`) |
| 244 | ||
| 245 | // Committed and pushed here rather than left as a note to whoever is | |
| 246 | // releasing. `gh` cuts the tag from the remote tip, so this has to land | |
| 247 | // first or the tagged commit does not contain its own release metadata, | |
| 248 | // and the site keeps advertising the previous version until somebody | |
| 249 | // remembers. Skipped when nothing changed, so re-running a release for | |
| 250 | // the same version is not an error. | |
| 251 | const pending = Bun.spawnSync(['git', 'status', '--porcelain', 'resources/data/release.json'], { cwd: appDir }).stdout.toString().trim() | |
| 252 | if (pending) { | |
| 253 | step(['git', 'add', 'resources/data/release.json']) | |
| 254 | step(['git', 'commit', '-m', `chore: Uplink ${version} is out`]) | |
| 255 | step(['git', 'push']) | |
| 256 | } | |
| 257 | ||
| 244 | 258 | step(['gh', 'release', 'create', `v${version}`, stable, built, '--title', `Uplink ${version}`, '--notes', `Uplink ${version} for macOS 13 or later. Signed with a Developer ID and notarized by Apple.`, ...(options.draft ? ['--draft'] : [])]) |
| 245 | 259 | process.exit(0) |
| 246 | 260 | }) |
| @@ -2,6 +2,7 @@ import { existsSync, mkdirSync, rmSync } from 'node:fs' | ||
| 2 | 2 | import { homedir } from 'node:os' |
| 3 | 3 | import { join } from 'node:path' |
| 4 | 4 | import process from 'node:process' |
| 5 | import pkg from '../../package.json' | |
| 5 | 6 | |
| 6 | 7 | /** |
| 7 | 8 | * Installs Uplink as a login item that stays running: an `Uplink.app` bundle |
| @@ -43,6 +44,12 @@ function xml(value: string): string { | ||
| 43 | 44 | return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') |
| 44 | 45 | } |
| 45 | 46 | |
| 47 | /** | |
| 48 | * The bundle `buddy uplink:install` writes, from source. Its version comes from | |
| 49 | * package.json for the same reason the launcher's does: a second copy is a | |
| 50 | * copy that goes stale, and this one had, so an install from a 0.1.4 tree | |
| 51 | * reported itself as 0.1.0 to macOS and to anyone reading Get Info. | |
| 52 | */ | |
| 46 | 53 | export function infoPlist(): string { |
| 47 | 54 | return `<?xml version="1.0" encoding="UTF-8"?> |
| 48 | 55 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| @@ -53,7 +60,7 @@ export function infoPlist(): string { | ||
| 53 | 60 | <key>CFBundleDisplayName</key><string>Uplink (source)</string> |
| 54 | 61 | <key>CFBundleExecutable</key><string>Uplink</string> |
| 55 | 62 | <key>CFBundlePackageType</key><string>APPL</string> |
| 56 | <key>CFBundleShortVersionString</key><string>0.1.0</string> | |
| 63 | <key>CFBundleShortVersionString</key><string>${xml(pkg.version)}</string> | |
| 57 | 64 | <key>CFBundleVersion</key><string>1</string> |
| 58 | 65 | <key>LSUIElement</key><true/> |
| 59 | 66 | <key>LSBackgroundOnly</key><true/> |
| @@ -23,6 +23,7 @@ | ||
| 23 | 23 | "deploy": "./buddy deploy", |
| 24 | 24 | "lint": "./buddy lint", |
| 25 | 25 | "lint:fix": "./buddy lint:fix", |
| 26 | "release:check": "bun .github/scripts/check-release-version.ts", | |
| 26 | 27 | "format": "./buddy format", |
| 27 | 28 | "format:check": "./buddy format:check", |
| 28 | 29 | "serve": "./buddy serve", |