From 6fd34d3e0a4f1b670b735276844080126e1bf2a2 Mon Sep 17 00:00:00 2001 From: Nightapes Date: Sat, 21 Mar 2020 15:47:03 +0100 Subject: [PATCH] feat(assets): calculate checksum for all assets and upload it --- cmd/go-semantic-release/commands/zip.go | 1 + go.mod | 2 +- internal/assets/asset.go | 160 ++++++++++++++++++++++++ internal/assets/assets.go | 79 ++++++++++++ internal/releaser/git/git.go | 3 +- internal/releaser/github/github.go | 27 ++-- internal/releaser/github/github_test.go | 17 ++- internal/releaser/gitlab/gitlab.go | 32 +++-- internal/releaser/gitlab/gitlab_test.go | 27 ++-- internal/releaser/releaser.go | 4 +- internal/releaser/util/util.go | 118 ++++++++--------- internal/releaser/util/util_test.go | 76 ----------- pkg/config/config.go | 10 +- pkg/semanticrelease/semantic-release.go | 48 ++++--- 14 files changed, 407 insertions(+), 197 deletions(-) create mode 100644 internal/assets/asset.go create mode 100644 internal/assets/assets.go diff --git a/cmd/go-semantic-release/commands/zip.go b/cmd/go-semantic-release/commands/zip.go index 40912dd..94a05b0 100644 --- a/cmd/go-semantic-release/commands/zip.go +++ b/cmd/go-semantic-release/commands/zip.go @@ -6,6 +6,7 @@ import ( ) func init() { + zipCmd.Flags().StringP("algorithm", "a", "sha256", "Algorithm for checksum (crc32,md5,sha1,sha224,sha384,sha256,sha512)") rootCmd.AddCommand(zipCmd) } diff --git a/go.mod b/go.mod index ba5b79e..cf88c44 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae // indirect - google.golang.org/appengine v1.6.5 // indirect + google.golang.org/appengine v1.6.5 gopkg.in/src-d/go-billy.v4 v4.3.2 gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/yaml.v2 v2.2.8 diff --git a/internal/assets/asset.go b/internal/assets/asset.go new file mode 100644 index 0000000..ebbda51 --- /dev/null +++ b/internal/assets/asset.go @@ -0,0 +1,160 @@ +package assets + +import ( + "archive/zip" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "hash" + "hash/crc32" + "io" + "io/ioutil" + "os" + "path" + "path/filepath" + + "github.com/Nightapes/go-semantic-release/pkg/config" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" +) + +// Asset struct +type Asset struct { + name string + path string + algorithm string + isCompressed bool +} + +//NewAsset from a config +func NewAsset(repository string, assetConfig config.Asset, algorithm string) (*Asset, error) { + + filePath := assetConfig.Path + if assetConfig.Name != "" && assetConfig.Path == "" { + filePath = assetConfig.Name + log.Warn("Name is deprecated. Please update your config. See https://nightapes.github.io/go-semantic-release/") + } + + realPath := path.Join(repository, filePath) + + file, err := os.Open(realPath) + if err != nil { + file.Close() + return nil, errors.Wrapf(err, "Could not open file %s", realPath) + } + defer file.Close() + + name := assetConfig.Rename + if assetConfig.Rename == "" { + info, _ := file.Stat() + name = info.Name() + } + + asset := &Asset{ + path: realPath, + name: name, + isCompressed: assetConfig.Compress, + algorithm: algorithm, + } + + return asset, nil +} + +func (a *Asset) getChecksum() (string, error) { + log.Debugf("Calculating checksum for %s", a.path) + file, err := os.Open(a.path) + if err != nil { + return "", errors.Wrapf(err, "Failed to open file %s to calculate checksum", a.name) + } + defer file.Close() // nolint: errcheck + var hash hash.Hash + switch a.algorithm { + case "crc32": + hash = crc32.NewIEEE() + case "md5": + hash = md5.New() + case "sha1": + hash = sha1.New() + case "sha224": + hash = sha256.New224() + case "sha384": + hash = sha512.New384() + case "sha256": + hash = sha256.New() + case "sha512": + hash = sha512.New() + default: + hash = sha256.New() + } + _, err = io.Copy(hash, file) + if err != nil { + return "", err + } + return hex.EncodeToString(hash.Sum(nil)), nil +} + +// GetPath where the file is located, if zipped true, it will compress it and give you the new location +func (a *Asset) GetPath() (string, error) { + if a.isCompressed { + return a.zipFile() + } + return a.path, nil +} + +// GetName of asset +func (a *Asset) GetName() string { + return a.name +} + +// IsCompressed return true if file was zipped +func (a *Asset) IsCompressed() bool { + return a.isCompressed +} + +// ZipFile compress given file in zip format +func (a *Asset) zipFile() (string, error) { + + path := a.path + fileToZip, err := os.Open(path) + if err != nil { + return "", errors.Wrapf(err, "Could not open file %s", path) + } + defer fileToZip.Close() + + zipFile, err := ioutil.TempFile(os.TempDir(), "asset.*.zip") + + if err != nil { + return "", errors.Wrap(err, "Could not generate tmp file") + } + log.Debugf("Created zipfile %s", zipFile.Name()) + + fileToZipInfo, err := fileToZip.Stat() + if err != nil { + return "", errors.Wrap(err, "Could not read file infos") + } + + zipWriter := zip.NewWriter(zipFile) + defer zipWriter.Close() + + fileToZipHeader, err := zip.FileInfoHeader(fileToZipInfo) + if err != nil { + return "", errors.Wrap(err, "Could not add file infos to zip handler") + } + + fileToZipHeader.Name = fileToZipInfo.Name() + + fileToZipWriter, err := zipWriter.CreateHeader(fileToZipHeader) + if err != nil { + return "", errors.Wrap(err, "Could not create zip header") + } + + if _, err = io.Copy(fileToZipWriter, fileToZip); err != nil { + return "", errors.Wrap(err, "Could not zip file") + } + if err := zipFile.Close(); err != nil { + return "", errors.Wrap(err, "Could not close file") + } + return filepath.Abs(fileToZipInfo.Name()) +} diff --git a/internal/assets/assets.go b/internal/assets/assets.go new file mode 100644 index 0000000..48965fc --- /dev/null +++ b/internal/assets/assets.go @@ -0,0 +1,79 @@ +package assets + +import ( + "bufio" + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "github.com/Nightapes/go-semantic-release/pkg/config" + "github.com/pkg/errors" +) + +// Container struct +type Container struct { + Assets []*Asset + repository string + algorithm string +} + +//New container for assets +func New(repository, algorithm string) *Container { + return &Container{ + Assets: []*Asset{}, + repository: repository, + algorithm: algorithm, + } +} + +// Add assets to the list +func (a *Container) Add(assetConfigs ...config.Asset) error { + for _, assetConfig := range assetConfigs { + asset, err := NewAsset(a.repository, assetConfig, a.algorithm) + if err != nil { + return err + } + a.Assets = append(a.Assets, asset) + } + return nil +} + +func (a *Container) All() []*Asset { + return a.Assets +} + +func (a *Container) GenerateChecksum() error { + checksumFile, err := ioutil.TempFile(os.TempDir(), "checksum.*.txt") + if err != nil { + return errors.Wrap(err, "Could not generate tmp file for checksum") + } + defer checksumFile.Close() + lines := []string{} + for _, asset := range a.Assets { + checksum, err := asset.getChecksum() + if err != nil { + return err + } + lines = append(lines, fmt.Sprintf("%s %s", checksum, asset.GetName())) + } + + w := bufio.NewWriter(checksumFile) + for _, line := range lines { + fmt.Fprintln(w, line) + } + + filePath, err := filepath.Abs(checksumFile.Name()) + if err != nil { + return err + } + + a.Assets = append(a.Assets, &Asset{ + path: filePath, + name: "checksum.txt", + isCompressed: false, + algorithm: "", + }) + return w.Flush() + +} diff --git a/internal/releaser/git/git.go b/internal/releaser/git/git.go index a3bef6e..c0276a5 100644 --- a/internal/releaser/git/git.go +++ b/internal/releaser/git/git.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/Nightapes/go-semantic-release/internal/assets" "github.com/Nightapes/go-semantic-release/internal/gitutil" "github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/pkg/config" @@ -64,7 +65,7 @@ func (g *Client) GetCompareURL(oldVersion, newVersion string) string { } // CreateRelease creates release on remote -func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error { +func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog, _ *assets.Container) error { tag := "v" + releaseVersion.Next.Version.String() g.log.Infof("create release with version %s", tag) diff --git a/internal/releaser/github/github.go b/internal/releaser/github/github.go index 9033a16..64be2b9 100644 --- a/internal/releaser/github/github.go +++ b/internal/releaser/github/github.go @@ -7,6 +7,7 @@ import ( "os" "strings" + "github.com/Nightapes/go-semantic-release/internal/assets" "github.com/Nightapes/go-semantic-release/internal/releaser/util" "github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/pkg/config" @@ -78,7 +79,16 @@ func (g *Client) GetCompareURL(oldVersion, newVersion string) string { } // CreateRelease creates release on remote -func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error { +func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog, assets *assets.Container) error { + err := g.makeRelease(releaseVersion, generatedChangelog) + if err != nil { + return err + } + return g.uploadAssets(assets) +} + +// CreateRelease creates release on remote +func (g *Client) makeRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error { tag := "v" + releaseVersion.Next.Version.String() g.log.Debugf("create release with version %s", tag) @@ -107,15 +117,14 @@ func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedC } // UploadAssets uploads specified assets -func (g *Client) UploadAssets(repoDir string, assets []config.Asset) error { +func (g *Client) uploadAssets(assets *assets.Container) error { if g.release != nil { - filesToUpload, err := util.PrepareAssets(repoDir, assets) - if err != nil { - return err - } - for _, f := range filesToUpload { - - file, err := os.Open(*f) + for _, asset := range assets.All() { + path, err := asset.GetPath() + if err != nil { + return err + } + file, err := os.Open(path) if err != nil { return err } diff --git a/internal/releaser/github/github_test.go b/internal/releaser/github/github_test.go index a40b2a2..7ef557f 100644 --- a/internal/releaser/github/github_test.go +++ b/internal/releaser/github/github_test.go @@ -1,4 +1,4 @@ -package github_test +package github import ( "fmt" @@ -11,7 +11,6 @@ import ( "github.com/Masterminds/semver" - "github.com/Nightapes/go-semantic-release/internal/releaser/github" "github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/pkg/config" "github.com/stretchr/testify/assert" @@ -123,7 +122,7 @@ func TestNew(t *testing.T) { os.Setenv("GITHUB_TOKEN", "XXX") } - _, err := github.New(&testOject.config, true) + _, err := New(&testOject.config, true) assert.Equal(t, testOject.valid, err == nil) os.Unsetenv("GITHUB_TOKEN") @@ -134,7 +133,7 @@ func TestNew(t *testing.T) { func TestGetCommitURL(t *testing.T) { os.Setenv("GITHUB_TOKEN", "XX") for _, testOject := range testNewClient { - client, _ := github.New(&testOject.config, false) + client, _ := New(&testOject.config, false) actualURL := client.GetCommitURL() if testOject.config.CustomURL != "" { expectedURL := fmt.Sprintf("%s/%s/%s/commit/{{hash}}", testOject.config.CustomURL, testOject.config.User, testOject.config.Repo) @@ -152,7 +151,7 @@ func TestGetCommitURL(t *testing.T) { func TestGetCompareURL(t *testing.T) { os.Setenv("GITHUB_TOKEN", "XX") for _, testOject := range testNewClient { - client, _ := github.New(&testOject.config, false) + client, _ := New(&testOject.config, false) actualURL := client.GetCompareURL("1", "2") if testOject.config.CustomURL != "" { expectedURL := fmt.Sprintf("%s/%s/%s/compare/%s...%s", testOject.config.CustomURL, testOject.config.User, testOject.config.Repo, "1", "2") @@ -174,9 +173,9 @@ func TestCreateRelease(t *testing.T) { if testObejct.valid { server := initHTTPServer(testObejct.requestResponseCode, testObejct.requestResponseBody) testObejct.config.CustomURL = server.URL - client, _ := github.New(&testObejct.config, false) + client, _ := New(&testObejct.config, false) - err := client.CreateRelease(testObejct.releaseVersion, testObejct.generatedChangelog) + err := client.makeRelease(testObejct.releaseVersion, testObejct.generatedChangelog) if err != nil { t.Log(err) } @@ -186,9 +185,9 @@ func TestCreateRelease(t *testing.T) { } else { testObejct.config.CustomURL = "http://foo" - client, _ := github.New(&testObejct.config, false) + client, _ := New(&testObejct.config, false) - err := client.CreateRelease(testObejct.releaseVersion, testObejct.generatedChangelog) + err := client.makeRelease(testObejct.releaseVersion, testObejct.generatedChangelog) if err != nil { t.Log(err) } diff --git a/internal/releaser/gitlab/gitlab.go b/internal/releaser/gitlab/gitlab.go index 98395b7..ef34dea 100644 --- a/internal/releaser/gitlab/gitlab.go +++ b/internal/releaser/gitlab/gitlab.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "github.com/Nightapes/go-semantic-release/internal/assets" "github.com/Nightapes/go-semantic-release/internal/releaser/util" "github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/pkg/config" @@ -86,7 +87,16 @@ func (g *Client) GetCompareURL(oldVersion, newVersion string) string { } // CreateRelease creates release on remote -func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error { +func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog, assets *assets.Container) error { + err := g.makeRelease(releaseVersion, generatedChangelog) + if err != nil { + return err + } + return g.uploadAssets(assets) +} + +// CreateRelease creates release on remote +func (g *Client) makeRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error { tag := "v" + releaseVersion.Next.Version.String() g.Release = tag @@ -126,15 +136,13 @@ func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedC return nil } -// UploadAssets uploads specified assets -func (g *Client) UploadAssets(repoDir string, assets []config.Asset) error { - filesToUpload, err := util.PrepareAssets(repoDir, assets) - if err != nil { - return err - } - for _, f := range filesToUpload { - - file, err := os.Open(*f) +func (g *Client) uploadAssets(assets *assets.Container) error { + for _, asset := range assets.All() { + path, err := asset.GetPath() + if err != nil { + return err + } + file, err := os.Open(path) if err != nil { return err } @@ -151,9 +159,9 @@ func (g *Client) UploadAssets(repoDir string, assets []config.Asset) error { g.log.Infof("Uploaded file %s to gitlab can be downloaded under %s", file.Name(), downloadURL) - path := fmt.Sprintf("%s/projects/%s/releases/%s/assets/links?name=%s&url=%s", g.apiURL, util.PathEscape(g.config.Repo), g.Release, util.PathEscape(fileInfo.Name()), downloadURL) + uploadURL := fmt.Sprintf("%s/projects/%s/releases/%s/assets/links?name=%s&url=%s", g.apiURL, util.PathEscape(g.config.Repo), g.Release, util.PathEscape(fileInfo.Name()), downloadURL) - req, err := http.NewRequest("POST", path, nil) + req, err := http.NewRequest("POST", uploadURL, nil) if err != nil { return err } diff --git a/internal/releaser/gitlab/gitlab_test.go b/internal/releaser/gitlab/gitlab_test.go index bdfabcf..0b2c71d 100644 --- a/internal/releaser/gitlab/gitlab_test.go +++ b/internal/releaser/gitlab/gitlab_test.go @@ -1,4 +1,4 @@ -package gitlab_test +package gitlab import ( "io/ioutil" @@ -13,7 +13,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" - "github.com/Nightapes/go-semantic-release/internal/releaser/gitlab" + "github.com/Nightapes/go-semantic-release/internal/assets" "github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/pkg/config" ) @@ -21,7 +21,7 @@ import ( func TestGetCommitURL(t *testing.T) { os.Setenv("GITLAB_ACCESS_TOKEN", "XXX") defer os.Unsetenv("GITLAB_ACCESS_TOKEN") - client, err := gitlab.New(&config.GitLabProvider{ + client, err := New(&config.GitLabProvider{ CustomURL: "https://localhost/", Repo: "test/test", }, true) @@ -32,7 +32,7 @@ func TestGetCommitURL(t *testing.T) { func TestGetCompareURL(t *testing.T) { os.Setenv("GITLAB_ACCESS_TOKEN", "XXX") defer os.Unsetenv("GITLAB_ACCESS_TOKEN") - client, err := gitlab.New(&config.GitLabProvider{ + client, err := New(&config.GitLabProvider{ CustomURL: "https://localhost/", Repo: "test/test", }, true) @@ -43,7 +43,7 @@ func TestGetCompareURL(t *testing.T) { func TestValidateConfig_EmptyRepro(t *testing.T) { os.Setenv("GITLAB_ACCESS_TOKEN", "XXX") defer os.Unsetenv("GITLAB_ACCESS_TOKEN") - _, err := gitlab.New(&config.GitLabProvider{ + _, err := New(&config.GitLabProvider{ CustomURL: "https://localhost/", }, true) assert.Error(t, err) @@ -55,7 +55,7 @@ func TestValidateConfig_DefaultURL(t *testing.T) { config := &config.GitLabProvider{ Repo: "localhost/test", } - _, err := gitlab.New(config, true) + _, err := New(config, true) assert.NoError(t, err) assert.Equal(t, "https://gitlab.com", config.CustomURL) } @@ -67,7 +67,7 @@ func TestValidateConfig_CustomURL(t *testing.T) { Repo: "/localhost/test/", CustomURL: "https://localhost/", } - _, err := gitlab.New(config, true) + _, err := New(config, true) assert.NoError(t, err) assert.Equal(t, "https://localhost", config.CustomURL) assert.Equal(t, "localhost/test", config.Repo) @@ -190,10 +190,10 @@ func TestCreateRelease(t *testing.T) { } os.Setenv("GITLAB_ACCESS_TOKEN", "aToken") defer os.Unsetenv("GITLAB_ACCESS_TOKEN") - client, err := gitlab.New(&testObject.config, false) + client, err := New(&testObject.config, false) assert.NoError(t, err) - err = client.CreateRelease(testObject.releaseVersion, testObject.generatedChangelog) + err = client.makeRelease(testObject.releaseVersion, testObject.generatedChangelog) if err != nil { t.Log(err) } @@ -317,11 +317,16 @@ func TestUploadAssets(t *testing.T) { } os.Setenv("GITLAB_ACCESS_TOKEN", "aToken") defer os.Unsetenv("GITLAB_ACCESS_TOKEN") - client, err := gitlab.New(&testObject.config, false) + client, err := New(&testObject.config, false) assert.NoError(t, err) client.Release = "1.0.0" - err = client.UploadAssets(testObject.testDir, testObject.assets) + assets := assets.New(testObject.testDir, "") + err = assets.Add(testObject.assets...) + if err != nil { + t.Log(err) + } + err = client.uploadAssets(assets) if err != nil { t.Log(err) } diff --git a/internal/releaser/releaser.go b/internal/releaser/releaser.go index 465525f..828c237 100644 --- a/internal/releaser/releaser.go +++ b/internal/releaser/releaser.go @@ -3,6 +3,7 @@ package releaser import ( "fmt" + "github.com/Nightapes/go-semantic-release/internal/assets" "github.com/Nightapes/go-semantic-release/internal/gitutil" "github.com/Nightapes/go-semantic-release/internal/releaser/git" "github.com/Nightapes/go-semantic-release/internal/releaser/github" @@ -21,8 +22,7 @@ type Releasers struct { // Releaser interface for providers type Releaser interface { - CreateRelease(*shared.ReleaseVersion, *shared.GeneratedChangelog) error - UploadAssets(repoDir string, assets []config.Asset) error + CreateRelease(*shared.ReleaseVersion, *shared.GeneratedChangelog, *assets.Container) error GetCommitURL() string GetCompareURL(oldVersion, newVersion string) string } diff --git a/internal/releaser/util/util.go b/internal/releaser/util/util.go index 5e4b42b..62d2206 100644 --- a/internal/releaser/util/util.go +++ b/internal/releaser/util/util.go @@ -1,7 +1,6 @@ package util import ( - "archive/zip" "context" "encoding/json" "fmt" @@ -11,7 +10,6 @@ import ( "os" "strings" - "github.com/Nightapes/go-semantic-release/pkg/config" log "github.com/sirupsen/logrus" "golang.org/x/oauth2" ) @@ -62,74 +60,78 @@ func GetAccessToken(envName string) (string, error) { return token, nil } -// PrepareAssets prepare all files before uploading -func PrepareAssets(repository string, assets []config.Asset) ([]*string, error) { - filesToUpload := []*string{} - for _, asset := range assets { - if asset.Name == "" { - return nil, fmt.Errorf("asset name declaration is empty, please check your configuration file") - } else if asset.Compress { - log.Debugf("Asset %s will now be compressed", asset.Name) - log.Debugf("Repo url %s", repository) - zipNameWithPath, err := zipFile(repository, asset.Name) - if err != nil { - return filesToUpload, err - } - filesToUpload = append(filesToUpload, &zipNameWithPath) - } else { - tmpFileName := fmt.Sprintf("%s/%s", repository, asset.Name) - filesToUpload = append(filesToUpload, &tmpFileName) - } - log.Debugf("Add asset %s to files to upload", asset.Name) - } - return filesToUpload, nil -} +// // PrepareAssets prepare all files before uploading +// func PrepareAssets(repository string, assets []config.Asset) ([]*string, error) { +// filesToUpload := []*string{} +// for _, asset := range assets { +// if asset.Name != "" && asset.Path == "" { +// log.Warn("Name is deprecated. Please update your config. See https://nightapes.github.io/go-semantic-release/") +// } -// ZipFile compress given file in zip format -func zipFile(repository string, file string) (string, error) { +// if asset.Path == "" { +// return nil, fmt.Errorf("asset path declaration is empty, please check your configuration file") +// } else if asset.Compress { +// log.Debugf("Asset %s will now be compressed", asset.Name) +// log.Debugf("Repo url %s", repository) +// zipNameWithPath, err := zipFile(repository, asset.Name) +// if err != nil { +// return filesToUpload, err +// } +// filesToUpload = append(filesToUpload, &zipNameWithPath) +// } else { +// tmpFileName := fmt.Sprintf("%s/%s", repository, asset.Name) +// filesToUpload = append(filesToUpload, &tmpFileName) +// } +// log.Debugf("Add asset %s to files to upload", asset.Name) +// } +// return filesToUpload, nil +// } - fileToZip, err := os.Open(repository + "/" + file) - if err != nil { - return "", err - } - defer fileToZip.Close() +// // ZipFile compress given file in zip format +// func zipFile(repository string, file string) (string, error) { - zipFileName := fmt.Sprintf("%s/%s.zip", strings.TrimSuffix(repository, "/"), file) - zipFile, err := os.Create(zipFileName) +// fileToZip, err := os.Open(repository + "/" + file) +// if err != nil { +// return "", err +// } +// defer fileToZip.Close() - if err != nil { - return "", err - } - log.Debugf("Created zipfile %s", zipFile.Name()) +// zipFileName := fmt.Sprintf("%s/%s.zip", strings.TrimSuffix(repository, "/"), file) +// zipFile, err := os.Create(zipFileName) - defer zipFile.Close() +// if err != nil { +// return "", err +// } +// log.Debugf("Created zipfile %s", zipFile.Name()) - fileToZipInfo, err := fileToZip.Stat() - if err != nil { - return "", err - } +// defer zipFile.Close() - zipWriter := zip.NewWriter(zipFile) - defer zipWriter.Close() +// fileToZipInfo, err := fileToZip.Stat() +// if err != nil { +// return "", err +// } - fileToZipHeader, err := zip.FileInfoHeader(fileToZipInfo) - if err != nil { - return "", err - } +// zipWriter := zip.NewWriter(zipFile) +// defer zipWriter.Close() - fileToZipHeader.Name = fileToZipInfo.Name() +// fileToZipHeader, err := zip.FileInfoHeader(fileToZipInfo) +// if err != nil { +// return "", err +// } - fileToZipWriter, err := zipWriter.CreateHeader(fileToZipHeader) - if err != nil { - return "", err - } +// fileToZipHeader.Name = fileToZipInfo.Name() - if _, err = io.Copy(fileToZipWriter, fileToZip); err != nil { - return "", err - } +// fileToZipWriter, err := zipWriter.CreateHeader(fileToZipHeader) +// if err != nil { +// return "", err +// } - return zipFileName, nil -} +// if _, err = io.Copy(fileToZipWriter, fileToZip); err != nil { +// return "", err +// } + +// return zipFileName, nil +// } //PathEscape to be url save func PathEscape(s string) string { diff --git a/internal/releaser/util/util_test.go b/internal/releaser/util/util_test.go index a6adfe5..8d01aca 100644 --- a/internal/releaser/util/util_test.go +++ b/internal/releaser/util/util_test.go @@ -13,8 +13,6 @@ import ( log "github.com/sirupsen/logrus" - "github.com/Nightapes/go-semantic-release/pkg/config" - "github.com/stretchr/testify/assert" "github.com/Nightapes/go-semantic-release/internal/releaser/util" @@ -50,80 +48,6 @@ func TestGetAccessToken(t *testing.T) { } } -type testDoubleFiles struct { - testFiles []config.Asset - valid bool -} - -var files = []testDoubleFiles{ - testDoubleFiles{ - testFiles: []config.Asset{ - config.Asset{ - Name: "file0", - Compress: true, - }, - config.Asset{ - Name: "file1", - Compress: true, - }, - }, - valid: true, - }, - testDoubleFiles{ - testFiles: []config.Asset{ - config.Asset{ - Name: "", - Compress: true, - }, - config.Asset{ - Name: "", - Compress: false, - }, - }, - valid: false, - }, -} - -func TestPrepareAssets(t *testing.T) { - for _, testObject := range files { - workDir, _ := os.Getwd() - filesToDelete := []string{} - - for _, testFile := range testObject.testFiles { - - if testFile.Name != "" { - filesToDelete = append(filesToDelete, testFile.Name) - - file, err := os.Create(testFile.Name) - if err != nil { - fmt.Print(err.Error()) - } - defer file.Close() - if testFile.Compress { - filesToDelete = append(filesToDelete, testFile.Name+".zip") - } - } - - } - preparedFiles, err := util.PrepareAssets(workDir, testObject.testFiles) - - if err == nil { - assert.Equal(t, 2, len(preparedFiles)) - } - - assert.Equal(t, testObject.valid, err == nil) - - for _, file := range filesToDelete { - if err := os.Remove(file); err != nil { - fmt.Println(err.Error()) - } - - } - - } - -} - func TestShouldRetry(t *testing.T) { assert.True(t, util.ShouldRetry(&http.Response{StatusCode: 429})) assert.False(t, util.ShouldRetry(&http.Response{StatusCode: 200})) diff --git a/pkg/config/config.go b/pkg/config/config.go index 8d795d2..008c176 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -32,7 +32,9 @@ type ChangelogNPM struct { //Asset type struct type Asset struct { - Name string `yaml:"name"` + Path string `yaml:"path"` + Rename string `yaml:"rename,omitempty"` + Name string `yaml:"name,omitempty"` // Deprecated Compress bool `yaml:"compress"` } @@ -65,6 +67,11 @@ type Hooks struct { PostRelease []string `yaml:"postRelease"` } +// Checksum struct +type Checksum struct { + Algorithm string `yaml:"algorithm"` +} + // ReleaseConfig struct type ReleaseConfig struct { CommitFormat string `yaml:"commitFormat"` @@ -75,6 +82,7 @@ type ReleaseConfig struct { GitLabProvider GitLabProvider `yaml:"gitlab,omitempty"` GitProvider GitProvider `yaml:"git,omitempty"` Assets []Asset `yaml:"assets"` + Checksum Checksum `yaml:"checksum,omitempty"` Hooks Hooks `yaml:"hooks"` ReleaseTitle string `yaml:"title"` IsPreRelease bool diff --git a/pkg/semanticrelease/semantic-release.go b/pkg/semanticrelease/semantic-release.go index 2f851f7..0d5321b 100644 --- a/pkg/semanticrelease/semantic-release.go +++ b/pkg/semanticrelease/semantic-release.go @@ -6,6 +6,7 @@ import ( "github.com/Masterminds/semver" "github.com/Nightapes/go-semantic-release/internal/analyzer" + "github.com/Nightapes/go-semantic-release/internal/assets" "github.com/Nightapes/go-semantic-release/internal/cache" "github.com/Nightapes/go-semantic-release/internal/calculator" "github.com/Nightapes/go-semantic-release/internal/changelog" @@ -13,7 +14,6 @@ import ( "github.com/Nightapes/go-semantic-release/internal/gitutil" "github.com/Nightapes/go-semantic-release/internal/hooks" "github.com/Nightapes/go-semantic-release/internal/releaser" - "github.com/Nightapes/go-semantic-release/internal/releaser/util" "github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/pkg/config" log "github.com/sirupsen/logrus" @@ -26,6 +26,7 @@ type SemanticRelease struct { analyzer *analyzer.Analyzer calculator *calculator.Calculator releaser releaser.Releaser + assets *assets.Container repository string checkConfig bool } @@ -46,6 +47,12 @@ func New(c *config.ReleaseConfig, repository string, checkConfig bool) (*Semanti log.Infof("Ignore config checks!. No guarantee to run without issues") } + assets := assets.New(repository, c.Checksum.Algorithm) + + if err := assets.Add(c.Assets...); err != nil { + return nil, err + } + releaser, err := releaser.New(c, util).GetReleaser(checkConfig) if err != nil { return nil, err @@ -57,6 +64,7 @@ func New(c *config.ReleaseConfig, repository string, checkConfig bool) (*Semanti releaser: releaser, analyzer: analyzer, repository: repository, + assets: assets, checkConfig: checkConfig, calculator: calculator.New(), }, nil @@ -214,30 +222,27 @@ func (s *SemanticRelease) Release(provider *ci.ProviderConfig, force bool) error return nil } - hook := hooks.New(s.config, releaseVersion) - generatedChangelog, err := s.GetChangelog(releaseVersion) if err != nil { log.Debugf("Could not get changelog") return err } - err = hook.PreRelease() - if err != nil { + if err := s.assets.GenerateChecksum(); err != nil { + return err + } + + hook := hooks.New(s.config, releaseVersion) + if err := hook.PreRelease(); err != nil { log.Debugf("Error during pre release hook") return err } - if err = s.releaser.CreateRelease(releaseVersion, generatedChangelog); err != nil { + if err = s.releaser.CreateRelease(releaseVersion, generatedChangelog, s.assets); err != nil { return err } - if err = s.releaser.UploadAssets(s.repository, s.config.Assets); err != nil { - return err - } - - err = hook.PostRelease() - if err != nil { + if err := hook.PostRelease(); err != nil { log.Debugf("Error during post release hook") return err } @@ -247,12 +252,21 @@ func (s *SemanticRelease) Release(provider *ci.ProviderConfig, force bool) error // ZipFiles zip files configured in release config func (s *SemanticRelease) ZipFiles() error { - for _, file := range s.config.Assets { - if file.Compress { - if _, err := util.PrepareAssets(s.repository, s.config.Assets); err != nil { - return err - } + assets := assets.New(s.repository, "") + + if err := assets.Add(s.config.Assets...); err != nil { + return err + } + if err := assets.GenerateChecksum(); err != nil { + return err + } + + for _, asset := range assets.All() { + path, err := asset.GetPath() + if err != nil { + return err } + log.Infof("File %s under %s is zipped %t", asset.GetName(), path, asset.IsCompressed()) } return nil }