selfupdate

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Sep 11, 2024 License: Apache-2.0 Imports: 18 Imported by: 1

README

Self Update for Golang

It's a dead-simple toolchain for updating Golang binaries. It is designed to leverage Github's Releases and Actions. It comes with its CLI and SDK to make things even simpler.

CLI Installation

go install selfupdate.blockthough.com/cmd/selfupdate@latest

CLI Usage

selfupdate's cli consists of a couple of handy commands which are described as follows

NOTE: all the helper commands can be accessed via --help or -h

crypto

it's a set of tools and commands that help generate public/private keys, sign and verify content

keys

generates a pair of public and private keys

selfupdate crypto keys
sign

sign a binary using a private key. The private key must be passed as an argument using --key

selfupdate crypto sign --key "CONTENT OF PRIVATE KEY" < ./bin/file > ./bin/file.sig
verify

verify a binary using a public key. The public key must be passed as an argument using --key

selfupdate crypto verify --key "CONTENT OF PUBLIC KEY"  < ./bin/file.sg > ./bin/file
github

a provider tool for working with Github's apis for releasing, uploading and downloading binaries.

NOTE: an environment variable, SELF_UPDATE_GH_TOKEN, needs to be created and set with GITHUB_TOKEN. It is highly recommened to use it GITHUB_TOKEN rather than personal token. Also, this command with all its sub commands needs to be called inside github's actions workflow.

check

check if there is a new version by providing the version

selfupdate github check --owner blockthough --repo selfupdate.go --filename selfupdate --version v0.0.1

for more info, run selfupdate github check --help

release

To provide a better developer experience, this command can create a new Github release, with a title, and a description and attach it to a specific tag.

NOTE: running this command with the same version will be noop. So it can be safely used in github actions workflow with matrix strategy.

selfupdate github release -owner blockthough --repo selfupdate.go --token GITHUB_TOKEN --version v0.0.1 --title version v0.0.1 --desc "this is an amazin release"

for more info, run selfupdate github release --help

upload

upload a new asset to an already created Github release. If required to sign the binary file before upload, provide --key with the content of the generated private key.

In order to upload assets, a github release must be created first. Please refer to release subcommand. Also this command can be used multiple times for each individual asset in github actions workflow.

selfupdate github upload -owner blockthough --repo selfupdate.go --token GITHUB_TOKEN --version v0.0.1 --filename selfupload.sign --key PRIVATE_KEY < /path/to/file
download

To download a specific asset from Github releases, this command can be used. It requires --filename and --version to be presented.

selfupdate github download -owner blockthough --repo selfupdate.go --version v0.0.1 --filename selfupload.sign --key PUBLIC_KEY > /path/to/file

Usage

To have successful self-updating binaries, two steps need to be followed:

( 1 ) Github Actions Workflow

First, compile your code and generate a binary, make sure to use -ldflags "-X main.Version=${{ github.ref_name }} -X main.PublicKey=${{ PUBLIC_KEY }}" flag during go build to inject the new tag as a version into the binary.

  • Create a new Release using selfupdate github release command
  • Sign and upload content using selfupdate github upload
( 2 ) Using selfudpate SDK inside the binary

inside the go project install the SKD by running the following command:

go get selfupdate.blockthrough.com@latest

selfupdate.go SDK is very comprehensive, but the majority of the projects can only call the single function at the beginning of the program.

package main

import (
    // ...
    "selfupdate.blockthrough.com"
    // ...
)


const (
    Version = ""
    PublicKey = ""
)

func main() {
    // NOTE: please refer to "Create a Fine-Grained Personal Access Tokens" section of doc
    ghToken, ok := os.LookupEnv("MY_AWESOME_PROJECT_GITHUB_TOKEN")
    if !ok {
        // error out that github token is not presented
    }

    selfupdate.Auto(
		context.Background(), // Context
		"blockthrough",       // Owner Name
		"selfupdate.go",      // Repo Name
		Version,              // Current Version
		"selfupdate",         // Executable Name,
		ghToken,              // Github Token
		PublicKey,            // Public Key
    )

    // rest of the program
}

