Select programming language for code examples

linkAuto-updates

Below you will find resources on how to implement auto-updates into your product, depending on the framework you're using, e.g. Electron, Sparkle, NSIS, etc.

Typically, a custom auto-update system would utilize the release upgrade action to check for an upgrade and then download and apply the upgrade when available.

We are working on official compatibility packages for popular open-source auto-update frameworks. Please let us know what frameworks you'd like to see supported. Wondering how to integrate with your framework? Reach out! We'd love to help.

linkAuto-updates for Go programs

You can integrate our Go SDK to implement license activation and automatic upgrades into your Go program. Installing an upgrade will replace the currently running binary with the new binary. After a restart, the end-user will be on the upgraded version.

Please do not embed admin or product API tokens within client-facing code. Instead, your Go application should use the licensee's API token — either a user token or an activation token that belongs to a license. This will ensure that the licensee has permission to access the given release.

Configuration

Variable Required Description
keygen.Account Yes Your Keygen account ID. You can find your account ID here.
keygen.Product Yes Your Keygen product ID. You can find your product here.
keygen.Token No An activation token. This will be used for license validations, activations, and for licensed upgrades.

If your product uses an OPEN distribution strategy, a Token is not required.

Example main.go

import "github.com/keygen-sh/keygen-go"
 
func upgrade() error {
keygen.Account = os.Getenv("KEYGEN_ACCOUNT")
keygen.Product = os.Getenv("KEYGEN_PRODUCT")
keygen.Token = os.Getenv("KEYGEN_TOKEN")
 
// The current version of the program
currentVersion := "1.0.0"
 
// Check for upgrade
release, err := keygen.Upgrade(currentVersion)
switch {
case err == keygen.ErrUpgradeNotAvailable:
fmt.Println("No upgrade available, already at the latest version!")
 
return nil
case err != nil:
fmt.Println("Upgrade check failed!")
 
return err
}
 
// Download the upgrade and install it
err = release.Install()
if err != nil {
return err
}
 
fmt.Println("Upgrade complete! Please restart.")
}

linkAuto-updates for Electron apps

Electron Builder

You can use the official Keygen provider for electron-builder to implement auto-updates for your Electron app. In addition, you can configure electron-builder to automatically publish new releases and artifacts to our API.

Please do not embed admin or product API tokens within client-facing code. Instead, your Electron application should use the licensee's API token — either a user token or an activation token that belongs to a license.

A full example app is available on our GitHub. We also have a how-to blog post.

Configuration

A Keygen product token is required for publishing. You can generate a product token from your dashboard. After generating a product token, define a KEYGEN_TOKEN environment variable and set its value to the product token. Outside of your local environment and CI/CD environments, your product token should never be shared.

In addition to the above, the following config must be defined in your package.json:

Key Description
build.publish.provider The publisher/provider to use. This value must be set to keygen.
build.publish.account Your Keygen account ID. You can find your account ID here.
build.publish.product Your Keygen product ID. You can find your product ID here.
build.publish.channel The channel used for publishing and updates. Available options are here.

Example electron-builder config

# Set the required KEYGEN_TOKEN environment variable be able to publish
# releases using electron-builder's official Keygen publisher
export KEYGEN_TOKEN="{PRODUCT_TOKEN}"
// Configure electron-builder in your package.json
{
"main": "main.js",
"scripts": { ...
"postinstall": "electron-builder install-app-deps",
"start": "electron .",
"dist": "electron-builder build --publish always"
},
"build": {
"publish": {
"provider": "keygen",
"account": "{ACCOUNT}",
"product": "{PRODUCT}",
"channel": "stable"
}
},
"dependencies": { ...
"electron-updater": "^4.5.0"
},
"devDependencies": { ...
"electron": "^12.0.1",
"electron-builder": "^22.13.0"
}
}

Example electron-builder auto-updater

const { autoUpdater } = require('electron-updater')
 
// Pass in an API token that belongs to the licensee (i.e. a user or
// activation token)
autoUpdater.addAuthHeader(`Bearer {ACTIVATION_TOKEN}`)
 
// Check for updates
autoUpdater.checkForUpdatesAndNotify()

linkAuto-updates for Mac apps

You can integrate our distribution API with tools such as Sparkle and Squirrel to provide automatic updates. Generating an appcast.xml should be handled by Sparkle's tooling, or be generated by hand outside of Keygen. For Squirrel, we recommend using their static JSON mode and uploading an artifact containing a valid JSON payload, according to Squirrel's required schema.

In the future, we'll be adding official API endpoints for popular tooling such as Sparkle, to automate XML Appcast generation, so please reach out if you'd like to be a part of our beta process for that.

Please do not embed admin or product API tokens within client-facing code. Instead, your Mac application should use the licensee's API token — either a user token or an activation token that belongs to a license. This will ensure that the licensee has permission to access the given release.

Sparkle

Below is an example appcast.xml file, as well as an example written in Swift of authenticating with our API before calling Sparkle to check for an update.

Your Sparkle feedURL should look like this and should contain your appcast.xml file:

https://api.keygen.sh/v1/accounts/{ACCOUNT}/artifacts/appcast.xml

Please don't hesitate to reach out if you need help integrating with Sparkle or Squirrel.

Example appcast.xml

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Releases for Example</title>
<description>Most recent changes with links to upgrades.</description>
<language>en</language>
<item>
<title>Cool App 2.0</title>
<link>https://cool-app.example</link>
<sparkle:version>
2.0.0
</sparkle:version>
<description>
<![CDATA[Cool app's 2.0 changelog here.]]>
</description>
<pubDate>Mon, 25 Oct 2021 14:05:04 GMT</pubDate>
<enclosure
url="https://api.keygen.sh/v1/accounts/{ACCOUNT}/artifacts/Cool%20App%202.0.zip"
sparkle:edSignature="WVyVJpOx+a5+vNWJVY79TRjFKveNk+VhGJf2iti4CZtJsJewIUGvh/1AKKEAFbH1qUwx+vro1ECuzOsMmumoBA=="
length="1623481"
type="application/octet-stream" />
</item>
</channel>
</rss>

Example AppDelegate.swift

import Sparkle
 
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
lazy var updater = SPUUpdater(
hostBundle: Bundle.main,
applicationBundle: Bundle.main,
userDriver: SPUStandardUserDriver(hostBundle: Bundle.main, delegate: nil),
delegate: self
)
 
@IBAction func checkForUpdates(_: Any) {
updater.httpHeaders = [
// Prompt for and pass in an API token that belongs to the licensee (i.e. a
// user or activation token). This is optional for product's with an "OPEN"
// distribution strategy, since authentication is not required.
"authorization": "Bearer \(getToken())"
]
 
updater.checkForUpdates()
}
}