Categorygithub.com/fynelabs/selfupdate
modulepackage
0.2.0
Repository: https://github.com/fynelabs/selfupdate.git
Documentation: pkg.go.dev

# README

self-update: Build self-updating Fyne programs

godoc reference Coverage Status

Package update provides functionality to implement secure, self-updating Fyne programs (or other single-file targets)

A program can update itself by replacing its executable file with a new version.

It provides the flexibility to implement different updating user experiences like auto-updating, or manual user-initiated updates. It also boasts advanced features like binary patching and code signing verification.

Unmanaged update

Example of updating from a URL:

import (
    "fmt"
    "net/http"

    "github.com/fynelabs/selfupdate"
)

func doUpdate(url string) error {
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    err = update.Apply(resp.Body, update.Options{})
    if err != nil {
        // error handling
    }
    return err
}

Managed update

To help make self updating Fyne application a new API and a tool, selfupdatectl have been introduced. The new API allow to provide a source where to get an update, configure a schedule for the update and a ed25519 public key to ensure that the update is only applied if they come from the proper source.

Example with the new API:

import (
	"crypto/ed25519"
	"log"
	"time"

	"github.com/fynelabs/selfupdate"
)

func main() {
	done := make(chan struct{}, 2)

	// Used `selfupdatectl create-keys` followed by `selfupdatectl print-key`
	publicKey := ed25519.PublicKey{178, 103, 83, 57, 61, 138, 18, 249, 244, 80, 163, 162, 24, 251, 190, 241, 11, 168, 179, 41, 245, 27, 166, 70, 220, 254, 118, 169, 101, 26, 199, 129}

	// The public key above match the signature of the below file served by our CDN
	httpSource := selfupdate.NewHTTPSource(nil, "http://localhost/{{.Executable}}-{{.OS}}-{{.Arch}}{{.Ext}}")
	config := &selfupdate.Config{
		Source:    httpSource,
		Schedule:  selfupdate.Schedule{FetchOnStart: true, Interval: time.Minute * time.Duration(60)},
		PublicKey: publicKey,

		ProgressCallback: func(f float64, err error) { log.Println("Download", f, "%") },
		RestartConfirmCallback: func() bool { return true},
		UpgradeConfirmCallback: func(_ string) bool { return true },
		ExitCallback: func(_ error) { os.Exit(1) }
	}

	_, err := selfupdate.Manage(config)
	if err != nil {
		log.Println("Error while setting up update manager: ", err)
		return
	}

	<-done
}

If you desire a GUI element and visual integration with Fyne, you should check fyneselfupdate.

To help you manage your key, sign binary and upload them to an online S3 bucket the selfupdatectl tool is provided. You can check its documentation here.

Logging

We provide three package wide variables: LogError, LogInfo and LogDebug that follow log.Printf API to provide an easy way to hook any logger in. To use it with go logger, you can just do

selfupdate.LogError = log.Printf

If you are using logrus for example, you could do the following:

selfupdate.LogError = logrus.Errorf
selfupdate.LogInfo = logrus.Infof
selfupdate.LogDebug = logrus.Debugf

Most logger module in the go ecosystem do provide an API that match the log.Printf and it should be straight forward to use in the same way as with logrus.

Features

  • Cross platform support
  • Binary patch application
  • Checksum verification
  • Code signing verification
  • Support for updating arbitrary files

API Compatibility Promises

The main branch of selfupdate is not guaranteed to have a stable API over time. Still we will try hard to not break its API unecessarily and will follow a proper versioning of our release when necessary.

The selfupdate package makes the following promises about API compatibility:

  1. A list of all API-breaking changes will be documented in this README.
  2. selfupdate will strive for as few API-breaking changes as possible.

API Breaking Changes

  • May 30, 2022: Many changes moving to a new API that will be supported going forward.
  • June 22, 2022: First tagged release, v0.1.0.

License

Apache

Sponsors

This project is kindly sponsored by the following companies:

# Packages

No description provided by the author

# Functions

Apply performs an update of the current executable (or opts.TargetFile, if set) with the contents of the given io.Reader.
Manage sets up an Updater and runs it to manage the current executable.
ManualUpdate applies a specific update manually instead of managing the update of this app automatically.
NewBSDiffPatcher returns a new Patcher that applies binary patches using the bsdiff algorithm.
NewECDSAVerifier returns a Verifier that uses the ECDSA algorithm to verify updates.
NewHTTPSource provide a selfupdate.Source that will fetch the specified base URL for update and signature using the http.Client provided.
NewRSAVerifier returns a Verifier that uses the RSA algorithm to verify updates.
RollbackError takes an error value returned by Apply and returns the error, if any, that occurred when attempting to roll back from a failed update.

# Constants

Daily will schedule next day and repeat it every day after.
Hourly will schedule in the next hour and repeat it every hour after.
Monthly will schedule next month and repeat it every month after.
None will not schedule.

# Variables

ErrNotSupported is returned by `Manage` when it is not possible to manage the current application.
LogDebug will be called to log any reason that prevented an executable update, because there wasn't any available detected.
LogError will be called to log any reason that have prevented an executable update.
LogInfo will be called to log any reason that prevented an executable update due to a "user" decision via one of the callback.

# Structs

Config define extra parameter necessary to manage the updating process.
HTTPSource provide a Source that will download the update from a HTTP url.
Options give additional parameters when calling Apply.
Schedule define when to trigger an update.
ScheduleAt define when a repeating update at a specific time should be triggered.
Updater is managing update for your application in the background.
Version define an executable versionning information.

# Interfaces

Patcher defines an interface for applying binary patches to an old item to get an updated item.
Source define an interface that is able to get an update.
Verifier defines an interface for verfiying an update's signature with a public key.

# Type aliases

Repeating pattern for scheduling update at a specific time.