Issue #430

Use electron builder

npm install electron-builder@latest --save-dev

package.json

{
  "name": "icon_generator",
  "version": "1.3.0",
  "description": "A macOS app to generate app icons",
  "main": "babel/main.js",
  "repository": "https://github.com/onmyway133/IconGenerator",
  "author": "Khoa Pham",
  "license": "MIT",
  "scripts": {
    "start": "npm run babel && electron .",
    "babel": "babel ./src --out-dir ./babel --copy-files",
    "dist": "npm run babel && electron-builder"
  },
  "build": {
    "appId": "com.onmyway133.IconGenerator",
    "buildVersion": "20",
    "productName": "Icon Generator",
    "icon": "./Icon/Icon.icns",
    "mac": {
      "category": "public.app-category.productivity",
      "hardenedRuntime": true,
      "gatekeeperAssess": false,
      "entitlements": "./entitlements.plist",
      "entitlementsInherit": "./entitlements.plist"
    },
    "win": {
      "target": "msi"
    },
    "linux": {
      "target": [
        "AppImage",
        "deb"
      ]
    },
    "afterSign": "./afterSignHook.js"
  }
}

Declare entitlements

entitlements.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
  </dict>
</plist>

Use electron-notarize

afterSignHook.js

const fs = require('fs');
const path = require('path');
var electron_notarize = require('electron-notarize');

module.exports = async function (params) {
    // Only notarize the app on Mac OS only.
    if (process.platform !== 'darwin') {
        return;
    }
    console.log('afterSign hook triggered', params);

    // Same appId in electron-builder.
    let appId = 'com.onmyway133.IconGenerator'

    let 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}`);

    try {
        await electron_notarize.notarize({
            appBundleId: appId,
            appPath: appPath,
            appleId: process.env.appleId,
            appleIdPassword: process.env.appleIdPassword,
        });
    } catch (error) {
        console.error(error);
    }

    console.log(`Done notarizing ${appId}`);
};

Run

Generate password for Apple Id because of 2FA

export appleId=onmyway133@gmail.com
export appleIdPassword=1234-abcd-efgh-7890
npm run dist

Check

spctl --assess --verbose Icon\ Generator.app

Troubleshooting

babel

  • Since electron-builder create dist folder for distribution, for example dist/mac/Icon Generator, I’ve renamed babel generated code to babel directory

babel 6 regeneratorRuntime is not defined

It is because of afterSignHook. Ignore in .babelrc not work

{
  "plugins": [
    "transform-react-jsx-source"
  ],
  "presets": ["env", "react"],
  "ignore": [
    "afterSignHook.js"
  ]
}

Should use babel 7 with babel.config.js

npm install --save @babel/runtime 
npm install --save-dev @babel/plugin-transform-runtime

Use electron-forge

https://httptoolkit.tech/blog/notarizing-electron-apps-with-electron-forge/

Read more