// Package github provides a GitHub release store. package github import ( "context" "fmt" "runtime" "time" "github.com/google/go-github/github" update "github.com/zan8in/goupdate" "github.com/zan8in/goupdate/progress" ) // Store is the store implementation. type Store struct { Owner string Repo string Version string } type GithubResult struct { Status int // update success = 1; have latest version = 2; LatestVersion string } // 更新最新版本 // owner = zan8in // repo = afrog // version = 2.8.8 当前版本 func Update(owner, repo, version string) (*GithubResult, error) { var ( result = &GithubResult{} err error ) m := &update.Manager{ Command: repo + ".exe", Store: &Store{ Owner: owner, Repo: repo, Version: version, }, } // fetch the new releases releases, err := m.LatestReleases() if err != nil { return result, fmt.Errorf("error fetching releases: %s", err) } // no updates if len(releases) == 0 { result.Status = 2 return result, nil } // latest release latest := releases[0] // find the tarball for this system a := latest.FindZip(runtime.GOOS, runtime.GOARCH) if a == nil { return result, fmt.Errorf("no binary for your system") } // download tarball to a tmp dir tarball, err := a.DownloadProxy(progress.Reader) if err != nil { return result, fmt.Errorf("error downloading: %s", err) } // install it if err := m.Install(tarball); err != nil { return result, fmt.Errorf("error installing: %s", err) } // gologger.Info().Msgf("Successfully updated to %s %s\n", repo, version) result.LatestVersion = version result.Status = 1 return result, nil } // GetRelease returns the specified release or ErrNotFound. func (s *Store) GetRelease(version string) (*update.Release, error) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() gh := github.NewClient(nil) r, res, err := gh.Repositories.GetReleaseByTag(ctx, s.Owner, s.Repo, "v"+version) if res.StatusCode == 404 { return nil, update.ErrNotFound } if err != nil { return nil, err } return githubRelease(r), nil } // LatestReleases returns releases newer than Version, or nil. func (s *Store) LatestReleases() (latest []*update.Release, err error) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() gh := github.NewClient(nil) releases, _, err := gh.Repositories.ListReleases(ctx, s.Owner, s.Repo, nil) if err != nil { return nil, err } for _, r := range releases { tag := r.GetTagName() if tag == s.Version || "v"+s.Version == tag { break } latest = append(latest, githubRelease(r)) } return } // githubRelease returns a Release. func githubRelease(r *github.RepositoryRelease) *update.Release { out := &update.Release{ Version: r.GetTagName(), Notes: r.GetBody(), PublishedAt: r.GetPublishedAt().Time, URL: r.GetURL(), } for _, a := range r.Assets { out.Assets = append(out.Assets, &update.Asset{ Name: a.GetName(), Size: a.GetSize(), URL: a.GetBrowserDownloadURL(), Downloads: a.GetDownloadCount(), }) } return out }