diff --git a/.github/workflows/package-client.yml b/.github/workflows/package-client.yml index 40d4e5423b7..beb99408b67 100644 --- a/.github/workflows/package-client.yml +++ b/.github/workflows/package-client.yml @@ -30,6 +30,20 @@ on: secrets: SENTRY_AUTH_TOKEN: required: true + MACOS_CI_KEYCHAIN_PASSWD: + required: true + MACOS_CERT_PASSWD: + required: true + MACOS_CERT: + required: true + MACOS_CERT_COMMON_NAME: + required: true + MACOS_NOTARIZATION_TEAM_ID: + required: true + MACOS_NOTARIZATION_APPLE_ID: + required: true + MACOS_NOTARIZATION_PASSWD: + required: true workflow_dispatch: inputs: version: @@ -326,20 +340,47 @@ jobs: working-directory: client timeout-minutes: 1 + - name: Prepare codesign + shell: bash -o pipefail -eux {0} + if: matrix.platform == 'macos' + run: | + printenv MACOS_CERT | base64 --decode > certificate.p12 + + security create-keychain -p "${{ secrets.MACOS_CI_KEYCHAIN_PASSWD }}" build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p "${{ secrets.MACOS_CI_KEYCHAIN_PASSWD }}" build.keychain + security import certificate.p12 -k build.keychain -P "${{ secrets.MACOS_CERT_PASSWD }}" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "${{ secrets.MACOS_CI_KEYCHAIN_PASSWD }}" build.keychain + env: + MACOS_CERT: ${{ secrets.MACOS_CERT }} + timeout-minutes: 2 + - name: Build Electron apps # What's about the extra `--` in `-- --nightly`? # The reason is for npm to pass the flag `--nightly` to the underlying npm script. # But since the base npm script `npm run electron:release` call another npm script, # we need to escape the flag another time by adding another `--`. - run: >- - npm run electron:release - ${{ (matrix.platform == 'linux' || inputs.nightly_build) && '--' || '' }} - ${{ matrix.platform == 'linux' && 'appimage' || '' }} - ${{ inputs.nightly_build && '--nightly' || '' }} + shell: bash -eux -o pipefail {0} + run: | + if ${{ matrix.platform == 'macos' }}; then + export CSC_LINK='${{ secrets.MACOS_CERT }}' + export CSC_KEY_PASSWORD='${{ secrets.MACOS_CERT_PASSWD }}' + export CSC_NAME='${{ secrets.MACOS_CERT_COMMON_NAME }}' + export CSC_IDENTITY_AUTO_DISCOVERY=true + export CSC_KEYCHAIN=build.keychain + export APPLE_TEAM_ID='${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}' + export APPLE_ID='${{ secrets.MACOS_NOTARIZATION_APPLE_ID }}' + export APPLE_APP_SPECIFIC_PASSWORD='${{ secrets.MACOS_NOTARIZATION_PASSWD }}' + fi + npm run electron:release \ + ${{ (matrix.platform == 'linux' || inputs.nightly_build || matrix.platform == 'macos') && '--' || '' }} \ + ${{ matrix.platform == 'linux' && 'appimage' || '' }} \ + ${{ inputs.nightly_build && '--nightly' || '' }} \ + ${{ matrix.platform == 'macos' && '--sign' || ''}} env: PARSEC_APP_SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} working-directory: client/electron - timeout-minutes: 5 + timeout-minutes: 10 - name: Upload client electron sourcemaps run: npm run sentry:sourcemaps @@ -365,7 +406,7 @@ jobs: shell: bash run: | arch=$(uname -m) - app_file="Parsec_${{ steps.version.outputs.full }}_${{ matrix.os_alias }}_${arch}${{ matrix.platform == 'linux' && '' || '.unsigned'}}.${{ matrix.extension }}" + app_file="Parsec_${{ steps.version.outputs.full }}_${{ matrix.os_alias }}_${arch}${{ (matrix.platform == 'windows' || matrix.platform == 'linux') && '.unsigned' || '' }}.${{ matrix.extension }}" latest_file="latest-${{ matrix.os_alias }}-${arch}.yml" cat << EOF | tee -a $GITHUB_OUTPUT @@ -380,9 +421,10 @@ jobs: working-directory: client/electron/dist - name: Sanity check that "latest" file contain the correct application file + shell: bash run: | cat "${{ steps.build-info.outputs.latest_file }}" - grep -e "${{ steps.build-info.outputs.app_file }}" "${{ steps.build-info.outputs.latest_file }}" + grep -q -e "${{ steps.build-info.outputs.app_file }}" "${{ steps.build-info.outputs.latest_file }}" working-directory: client/electron/dist - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin v4.4.3 diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml index 5d6226cd4d5..14440f11466 100644 --- a/.github/workflows/releaser.yml +++ b/.github/workflows/releaser.yml @@ -63,6 +63,13 @@ jobs: nightly_build: ${{ github.event_name == 'schedule' || github.ref == 'refs/tags/nightly' }} secrets: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + MACOS_CI_KEYCHAIN_PASSWD: ${{ secrets.MACOS_CI_KEYCHAIN_PASSWD }} + MACOS_CERT_PASSWD: ${{ secrets.MACOS_CERT_PASSWD }} + MACOS_CERT: ${{ secrets.MACOS_CERT }} + MACOS_CERT_COMMON_NAME: ${{ secrets.MACOS_CERT_COMMON_NAME }} + MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }} + MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.MACOS_NOTARIZATION_APPLE_ID }} + MACOS_NOTARIZATION_PASSWD: ${{ secrets.MACOS_NOTARIZATION_PASSWD }} package-parsec-cli: needs: version @@ -116,7 +123,7 @@ jobs: cp ${CP_ARGS} artifacts/linux-appimage-X64-electron/latest-linux-*.yml release-files # DMG & ZIP - cp ${CP_ARGS} artifacts/macos-dmg-X64-electron/Parsec_${{ needs.version.outputs.full }}_mac_*.unsigned{.dmg,.zip}{,.blockmap} release-files + cp ${CP_ARGS} artifacts/macos-dmg-X64-electron/Parsec_${{ needs.version.outputs.full }}_mac_*.{dmg,zip}{,.blockmap} release-files cp ${CP_ARGS} artifacts/macos-dmg-X64-electron/latest-mac-*.yml release-files # TODO: Currently, Windows electron client is not signed by the CI, thus diff --git a/bindings/README.md b/bindings/README.md index e1c151d7a2f..b34d93800f0 100644 --- a/bindings/README.md +++ b/bindings/README.md @@ -26,10 +26,10 @@ Install electron dependencies and build: ```bash # In /bindings/electron npm install -npm run build # Generate index.node (basically a .so that node can load) +npm run build # Generate libparsec.node (basically a .so that node can load) ``` -> *Note: `../client/electron` project automatically does `npm build` and copy `index.node` where needed.* +> *Note: `../client/electron` project automatically does `npm build` and copy `libparsec.node` where needed.* ## 2. Android diff --git a/bindings/electron/Cargo.toml b/bindings/electron/Cargo.toml index c16dee99e18..7c11ec9cfc4 100644 --- a/bindings/electron/Cargo.toml +++ b/bindings/electron/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libparsec_bindings_electron" -exclude = ["index.node"] +exclude = ["libparsec.node"] publish.workspace = true authors.workspace = true edition.workspace = true diff --git a/bindings/electron/README.md b/bindings/electron/README.md index 10ca5aebe7a..9f097aeeb08 100644 --- a/bindings/electron/README.md +++ b/bindings/electron/README.md @@ -20,7 +20,7 @@ Basically `make.py` wraps the following commands: ```shell npm install -# (re)generate index.node +# (re)generate dist/libparsec.node npm run build:dev # Or for release npm run build:release diff --git a/bindings/electron/package.json b/bindings/electron/package.json index fdbbe25f854..c980bd5f7ad 100644 --- a/bindings/electron/package.json +++ b/bindings/electron/package.json @@ -2,7 +2,7 @@ "name": "libparsec_bindings_electron", "version": "3.1.1-a.0+dev", "description": "", - "main": "index.node", + "main": "dist/libparsec.node", "scripts": { "build:ci": "node scripts/build.js ci", "build:dev": "node scripts/build.js dev", diff --git a/bindings/electron/scripts/build.js b/bindings/electron/scripts/build.js index b804eee7494..256b6d5e2bd 100644 --- a/bindings/electron/scripts/build.js +++ b/bindings/electron/scripts/build.js @@ -72,7 +72,7 @@ function build_electron_bindings(cargo_flags) { "cargo-cp-artifact", "--npm", "cdylib", - "dist/libparsec/index.node", + "dist/libparsec.node", "--", "cargo", "build", @@ -100,4 +100,4 @@ build_electron_bindings(cargo_flags); // Finally, copy the typing info -fs.copyFileSync('src/index.d.ts', 'dist/libparsec/index.d.ts'); +fs.copyFileSync('src/index.d.ts', 'dist/libparsec.d.ts'); diff --git a/bindings/web/README.md b/bindings/web/README.md index 720753d0871..dc9b3c0caab 100644 --- a/bindings/web/README.md +++ b/bindings/web/README.md @@ -22,7 +22,7 @@ Basically `make.py` wraps the following commands: ```shell npm install -# (re)generate index.node +# (re)generate dist/libparsec.node npm run build:dev # Or for release npm run build:release diff --git a/client/README.md b/client/README.md index e1c3c35435c..6e291d8d42c 100644 --- a/client/README.md +++ b/client/README.md @@ -83,7 +83,7 @@ npm run electron:dist -- -- --dir # To debug the generated payload npm run electron:dist -- -- --linux snap # To generate a subset (see `npx electron-builder build --help`) ``` -> The `index.node` will be automatically copied by electron on build (see +> The `libparsec.node` will be automatically copied by electron on build (see > `libparsec` script defined in `client/electron/package.json`) ## Android dev diff --git a/client/electron/macOS/entitlements.plist b/client/electron/macOS/entitlements.plist index dad3e20e6ab..92b12241d01 100644 --- a/client/electron/macOS/entitlements.plist +++ b/client/electron/macOS/entitlements.plist @@ -6,5 +6,12 @@ com.apple.security.cs.allow-jit + + com.apple.security.cs.disable-library-validation + diff --git a/client/electron/package.js b/client/electron/package.js index 6e733405168..df9df221b27 100644 --- a/client/electron/package.js +++ b/client/electron/package.js @@ -82,11 +82,23 @@ const fs = require('node:fs'); fs.mkdirSync('build/assets', { recursive: true }); fs.writeFileSync('build/assets/publishConfig.json', JSON.stringify(publishConfig)); -const SIGN_OPTIONS = { +/** + * @type {Partial} + */ +const WIN_SIGN_OPTIONS = { certificateSubjectName: 'Scille', certificateSha1: '9EB59B224218EE4B9C436CBD327BE60940592013', }; +/** + * @type {Partial} + */ +const MACOS_SIGN_OPTIONS = { + notarize: { + teamId: process.env.APPLE_TEAM_ID, + }, +}; + const UNSIGNED_ARTIFACT_NAME = OPTS.sign || OPTS.platform === 'linux' ? 'Parsec_${buildVersion}_${os}_${env.BUILD_MACHINE_ARCH}.${ext}' @@ -138,7 +150,7 @@ const options = { win: { target: 'nsis', - ...(OPTS.sign ? SIGN_OPTIONS : {}), + ...(OPTS.sign ? WIN_SIGN_OPTIONS : {}), extraResources: [ { from: 'node_modules/regedit/vbs', @@ -164,6 +176,9 @@ const options = { hardenedRuntime: true, entitlements: './macOS/entitlements.plist', entitlementsInherit: './macOS/entitlements.plist', + ...(OPTS.sign ? MACOS_SIGN_OPTIONS : {}), + // https://www.electron.build/mac#binaries + binaries: ['build/src/libparsec.node'], }, linux: { diff --git a/client/electron/scripts/copy_bindings.js b/client/electron/scripts/copy_bindings.js index bf338b4c090..2c2e80a1d66 100644 --- a/client/electron/scripts/copy_bindings.js +++ b/client/electron/scripts/copy_bindings.js @@ -5,7 +5,7 @@ const fs = require('fs'); const path = require('path'); const WORKDIR = path.join(__dirname, '..'); -const SRCDIR = path.join(WORKDIR, '../../bindings/electron/dist/libparsec'); +const SRCDIR = path.join(WORKDIR, '../../bindings/electron/dist/'); const DSTDIR = path.join(WORKDIR, 'build'); function copy(src, dst) { @@ -15,16 +15,10 @@ function copy(src, dst) { const dstParent = path.dirname(dst); console.log(`>>> mkdir -p ${path.relative(WORKDIR, dstParent)}`); - fs.mkdirSync(dstParent, {recursive: true}); + fs.mkdirSync(dstParent, { recursive: true }); console.log(`>>> cp ${path.relative(WORKDIR, src)} ${path.relative(WORKDIR, dst)}`); fs.copyFileSync(src, dst); } -copy( - path.join(SRCDIR, 'index.node'), - path.join(DSTDIR, 'src/libparsec/index.node'), -); -copy( - path.join(SRCDIR, 'index.d.ts'), - path.join(DSTDIR, 'generated-ts/src/libparsec.d.ts'), -); +copy(path.join(SRCDIR, 'libparsec.node'), path.join(DSTDIR, 'src/libparsec.node')); +copy(path.join(SRCDIR, 'libparsec.d.ts'), path.join(DSTDIR, 'generated-ts/src/libparsec.d.ts')); diff --git a/client/electron/snap/snapcraft.yaml b/client/electron/snap/snapcraft.yaml index cbf190af91f..d9fa96f5ce5 100644 --- a/client/electron/snap/snapcraft.yaml +++ b/client/electron/snap/snapcraft.yaml @@ -76,8 +76,8 @@ parts: npm clean-install npm run build:release - cp -va dist/libparsec/index.node "$CRAFT_PART_INSTALL/libparsec.node" - cp -va dist/libparsec/index.d.ts "$CRAFT_PART_INSTALL/libparsec.d.ts" + cp -va dist/libparsec.node "$CRAFT_PART_INSTALL/libparsec.node" + cp -va dist/libparsec.d.ts "$CRAFT_PART_INSTALL/libparsec.d.ts" # We pre-package `megashark-lib` to workaround a permission issue during it's `prepare` step when installed as a 3rd dependencies from `client-vite`. megashark-lib: diff --git a/client/electron/src/setup.ts b/client/electron/src/setup.ts index 281779a8703..551c0f1d9c6 100644 --- a/client/electron/src/setup.ts +++ b/client/electron/src/setup.ts @@ -467,7 +467,7 @@ export class ElectronCapacitorApp { this.MainWindow.show(); } setTimeout(() => { - if (electronIsDev) { + if (electronIsDev || process.env.OPEN_DEV_TOOLS == 'true') { this.MainWindow.webContents.openDevTools(); } CapElectronEventEmitter.emit('CAPELECTRON_DeeplinkListenerInitialized', '');