Sign the macOS bundle, or it arrives "damaged"
The first release could not be opened: macOS said "WarpEngine Store is damaged and can't be opened. You should move it to the Bin." Not a wording problem — an integrity one. electron-builder found no signing identity and skipped signing, so the bundle kept only the linker's ad-hoc signature on its main executable, with no resource seal. `codesign --verify` said "code has no resources but signature indicates they must be present", and Gatekeeper reports that as damaged and offers no way past it, unlike an un-notarised app which can at least be approved. `scripts/after-pack.js` now signs the bundle itself during packaging. Measured on a copy unzipped from the artifact with the quarantine flag set by hand: before code has no resources but signature indicates they must be present after valid on disk; satisfies its Designated Requirement and the identifier is ours rather than `Electron`. `syspolicy_check` is down to its expected "adhoc signed" warning. A downloaded copy still has to be approved — that is Gatekeeper policy for anything un-notarised, and notarisation needs a paid Developer ID — so the README and the release notes lead with the one command that does it. Two smaller things the failure turned up: - The self-test was passing silently. With a copy of the app already open, the second process lost the single-instance lock and exited 0 with no output, which reads exactly like success. It now uses its own user-data directory and skips the lock, and it caught a real launch failure immediately afterwards. - The README claimed right-click ▸ Open was enough. It was not, and I had not checked it — replaced with what the measurements support. v1.0.0's attachments are withdrawn rather than left downloadable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -60,6 +60,13 @@ async function guarded (fn) {
|
||||
// would otherwise be noticed: the main process log stays empty.
|
||||
const SELFTEST = process.argv.includes('--selftest')
|
||||
|
||||
// A test run must never be swallowed by a copy the user already has open: it gets
|
||||
// its own user-data directory and skips the single-instance lock. Without this the
|
||||
// second process exits silently with status 0, which reads as a passing test.
|
||||
if (SELFTEST) {
|
||||
app.setPath('userData', path.join(app.getPath('temp'), 'warpstore-gui-selftest'))
|
||||
}
|
||||
|
||||
async function selftest () {
|
||||
const result = await win.webContents.executeJavaScript(`(() => ({
|
||||
cards: document.querySelectorAll('.card').length,
|
||||
@@ -215,7 +222,7 @@ ipcMain.handle('app:openExternal', async (_event, url) => {
|
||||
|
||||
// --- lifecycle ------------------------------------------------------------
|
||||
|
||||
if (!app.requestSingleInstanceLock()) {
|
||||
if (!SELFTEST && !app.requestSingleInstanceLock()) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', () => {
|
||||
|
||||
Reference in New Issue
Block a user