mirror of
https://github.com/MedzikUser/go-github-selfupdate.git
synced 2024-08-15 03:25:29 +00:00
download an asset via GitHub Releases API by default
This commit is contained in:
parent
fd492d6b01
commit
6b4eeadeb7
5 changed files with 63 additions and 14 deletions
|
@ -92,10 +92,13 @@ func (up *Updater) DetectLatest(slug string) (release *Release, found bool, err
|
|||
release = &Release{
|
||||
AssetURL: url,
|
||||
AssetByteSize: asset.GetSize(),
|
||||
AssetID: asset.GetID(),
|
||||
URL: rel.GetHTMLURL(),
|
||||
ReleaseNotes: rel.GetBody(),
|
||||
Name: rel.GetName(),
|
||||
PublishedAt: &publishedAt,
|
||||
RepoOwner: repo[0],
|
||||
RepoName: repo[1],
|
||||
}
|
||||
|
||||
release.Version, err = semver.Make(tag)
|
||||
|
|
|
@ -36,9 +36,18 @@ func TestDetectReleaseWithVersionPrefix(t *testing.T) {
|
|||
if r.AssetByteSize == 0 {
|
||||
t.Error("Asset's size is unexpectedly zero")
|
||||
}
|
||||
if r.AssetID == 0 {
|
||||
t.Error("Asset's ID is unexpectedly zero")
|
||||
}
|
||||
if r.PublishedAt.IsZero() {
|
||||
t.Error("Release time is unexpectedly zero")
|
||||
}
|
||||
if r.RepoOwner != "rhysd" {
|
||||
t.Error("Repo owner is not correct:", r.RepoOwner)
|
||||
}
|
||||
if r.RepoName != "github-clone-all" {
|
||||
t.Error("Repo name was not properly detectd:", r.RepoName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectReleasesForVariousArchives(t *testing.T) {
|
||||
|
@ -82,9 +91,18 @@ func TestDetectReleasesForVariousArchives(t *testing.T) {
|
|||
if r.AssetByteSize == 0 {
|
||||
t.Error("Asset's size is unexpectedly zero")
|
||||
}
|
||||
if r.AssetID == 0 {
|
||||
t.Error("Asset's ID is unexpectedly zero")
|
||||
}
|
||||
if r.PublishedAt.IsZero() {
|
||||
t.Error("Release time is unexpectedly zero")
|
||||
}
|
||||
if r.RepoOwner != "rhysd-test" {
|
||||
t.Error("Repo owner should be rhysd-test:", r.RepoOwner)
|
||||
}
|
||||
if !strings.HasPrefix(r.RepoName, "test-release-") {
|
||||
t.Error("Repo name was not properly detectd:", r.RepoName)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ type Release struct {
|
|||
AssetURL string
|
||||
// AssetSize represents the size of asset in bytes
|
||||
AssetByteSize int
|
||||
// AssetID is the ID of the asset on GitHub
|
||||
AssetID int
|
||||
// URL is a URL to release page for browsing
|
||||
URL string
|
||||
// ReleaseNotes is a release notes of the release
|
||||
|
@ -21,4 +23,8 @@ type Release struct {
|
|||
Name string
|
||||
// PublishedAt is the time when the release was published
|
||||
PublishedAt *time.Time
|
||||
// RepoOwner is the owner of the repository of the release
|
||||
RepoOwner string
|
||||
// RepoName is the name of the repository of the release
|
||||
RepoName string
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package selfupdate
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -12,10 +13,26 @@ import (
|
|||
"github.com/inconshreveable/go-update"
|
||||
)
|
||||
|
||||
// UpdateTo download an executable from assetURL and replace the current binary with the downloaded one. cmdPath is a file path to command executable.
|
||||
func (up *Updater) UpdateTo(assetURL, cmdPath string) error {
|
||||
// TODO: Use GitHub API client to download assets
|
||||
func readAndUpdate(src io.ReadCloser, assetURL, cmdPath string) error {
|
||||
defer src.Close()
|
||||
|
||||
_, cmd := filepath.Split(cmdPath)
|
||||
asset, err := UncompressCommand(src, assetURL, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println("Will update", cmdPath, "to the latest downloaded from", assetURL)
|
||||
return update.Apply(asset, update.Options{
|
||||
TargetPath: cmdPath,
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateTo downloads an executable from assetURL and replace the current binary with the downloaded one.
|
||||
// This function is low-level API to update the binary. Because it does not use GitHub API and downloads asset directly from the URL via HTTP,
|
||||
// this function is not available to update a release for private repositories.
|
||||
// cmdPath is a file path to command executable.
|
||||
func UpdateTo(assetURL, cmdPath string) error {
|
||||
res, err := http.Get(assetURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to download a release file from %s: %s", assetURL, err)
|
||||
|
@ -25,17 +42,22 @@ func (up *Updater) UpdateTo(assetURL, cmdPath string) error {
|
|||
return fmt.Errorf("Failed to download a release file from %s", assetURL)
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
_, cmd := filepath.Split(cmdPath)
|
||||
asset, err := UncompressCommand(res.Body, assetURL, cmd)
|
||||
return readAndUpdate(res.Body, assetURL, cmdPath)
|
||||
}
|
||||
|
||||
// UpdateTo downloads an executable from GitHub Releases API and replace current binary with the downloaded one.
|
||||
// It downloads a release asset via GitHub Releases API so this function is available for update releases on private repository.
|
||||
// If a redirect occurs, it fallbacks into directly downloading from the redirect URL.
|
||||
func (up *Updater) UpdateTo(rel *Release, cmdPath string) error {
|
||||
src, redirectURL, err := up.api.Repositories.DownloadReleaseAsset(up.apiCtx, rel.RepoOwner, rel.RepoName, rel.AssetID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println("Will update", cmdPath, "to the latest downloaded from", assetURL)
|
||||
return update.Apply(asset, update.Options{
|
||||
TargetPath: cmdPath,
|
||||
})
|
||||
if redirectURL != "" {
|
||||
log.Println("Redirect URL was returned while trying to download a release asset from GitHub API. Falling back to downloading from asset URL directly:", redirectURL)
|
||||
return UpdateTo(redirectURL, cmdPath)
|
||||
}
|
||||
return readAndUpdate(src, rel.AssetURL, cmdPath)
|
||||
}
|
||||
|
||||
// UpdateCommand updates a given command binary to the latest version.
|
||||
|
@ -71,7 +93,7 @@ func (up *Updater) UpdateCommand(cmdPath string, current semver.Version, slug st
|
|||
return rel, nil
|
||||
}
|
||||
log.Println("Will update", cmdPath, "to the latest version", rel.Version)
|
||||
if err := up.UpdateTo(rel.AssetURL, cmdPath); err != nil {
|
||||
if err := up.UpdateTo(rel, cmdPath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rel, nil
|
||||
|
|
|
@ -237,7 +237,7 @@ func TestInvalidSlugForUpdate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestInvalidAssetURL(t *testing.T) {
|
||||
err := NewUpdater(Config{}).UpdateTo("https://github.com/rhysd/non-existing-repo/releases/download/v1.2.3/foo.zip", "foo")
|
||||
err := UpdateTo("https://github.com/rhysd/non-existing-repo/releases/download/v1.2.3/foo.zip", "foo")
|
||||
if err == nil {
|
||||
t.Fatal("Error should occur for URL not found")
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ func TestInvalidAssetURL(t *testing.T) {
|
|||
|
||||
func TestBrokenAsset(t *testing.T) {
|
||||
asset := "https://github.com/rhysd-test/test-incorrect-release/releases/download/invalid/broken-zip.zip"
|
||||
err := NewUpdater(Config{}).UpdateTo(asset, "foo")
|
||||
err := UpdateTo(asset, "foo")
|
||||
if err == nil {
|
||||
t.Fatal("Error should occur for URL not found")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue