Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,10 @@ chrome.crx

# env
.env
# App Store Connect credentials for scripts/release_safari.sh — deliberately not
# .env, which build_src.sh ships inside the source-review package
.env.release
# generated by scripts/build_src.sh for reproducible source-review rebuilds
build-hash.json

AuthKey_*.p8
72 changes: 62 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ To open as a tab:

### Load Wallet Extension in Safari

1. Open `build/safari` folder from `builds.zip` or `builds` folder when building from sources.
2. Double click on "Casper Wallet.app" file.
The Safari build is distributed through TestFlight — install it from there,
then follow steps 3-4 below.

To run it from sources instead:

1. Run `npm run build:safari` to produce the web-extension resources in `build/safari`.
2. Open `xcode-project/Casper Wallet/Casper Wallet.xcodeproj` and run the "Casper Wallet" scheme.
3. Follow instructions and enable Casper Wallet in opened Extensions Preferences window.
4. Open Safari and enable unsigned extensions. Extension should be available.

Expand Down Expand Up @@ -102,13 +107,8 @@ Firefox:
npm run start:firefox
```

Safari:

```shell
npm run start:safari
```

You can run all these commands in parallel.
You can run both of these commands in parallel. Safari has no watch mode —
build it with `npm run build:safari` and run the app from Xcode.

### Build deliverable from sources (`build` folder)

Expand All @@ -124,7 +124,7 @@ Firefox:
npm run build:firefox
```

Safari:
Safari (web-extension resources only — see below):

```shell
npm run build:safari
Expand All @@ -136,6 +136,58 @@ All at once:
npm run build:all
```

For Safari both commands stop at the web-extension resources in `build/safari`.
The app around them lives in `xcode-project/Casper Wallet` and is built by
`npm run release:safari` (see below), which reads those resources from
`build/safari` directly — they are not part of the archive below.

`build:all` bundles the Chrome and Firefox builds into
`build/casper-wallet-<version>rc<n>#<sha>.zip`, taking `<version>` from
`package.json`. The rc number restarts at 1 whenever that version changes and
otherwise continues from the highest archive already sitting in `build/` — so
keep the previous archives there if you want the count to carry on.

Alongside it come `build/casper-wallet-chrome-<version>rc<n>#<sha>.zip` and its
`firefox` counterpart, ready to upload to the stores as they are: each holds
the extension at the zip root, which is what the stores expect.

### Safari release to TestFlight

`npm run release:safari` takes the Safari extension the whole way: it rebuilds
`build/safari`, stamps the version into the Xcode project, archives the app and
uploads it to App Store Connect. It needs macOS with Xcode and an App Store
Connect API key, described by a gitignored `.env.release` in the repo root:

```shell
ASC_KEY_PATH=AuthKey_XXXXXXXXXX.p8
ASC_KEY_ID=XXXXXXXXXX
ASC_ISSUER_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ASC_TEAM_ID=XXXXXXXXXX
```

Keep these out of `.env`, which `npm run build:src` copies into the source-review
package — the script refuses to run if it finds `ASC_` values there. Exported
variables win over the file. `ASC_KEY_PATH` is resolved against the repo root and
`.p8` files are excluded from that package, so the key may sit next to it under
its Apple-issued name.

`MARKETING_VERSION` comes from `package.json`, so the app version is bumped by
editing `package.json` and nothing else. `CURRENT_PROJECT_VERSION` is incremented
on every upload, because App Store Connect rejects a build number it has already
seen; the script prints the `git commit` that records it in
`Casper Wallet.xcodeproj/project.pbxproj`. A run that ships nothing — a failure,
or `--no-upload` — restores it instead. `SAFARI_BUILD=<n>` overrides it for one
run.

Signing is left to Xcode's automatic mode, which needs a **Mac Installer
Distribution** certificate in the login keychain to sign the `.pkg`. An API key
with the App Manager or Admin role mints one on demand; otherwise create it once
in the Apple Developer portal. To exercise all of that without sending a build:

```shell
npm run release:safari -- --no-upload
```

