diff --git a/.eslintignore b/.eslintignore index 1e4ed3e2f..e966676c7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -357,6 +357,7 @@ packages/app-desktop/services/sortOrder/PerFolderSortOrderService.test.js packages/app-desktop/services/sortOrder/notesSortOrderUtils.js packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.js packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js +packages/app-desktop/tools/notarizeMacApp.js packages/app-desktop/utils/markupLanguageUtils.js packages/app-mobile/PluginAssetsLoader.js packages/app-mobile/components/ActionButton.js diff --git a/.gitignore b/.gitignore index 3fca94bb1..2f04098ad 100644 --- a/.gitignore +++ b/.gitignore @@ -342,6 +342,7 @@ packages/app-desktop/services/sortOrder/PerFolderSortOrderService.test.js packages/app-desktop/services/sortOrder/notesSortOrderUtils.js packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.js packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js +packages/app-desktop/tools/notarizeMacApp.js packages/app-desktop/utils/markupLanguageUtils.js packages/app-mobile/PluginAssetsLoader.js packages/app-mobile/components/ActionButton.js diff --git a/packages/app-desktop/package.json b/packages/app-desktop/package.json index df6a9c939..6206d5e11 100644 --- a/packages/app-desktop/package.json +++ b/packages/app-desktop/package.json @@ -117,7 +117,6 @@ "@types/styled-components": "5.1.26", "electron": "19.1.4", "electron-builder": "22.11.7", - "electron-notarize": "1.2.2", "electron-rebuild": "3.2.9", "glob": "8.1.0", "gulp": "4.0.2", @@ -134,6 +133,7 @@ "7zip-bin-win": "^2.1.1" }, "dependencies": { + "@electron/notarize": "1.2.4", "@electron/remote": "2.0.9", "@fortawesome/fontawesome-free": "5.15.4", "@joeattardi/emoji-button": "4.6.4", diff --git a/packages/app-desktop/tools/notarizeMacApp.js b/packages/app-desktop/tools/notarizeMacApp.js index 805e618fc..7174da34d 100644 --- a/packages/app-desktop/tools/notarizeMacApp.js +++ b/packages/app-desktop/tools/notarizeMacApp.js @@ -1,82 +1,81 @@ -const fs = require('fs'); -const path = require('path'); -const electron_notarize = require('electron-notarize'); -const execCommand = require('./execCommand'); - -function isDesktopAppTag(tagName) { - if (!tagName) return false; - return tagName[0] === 'v'; -} - -module.exports = async function(params) { - if (process.platform !== 'darwin') return; - - console.info('Checking if notarization should be done...'); - - if (!process.env.IS_CONTINUOUS_INTEGRATION || !isDesktopAppTag(process.env.GIT_TAG_NAME)) { - console.info(`Either not running in CI or not processing a desktop app tag - skipping notarization. process.env.IS_CONTINUOUS_INTEGRATION = ${process.env.IS_CONTINUOUS_INTEGRATION}; process.env.GIT_TAG_NAME = ${process.env.GIT_TAG_NAME}`); - return; - } - - if (!process.env.APPLE_ID || !process.env.APPLE_ID_PASSWORD) { - console.warn('Environment variables APPLE_ID and APPLE_ID_PASSWORD not found - notarization will NOT be done.'); - return; - } - - // Same appId in electron-builder. - const appId = 'net.cozic.joplin-desktop'; - - const appPath = path.join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`); - if (!fs.existsSync(appPath)) { - throw new Error(`Cannot find application at: ${appPath}`); - } - - console.log(`Notarizing ${appId} found at ${appPath}`); - - // Every x seconds we print something to stdout, otherwise CI may timeout - // the task after 10 minutes, and Apple notarization can take more time. - const waitingIntervalId = setInterval(() => { - console.log('.'); - }, 60000); - - try { - await electron_notarize.notarize({ - appBundleId: appId, - appPath: appPath, - - // Apple Developer email address - appleId: process.env.APPLE_ID, - - // App-specific password: https://support.apple.com/en-us/HT204397 - appleIdPassword: process.env.APPLE_ID_PASSWORD, - - // When Apple ID is attached to multiple providers (eg if the - // account has been used to build multiple apps for different - // companies), in that case the provider "Team Short Name" (also - // known as "ProviderShortname") must be provided. - // - // Use this to get it: - // - // xcrun altool --list-providers -u APPLE_ID -p APPLE_ID_PASSWORD - ascProvider: process.env.APPLE_ASC_PROVIDER, - }); - } catch (error) { - console.error(error); - process.exit(1); - } - - clearInterval(waitingIntervalId); - - // It appears that electron-notarize doesn't staple the app, but without - // this we were still getting the malware warning when launching the app. - // Stapling the app means attaching the notarization ticket to it, so that - // if the user is offline, macOS can still check if the app was notarized. - // So it seems to be more or less optional, but at least in our case it - // wasn't. - console.log('Staple notarization ticket to the app...'); - const staplerCmd = `xcrun stapler staple "${appPath}"`; - console.log(`> ${staplerCmd}`); - console.log(await execCommand(staplerCmd)); - - console.log(`Done notarizing ${appId}`); +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); }; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs_1 = require("fs"); +const path_1 = require("path"); +const notarize_1 = require("@electron/notarize"); +const execCommand = require('./execCommand'); +function isDesktopAppTag(tagName) { + if (!tagName) + return false; + return tagName[0] === 'v'; +} +exports.default = (params) => __awaiter(void 0, void 0, void 0, function* () { + if (process.platform !== 'darwin') + return; + console.info('Checking if notarization should be done...'); + if (!process.env.IS_CONTINUOUS_INTEGRATION || !isDesktopAppTag(process.env.GIT_TAG_NAME)) { + console.info(`Either not running in CI or not processing a desktop app tag - skipping notarization. process.env.IS_CONTINUOUS_INTEGRATION = ${process.env.IS_CONTINUOUS_INTEGRATION}; process.env.GIT_TAG_NAME = ${process.env.GIT_TAG_NAME}`); + return; + } + if (!process.env.APPLE_ID || !process.env.APPLE_ID_PASSWORD) { + console.warn('Environment variables APPLE_ID and APPLE_ID_PASSWORD not found - notarization will NOT be done.'); + return; + } + // Same appId in electron-builder. + const appId = 'net.cozic.joplin-desktop'; + const appPath = (0, path_1.join)(params.appOutDir, `${params.packager.appInfo.productFilename}.app`); + if (!(0, fs_1.existsSync)(appPath)) { + throw new Error(`Cannot find application at: ${appPath}`); + } + console.log(`Notarizing ${appId} found at ${appPath}`); + // Every x seconds we print something to stdout, otherwise CI may timeout + // the task after 10 minutes, and Apple notarization can take more time. + const waitingIntervalId = setInterval(() => { + console.log('.'); + }, 60000); + try { + yield (0, notarize_1.notarize)({ + appBundleId: appId, + appPath: appPath, + // Apple Developer email address + appleId: process.env.APPLE_ID, + // App-specific password: https://support.apple.com/en-us/HT204397 + appleIdPassword: process.env.APPLE_ID_PASSWORD, + // When Apple ID is attached to multiple providers (eg if the + // account has been used to build multiple apps for different + // companies), in that case the provider "Team Short Name" (also + // known as "ProviderShortname") must be provided. + // + // Use this to get it: + // + // xcrun altool --list-providers -u APPLE_ID -p APPLE_ID_PASSWORD + ascProvider: process.env.APPLE_ASC_PROVIDER, + }); + } + catch (error) { + console.error(error); + process.exit(1); + } + clearInterval(waitingIntervalId); + // It appears that electron-notarize doesn't staple the app, but without + // this we were still getting the malware warning when launching the app. + // Stapling the app means attaching the notarization ticket to it, so that + // if the user is offline, macOS can still check if the app was notarized. + // So it seems to be more or less optional, but at least in our case it + // wasn't. + console.log('Staple notarization ticket to the app...'); + const staplerCmd = `xcrun stapler staple "${appPath}"`; + console.log(`> ${staplerCmd}`); + console.log(yield execCommand(staplerCmd)); + console.log(`Done notarizing ${appId}`); +}); +//# sourceMappingURL=notarizeMacApp.js.map \ No newline at end of file diff --git a/packages/app-desktop/tools/notarizeMacApp.ts b/packages/app-desktop/tools/notarizeMacApp.ts new file mode 100644 index 000000000..f4c4e352b --- /dev/null +++ b/packages/app-desktop/tools/notarizeMacApp.ts @@ -0,0 +1,91 @@ +import { existsSync } from 'fs'; +import { join } from 'path'; +import { notarize } from '@electron/notarize'; +const execCommand = require('./execCommand'); + +function isDesktopAppTag(tagName: string) { + if (!tagName) return false; + return tagName[0] === 'v'; +} + +interface Params { + appOutDir: string; + packager: { + appInfo: { + productFilename: string; + }; + }; +} + +export default async (params: Params) => { + if (process.platform !== 'darwin') return; + + console.info('Checking if notarization should be done...'); + + if (!process.env.IS_CONTINUOUS_INTEGRATION || !isDesktopAppTag(process.env.GIT_TAG_NAME)) { + console.info(`Either not running in CI or not processing a desktop app tag - skipping notarization. process.env.IS_CONTINUOUS_INTEGRATION = ${process.env.IS_CONTINUOUS_INTEGRATION}; process.env.GIT_TAG_NAME = ${process.env.GIT_TAG_NAME}`); + return; + } + + if (!process.env.APPLE_ID || !process.env.APPLE_ID_PASSWORD) { + console.warn('Environment variables APPLE_ID and APPLE_ID_PASSWORD not found - notarization will NOT be done.'); + return; + } + + // Same appId in electron-builder. + const appId = 'net.cozic.joplin-desktop'; + + const appPath = join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`); + if (!existsSync(appPath)) { + throw new Error(`Cannot find application at: ${appPath}`); + } + + console.log(`Notarizing ${appId} found at ${appPath}`); + + // Every x seconds we print something to stdout, otherwise CI may timeout + // the task after 10 minutes, and Apple notarization can take more time. + const waitingIntervalId = setInterval(() => { + console.log('.'); + }, 60000); + + try { + await notarize({ + appBundleId: appId, + appPath: appPath, + + // Apple Developer email address + appleId: process.env.APPLE_ID, + + // App-specific password: https://support.apple.com/en-us/HT204397 + appleIdPassword: process.env.APPLE_ID_PASSWORD, + + // When Apple ID is attached to multiple providers (eg if the + // account has been used to build multiple apps for different + // companies), in that case the provider "Team Short Name" (also + // known as "ProviderShortname") must be provided. + // + // Use this to get it: + // + // xcrun altool --list-providers -u APPLE_ID -p APPLE_ID_PASSWORD + ascProvider: process.env.APPLE_ASC_PROVIDER, + }); + } catch (error) { + console.error(error); + process.exit(1); + } + + clearInterval(waitingIntervalId); + + // It appears that electron-notarize doesn't staple the app, but without + // this we were still getting the malware warning when launching the app. + // Stapling the app means attaching the notarization ticket to it, so that + // if the user is offline, macOS can still check if the app was notarized. + // So it seems to be more or less optional, but at least in our case it + // wasn't. + console.log('Staple notarization ticket to the app...'); + const staplerCmd = `xcrun stapler staple "${appPath}"`; + console.log(`> ${staplerCmd}`); + console.log(await execCommand(staplerCmd)); + + console.log(`Done notarizing ${appId}`); +}; diff --git a/yarn.lock b/yarn.lock index 49f617302..39033a9ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3408,6 +3408,16 @@ __metadata: languageName: node linkType: hard +"@electron/notarize@npm:1.2.4": + version: 1.2.4 + resolution: "@electron/notarize@npm:1.2.4" + dependencies: + debug: ^4.1.1 + fs-extra: ^9.0.1 + checksum: 3aa19fb247f9297b96a25f1a082f552e0c78a726ddfc98de9cdd4e4b092fc36fe07d680b762dd5a2bceda97b1044d3a0e6d9eadc5022f7c329a1fcf081133c9b + languageName: node + linkType: hard + "@electron/remote@npm:2.0.9": version: 2.0.9 resolution: "@electron/remote@npm:2.0.9" @@ -4264,6 +4274,7 @@ __metadata: 7zip-bin-linux: ^1.0.1 7zip-bin-mac: ^1.0.1 7zip-bin-win: ^2.1.1 + "@electron/notarize": 1.2.4 "@electron/remote": 2.0.9 "@fortawesome/fontawesome-free": 5.15.4 "@joeattardi/emoji-button": 4.6.4 @@ -4284,7 +4295,6 @@ __metadata: debounce: 1.2.1 electron: 19.1.4 electron-builder: 22.11.7 - electron-notarize: 1.2.2 electron-rebuild: 3.2.9 electron-window-state: 5.0.3 formatcoords: 1.1.3 @@ -14492,16 +14502,6 @@ __metadata: languageName: node linkType: hard -"electron-notarize@npm:1.2.2": - version: 1.2.2 - resolution: "electron-notarize@npm:1.2.2" - dependencies: - debug: ^4.1.1 - fs-extra: ^9.0.1 - checksum: 98909bc90f0840a4bd3da0edc6895d719eb0d17942812a8c8f5a130d323c7fbaafd819245cfe9a6c5b5abfa8dd3b0eb2bd8ee9c0b2dcf0c3b238b6845730c368 - languageName: node - linkType: hard - "electron-publish@npm:22.11.7": version: 22.11.7 resolution: "electron-publish@npm:22.11.7"