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 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.