Releasing an Electron app on the Mac App Store

This week I released an Electron app on the Mac App store. Since this isn’t the traditional process of building macOS apps, it’s not well documented and the instructions that do exist tend to contradict one another. This article is a path that what worked for me, but may not be the best one out there.

The build process.

To create a pkg file that I could eventually upload, I used electron-builder. Many tutorials out there suggest using electron-packager, however they often were written before electron-builder became a thing so I wouldn’t recommend going this approach. Electron builder is an all-in-one tool that will make your life much easier.

Electron builder has you add a parameter to your package.json called build. My full package.json looks like this:

{
 // ... name, description, dependencies, ect
 "build": {
"appId": "com.flaque.penguin",
"mac": {
"category": "public.app-category.graphics-design",
"target": [
"pkg",
"dmg",
"zip",
"mas"
],
"entitlements": "build/entitlements.mac.plist",
"type": "distribution",
"icon": "build/icon.icns"
},
"mas": {
"entitlements": "build/entitlements.mas.plist",
"type": "distribution",
"category": "public.app-category.graphics-design"
},
"files": [
"main.js",
"node_modules/**/*",
"app/**/*",
"package.json",
"embedded.provisionprofile"
]
}
}

The first thing you’ll need is your appId. You can register this id on the Apple Developer portal under “Certificates, Identifiers & Profiles” and then click the dropdown, select OS X (funny that Apple hasn’t changed this to macOS yet) and then “App Ids”. Or you could just click this link.

Next, you’ll need to set your mac options, starting with a category. All mac options are defined here. You can see all category options here. Then, you should set your target.

Make sure to set mas as a target. When you eventually run your build, the mas version of the app will be what you submit to the Mac App Store (mas).

Entitlements and the File Structure

Electron-Builder looks for a build folder in your root directory where you should put a couple important files. There’s a few different ways to do this, but I had four main files in there.

I had two .plist files for my entitlements: entitlements.mac.plist and entitlements.mas.plist .

The mac plist looks like this:

<?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.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>

And the mas plist looks like this:

<?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.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<string>F29L6XF84H.com.flaque.penguin</string>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>

But you should replace the F29L6XF84H.com.flaque.penguin with your own developer id followed by your app id in the format <dev_id>.<app_id> .

I also had an info.plist file that looked like this:

<?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.developer.team-identifier</key>
<string>F29L6XF84H</string>
<key>com.apple.application-identifier</key>
<string>F29L6XF84H.com.flaque.penguin</string>
</dict>
</plist>

Again, replace the dev team id and app id with your own.

Finally, I had an icon.icns file which was the logo for my app.

The icon for my app.

The Provisioning Profile.

In the Apple Developer portal, I grabbed a Mac Distribution provisioning profile. This will give you a .provisionprofile file that you should download and save in the root of your project as embedded.provisionprofile .

Code Signing

I generated 5 different certificates on the Apple Developer portal:

  • Mac Developer
  • Mac App Distribution
  • Mac Installer Distribution
  • Developer ID Application
  • Developer ID Installer

Then, I downloaded all the certificates and double clicked them so they would open in Keychain Access on my Mac. Then, I cmd-clicked all five certs, right clicked, and then clicked “Export 5 items”. This will generate a .p12 file that will ask you for a password.

Then came the actual code signing. Code signing is a really annoying process. So I wrote a script to do it. You’re welcome to use it as well if you’d like. Make sure you store your .p12 file in ~/.certs .

Setting up scripts

To make things easy on myself, I edited the scripts section of my package.json to add two scripts:

"scripts": {
"dist": "node_modules/.bin/build",
"release": "bash scripts/publish_penguin.sh",
/* other stuff */
}

Releasing!

Finally, I ran npm run release and my scripts created a dist folder that contained all my deliverables. I then used Application Loader to deliver my app build to iTunes Connect.