### Reproducible builds from the source package

`npm run build:src` produces `build/casper-wallet-src#<sha>.zip`, the package
Expand Down
6 changes: 3 additions & 3 deletions constants.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const { NODE_ENV, BROWSER: browserEnvVar } = require('./utils/env');

const extensionName = 'Casper Wallet';
const buildRootDir = ['test', 'production'].includes(NODE_ENV)
? 'build'
: 'output';

const ExtensionBuildPath = {
Chrome: `${buildRootDir}/chrome`,
Firefox: `${buildRootDir}/firefox`,
Safari: `${buildRootDir}/safari/${extensionName}`
// Web-extension resources only. The Xcode project reads them from here; the
// .app it produces is built and shipped from Xcode, never into this tree.
Safari: `${buildRootDir}/safari`
};

const ManifestPath = {
Expand All @@ -23,7 +24,6 @@ const isFirefox = browserEnvVar && browserEnvVar === 'firefox';

module.exports = {
ExtensionBuildPath,
extensionName,
browserEnvVar,
ManifestPath,
isFirefox,
Expand Down
23 changes: 1 addition & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,22 @@
"build:manifest:v2:safari": "NODE_ENV=production BROWSER=safari HASH=$(git rev-parse HEAD) node utils/build.js",
"build:manifest:v3:chrome": "NODE_ENV=production BROWSER=chrome HASH=$(git rev-parse HEAD) node utils/build.js",
"dev:build:manifest:v2:firefox": "NODE_ENV=development BROWSER=firefox HASH=$(git rev-parse HEAD) node utils/build.js",
"dev:build:manifest:v2:safari": "NODE_ENV=development BROWSER=safari HASH=$(git rev-parse HEAD) node utils/build.js",
"dev:build:manifest:v3:chrome": "NODE_ENV=development BROWSER=chrome HASH=$(git rev-parse HEAD) node utils/build.js",
"build:chrome": "rm -rf ./build/chrome && npm run build:manifest:v3:chrome",
"build:analyze": "ANALYZE=true npm run build:chrome",
"package:chrome": "web-ext --no-config-discovery build -s ./build/chrome --overwrite-dest",
"build:firefox": "rm -rf ./build/firefox && npm run build:manifest:v2:firefox",
"package:firefox": "web-ext --no-config-discovery build -s ./build/firefox --overwrite-dest",
"build:safari": "npm run build:manifest:v2:safari && ./scripts/build_safari.sh",
"build:safari": "rm -rf ./build/safari && npm run build:manifest:v2:safari",
"build:src": "./scripts/build_src.sh",
"build:all": "./scripts/build_all.sh",
"release:safari": "./scripts/release_safari.sh",
"dev:build:chrome": "rm -rf ./output/chrome && npm run dev:build:manifest:v3:chrome",
"dev:build:firefox": "rm -rf ./output/firefox && npm run dev:build:manifest:v2:firefox",
"dev:chrome": "npm run dev:build:chrome && NODE_ENV=development BROWSER=chrome HASH=$(git rev-parse HEAD) PORT=3001 node utils/webserver.js",
"start:chrome": "npm run dev:chrome",
"dev:firefox": "npm run dev:build:firefox && NODE_ENV=development BROWSER=firefox HASH=$(git rev-parse HEAD) PORT=3002 node utils/webserver.js",
"start:firefox": "npm run dev:firefox",
"start:safari": "npm run dev:build:manifest:v2:safari && ./convert-web-extension.sh && NODE_ENV=development BROWSER=safari PORT=3003 node utils/webserver.js",
"format:check": "prettier --check 'src/*.{js,jsx,ts,tsx,json,md}'",
"format:write": "prettier --write 'src/*.{js,jsx,ts,tsx,json,md}'",
"lint": "eslint ./src",
Expand Down Expand Up @@ -198,8 +197,7 @@
"webextension-polyfill": "0.12.0",
"webpack": "^5.109.2",
"webpack-bundle-analyzer": "^5.3.1",
"webpack-dev-server": "^6.0.0",
"xcode-build-webpack-plugin": "^1.0.2"
"webpack-dev-server": "^6.0.0"
},
"lavamoat": {
"allowScripts": {
Expand Down
4 changes: 0 additions & 4 deletions scripts/build-xcode-project.sh

This file was deleted.

50 changes: 49 additions & 1 deletion scripts/build_all.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,51 @@
#!/usr/bin/env bash
set -euo pipefail

cd "$(dirname "${BASH_SOURCE[0]}")/.."

HASH=$(git rev-parse --short HEAD)
VERSION=$(node -p "require('./package.json').version")

# The rc counter runs per version: bumping the version in package.json starts
# over at rc1, a rebuild of the same version continues after the highest
# archive already in build/. Clearing build/ therefore restarts the count.
last_rc=0
for archive in "build/casper-wallet-${VERSION}rc"*"#"*.zip; do
[ -e "$archive" ] || continue
rc=${archive#"build/casper-wallet-${VERSION}rc"}
rc=${rc%%#*}
case $rc in
'' | *[!0-9]*) continue ;;
esac
if [ "$rc" -gt "$last_rc" ]; then
last_rc=$rc
fi
done

RC=$((last_rc + 1))
STAMP="${VERSION}rc${RC}#${HASH}"

npm run build:chrome
npm run build:firefox
npm run build:safari

# Store uploads want the extension at the zip root, so each one is zipped from
# inside its own build dir. Dotfiles are dropped: a Finder visit leaves a
# .DS_Store behind, and the stores flag it.
for target in chrome firefox; do
store_archive="casper-wallet-${target}-${STAMP}.zip"
rm -f "build/$store_archive"
(cd "./build/$target" && zip -qr -X "../$store_archive" . -x '.*' '*/.*')
echo "Store archive: build/$store_archive"
done

# Named explicitly, not `./*`: the archives above and the ones from earlier runs
# live in build/ too, and `./*` would nest all of them into this one. Safari is
# out on purpose — Xcode reads those resources straight from build/safari and
# ships them inside the app.
rm -f "build/casper-wallet-${STAMP}.zip"
(cd ./build && zip -qr "casper-wallet-${STAMP}.zip" chrome firefox)

npm run build:src

npm run build:chrome && npm run build:firefox && cd ./build && zip -r casper-wallet-2.7.0rc1#$HASH.zip ./* && npm run build:src
echo "Archive: build/casper-wallet-${STAMP}.zip"
7 changes: 0 additions & 7 deletions scripts/build_safari.sh

This file was deleted.

5 changes: 4 additions & 1 deletion scripts/build_src.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ trap 'rm -f build-hash.json' EXIT
printf '{\n "commitHash": "%s"\n}\n' "$HASH" > build-hash.json

# `*.*` already covers build-hash.json; naming it keeps the dependency visible.
zip -r "casper-wallet-src#${HASH:0:7}.zip" src scripts utils *.* .env build-hash.json
# It would also sweep up the App Store Connect key that release_safari.sh reads
# from the repo root, and this package goes to store reviewers. Nothing the build
# needs is a .p8, so the exclusion covers the key under any name.
zip -r "casper-wallet-src#${HASH:0:7}.zip" src scripts utils *.* .env build-hash.json -x '*.p8'

mkdir -p build
mv "casper-wallet-src#${HASH:0:7}.zip" build/
6 changes: 3 additions & 3 deletions scripts/create-xcode-project.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Converting Firefox build folder into a Xcode Project
# Firefox extension is built on manifest V2, the same version Safari required
xcrun safari-web-extension-converter ./build/firefox --project-location xcode-project --bundle-identifier software.make.Casper-Wallet --macos-only --no-open --no-prompt
# Converting the Safari build folder into a Xcode Project.
# It carries manifest V2 (src/manifest.v2.safari.json), the version Safari requires.
xcrun safari-web-extension-converter ./build/safari --project-location xcode-project --bundle-identifier software.make.Casper-Wallet --macos-only --no-open --no-prompt
Loading
Loading