golang的私有化定制自动更新插件
shenwc
2024-11-26 5a1d99989fa32be1684b9290b4a58e8418b7b92d
stores/github/github.go
New file
@@ -0,0 +1,148 @@
// 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
}