selfupdate.Auto function automatically checks, downloads, patches and re-runs the previously issued command.

Example

selfupdate CLI is using itself for self-updating. Please refer to both cmd/selfupdate/main.go and .github/workflows/build.yml files for more info.

Create Fine-Grained Personal Access Tokens

Each person who needs to use your app CLI and leverage the self-updating is required to create a GitHub API token. It is recommended to use the following Token/Settings to generate the API keys.

The only required option is to select the project, and on Repository Permissions, select only Contents as Read access. We only need to read the metadata and download assets during the update, nothing more.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrGithubReleaseNotFound = errors.New("github release not found")
	ErrGithubRedirect        = errors.New("github redirect")
)
View Source
var (
	ErrNoNewVersion = errors.New("no new version")
)
View Source
var (
	ErrVerificationFailed = errors.New("verification failed")
)

Functions

func Auto

func Auto(ctx context.Context, owner string, repo string, currentVersion string, filename string, ghToken string, publicKey string)

func WithGithubVersionCompare added in v1.0.1

func WithGithubVersionCompare(fn func(a, b string) bool) githubOptFn

Types

type Checker

type Checker interface {
	Check(ctx context.Context, filename string, currentVersion string) (newVersion string, desc string, err error)
}

type Downloader

type Downloader interface {
	Download(ctx context.Context, name string, version string) io.ReadCloser
}

type Github

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

func NewGithub

func NewGithub(token, repoOwner, repoName string, optFns ...githubOptFn) *Github

func (*Github) Check

func (g *Github) Check(ctx context.Context, filename string, currentVersion string) (newVersion string, desc string, err error)

func (*Github) DeleteAsset

func (g *Github) DeleteAsset(ctx context.Context, filename string, version string) (err error)

func (*Github) Download

func (g *Github) Download(ctx context.Context, name string, version string) io.ReadCloser

func (*Github) GetReleaseIDByVersion

func (g *Github) GetReleaseIDByVersion(ctx context.Context, version string) (int64, error)

func (*Github) Release

func (g *Github) Release(ctx context.Context, tag string, releaseTitle string, releaseBody string) error

func (*Github) Upload

func (g *Github) Upload(ctx context.Context, filename string, version string, r io.Reader) error

type Patcher

type Patcher interface {
	Patch(ctx context.Context, patch io.Reader) error
}

func NewPatcher

func NewPatcher(outfile string) Patcher

type PatcherFunc

type PatcherFunc func(ctx context.Context, patch io.Reader) error

func (PatcherFunc) Patch

func (f PatcherFunc) Patch(ctx context.Context, patch io.Reader) error

type Runner

type Runner interface {
	Run(ctx context.Context) error
}

func NewCliRunner

func NewCliRunner(path string, args ...string) Runner

NewCliRunner rerun the an executable with the same arguments. it requires the first argument to be the path to the executable.

type RunnerFunc

type RunnerFunc func(ctx context.Context) error

func (RunnerFunc) Run

func (f RunnerFunc) Run(ctx context.Context) error

type Signer

type Signer interface {
	Sign(ctx context.Context, r io.Reader) io.Reader
}

func NewHashSigner

func NewHashSigner(privateKey crypto.PrivateKey) Signer

type SignerFunc

type SignerFunc func(ctx context.Context, r io.Reader) io.Reader

func (SignerFunc) Sign

func (f SignerFunc) Sign(ctx context.Context, r io.Reader) io.Reader

type Uploader

type Uploader interface {
	Upload(ctx context.Context, filename string, version string, r io.Reader) error
}

type Verifier

type Verifier interface {
	Verify(ctx context.Context, r io.Reader) io.Reader
}

func NewHashVerifier

func NewHashVerifier(publicKey crypto.PublicKey) Verifier

type VerifierFunc

type VerifierFunc func(ctx context.Context, r io.Reader) io.Reader

func (VerifierFunc) Verify

func (f VerifierFunc) Verify(ctx context.Context, r io.Reader) io.Reader

Directories

Path Synopsis
cmd
selfupdate command
pkg
cli
env

Jump to

Keyboard shortcuts

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