Skip to content

Give Safari its own build dir and automate the TestFlight release - #1529

Merged
Comp0te merged 6 commits into
developfrom
build/safari-own-build-dir
Aug 27, 2026
Merged

Give Safari its own build dir and automate the TestFlight release#1529
Comp0te merged 6 commits into
developfrom
build/safari-own-build-dir

Conversation

@Comp0te

@Comp0te Comp0te commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

The Safari build shared build/firefox, and the release steps around it were partly manual and partly dead. This branch separates the Safari output, makes the release archives self-describing, and adds the TestFlight step that was missing entirely.

Safari gets its own build dir. buildDir only branched chrome vs everything-else, so a Safari run overwrote the Firefox output with the Safari manifest. The .app step goes with it — the committed xcode-project/ is what builds the app.

Archive names come from package.json. The name carried a hardcoded 2.7.0rc1, so every build:all since the version bump produced a file claiming to be the first release candidate of a version it may no longer have been building. The version now comes from package.json, and the rc number from the archives already sitting in build/.

Store-ready archives for Chrome and Firefox. Uploading used to mean opening the build dir in Finder, selecting its contents and zipping them by hand — the stores want the extension at the zip root, so zipping the folder does not work. build:all now writes those archives directly, without the .DS_Store the Finder visit left behind.

The dead Safari dev-server flow is removed. start:safari invoked ./convert-web-extension.sh, a file that has never existed in this repository. Removing it drops xcode-build-webpack-plugin — unpublished since 2022, and required at the top of webserver.js, so start:chrome and start:firefox were loading it too. Safari development is npm run build:safari plus Run in Xcode; there is no watch mode.

npm run release:safari finishes the job. It builds the web-extension resources, stamps the version into the Xcode project, archives the app and uploads it to App Store Connect. MARKETING_VERSION follows package.json, so bumping the app version is a package.json edit and nothing else. CURRENT_PROJECT_VERSION increments on every upload and is restored again when a run ships nothing, so only a real upload consumes a build number. --no-upload stops at a signed .pkg, which is the way to set up signing on a new machine.

Credentials come from a gitignored .env.release rather than .env, which build_src.sh copies into the source-review package handed to store reviewers — the script refuses to start if it finds them there. That package now excludes .p8 files as well, so the API key may sit in the repo root without riding along.

2.7.0 (160) was archived and uploaded to TestFlight through this path.

The Safari webpack build shared `build/firefox`: `buildDir` only branched
chrome vs everything-else, so a Safari run overwrote the Firefox output with
the Safari manifest, and `cleanUpBuildDir` wiped `build/safari/Casper Wallet`,
a path nothing ever wrote to. The Xcode project read its resources from
`build/firefox` for the same reason.

Safari now builds into `build/safari` and the Xcode project reads from there.
`build:all` covers it, so one run produces every deliverable.

The `.app` was only ever ad-hoc signed — no DEVELOPMENT_TEAM in the project,
and `xcodebuild -alltargets` produces no archive — so it could not go to
TestFlight anyway. It is built and submitted from Xcode instead, and
`build:safari` now mirrors `build:chrome`/`build:firefox`: resources only.
The archive name carried a hardcoded `2.7.0rc1`, so every run of `build:all`
since the 2.7.0 bump has produced a file claiming to be the first release
candidate of a version it may no longer be building.

The version now comes from package.json and the rc number from the archives
already in build/: a version change starts over at rc1, a rebuild of the same
version takes the highest rc there and adds one. Clearing build/ restarts the
count, which is why the zip names the build dirs it wants instead of `./*` —
that glob would have nested every past archive into the new one, and it is
also how Safari stays out: Xcode reads those resources from build/safari and
ships them inside the app, so the store archive has no use for them.
Uploading a build meant opening build/chrome in Finder, selecting its contents
and zipping them by hand — the stores want the extension at the zip root, so
zipping the folder itself does not work.

build:all now writes casper-wallet-{chrome,firefox}-<version>rc<n>#<sha>.zip
next to the bundle, each zipped from inside its build dir. Dotfiles are left
out: the manual route picked up whatever .DS_Store the Finder visit had just
created. The rc counter only ever globs the bundle name, so these do not
advance it.

The web-ext `package:chrome` path stays as it is — the release workflow uploads
its artifact to the Chrome Web Store.
`start:safari` ran `./convert-web-extension.sh`, a file that has never existed
in this repository — the command has been dead since it was written. It was
built around generating a throwaway Xcode project into the Safari build dir
(`ExtensionBuildPath.Safari` used to end in the extension name for exactly
that reason) and rebuilding it from a webpack plugin on every recompile. The
repo has carried a committed `xcode-project/` for a long time instead.

Removing it takes `xcode-build-webpack-plugin` with it — unpublished since
2022, and required at the top of webserver.js, so `start:chrome` and
`start:firefox` were loading it too. Safari development is `npm run
build:safari` plus Run in Xcode; there is no watch mode.
`npm run release:safari` builds the web-extension resources, stamps the version
into the Xcode project, archives the app and uploads it to App Store Connect.
MARKETING_VERSION follows package.json, so bumping the app version is a
package.json edit and nothing else; CURRENT_PROJECT_VERSION increments on every
upload and is restored again when a run ships nothing, so only a real upload
consumes a build number.

Credentials come from a gitignored .env.release rather than .env, which
build_src.sh copies into the source-review package handed to store reviewers —
the script refuses to start if it finds them there. That package now excludes
.p8 files as well, so the API key may sit in the repo root without riding along.
@Comp0te Comp0te self-assigned this Aug 27, 2026
@Comp0te Comp0te added the enhancement New feature or request label Aug 27, 2026
@Comp0te
Comp0te merged commit f8e6b2a into develop Aug 27, 2026
7 checks passed
@Comp0te
Comp0te deleted the build/safari-own-build-dir branch August 27, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant