diff --git a/config/electron-builder.js b/config/electron-builder.js new file mode 100644 index 000000000..3bd2d15fe --- /dev/null +++ b/config/electron-builder.js @@ -0,0 +1,72 @@ +const { Configuration } = require('electron-builder'); + +/** + * @type {Configuration} + */ +const config = { + productName: 'Gitify', + appId: 'com.electron.gitify', + copyright: 'Copyright © 2025 Gitify Team', + asar: true, + files: [ + 'assets/images/*', + 'assets/sounds/*', + 'build/**/*', + 'LICENSE', + 'node_modules/**/*', + 'package.json', + ], + electronLanguages: ['en'], + protocols: [ + { + name: 'Gitify', + schemes: ['gitify', 'gitify-dev'], + }, + ], + mac: { + category: 'public.app-category.developer-tools', + icon: 'assets/images/app-icon.icns', + identity: 'Adam Setch (5KD23H9729)', + type: 'distribution', + notarize: false, + target: { + target: 'default', + arch: ['universal'], + }, + hardenedRuntime: true, + entitlements: 'assets/entitlements.mac.plist', + entitlementsInherit: 'assets/entitlements.mac.plist', + gatekeeperAssess: false, + extendInfo: { + NSBluetoothAlwaysUsageDescription: null, + NSBluetoothPeripheralUsageDescription: null, + NSCameraUsageDescription: null, + NSMicrophoneUsageDescription: null, + }, + }, + dmg: { + icon: 'assets/images/app-icon.icns', + sign: false, + }, + win: { + target: 'nsis', + icon: 'assets/images/app-icon.ico', + }, + nsis: { + oneClick: false, + }, + linux: { + target: ['AppImage', 'deb', 'rpm'], + category: 'Development', + maintainer: 'Gitify Team', + }, + publish: { + provider: 'github', + owner: 'gitify-app', + repo: 'gitify', + }, + afterSign: 'scripts/afterSign.js', + afterPack: 'scripts/afterPack.js', +}; + +module.exports = config; diff --git a/package.json b/package.json index 814fe516d..da5449d49 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "watch:main": "webpack --watch --config ./config/webpack.config.main.base.ts", "watch:renderer": "webpack --watch --config ./config/webpack.config.renderer.base.ts", "prepare:remove-source-maps": "ts-node ./scripts/delete-source-maps.ts", - "package:linux": "electron-builder --linux", - "package:macos": "electron-builder --mac", - "package:win": "electron-builder --win", + "package:linux": "electron-builder --linux --config ./config/electron-builder.js", + "package:macos": "electron-builder --mac --config ./config/electron-builder.js", + "package:win": "electron-builder --win --config ./config/electron-builder.js", "lint:check": "biome check", "lint": "biome check --fix", "test": "jest", @@ -66,71 +66,6 @@ "url": "https://github.com/gitify-app/gitify/issues" }, "homepage": "https://gitify.io/", - "build": { - "productName": "Gitify", - "appId": "com.electron.gitify", - "copyright": "Copyright © 2025 Gitify Team", - "asar": true, - "files": [ - "assets/images/*", - "assets/sounds/*", - "build/**/*", - "LICENSE", - "node_modules/**/*", - "package.json" - ], - "electronLanguages": ["en"], - "protocols": [ - { - "name": "Gitify", - "schemes": ["gitify", "gitify-dev"] - } - ], - "mac": { - "category": "public.app-category.developer-tools", - "icon": "assets/images/app-icon.icns", - "identity": "Adam Setch (5KD23H9729)", - "type": "distribution", - "notarize": false, - "target": { - "target": "default", - "arch": ["universal"] - }, - "hardenedRuntime": true, - "entitlements": "assets/entitlements.mac.plist", - "entitlementsInherit": "assets/entitlements.mac.plist", - "gatekeeperAssess": false, - "extendInfo": { - "NSBluetoothAlwaysUsageDescription": null, - "NSBluetoothPeripheralUsageDescription": null, - "NSCameraUsageDescription": null, - "NSMicrophoneUsageDescription": null - } - }, - "dmg": { - "icon": "assets/images/app-icon.icns", - "sign": false - }, - "win": { - "target": "nsis", - "icon": "assets/images/app-icon.ico" - }, - "nsis": { - "oneClick": false - }, - "linux": { - "target": ["AppImage", "deb", "rpm"], - "category": "Development", - "maintainer": "Gitify Team" - }, - "publish": { - "provider": "github", - "owner": "gitify-app", - "repo": "gitify" - }, - "afterSign": "scripts/notarize.js", - "afterPack": "scripts/afterPack.js" - }, "dependencies": { "@electron/remote": "2.1.2", "electron-log": "5.3.2", diff --git a/scripts/afterPack.js b/scripts/afterPack.js index 20b77d826..a95bdaf39 100644 --- a/scripts/afterPack.js +++ b/scripts/afterPack.js @@ -2,15 +2,19 @@ const path = require('node:path'); const fs = require('node:fs'); const { AfterPackContext } = require('electron-builder'); -const packageJson = require('../package.json'); -const electronLanguages = packageJson.build.electronLanguages; +const builderConfig = require('../config/electron-builder'); +const electronLanguages = builderConfig.electronLanguages; + +function logAfterPackProgress(msg) { + // biome-ignore lint/suspicious/noConsoleLog: log notarizing progress + console.log(` • [afterPack]: ${msg}`); +} /** * @param {AfterPackContext} context */ const afterPack = async (context) => { - // biome-ignore lint/suspicious/noConsoleLog: disabled - console.log('[afterPack]: Starting...'); + logAfterPackProgress('Starting...'); const appName = context.packager.appInfo.productFilename; const appOutDir = context.appOutDir; @@ -20,8 +24,7 @@ const afterPack = async (context) => { removeUnusedLocales(appOutDir, appName); } - // biome-ignore lint/suspicious/noConsoleLog: disabled - console.log('[afterPack]: Completed'); + logAfterPackProgress('Completed'); }; /** @@ -30,8 +33,7 @@ const afterPack = async (context) => { * @param {string} appName */ const removeUnusedLocales = (appOutDir, appName) => { - // biome-ignore lint/suspicious/noConsoleLog: disabled - console.log('[afterPack]: removing unused locales'); + logAfterPackProgress('removing unused locales'); const resourcesPath = path.join( appOutDir, diff --git a/scripts/afterSign.js b/scripts/afterSign.js new file mode 100644 index 000000000..a88758ee4 --- /dev/null +++ b/scripts/afterSign.js @@ -0,0 +1,52 @@ +const { notarize } = require('@electron/notarize'); +const { AfterPackContext } = require('electron-builder'); + +const builderConfig = require('../config/electron-builder'); +const appBundleId = builderConfig.appId; + +function logAfterSignProgress(msg) { + // biome-ignore lint/suspicious/noConsoleLog: log notarizing progress + console.log(` • [afterSign]: ${msg}`); +} + +/** + * @param {AfterPackContext} context + */ +const afterSign = async (context) => { + logAfterSignProgress('Starting...'); + + const { appOutDir } = context; + const appName = context.packager.appInfo.productFilename; + const shouldNotarize = process.env.NOTARIZE === 'true'; + + if (!shouldNotarize) { + logAfterSignProgress( + 'skipping notarize step as NOTARIZE env flag was not set', + ); + return; + } + + notarizeApp(appName, appOutDir); + + logAfterSignProgress('Completed'); +}; + +/** + * Notarizes the application + * @param {string} appOutDir + * @param {string} appName + */ +const notarizeApp = (appOutDir, appName) => { + logAfterSignProgress('notarizing app'); + + return notarize({ + appBundleId, + appPath: `${appOutDir}/${appName}.app`, + appleId: process.env.APPLE_ID_USERNAME, + appleIdPassword: process.env.APPLE_ID_PASSWORD, + teamId: process.env.APPLE_ID_TEAM_ID, + tool: 'notarytool', + }); +}; + +module.exports = afterSign; diff --git a/scripts/notarize.js b/scripts/notarize.js deleted file mode 100644 index 8c6b76b65..000000000 --- a/scripts/notarize.js +++ /dev/null @@ -1,40 +0,0 @@ -const { notarize } = require('@electron/notarize'); -const { AfterPackContext } = require('electron-builder'); - -const packageJson = require('../package.json'); -const appBundleId = packageJson.build.appId; - -function logNotarizingProgress(msg) { - // biome-ignore lint/suspicious/noConsoleLog: log notarizing progress - console.log(` • notarizing ${msg}`); -} - -/** - * @param {AfterPackContext} context - */ -const notarizeApp = async (context) => { - const { electronPlatformName, appOutDir } = context; - const appName = context.packager.appInfo.productFilename; - const isMacOS = electronPlatformName === 'darwin'; - const shouldNotarize = process.env.NOTARIZE === 'true'; - - if (!shouldNotarize || !isMacOS) { - logNotarizingProgress( - 'either should not notarize or not building for macOS', - ); - return; - } - - logNotarizingProgress('process started'); - - return await notarize({ - appBundleId, - appPath: `${appOutDir}/${appName}.app`, - appleId: process.env.APPLE_ID_USERNAME, - appleIdPassword: process.env.APPLE_ID_PASSWORD, - teamId: process.env.APPLE_ID_TEAM_ID, - tool: 'notarytool', - }); -}; - -exports.default = notarizeApp;