Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement method to list releases #56

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 14 additions & 36 deletions selfupdate/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,21 +91,12 @@ func findReleaseAndAsset(rels []*github.RepositoryRelease,
targetVersion string,
filters []*regexp.Regexp) (*github.RepositoryRelease, *github.ReleaseAsset, semver.Version, bool) {
// Generate candidates
suffixes := make([]string, 0, 2*7*2)
for _, sep := range []rune{'_', '-'} {
for _, ext := range []string{".zip", ".tar.gz", ".tgz", ".gzip", ".gz", ".tar.xz", ".xz", ""} {
suffix := fmt.Sprintf("%s%c%s%s", runtime.GOOS, sep, runtime.GOARCH, ext)
suffixes = append(suffixes, suffix)
if runtime.GOOS == "windows" {
suffix = fmt.Sprintf("%s%c%s.exe%s", runtime.GOOS, sep, runtime.GOARCH, ext)
suffixes = append(suffixes, suffix)
}
}
}

var ver semver.Version
var asset *github.ReleaseAsset
var release *github.RepositoryRelease
var (
suffixes = assetSuffixes()
ver semver.Version
asset *github.ReleaseAsset
release *github.RepositoryRelease
)

// Find the latest version from the list of releases.
// Returned list from GitHub API is in the order of the date when created.
Expand Down Expand Up @@ -143,12 +134,12 @@ func (up *Updater) DetectLatest(slug string) (release *Release, found bool, err
// DetectVersion tries to get the given version of the repository on Github. `slug` means `owner/name` formatted string.
// And version indicates the required version.
func (up *Updater) DetectVersion(slug string, version string) (release *Release, found bool, err error) {
repo := strings.Split(slug, "/")
if len(repo) != 2 || repo[0] == "" || repo[1] == "" {
return nil, false, fmt.Errorf("Invalid slug format. It should be 'owner/name': %s", slug)
repo, err := parseRepo(slug)
if err != nil {
return nil, false, fmt.Errorf("parse slug: %v", err)
}

rels, res, err := up.api.Repositories.ListReleases(up.apiCtx, repo[0], repo[1], nil)
rels, res, err := up.api.Repositories.ListReleases(up.apiCtx, repo.owner, repo.name, nil)
if err != nil {
log.Println("API returned an error response:", err)
if res != nil && res.StatusCode == 404 {
Expand All @@ -164,23 +155,10 @@ func (up *Updater) DetectVersion(slug string, version string) (release *Release,
return nil, false, nil
}

url := asset.GetBrowserDownloadURL()
log.Println("Successfully fetched the latest release. tag:", rel.GetTagName(), ", name:", rel.GetName(), ", URL:", rel.GetURL(), ", Asset:", url)

publishedAt := rel.GetPublishedAt().Time
release = &Release{
ver,
url,
asset.GetSize(),
asset.GetID(),
-1,
rel.GetHTMLURL(),
rel.GetBody(),
rel.GetName(),
&publishedAt,
repo[0],
repo[1],
}
log.Println("Successfully fetched the latest release. tag:", rel.GetTagName(),
", name:", rel.GetName(), ", URL:", rel.GetURL(), ", Asset:", asset.GetBrowserDownloadURL())

release = newRelease(repo, rel, asset, &ver)

if up.validator != nil {
validationName := asset.GetName() + up.validator.Suffix()
Expand Down
49 changes: 49 additions & 0 deletions selfupdate/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package selfupdate

import (
"fmt"
"regexp"
"runtime"

"github.com/google/go-github/v30/github"
)

func findReleases(repo *repoInfo, rels []*github.RepositoryRelease, filters []*regexp.Regexp) ([]*Release, error) {
var (
suffixes = assetSuffixes()
found = make([]*Release, 0)
)
for _, rel := range rels {
asset, ver, ok := findAssetFromRelease(rel, suffixes, "", filters)
if ok {
found = append(found, newRelease(repo, rel, asset, &ver))
}
}
if len(found) == 0 {
return nil, fmt.Errorf("could not find any release for %s and %s", runtime.GOOS, runtime.GOARCH)
}
return found, nil
}

func (up *Updater) ListReleases(slug string) ([]*Release, bool, error) {
repo, err := parseRepo(slug)
if err != nil {
return nil, false, fmt.Errorf("parse slug: %v", err)
}

rels, _, err := up.api.Repositories.ListReleases(up.apiCtx, repo.owner, repo.name, nil)
if err != nil {
return nil, false, fmt.Errorf("list GitHub releases (owner=%q, name=%q): %v", repo.owner, repo.name, err)
}

releases, err := findReleases(repo, rels, up.filters)
if err != nil {
return nil, false, fmt.Errorf("find releases: %v", err)
}

return releases, true, nil
}

func ListReleases(slug string) ([]*Release, bool, error) {
return DefaultUpdater().ListReleases(slug)
}
20 changes: 20 additions & 0 deletions selfupdate/list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package selfupdate

import "testing"

func TestListReleases(t *testing.T) {
r, ok, err := ListReleases("rhysd/github-clone-all")
if err != nil {
t.Fatal("List releases:", err)
}
if !ok {
t.Fatalf("Failed to list releases")
}
if r == nil {
t.Fatal("Release detected but nil returned for it")
}
if len(r) != 7 {
t.Fatalf("The of releases does not match: got %d, expected %d", len(r), 7)
}
t.Logf("Found releases: %#v", r)
}
21 changes: 21 additions & 0 deletions selfupdate/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"time"

"github.com/blang/semver"
"github.com/google/go-github/v30/github"
)

// Release represents a release asset for current OS and arch.
Expand Down Expand Up @@ -31,3 +32,23 @@ type Release struct {
// RepoName is the name of the repository of the release
RepoName string
}

func newRelease(repo *repoInfo, release *github.RepositoryRelease,
asset *github.ReleaseAsset, version *semver.Version) *Release {

publishedAt := release.GetPublishedAt().Time

return &Release{
Version: *version,
AssetURL: asset.GetBrowserDownloadURL(),
AssetByteSize: asset.GetSize(),
AssetID: asset.GetID(),
ValidationAssetID: -1,
URL: release.GetHTMLURL(),
ReleaseNotes: release.GetBody(),
Name: release.GetName(),
PublishedAt: &publishedAt,
RepoOwner: repo.owner,
RepoName: repo.name,
}
}
22 changes: 22 additions & 0 deletions selfupdate/repoinfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package selfupdate

import (
"fmt"
"strings"
)

type repoInfo struct {
owner string
name string
}

func parseRepo(slug string) (*repoInfo, error) {
parts := strings.Split(slug, "/")
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
return nil, fmt.Errorf("invalid slug %q: it should be in the format %q", slug, "owner/name")
}
return &repoInfo{
owner: parts[0],
name: parts[1],
}, nil
}
21 changes: 21 additions & 0 deletions selfupdate/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package selfupdate

import (
"fmt"
"runtime"
)

func assetSuffixes() []string {
suffixes := make([]string, 0, 2*7*2)
for _, sep := range []rune{'_', '-'} {
for _, ext := range []string{".zip", ".tar.gz", ".tgz", ".gzip", ".gz", ".tar.xz", ".xz", ""} {
suffix := fmt.Sprintf("%s%c%s%s", runtime.GOOS, sep, runtime.GOARCH, ext)
suffixes = append(suffixes, suffix)
if runtime.GOOS == "windows" {
suffix = fmt.Sprintf("%s%c%s.exe%s", runtime.GOOS, sep, runtime.GOARCH, ext)
suffixes = append(suffixes, suffix)
}
}
}
return suffixes
}