updater

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2020 License: MIT Imports: 17 Imported by: 1

README

updater-go

Library that heps verifying/updating go binary with new version

Usage example

package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"strings"

	"github.com/hellofresh/updater-go"
	"github.com/palantir/stacktrace"
	log "github.com/sirupsen/logrus"
)

const (
	githubOwner = "hellofresh"
	githubRepo  = "jetstream"
)

func main() {
	var (
		updateToVersion string
		ghToken string
	)
	flag.StringVar(&updateToVersion, "version", "", "update to a particular version instead of the latest stable")
	flag.StringVar(&ghToken, "token", "", "GitHub token to use for Github access")

	flag.Parse()

	// Check to which version we need to update
	versionFilter := updater.StableRelease
	if updateToVersion != "" {
		versionFilter = func(name string, _ bool, _ bool) bool {
		return updateToVersion == name
		}
	}

	// Create release locator
	locator := updater.NewGithubClient(
		githubOwner,
		githubRepo,
		ghToken,
		versionFilter,
		func(asset string) bool {
			return strings.Contains(asset, fmt.Sprintf("-%s-%s-", runtime.GOARCH, runtime.GOOS))
		},
	)

	// Find the release
	updateTo, err := locateRelease(locator, updateToVersion)
	if rootErr := stacktrace.RootCause(err); rootErr == updater.ErrNoRepository {
		log.Error("Unable to access the Jetstream repository.\n  This is probably due to insufficient privileges of the access token.")
		os.Exit(1)
	}
	failOnError(err, "failed to retrieve the update release")

	// Fetch the release and update
	err = updater.SelfUpdate(updateTo)
	failOnError(err, "failed to update to version %s")

	fmt.Printf("Successfully updated to version %s!\n", updateTo.Name)
}

func failOnError(err error, message string) {
	if err != nil {
		log.WithError(err).Error(message)
		os.Exit(1)
	}
}

func locateRelease(locator updater.ReleaseLocator, version string) (updater.Release, error) {
	// No specific version use the latest
	if version == "" {
		return updater.LatestRelease(locator)
	}

	// Find a specific release
	var release updater.Release
	updates, err := locator.ListReleases(1)
	if err != nil {
		return release, err
	}

	if len(updates) == 0 {
		return release, fmt.Errorf("unable to locate release %s", version)
	}

	if len(updates) > 1 {
		return release, fmt.Errorf("multiple releases locate for %s", version)
	}

	return updates[0], nil
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoRepository error is returned is the repository is not found or user token has no access to it
	ErrNoRepository = errors.New("no repository")
)

Functions

func Apply

func Apply(update io.Reader, targetPath string, targetMode os.FileMode) error

Apply performs an update of the current executable (or opts.TargetFile, if set) with the contents of the given io.Reader.

Apply performs the following actions to ensure a safe cross-platform update:

  • Creates a new file, /path/to/.target.new with the TargetMode with the contents of the updated file
  • Renames /path/to/target to /path/to/.target.old
  • Renames /path/to/.target.new to /path/to/target
  • If the final rename is successful, deletes /path/to/.target.old, returns no error. On Windows, the removal of /path/to/target.old always fails, so instead Apply hides the old file instead.
  • If the final rename fails, attempts to roll back by renaming /path/to/.target.old back to /path/to/target.

If the roll back operation fails, the file system is left in an inconsistent state where there is no new executable file and the old executable file could not be be moved to its original location. In this case you should notify the user of the bad news and ask them to recover manually. Applications can determine whether the rollback failed by calling RollbackError, see the documentation on that function for additional detail.

func RegisterFormat

func RegisterFormat(name string, extractor Extractor)

RegisterFormat adds a supported archive format

func SelfUpdate

func SelfUpdate(release Release) error

SelfUpdate update the current executable to the release

func StableRelease

func StableRelease(_ string, draft bool, preRelease bool) bool

StableRelease filters out any release that is a draft or pre-release

Types

type AssetFilter

type AssetFilter func(asset string) bool

AssetFilter is a function that will filter out unsupported assets for the current system

type BinaryFilter

type BinaryFilter func(path os.FileInfo) bool

BinaryFilter is a function used to check if a given path/file is the binary needed

type Extractor

type Extractor interface {
	// Match checks supported files
	Match(filename string) bool
	// FetchBinary reads an archive and find return the reader for the binary based on the filter
	FetchBinary(input io.Reader, isBinary BinaryFilter) (io.Reader, error)
}

Extractor represent a archive extractor

func MatchingExtractor

func MatchingExtractor(path string) Extractor

MatchingExtractor returns the first extractor that matches the given file, or nil if there is no match

type GithubLocator

type GithubLocator struct {
	// contains filtered or unexported fields
}

GithubLocator struct encapsulates information about github repo

func NewGithubClient

func NewGithubClient(
	owner string,
	repository string,
	token string,
	releaseFilter ReleaseFilter,
	assetFilter AssetFilter,
	connectionTimeout time.Duration,
) *GithubLocator

NewGithubClient creates new github locator instance

func (*GithubLocator) ListReleases

func (g *GithubLocator) ListReleases(amount int) ([]Release, error)

ListReleases returns available GH releases list

type HTTPDownloader

type HTTPDownloader struct {
	// contains filtered or unexported fields
}

HTTPDownloader represents http downloader client

func NewHTTPDownloader

func NewHTTPDownloader(client *http.Client) *HTTPDownloader

NewHTTPDownloader creates new http downloader client instance. If the passed client is nil http.DefaultClient is used.

func (*HTTPDownloader) Fetch

func (d *HTTPDownloader) Fetch(r Release) (io.ReadCloser, error)

Fetch downloads GH release

type Release

type Release struct {
	// Name the name of the release. In most cases this will be the version number
	Name string
	// Assert the name of the asset related to the URL
	Asset string
	// URL the download location of the Asset
	URL string
}

Release contains information about a release for the current system

func LatestRelease

func LatestRelease(locator ReleaseLocator) (Release, error)

LatestRelease retrieve the latest release from the locator using semver

func SelfUpdateToLatest

func SelfUpdateToLatest(locator ReleaseLocator) (Release, error)

SelfUpdateToLatest update the current executable to it's latest version

type ReleaseDownloader

type ReleaseDownloader interface {
	// Fetch downloads the release
	Fetch(r Release) (io.ReadCloser, error)
}

ReleaseDownloader describes a way to download/load a release

var (
	// ErrNoRelease error is returned in case no available releases were found.
	ErrNoRelease = errors.New("no releases were found")

	// DefaultDownloader the default downloaded to use.
	DefaultDownloader ReleaseDownloader
)

type ReleaseFilter

type ReleaseFilter func(name string, draft bool, preRelease bool) bool

ReleaseFilter is a function that will filter out releases. This is very useful when you want to support stable, beta and dev channels.

type ReleaseLocator

type ReleaseLocator interface {
	ListReleases(amount int) ([]Release, error)
}

ReleaseLocator describing a release locator that will fetch releases. A release locator should use the ReleaseFilter and AssetFilter during initialization.

type RollbackErr

type RollbackErr struct {

	// RollbackErr the error encountered while rolling back
	RollbackErr error
	// contains filtered or unexported fields
}

RollbackErr represents an error occurred during rollback operation

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL