diff --git a/.github/workflows/desktop-macos.yml b/.github/workflows/desktop-macos.yml new file mode 100644 index 0000000..ba61252 --- /dev/null +++ b/.github/workflows/desktop-macos.yml @@ -0,0 +1,77 @@ +# macOS builds of the Pithos desktop app. Windows and Linux are built on +# those systems directly; this runs on a GitHub-hosted Mac because macOS +# packages can only be made on macOS. Builds are ad-hoc signed (no Apple +# Developer ID), so Apple Silicon runs them and Gatekeeper asks once. +name: desktop-macos + +on: + workflow_dispatch: + push: + tags: ['v*'] + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - arch: arm64 + runner: macos-14 + - arch: x64 + runner: macos-13 + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Install + run: npm ci --no-audit --no-fund + + - name: Tests + run: npm test + + - name: Build + env: + CSC_IDENTITY_AUTO_DISCOVERY: 'false' + run: npx electron-builder --mac dmg zip --${{ matrix.arch }} --publish never + + # The packaged server starts, installs the pinned macOS s3d (checksum + # checked) and runs it, and the bundled pty spawns: what a first run needs. + - name: Smoke test the packaged app + run: | + APP=$(ls -d dist/desktop/mac*/Pithos.app | head -1) + codesign --verify --deep --strict "$APP" && echo "signature ok" + cat > smoke.mjs <<'JS' + const asar = process.argv[2]; + const { createPithos } = await import(`file://${asar}/core/server.js`); + const { installS3d } = await import(`file://${asar}/core/binary.js`); + const { execFileSync } = await import('node:child_process'); + const os = await import('node:os'); + const p = await createPithos({ host: '127.0.0.1', port: 0, hostName: 'desktop', binDir: os.tmpdir() + '/pithos-bin' }); + console.log('server up', new URL(p.url).host); + const bin = await installS3d(os.tmpdir() + '/pithos-bin'); + console.log(execFileSync(bin, ['version'], { encoding: 'utf8' }).split('\n')[0]); + const ptyMod = await import(`file://${asar}.unpacked/node_modules/@lydell/node-pty/lib/index.js`).catch(() => null); + if (ptyMod) { + const pty = ptyMod.default || ptyMod; + const t = pty.spawn('/bin/sh', ['-c', 'echo pty-ok'], {}); + await new Promise((r) => { let o = ''; t.onData((d) => { o += d; }); t.onExit(() => { console.log('pty:', o.trim()); r(); }); }); + } else console.log('pty: loaded on demand'); + await p.close(); + JS + ELECTRON_RUN_AS_NODE=1 "$APP/Contents/MacOS/Pithos" smoke.mjs "$APP/Contents/Resources/app.asar" + + - name: Checksums + run: cd dist/desktop && shasum -a 256 *.dmg *.zip | tee SHA256SUMS-${{ matrix.arch }}.txt + + - uses: actions/upload-artifact@v4 + with: + name: pithos-macos-${{ matrix.arch }} + path: | + dist/desktop/*.dmg + dist/desktop/*.zip + dist/desktop/SHA256SUMS-*.txt + retention-days: 14 diff --git a/package.json b/package.json index c8fcf32..9c31473 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,17 @@ }, "mac": { "icon": "desktop/icons/icon.png", - "category": "public.app-category.utilities" + "category": "public.app-category.utilities", + "target": [ + "dmg", + "zip" + ], + "identity": "-", + "hardenedRuntime": false, + "gatekeeperAssess": false + }, + "dmg": { + "title": "Pithos ${version}" } } }