From 2dd59be36222ef712a69d9c11b9cb8a1bcd86ace Mon Sep 17 00:00:00 2001 From: Felix Wiedmann Date: Wed, 5 Jun 2019 22:20:42 +0200 Subject: [PATCH] ref(releaser/github): uses now the google github libary --- go.mod | 3 +- internal/releaser/github.go | 89 ++++++++++++++++++----------------- internal/releaser/releaser.go | 88 ++++++++-------------------------- 3 files changed, 67 insertions(+), 113 deletions(-) diff --git a/go.mod b/go.mod index 89ee791..9a92235 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,9 @@ require ( github.com/Masterminds/semver v1.4.2 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect + github.com/google/go-github/v25 v25.1.1 github.com/sirupsen/logrus v1.4.1 - golang.org/x/net v0.0.0-20190311183353-d8887717615a // indirect + golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/src-d/go-git.v4 v4.11.0 gopkg.in/yaml.v2 v2.2.2 diff --git a/internal/releaser/github.go b/internal/releaser/github.go index e46cd47..475b19a 100644 --- a/internal/releaser/github.go +++ b/internal/releaser/github.go @@ -1,29 +1,23 @@ package releaser import ( - "encoding/json" + "context" "fmt" "github.com/Nightapes/go-semantic-release/pkg/config" - "io/ioutil" - "strings" + "github.com/google/go-github/v25/github" + "net/http" + "os" ) // GITHUB identifer for github interface const GITHUB = "github" -const githubCreateRleasURL = "https://api.github.com/repos" -const githubUploadAssetURL = "https://uploads.github.com" // GitHubReleaser type struct type GitHubReleaser struct { - repositoryURL string - authToken string - assets []config.Asset - Version string `json:"tag_name"` - Branch string `json:"target_commitish"` - ReleaseName string `json:"name"` - ReleaseMessage string `json:"body"` - Draft bool `json:"draft,omitempty"` - Prerelease bool `json:"prerelease,omitempty"` + config *config.ReleaseConfig + client *github.Client + context context.Context + release *github.RepositoryRelease } type gitHubCreateReleaseResponse struct { @@ -33,50 +27,57 @@ type gitHubCreateReleaseResponse struct { // NewGitHubReleaser initialize a new GitHubRelease func NewGitHubReleaser(c *config.ReleaseConfig) *GitHubReleaser { + ctx := context.Background() + httpClient := createHTTPClient(ctx, c.Github.AccessToken) + return &GitHubReleaser{ - repositoryURL: c.Github["url"], - authToken: c.Github["authToken"], - assets: c.Assets, + config: c, + client: github.NewClient(httpClient), + context: ctx, } } // CreateRelease creates release on remote -func (g *GitHubReleaser) CreateRelease(releaseName, releaseMessage, branch, version string) error { - g.ReleaseName = releaseName - g.ReleaseMessage = releaseMessage - g.Branch = branch - g.Version = version +func (g GitHubReleaser) CreateRelease(tag, releaseName, releaseMessage, targetBranch string) error { - repositoryURI := strings.TrimLeft(g.repositoryURL, "/") - jsonRelease, err := json.Marshal(g) + release, resp, err := g.client.Repositories.CreateRelease(g.context, g.config.Github.User, g.config.Github.URL, &github.RepositoryRelease{ + TagName: &tag, + TargetCommitish: &targetBranch, + Name: &releaseName, + Body: &releaseMessage, + Draft: &g.config.IsDraft, + Prerelease: &g.config.IsPreRelease, + }) if err != nil { - return fmt.Errorf("releaser: github: could not marshal GitHubReleaser struct. Error: %s", err.Error()) + return fmt.Errorf("releaser: github: Could not create release: %v", err) } - tempDir, err := ioutil.TempDir(".", "tempZipAssets") - if err != nil { - return fmt.Errorf("releaser: github: Could not create a temp directory. Error: %s", err.Error()) - } - assetList, err := prepareAssets(tempDir, g.assets) - if err != nil { - return err + if resp.StatusCode >= http.StatusBadRequest { + return fmt.Errorf("releaser: github: Could not create release: response statuscode: %s", resp.Status) } - response, err := makeReleaseRequest(githubCreateRleasURL+repositoryURI, g.authToken, jsonRelease) - if err != nil { - return err - } + g.release = release + return nil - releaseInfo := gitHubCreateReleaseResponse{} - if err := json.Unmarshal(response, &releaseInfo); err != nil { - return err - } +} - // tbd build new upload url - if err := uploadReleaseAssets(releaseInfo.AssetUploadURL, g.authToken, assetList); err != nil { - return err - } +// UploadAssets uploads specified assets +func (g GitHubReleaser) UploadAssets(assets []config.Asset) error { + for _, asset := range assets { + file, err := os.Open(asset.Name) + if err != nil { + return err + } + _, resp, err := g.client.Repositories.UploadReleaseAsset(g.context, g.config.Github.User, g.config.Github.URL, *g.release.ID, &github.UploadOptions{Name: asset.Name}, file) + if err != nil { + return err + } + + if resp.StatusCode >= http.StatusBadRequest { + return fmt.Errorf("releaser: github: Could not create release: response statuscode: %s", resp.Status) + } + } return nil } diff --git a/internal/releaser/releaser.go b/internal/releaser/releaser.go index adec996..4541a50 100644 --- a/internal/releaser/releaser.go +++ b/internal/releaser/releaser.go @@ -1,12 +1,12 @@ package releaser import ( - "archive/zip" - "bytes" + "context" "fmt" "github.com/Nightapes/go-semantic-release/pkg/config" - "io/ioutil" + "golang.org/x/oauth2" "net/http" + "os" ) // Releasers struct type @@ -16,7 +16,8 @@ type Releasers struct { // Releaser interface for providers type Releaser interface { - CreateRelease(releaseName, releaseMessage string) error + CreateRelease(tag, releaseName, releaseMessage, targetBranch string) error + UploadAssets(assets []config.Asset) error } // New initialize a Relerser @@ -37,78 +38,29 @@ func (r *Releasers) GetReleaser(releaserType string) (Releaser, error) { // tbd. http helper function -func makeReleaseRequest(url, authToken string, jsonRelease []byte) ([]byte, error) { - request, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(jsonRelease)) - request.Header.Set("Authorization", authToken) - request.Header.Set("content-type", "application/json") +func createHTTPClient(ctx context.Context, token string) *http.Client { + tokenSource := oauth2.StaticTokenSource(&oauth2.Token{ + AccessToken: token}, + ) - client := http.Client{} - defer client.CloseIdleConnections() + client := oauth2.NewClient(ctx, tokenSource) - response, err := client.Do(request) - - if err != nil { - return []byte{}, err - - } - bodyContent, _ := ioutil.ReadAll(response.Body) - - if response.StatusCode >= http.StatusMultipleChoices { - return []byte{}, fmt.Errorf("Could not create new release. HTTP %d: %s", response.StatusCode, string(bodyContent)) - } - - return bodyContent, nil + return client } -func uploadReleaseAssets(url, authToken string, assets []string) error { - body := []byte{} - request, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body)) - - request.Header.Set("Authorization", authToken) - client := http.Client{} - defer client.CloseIdleConnections() - - response, err := client.Do(request) - - if err != nil { - return err +func checkIfAssetsExists(assets []config.Asset) error { + var missingAssets []string + for _, asset := range assets { + if _, err := os.Stat(asset.Name); err != nil { + missingAssets = append(missingAssets, asset.Name) + } } - bodyContent, _ := ioutil.ReadAll(response.Body) - if response.StatusCode >= http.StatusMultipleChoices { - return fmt.Errorf("Could not create new release. HTTP %d: %s", response.StatusCode, string(bodyContent)) + if len(missingAssets) != 0 { + return fmt.Errorf("Could not find specified Asset: %+v ", assets) } return nil -} - -func prepareAssets(tempDir string, asset []config.Asset) ([]string, error) { - buf := new(bytes.Buffer) - tempAssets := []string{} - for _, asset := range asset { - if asset.Compress { - fileContent, err := ioutil.ReadFile(asset.Name) - if err != nil { - return []string{}, err - } - - w := zip.NewWriter(buf) - zip, err := w.Create(tempDir + asset.Name) - - if err != nil { - return []string{}, err - } - - _, err = zip.Write(fileContent) - if err != nil { - return []string{}, err - } - tempAssets = append(tempAssets, tempDir+asset.Name) - - } else { - tempAssets = append(tempAssets, asset.Name) - } - } - return tempAssets, nil + }