Transforming multi-git to a Self-Updateable Program
In this lesson, we'll use the `go-github-update` third party library to make multi-git self-updateable by checking the latest release and fetch it if it is newer than the running program.
We'll cover the following
Using go-github-selfupdate
The go-github-selfupdate library has many things going for it:
- It automatically detects the latest version of the released binary on GitHub
- It retrieves the proper binary for the OS and arch where the binary is running
- It updates the binary with rollback support on failure
- It is tested on Linux, macOS and Windows (using Travis CI and AppVeyor)
- It supports many archive and compression formats (zip, tar, gzip, xzip)
- It supports private repositories
- It supports GitHub Enterprise
- It supports hash and signature validation
To detect the latest version, it requires a semantic versioning scheme. Letβs see how we can implement an auto-update functionality for multi-git.
To simplify matters letβs remove the embedded git tag and build a timestamp. We will replace them with an explicit version variable:
package main
import (
"fmt"
"log"
"github.com/blang/semver"
"github.com/rhysd/go-github-selfupdate/selfupdate"
"github.com/the-gigi/multi-git/cmd"
)
const (
version = "v0.8.18"
)
In the main() function, we will parse the version using the semver package and then call selfupdate.UpdateSelf(the-gigi/multi-git)
:
func main() {
fmt.Println("version: ", version)
v := semver.MustParse(version[1:])
latest, err := selfupdate.UpdateSelf(v, "the-gigi/multi-git")
if err != nil {
log.Fatalf("Binary update failed: %v", err)
return
} else {
fmt.Println("Current version is:", latest.Version)
}
cmd.Execute()
}
The selfupdate
package does the rest:
- Compares the latest release tag against current version
- Updates if necessary
- Displays the error message or the new version
Auto-updating with new releases
Letβs see it in action. Before making changes we have:
$ multi-git -h | grep version
version: v0.8.18
Current version is: 0.8.18
Now, letβs update the version to 0.8.19
const (
version = "v0.8.19"
)
Then, add commit, push and tag:
(π)/multi-git/
$ git add -A .
(π)/multi-git/
$ git commit -m "bump version to v0.8.19"
[master e78e9be] bump version to v0.8.19
1 file changed, 1 insertion(+), 1 deletion(-)
(π)/multi-git/
$ git push
Enumerating objects: 5, done.
Delta compression using up to 16 threads
Total 3 (delta 2), reused 0 (delta 0)
To github.com:the-gigi/multi-git.git
refs/heads/master:refs/heads/master 172b801..e78e9be
Done
(π)/multi-git/
$ git push --tags
Total 0 (delta 0), reused 0 (delta 0)
To github.com:the-gigi/multi-git.git
* [new tag] v0.8.19 -> v0.8.19
Now, we need to wait for the workflow to finish and once release v0.8.19 is ready on GitHub, we can run multi-git again, using the same executable:
(π)/multi-git/
$ multi-git -h | grep version
version: v0.8.18
Current version is: 0.8.19
Multi-git was automatically updated to 0.8.19. Letβs run it again to make sure:
(π)/multi-git/
$ multi-git -h | grep version
version: v0.8.19
Current version is: 0.8.19
Get hands-on with 1400+ tech skills courses.