From d0de60fba111ad7416e8546a4da6e6794e854be1 Mon Sep 17 00:00:00 2001 From: rhysd Date: Fri, 19 Jan 2018 17:47:21 +0900 Subject: [PATCH] enable to have enterprise base URL and upload URL --- selfupdate/detect.go | 2 +- selfupdate/detect_test.go | 2 +- selfupdate/update.go | 6 ++-- selfupdate/updater.go | 59 +++++++++++++++++++++++++++++++------- selfupdate/updater_test.go | 9 ++++-- 5 files changed, 61 insertions(+), 17 deletions(-) diff --git a/selfupdate/detect.go b/selfupdate/detect.go index b625aa6..ae04fc2 100644 --- a/selfupdate/detect.go +++ b/selfupdate/detect.go @@ -107,5 +107,5 @@ func (up *Updater) DetectLatest(slug string) (release *Release, found bool, err // DetectLatest detects the latest release of the slug (owner/repo). func DetectLatest(slug string) (*Release, bool, error) { - return NewUpdater(Config{}).DetectLatest(slug) + return DefaultUpdater().DetectLatest(slug) } diff --git a/selfupdate/detect_test.go b/selfupdate/detect_test.go index 38aef2c..b9fa6ba 100644 --- a/selfupdate/detect_test.go +++ b/selfupdate/detect_test.go @@ -128,7 +128,7 @@ func TestDetectNoRelease(t *testing.T) { } func TestInvalidSlug(t *testing.T) { - up := NewUpdater(Config{}) + up := DefaultUpdater() for _, slug := range []string{ "foo", diff --git a/selfupdate/update.go b/selfupdate/update.go index b30447d..0aabaec 100644 --- a/selfupdate/update.go +++ b/selfupdate/update.go @@ -124,7 +124,7 @@ func (up *Updater) UpdateSelf(current semver.Version, slug string) (*Release, er // 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 { - up := NewUpdater(Config{}) + up := DefaultUpdater() src, err := up.downloadDirectlyFromURL(assetURL) if err != nil { return err @@ -135,11 +135,11 @@ func UpdateTo(assetURL, cmdPath string) error { // UpdateCommand updates a given command binary to the latest version. // This function is a shortcut version of updater.UpdateCommand. func UpdateCommand(cmdPath string, current semver.Version, slug string) (*Release, error) { - return NewUpdater(Config{}).UpdateCommand(cmdPath, current, slug) + return DefaultUpdater().UpdateCommand(cmdPath, current, slug) } // UpdateSelf updates the running executable itself to the latest version. // This function is a shortcut version of updater.UpdateSelf. func UpdateSelf(current semver.Version, slug string) (*Release, error) { - return NewUpdater(Config{}).UpdateSelf(current, slug) + return DefaultUpdater().UpdateSelf(current, slug) } diff --git a/selfupdate/updater.go b/selfupdate/updater.go index 1804e6a..2e48373 100644 --- a/selfupdate/updater.go +++ b/selfupdate/updater.go @@ -2,6 +2,7 @@ package selfupdate import ( "context" + "errors" "net/http" "os" @@ -22,11 +23,25 @@ type Updater struct { type Config struct { // APIToken represents GitHub API token. If it's not empty, it will be used for authentication of GitHub API APIToken string - // TODO: Add host URL for API endpoint + // EnterpriseBaseURL is a base URL of GitHub API. If you want to use this library with GitHub Enterprise, + // please set "https://{your-organization-address}/api/v3/" to this field. + EnterpriseBaseURL string + // EnterpriseUploadURL is a URL to upload stuffs to GitHub Enterprise instance. This is often the same as an API base URL. + // So if this field is not set and EnterpriseBaseURL is set, EnterpriseBaseURL is also set to this field. + EnterpriseUploadURL string } -// NewUpdater crates a new detector instance. It initializes GitHub API client. -func NewUpdater(config Config) *Updater { +func newHTTPClient(ctx context.Context, token string) *http.Client { + if token == "" { + return http.DefaultClient + } + src := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) + return oauth2.NewClient(ctx, src) +} + +// NewUpdater creates a new updater instance. It initializes GitHub API client. +// If you set your API token to $GITHUB_TOKEN, the client will use it. +func NewUpdater(config Config) (*Updater, error) { token := config.APIToken if token == "" { token = os.Getenv("GITHUB_TOKEN") @@ -35,13 +50,37 @@ func NewUpdater(config Config) *Updater { token, _ = gitconfig.GithubToken() } ctx := context.Background() + hc := newHTTPClient(ctx, token) - auth := http.DefaultClient - if token != "" { - src := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) - auth = oauth2.NewClient(ctx, src) + var client *github.Client + if config.EnterpriseBaseURL == "" { + client = github.NewClient(hc) + } else { + if token == "" { + return nil, errors.New("GitHub API token cannot be empty when releases are hosted on GitHub Enterprise instance") + } + u := config.EnterpriseUploadURL + if u == "" { + u = config.EnterpriseBaseURL + } + var err error + client, err = github.NewEnterpriseClient(config.EnterpriseBaseURL, u, hc) + if err != nil { + return nil, err + } } - - client := github.NewClient(auth) - return &Updater{client, ctx, auth} + return &Updater{client, ctx, hc}, nil +} + +// DefaultUpdater creates a new updater instance with default configuration. +// It initializes GitHub API client with default API base URL. +// If you set your API token to $GITHUB_TOKEN, the client will use it. +func DefaultUpdater() *Updater { + token := os.Getenv("GITHUB_TOKEN") + if token == "" { + token, _ = gitconfig.GithubToken() + } + ctx := context.Background() + client := newHTTPClient(ctx, token) + return &Updater{github.NewClient(client), ctx, client} } diff --git a/selfupdate/updater_test.go b/selfupdate/updater_test.go index cb5b18b..03e3d5d 100644 --- a/selfupdate/updater_test.go +++ b/selfupdate/updater_test.go @@ -10,6 +10,11 @@ func TestGitHubTokenEnv(t *testing.T) { if token == "" { t.Skip("because $GITHUB_TOKEN is not set") } - _ = NewUpdater(Config{}) - _ = NewUpdater(Config{APIToken: token}) + _ = DefaultUpdater() + if _, err := NewUpdater(Config{}); err != nil { + t.Error("Failed to initialize updater with empty config") + } + if _, err := NewUpdater(Config{APIToken: token}); err != nil { + t.Error("Failed to initialize updater with API token config") + } }