Make sure to fork this repo first as you need to configure some settings
get self-update library using
go get selfupdate.blockthrough.com@latest
install the self-update cli
go install selfupdate.blockthrough.com/cmd/selfupdate@latest
create public/private key pair
selfupdate crypto keys
create two repository secret
variables using the provide the link below. Make sure the change the example-cli
with your project name
- EXAMPLE_CLI_SELFUPDATE_PRIVATE_KEY, and put the content of
selfupdate.key
- EXAMPLE_CLI_SELFUPDATE_PUBLIC_KEY, and put the content of
selfupdate.pub
https://github.com/alinz/example-cli/settings/secrets/actions
NOTE: make sure to keep
selfupdate.key
safe as it will be used to sign the binary of your program
Create a fine-grain github token by going to this URL
- Click on
Generate new token
- Give your token a name
- Set your token an expiration based on your need
- Select your Organization from
Resource owner
that your project is - From
Repository access
selectOnly select repositories
and chose the repository and project that your cli is - From
Repository permission
, make sureContents
hasRead-only
access - Click on
Generate token
- Save that token as you won't be able to access it
add the following Go code to your main execution, it is recommended to add it at the beginning of the main function. Make sure to set these variables ownerName
, repoName
, execName
, according to your project needs. Version
and PublicKey
will be set during the build times so leave them empty
package main
import (
"context"
"fmt"
"os"
"selfupdate.blockthrough.com"
)
var (
Version = ""
PublicKey = ""
)
const (
ownerName = "alinz"
repoName = "example-cli"
execName = "example-cli"
)
func main() {
runUpdate()
// this is the rest of your main function
// ...
}
func runUpdate() {
// In order for selfupdating to work, the following conditions must be met:
// 1. Version must be set
// 2. EXAMPLE_CLI_GH_TOKEN must be set
// 3. PublicKey must be set
// for setting up the token please refer to
// "Create a Fine-Grained Personal Access Tokens" in README.md
ghToken, ok := os.LookupEnv("EXAMPLE_CLI_GH_TOKEN")
if !ok {
fmt.Fprintf(os.Stderr, "Warning: EXAMPLE_CLI_GH_TOKEN env is not set, selfupdating is disabled")
return
}
selfupdate.Auto(
context.Background(), // Context
ownerName, // Owner Name
repoName, // Repo Name
Version, // Current Version
execName, // Executable Name,
ghToken, // Github Token
PublicKey, // Public Key
)
}
Create a new Github actions workflow as follows
name: Build and Release
on:
push:
tags:
- "v*"
jobs:
build:
runs-on: ubuntu-latest
permissions: write-all
env:
EXAMPLE_CLI_OWNER: alinz
EXAMPLE_CLI_REPO: example-cli
EXAMPLE_CLI_GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EXAMPLE_CLI_PRIVATE_KEY: ${{ secrets.EXAMPLE_CLI_SELFUPDATE_PRIVATE_KEY }}
EXAMPLE_CLI_PUBLIC_KEY: ${{ secrets.EXAMPLE_CLI_SELFUPDATE_PUBLIC_KEY }}
EXAMPLE_CLI_VERSION: ${{ github.ref_name }}
steps:
- name: Setup Go 1.22
uses: actions/setup-go@v3
with:
go-version: ^1.22
- name: Setup Repo
uses: actions/checkout@v3
- name: Install latest selfupdate cli
run: go install selfupdate.blockthrough.com/cmd/selfupdate@latest
- name: Create a Release
run: |
selfupdate github release \
--owner ${{ env.EXAMPLE_CLI_OWNER }} \
--repo ${{ env.EXAMPLE_CLI_REPO }} \
--version ${{ env.EXAMPLE_CLI_VERSION }} \
--title ${{ env.EXAMPLE_CLI_VERSION }} \
--token ${{ env.EXAMPLE_CLI_GH_TOKEN }}
- name: Build Darwin arm64
run: |
GOOS=darwin GOARCH=arm64 go build \
-ldflags "-X main.Version=${{ env.EXAMPLE_CLI_VERSION }} -X main.PublicKey=${{ env.EXAMPLE_CLI_PUBLIC_KEY }}" \
-o ./example-cli-darwin-arm64 \
./main.go
- name: Upload Darwin arm64
run: |
selfupdate github upload \
--owner blockthrough \
--repo selfupdate.go \
--filename example-cli-darwin-arm64.sign \
--version ${{ env.EXAMPLE_CLI_VERSION }} \
--token ${{ env.EXAMPLE_CLI_GH_TOKEN }} \
--key ${{ env.EXAMPLE_CLI_PRIVATE_KEY }} < ./example-cli-darwin-arm64
selfupdate github upload \
--owner blockthrough \
--repo selfupdate.go \
--filename example-cli-darwin-arm64 \
--version ${{ env.EXAMPLE_CLI_VERSION }} \
--token ${{ env.EXAMPLE_CLI_GH_TOKEN }} < ./example-cli-darwin-arm64
Make sure everyone sets EXAMPLE_CLI_GH_TOKEN
in their system as an env and sets it to the fine-grain token which was described in Step 5
Compile the code
go build -ldflags "-X main.Version=v0.0.0 -X main.PublicKey=PUBLIC_KEY" -o ./example-cli ./main.go
then run the code
./example-cli
you should be able to see the code is updating and running the code again
downloading new version (v0.0.1)...done
running new version...
Version
args: [/Users/ali/Documents/ali/projects/example-cli/example-cli-downloaded]