Managing New Versions of my App

Ive tried searching this (im sure someone else must have asked this but I cant seem to find the right keywords to find it)

Basically im wanting to find a way that I can add a module to my applescript app that will check for a newer version of the app and auto download and replace the existing app. Obviously the new files will need to be stored somewhere where it can access and download from.

My current setup is an Applescript Cocoa app that is linked to a SQL database to pull and push data.
Ideally the auto update module would simply look at a storage location such as github and if it detects a newer version it would then grab the new updated - Or I could create a version number table in my SQL database that would do a compare to a local version number in the app info.

Please can someone point me in the right direction.

Thanks in advance.

Model: Macbook Pro
AppleScript: Xcode 8.2.1
Browser: Firefox 51.0
Operating System: Mac OS X (10.10)

Simplest method is an separate update application/script within the bundle and is launched when the application starts up. When there is a difference between versions the user is prompted that there is a newer version and asked if it wanted to be downloaded or not. The updater will quit gracefully the application and override the entire application with the new version. At least that is how the most simplest updaters work. You’ll not only update the application but also the updater if needed because it’s embedded inside the application bundle.

If you want to take it to the next level you download an installer/application or MPKG bundle that is run by the systems default installer. The installer will have it’s own BOM and replace only the required components depending on the installed version. When the application doesn’t require external components I wouldn’t go for this solution.

Either way, downloading the entire application or updater you need to download an entire application and need an controller application to handle this outside the application.

You can set the LSBackgroundOnly or LSUIElement key to true for the the updater application so it doesn’t appear in the Dock and Force Quit menu. Use LSUIElement if you want user interaction by the updater or use LSBackgroundOnly if you want user interaction within the main application. I would choose the latter.

p.s. Not sure if you want to use this code 1:1 on your server and if you want to make it public but if you do you need to escape those incoming variable send by the query string over the network. It’s visible to everybody on the network and it becomes vulnerable for SQL injections.

Hi DJ,
Thanks again for your help.
I think this (as you rightfully said) is the best method - Especially for this app.
There are no external elements being used and will only be a self contained app.
Although, Im not sure how to go about this:
Would I simply get the launcher to run first, compare the version numbers of the bundle stored on my server against the local copy of the app and just replace?
This could work thinking about it as the app will only be usable on the local network - Meaning to use it you would need to be connected via VPN anyway.
So it could mount the volume where the bundle is located and replace if needed.

This would be fine to remain - This wont be a public app but only used internally for my company.
Operators would need to be the local network to fully use the app.

Thanks again

See it as two completely independent applications. One is your main application and the other is a file synchronizer (updater) but the synchronizer is sitting in the main application bundle in the resource folder (quite easily to make in Xcode as an build rule). The updater will be launched by your main application when it starts up and you can run it periodically afterwards, like every hour. When the updater is launched it will compare the version of the running application with the version number of the server. When they match or somehow (not sure if possible) the server version is older the update application will simply quit and stop. The same applies when the updater application cannot find the server somehow. But when they differ and the currently running application is older you could ask the user if he wants to update the application and start the update procedure.

However you will get into trouble if you run the updater from the main application bundle because files will be in used and cannot be removed or overwritten. You could unlink() the file from the directory so it becomes overwritable but you could also create an copy of the updater application in an temporary folder and run it from there. This way you can quit the main application from the copied updater application and overwrite the entire bundle you have downloaded from your server.

As far as the download part I would create an URL on your web server with that will return the version number, the download URL and it’s checksum in a single request. You download the zip file of the application bundle and check with the checksum if it is the correct and complete file, md5 is safe enough for these kind of tasks. If everything is correct you unzip the downloaded zip file and then you quit the main application (if it wasn’t stopped already). Last but not least you replace it with the new version and launch the new application (beware, it will launch it’s new embedded updater immediately so avoid if you use generic names for the copied updater application). This procedure makes sure that when you’re updating the update server nothing can go wrong with the client software as long as the link to the previous version is up. Another advantage is that as long as the server is accessible it doesn’t matter if it connects thru VPN, in a local network or even intranet; the server (by hostname or ip) must be reachable.

This sounds more difficult than mounting a volume and replace it but to make a network copy safe you need those safety issues as well. A mounted volume is a virtual file system with no guarantee that each copy is 100% correct. At the end, the extra effort using a web server rather than a file server is minor while the web server solution provides more control for you as administrator of distributing the software versions. If the web server uses a dynamic page like a PHP script you can send OS versions to the server and distribute specific versions to. Or send the version of the updater software to make sure it returns the right format of data which you’ll probably change over the years ;). Anyway, my point is that you can control each workstation individually if you like which would be very important to me.

It’s a long story and I hope it’ll help you.

Good luck!

IMO the easiest solution in the long run is to add the Sparkle framework to your app: sparkle-project.org. That’s what most apps outside the App Store use.