consider draft/prerelease and remember asset URL
This commit is contained in:
parent
49bc104362
commit
7cdec8424f
|
@ -10,6 +10,7 @@ import (
|
|||
const version = "1.2.3"
|
||||
|
||||
func selfUpdate() error {
|
||||
selfupdate.EnableLog()
|
||||
up, err := selfupdate.TryUpdate(version, "go-github-selfupdate", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -29,7 +30,7 @@ func usage() {
|
|||
func main() {
|
||||
help := flag.Bool("help", false, "Show this help")
|
||||
ver := flag.Bool("version", false, "Show version")
|
||||
selfupdate := flag.Bool("selfupdate", false, "Try go-github-selfupdate via GitHub")
|
||||
update := flag.Bool("selfupdate", false, "Try go-github-selfupdate via GitHub")
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
|
@ -44,7 +45,7 @@ func main() {
|
|||
os.Exit(0)
|
||||
}
|
||||
|
||||
if *selfupdate {
|
||||
if *update {
|
||||
if err := selfUpdate(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -20,6 +21,47 @@ type ReleaseDetector struct {
|
|||
apiCtx context.Context
|
||||
}
|
||||
|
||||
func findSuitableReleaseAndAsset(rels []*github.RepositoryRelease) (*github.RepositoryRelease, *github.ReleaseAsset, bool) {
|
||||
// Generate candidates
|
||||
cs := make([]string, 0, 8)
|
||||
for _, sep := range []rune{'_', '-'} {
|
||||
for _, ext := range []string{"zip", "tar.gz"} {
|
||||
suffix := fmt.Sprintf("%s%c%s.%s", runtime.GOOS, sep, runtime.GOARCH, ext)
|
||||
cs = append(cs, suffix)
|
||||
if runtime.GOOS == "windows" {
|
||||
suffix = fmt.Sprintf("%s%c%s.exe.%s", runtime.GOOS, sep, runtime.GOARCH, ext)
|
||||
cs = append(cs, suffix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, rel := range rels {
|
||||
if rel.GetDraft() {
|
||||
log.Println("Skip draft version", rel.GetTagName())
|
||||
continue
|
||||
}
|
||||
if rel.GetPrerelease() {
|
||||
log.Println("Skip pre-release version", rel.GetTagName())
|
||||
continue
|
||||
}
|
||||
if !reVersion.MatchString(rel.GetTagName()) {
|
||||
log.Println("Skip version not adopting semver", rel.GetTagName())
|
||||
continue
|
||||
}
|
||||
for _, asset := range rel.Assets {
|
||||
name := asset.GetName()
|
||||
for _, c := range cs {
|
||||
if strings.HasSuffix(name, c) {
|
||||
return rel, &asset, true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Could no find any release for", runtime.GOOS, "and", runtime.GOARCH)
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
// NewDetector crates a new detector instance. It initializes GitHub API client.
|
||||
func NewDetector() *ReleaseDetector {
|
||||
token := os.Getenv("GITHUB_TOKEN")
|
||||
|
@ -36,14 +78,14 @@ func NewDetector() *ReleaseDetector {
|
|||
}
|
||||
|
||||
// DetectLatest tries to get the latest version of the repository on GitHub. 'slug' means 'owner/name' formatted string.
|
||||
func (d *ReleaseDetector) DetectLatest(slug string) (ver semver.Version, found bool, err error) {
|
||||
func (d *ReleaseDetector) DetectLatest(slug string) (release *Release, found bool, err error) {
|
||||
repo := strings.Split(slug, "/")
|
||||
if len(repo) != 2 || repo[0] == "" || repo[1] == "" {
|
||||
err = fmt.Errorf("Invalid slug format. It should be 'owner/name': %s", slug)
|
||||
return
|
||||
}
|
||||
|
||||
rel, res, err := d.api.Repositories.GetLatestRelease(d.apiCtx, repo[0], repo[1])
|
||||
rels, res, err := d.api.Repositories.ListReleases(d.apiCtx, repo[0], repo[1], nil)
|
||||
if err != nil {
|
||||
log.Println("API returned an error response:", err)
|
||||
if res.StatusCode == 404 {
|
||||
|
@ -55,23 +97,27 @@ func (d *ReleaseDetector) DetectLatest(slug string) (ver semver.Version, found b
|
|||
return
|
||||
}
|
||||
|
||||
rel, asset, found := findSuitableReleaseAndAsset(rels)
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
|
||||
tag := rel.GetTagName()
|
||||
log.Println("Successfully fetched the latest release. tag:", tag, ", name:", rel.GetName(), ", URL:", rel.GetURL())
|
||||
url := asset.GetBrowserDownloadURL()
|
||||
log.Println("Successfully fetched the latest release. tag:", tag, ", name:", rel.GetName(), ", URL:", rel.GetURL(), ", Asset:", url)
|
||||
|
||||
// Strip version prefix
|
||||
if indices := reVersion.FindStringIndex(tag); indices != nil && indices[0] > 0 {
|
||||
log.Println("Strip prefix of version:", tag[:indices[0]])
|
||||
tag = tag[indices[0]:]
|
||||
}
|
||||
|
||||
ver, err = semver.Make(tag)
|
||||
if err == nil {
|
||||
found = true
|
||||
}
|
||||
|
||||
release = &Release{AssetURL: url}
|
||||
release.Version, err = semver.Make(tag)
|
||||
return
|
||||
}
|
||||
|
||||
// DetectLatest detects the latest release of the slug (owner/repo).
|
||||
func DetectLatest(slug string) (semver.Version, bool, error) {
|
||||
func DetectLatest(slug string) (*Release, bool, error) {
|
||||
return NewDetector().DetectLatest(slug)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package selfupdate
|
|||
import (
|
||||
"github.com/blang/semver"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -15,15 +16,21 @@ func TestGitHubTokenEnv(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDetectReleaseWithVersionPrefix(t *testing.T) {
|
||||
v, ok, err := DetectLatest("rhysd/github-clone-all")
|
||||
r, ok, err := DetectLatest("rhysd/github-clone-all")
|
||||
if err != nil {
|
||||
t.Fatal("Fetch failed:", err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatal("Failed to detect latest")
|
||||
}
|
||||
if v.LE(semver.MustParse("2.0.0")) {
|
||||
t.Fatal("Incorrect version:", v)
|
||||
if r == nil {
|
||||
t.Fatal("Release detected but nil returned for it")
|
||||
}
|
||||
if r.Version.LE(semver.MustParse("2.0.0")) {
|
||||
t.Fatal("Incorrect version:", r.Version)
|
||||
}
|
||||
if !strings.HasSuffix(r.AssetURL, ".zip") && !strings.HasSuffix(r.AssetURL, ".tar.gz") {
|
||||
t.Fatal("Incorrect URL for asset:", r.AssetURL)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
var log = stdlog.New(os.Stderr, "", stdlog.Ltime)
|
||||
var logEnabled = true
|
||||
var log = stdlog.New(ioutil.Discard, "", stdlog.Ltime)
|
||||
var logEnabled = false
|
||||
|
||||
// EnableLog enables to output logging messages in library
|
||||
func EnableLog() {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package selfupdate
|
||||
|
||||
import (
|
||||
"github.com/blang/semver"
|
||||
)
|
||||
|
||||
// Release represents a release asset for current OS and arch.
|
||||
type Release struct {
|
||||
Version semver.Version
|
||||
AssetURL string
|
||||
}
|
Loading…
Reference in New Issue