Publishing for OS X

This article is part of the Distributing Electron apps series.

If you've missed, I suggest reading explanation of electron-builder first.

What's the endgame?

To build DMG for our app and be able to automatically update.

Creating installer

If you followed through article where I explained electron-builder, you're mostly done to build distributable for OS X.

Electron-builder is going to generate couple of things:

  • Application executable (.app)
  • Squirrel update package (.zip)
  • Disk image for your app (.dmg)

One extra thing you'll need to do is sign your application. You don't need to do it, but if you don't sign it, auto-updating mechanism won't work.

You can create your own certificate for testing purposes by Keychain Access.
Create new certificate:

Keychain Access -> Certificate Assistant -> Create a Certificate...  

Set certificate name and don't forget to select Code Signing as Certificate Type.

Once you generated your certificate, you can use it by setting your environment variable:

export CSC_NAME="Certificate Name"  

Now, when you run electron-builder, it will pick up that name and sign your application with that certificate.

Automatic updates

Electron is using Squirrel.Mac to auto-update your application. Auto-updating with Squirrel consists of two parts: requesting Squirrel package from your application and serving it on server.

Application

In short, you main application file will need to include auto-updater module:

const autoUpdater = require('auto-updater');  

Then if you'd like, you can add listeners for relevant events:

autoUpdater.addListener("update-available", function(event) {  
    ...
});
autoUpdater.addListener("update-downloaded", function(event, releaseNotes, releaseName, releaseDate, updateURL) {  
    ...
});
autoUpdater.addListener("error", function(error) {  
    ...
});
autoUpdater.addListener("checking-for-update", function(event) {  
    ...
});
autoUpdater.addListener("update-not-available", function(event) {  
    ...
});

Next, we need to provide Squirrel with server URL:

var updateFeed = 'http://ea-todo.herokuapp.com/updates/latest';  
const appVersion = require('./package.json').version;  
const feedURL = updateFeed + '?v=' + appVersion;  
autoUpdater.setFeedURL(feedURL);  

Now everything is setup, so finally you need to request checking for update:

autoUpdater.checkForUpdates();  

Tip: Don't use auto-updater in development, since it won't work. It needs to be app, and needs to be signed. I've wrapped my code in conditional check.

I've updated EA Todo code to include auto-update mechanism, so you can check it out here.

Update server

Squirrel for Mac is expecting server to respond with 200 in JSON format if update is needed, or with 204 if app doesn't need to update.

To do so, easiest is to create simple Express server which will as parameter receive application version. Then server will compare it and see if it needs to be updated and return appropriate response (thanks Svilen for idea).

I'm hosting files on Amazon S3 and not on same server, so I've added another step. On start and every 5 minutes, server will fetch VERSION file from S3 which provides data relevant to updates.

Note: If you have any special characters in your update-url, you must encodeURI() it in your 200 response json. - (thanks Greg)

Complete process

  • Server will fetch VERSION, i.e.:
http://eatodo.s3.amazonaws.com/updates/latest/osx/VERSION  
  • Application will place request with it's version, i.e.:
http://ea-todo.herokuapp.com/updates/latest?v=0.0.1  
  • Server will compare version from VERSION file and version from param v

  • Let's say that version in manifest is different, so server will respond in 200 with:

{
    url: "http://eatodo.s3.amazonaws.com/updates/latest/osx/eatodo-0.0.2-mac.zip"
}
  • Application will get response and start downloading package from url.

  • When download is finished, it will be automatically installed. On next start, your app will start with updated version.

See EA Todo Server project which I've uploaded to Heroku.
Note: I'm using free account so it may be some downtimes if you're testing it.

In the end...

Also, there are no delta updates on OS X like there are for Windows - you have to distribute complete app, just compressed in ZIP.

Thoughts? Problems? Ideas? Feel free to leave them in comments.

Also, check out how to publish for Windows.

About Vjekoslav Ratkajec

Software developer from Zagreb, Croatia. Love programming, running, hiking and biking. Adore nature and animals. Also author of this blog.

Comments