test(gitlab): add missing tests

This commit is contained in:
Nightapes
2019-08-11 15:03:55 +02:00
parent 0fd39c72a0
commit 7b16b164f2
6 changed files with 480 additions and 61 deletions

View File

@@ -91,6 +91,8 @@ func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedC
prerelease := releaseVersion.Next.Version.Prerelease() != ""
log.Debugf("Send %+v", generatedChangelog)
release, _, err := g.client.Repositories.CreateRelease(g.context, g.config.User, g.config.Repo, &github.RepositoryRelease{
TagName: &tag,
TargetCommitish: &releaseVersion.Branch,

View File

@@ -31,17 +31,12 @@ type Client struct {
baseURL string
apiURL string
token string
release string
Release string
log *log.Entry
}
// New initialize a new gitlabRelease
func New(config *config.GitLabProvider) (*Client, error) {
accessToken, err := util.GetAccessToken(GITLAB)
if err != nil {
return nil, err
}
func New(config *config.GitLabProvider, accessToken string) (*Client, error) {
ctx := context.Background()
tokenHeader := util.NewAddHeaderTransport(nil, "PRIVATE-TOKEN", accessToken)
acceptHeader := util.NewAddHeaderTransport(tokenHeader, "Accept", "application/json")
@@ -50,44 +45,46 @@ func New(config *config.GitLabProvider) (*Client, error) {
Timeout: time.Second * 60,
}
logger := log.WithField("releaser", GITLAB)
logger.Debugf("validate gitlab provider config")
if config.Repo == "" {
return nil, fmt.Errorf("gitlab Repro is not set")
}
config.Repo = strings.Trim(config.Repo, "/")
if config.CustomURL == "" {
config.CustomURL = "https://gitlab.com"
}
config.CustomURL = strings.Trim(config.CustomURL, "/")
logger.Debugf("Use gitlab url %s", config.CustomURL)
return &Client{
token: accessToken,
config: config,
context: ctx,
baseURL: config.CustomURL,
apiURL: config.CustomURL + "api/v4",
apiURL: config.CustomURL + "/api/v4",
client: httpClient,
log: log.WithField("releaser", GITLAB),
log: logger,
}, nil
}
//GetCommitURL for gitlab
func (g *Client) GetCommitURL() string {
return fmt.Sprintf("%s%s/commit/{{hash}}", g.baseURL, g.config.Repo)
return fmt.Sprintf("%s/%s/commit/{{hash}}", g.baseURL, g.config.Repo)
}
//GetCompareURL for gitlab
func (g *Client) GetCompareURL(oldVersion, newVersion string) string {
return fmt.Sprintf("%s%s/compare/%s...%s", g.baseURL, g.config.Repo, oldVersion, newVersion)
return fmt.Sprintf("%s/%s/compare/%s...%s", g.baseURL, g.config.Repo, oldVersion, newVersion)
}
//ValidateConfig for gitlab
func (g *Client) ValidateConfig() error {
g.log.Debugf("validate gitlab provider config")
if g.config.Repo == "" {
return fmt.Errorf("gitlab Repro is not set")
}
g.config.Repo = strings.Trim(g.config.Repo, "/")
if g.config.CustomURL == "" {
g.config.CustomURL = "https://gitlab.com"
}
g.config.CustomURL = strings.Trim(g.config.CustomURL, "/")
g.log.Debugf("Use gitlab url %s", g.config.CustomURL)
return nil
}
@@ -96,10 +93,10 @@ func (g *Client) ValidateConfig() error {
func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error {
tag := releaseVersion.Next.Version.String()
g.release = tag
g.log.Debugf("create release with version %s", tag)
g.Release = tag
g.log.Infof("create release with version %s", tag)
url := fmt.Sprintf("%s/projects/%s/releases", g.apiURL, util.PathEscape(g.config.Repo))
g.log.Debugf("Send release to %s", url)
g.log.Infof("Send release to %s", url)
bodyBytes, err := json.Marshal(Release{
TagName: tag,
@@ -113,23 +110,15 @@ func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedC
req, err := http.NewRequest("POST", url, bytes.NewReader(bodyBytes))
if err != nil {
return err
return fmt.Errorf("could not create request: %s", err.Error())
}
req.Header.Set("Content-Type", "application/json")
resp, err := util.Do(g.client, req, nil)
if err != nil {
return fmt.Errorf("could not create release: %s", err.Error())
}
respBodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
log.Debugf("Release repsone: %+v", string(respBodyBytes))
if err := util.IsValidResult(resp); err != nil {
return err
}
@@ -160,18 +149,18 @@ func (g *Client) UploadAssets(repoDir string, assets []config.Asset) error {
return fmt.Errorf("could not upload asset %s: %s", file.Name(), err.Error())
}
downloadURL := fmt.Sprintf("%s%s%s", g.baseURL, g.config.Repo, result.URL)
downloadURL := fmt.Sprintf("%s/%s%s", g.baseURL, g.config.Repo, result.URL)
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)
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)
req, err := http.NewRequest("POST", path, nil)
if err != nil {
return err
}
log.Infof("Link file %s with release %s", file.Name(), g.release)
log.Infof("Link file %s with release %s", file.Name(), g.Release)
resp, err := util.Do(g.client, req, nil)
if err != nil {
@@ -182,7 +171,7 @@ func (g *Client) UploadAssets(repoDir string, assets []config.Asset) error {
return err
}
log.Infof("Link file with release %s is done", g.release)
log.Infof("Link file with release %s is done", g.Release)
}
return nil
}

View File

@@ -0,0 +1,327 @@
package gitlab_test
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"github.com/Masterminds/semver"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
//"github.com/Nightapes/go-semantic-release/internal/releaser/util"
"github.com/Nightapes/go-semantic-release/internal/releaser/gitlab"
"github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config"
)
func TestGetCommitURL(t *testing.T) {
client, err := gitlab.New(&config.GitLabProvider{
CustomURL: "https://localhost/",
Repo: "test/test",
}, "aToken")
assert.NoError(t, err)
assert.Equal(t, "https://localhost/test/test/commit/{{hash}}", client.GetCommitURL())
}
func TestGetCompareURL(t *testing.T) {
client, err := gitlab.New(&config.GitLabProvider{
CustomURL: "https://localhost/",
Repo: "test/test",
}, "aToken")
assert.NoError(t, err)
assert.Equal(t, "https://localhost/test/test/compare/1.0.0...1.0.1", client.GetCompareURL("1.0.0", "1.0.1"))
}
func TestValidateConfig_EmptyRepro(t *testing.T) {
_, err := gitlab.New(&config.GitLabProvider{
CustomURL: "https://localhost/",
}, "aToken")
assert.Error(t, err)
}
func TestValidateConfig_DefaultURL(t *testing.T) {
config := &config.GitLabProvider{
Repo: "localhost/test",
}
_, err := gitlab.New(config, "aToken")
assert.NoError(t, err)
assert.Equal(t, "https://gitlab.com", config.CustomURL)
}
func TestValidateConfig_CustomURL(t *testing.T) {
config := &config.GitLabProvider{
Repo: "/localhost/test/",
CustomURL: "https://localhost/",
}
_, err := gitlab.New(config, "aToken")
assert.NoError(t, err)
assert.Equal(t, "https://localhost", config.CustomURL)
assert.Equal(t, "localhost/test", config.Repo)
}
func TestCreateRelease(t *testing.T) {
lastVersion, _ := semver.NewVersion("1.0.0")
newVersion, _ := semver.NewVersion("2.0.0")
testReleases := []struct {
config config.GitLabProvider
releaseVersion *shared.ReleaseVersion
generatedChangelog *shared.GeneratedChangelog
responseBody string
responseCode int
requestBody string
valid bool
}{
{
config: config.GitLabProvider{
Repo: "foo/bar",
},
releaseVersion: &shared.ReleaseVersion{
Last: shared.ReleaseVersionEntry{
Version: lastVersion,
Commit: "foo",
},
Next: shared.ReleaseVersionEntry{
Version: newVersion,
Commit: "bar",
},
Branch: "master",
Draft: false,
},
generatedChangelog: &shared.GeneratedChangelog{
Title: "title",
Content: "content",
},
responseBody: "{}",
responseCode: 200,
requestBody: `{"tag_name":"2.0.0","name":"title","ref":"master","description":"content","assets":{"links":null}}`,
valid: true,
},
{
config: config.GitLabProvider{
Repo: "foo/bar",
},
releaseVersion: &shared.ReleaseVersion{
Last: shared.ReleaseVersionEntry{
Version: lastVersion,
Commit: "foo",
},
Next: shared.ReleaseVersionEntry{
Version: newVersion,
Commit: "bar",
},
Branch: "master",
Draft: false,
},
generatedChangelog: &shared.GeneratedChangelog{
Title: "title",
Content: "content",
},
responseBody: "{}",
responseCode: 500,
requestBody: `{"tag_name":"2.0.0","name":"title","ref":"master","description":"content","assets":{"links":null}}`,
valid: false,
},
{
config: config.GitLabProvider{
Repo: "foo/bar",
CustomURL: "broken",
},
releaseVersion: &shared.ReleaseVersion{
Last: shared.ReleaseVersionEntry{
Version: lastVersion,
Commit: "foo",
},
Next: shared.ReleaseVersionEntry{
Version: newVersion,
Commit: "bar",
},
Branch: "master",
Draft: false,
},
generatedChangelog: &shared.GeneratedChangelog{
Title: "title",
Content: "content",
},
responseCode: 400,
responseBody: "{}",
requestBody: `{"tag_name":"2.0.0","name":"title","ref":"master","description":"content","assets":{"links":null}}`,
valid: false,
},
}
for _, testObject := range testReleases {
testServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
log.Infof("Got call from %s %s", req.Method, req.URL.String())
assert.Equal(t, req.Header.Get("PRIVATE-TOKEN"), "aToken")
assert.Equal(t, req.Header.Get("Accept"), "application/json")
bodyBytes, err := ioutil.ReadAll(req.Body)
if err != nil {
log.Fatal(err)
}
assert.Equal(t, testObject.requestBody, string(bodyBytes))
rw.WriteHeader(testObject.responseCode)
rw.Header().Set("Content-Type", "application/json")
if _, err := rw.Write([]byte(testObject.responseBody)); err != nil {
log.Info(err)
}
}))
if testObject.config.CustomURL == "" {
testObject.config.CustomURL = testServer.URL
}
client, err := gitlab.New(&testObject.config, "aToken")
assert.NoError(t, err)
err = client.CreateRelease(testObject.releaseVersion, testObject.generatedChangelog)
if err != nil {
t.Log(err)
}
assert.Equal(t, testObject.valid, err == nil)
testServer.Close()
}
}
func TestUploadAssets(t *testing.T) {
file, err := ioutil.TempFile("", "prefix")
if err != nil {
log.Fatal(err)
}
defer os.Remove(file.Name())
_, err = file.WriteString("testFile")
assert.NoError(t, err)
testReleases := []struct {
config config.GitLabProvider
responseBody []string
responseCode []int
assets []config.Asset
requestBody []string
testDir string
url []string
method []string
valid bool
}{
{
config: config.GitLabProvider{
Repo: "foo/bar",
},
responseBody: []string{`{"alt" : "dk", "url": "/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png", "markdown" :"![dk](/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png)"}`, ""},
responseCode: []int{200, 200},
requestBody: []string{
filepath.Base(file.Name()), ""},
url: []string{`/api/v4/projects/foo%2Fbar/uploads`, "/api/v4/projects/foo%2Fbar/releases/1.0.0/assets/links?name=" + filepath.Base(file.Name()) + "&url=<SERVER>/foo/bar/uploads/"},
method: []string{"POST", "POST"},
valid: true,
testDir: os.TempDir(),
assets: []config.Asset{
config.Asset{
Name: filepath.Base(file.Name()),
Compress: false,
},
},
},
{
config: config.GitLabProvider{
Repo: "foo/bar",
},
responseBody: []string{`{"alt" : "dk", "url": "/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png", "markdown" :"![dk](/uploads/66dbcd21ec5d24ed6ea225176098d52b/dk.png)"}`, ""},
responseCode: []int{400, 200},
requestBody: []string{
filepath.Base(file.Name()), ""},
url: []string{`/api/v4/projects/foo%2Fbar/uploads`, "/api/v4/projects/foo%2Fbar/releases/1.0.0/assets/links?name=" + filepath.Base(file.Name()) + "&url=<SERVER>/foo/bar/uploads/"},
method: []string{"POST", "POST"},
valid: false,
testDir: os.TempDir(),
assets: []config.Asset{
config.Asset{
Name: filepath.Base(file.Name()),
Compress: false,
},
},
},
{
config: config.GitLabProvider{
Repo: "foo/bar",
},
responseBody: []string{`broken`, ""},
responseCode: []int{200, 200},
requestBody: []string{
filepath.Base(file.Name()), ""},
url: []string{`/api/v4/projects/foo%2Fbar/uploads`, "/api/v4/projects/foo%2Fbar/releases/1.0.0/assets/links?name=" + filepath.Base(file.Name()) + "&url=<SERVER>/foo/bar/uploads/"},
method: []string{"POST", "POST"},
valid: false,
testDir: os.TempDir(),
assets: []config.Asset{
config.Asset{
Name: filepath.Base(file.Name()),
Compress: false,
},
},
},
}
for _, testObject := range testReleases {
calls := 0
testServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
log.Infof("Got call from %s %s", req.Method, req.URL.String())
assert.Contains(t, req.URL.String(), strings.ReplaceAll(testObject.url[calls], "<SERVER>", testObject.config.CustomURL))
assert.Equal(t, req.Method, testObject.method[calls])
assert.Equal(t, req.Header.Get("PRIVATE-TOKEN"), "aToken")
assert.Equal(t, req.Header.Get("Accept"), "application/json")
bodyBytes, err := ioutil.ReadAll(req.Body)
if err != nil {
log.Fatal(err)
}
assert.Contains(t, string(bodyBytes), testObject.requestBody[calls])
rw.WriteHeader(testObject.responseCode[calls])
rw.Header().Set("Content-Type", "application/json")
if _, err := rw.Write([]byte(testObject.responseBody[calls])); err != nil {
log.Info(err)
}
calls++
}))
if testObject.config.CustomURL == "" {
testObject.config.CustomURL = testServer.URL
}
client, err := gitlab.New(&testObject.config, "aToken")
assert.NoError(t, err)
client.Release = "1.0.0"
err = client.UploadAssets(testObject.testDir, testObject.assets)
if err != nil {
t.Log(err)
}
assert.Equal(t, testObject.valid, err == nil)
testServer.Close()
}
}

View File

@@ -5,6 +5,7 @@ import (
"github.com/Nightapes/go-semantic-release/internal/releaser/github"
"github.com/Nightapes/go-semantic-release/internal/releaser/gitlab"
"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"
@@ -40,7 +41,11 @@ func (r *Releasers) GetReleaser() (Releaser, error) {
return github.New(&r.config.GitHubProvider)
case gitlab.GITLAB:
log.Debugf("initialize new %s-provider", gitlab.GITLAB)
return gitlab.New(&r.config.GitLabProvider)
accessToken, err := util.GetAccessToken(gitlab.GITLAB)
if err != nil {
return nil, err
}
return gitlab.New(&r.config.GitLabProvider, accessToken)
}
return nil, fmt.Errorf("could not initialize a releaser from this type: %s", r.config.Release)
}

View File

@@ -133,21 +133,6 @@ func zipFile(repository string, file string) (string, error) {
return zipFileName, nil
}
// CheckURL if is valid
func CheckURL(urlStr string) (string, error) {
if !strings.HasSuffix(urlStr, "/") {
urlStr += "/"
}
_, err := url.Parse(urlStr)
if err != nil {
return "", err
}
return urlStr, nil
}
//PathEscape to be url save
func PathEscape(s string) string {
return strings.Replace(url.PathEscape(s), ".", "%2E", -1)
@@ -162,7 +147,7 @@ func Do(client *http.Client, req *http.Request, v interface{}) (*http.Response,
defer resp.Body.Close()
switch resp.StatusCode {
case 200, 201, 202, 204, 304:
case 200, 201, 202, 204:
if v != nil {
if w, ok := v.(io.Writer); ok {
_, err = io.Copy(w, resp.Body)
@@ -178,7 +163,7 @@ func Do(client *http.Client, req *http.Request, v interface{}) (*http.Response,
// IsValidResult validates response code
func IsValidResult(resp *http.Response) error {
switch resp.StatusCode {
case 200, 201, 202, 204, 304:
case 200, 201, 202, 204:
return nil
default:
return fmt.Errorf("%s %s: %d", resp.Request.Method, resp.Request.URL, resp.StatusCode)

View File

@@ -3,9 +3,15 @@ package util_test
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"os"
"strings"
"testing"
"time"
log "github.com/sirupsen/logrus"
"github.com/Nightapes/go-semantic-release/pkg/config"
@@ -117,3 +123,108 @@ func TestPrepareAssets(t *testing.T) {
}
}
func TestShouldRetry(t *testing.T) {
assert.True(t, util.ShouldRetry(&http.Response{StatusCode: 429}))
assert.False(t, util.ShouldRetry(&http.Response{StatusCode: 200}))
}
func TestIsValidResult(t *testing.T) {
assert.NoError(t, util.IsValidResult(&http.Response{StatusCode: 200}))
assert.NoError(t, util.IsValidResult(&http.Response{StatusCode: 201}))
assert.NoError(t, util.IsValidResult(&http.Response{StatusCode: 202}))
assert.NoError(t, util.IsValidResult(&http.Response{StatusCode: 204}))
u, err := url.Parse("https://localhost")
assert.NoError(t, err)
assert.Error(t, util.IsValidResult(&http.Response{StatusCode: 500, Request: &http.Request{
Method: "POST",
URL: u,
}}))
}
func TestPathEscape(t *testing.T) {
assert.Equal(t, "test%2Ftest", util.PathEscape("test/test"))
assert.Equal(t, "test", util.PathEscape("test"))
assert.Equal(t, "test%2Etest", util.PathEscape("test.test"))
}
type example struct {
Test string `json:"test"`
}
func TestDoAndRoundTrip(t *testing.T) {
tokenHeader := util.NewAddHeaderTransport(nil, "PRIVATE-TOKEN", "aToken")
acceptHeader := util.NewAddHeaderTransport(tokenHeader, "Accept", "application/json")
httpClient := &http.Client{
Transport: acceptHeader,
Timeout: time.Second * 60,
}
testsDoMethod := []struct {
statusCode int
body string
responseBody interface{}
responseBodyType interface{}
hasError bool
path string
}{
{
statusCode: 200,
body: `{"test" : "hallo"}`,
responseBody: &example{
Test: "hallo",
},
responseBodyType: &example{},
hasError: false,
path: "",
},
{
statusCode: 400,
body: `{"test" : "hallo"}`,
responseBody: &example{},
responseBodyType: &example{},
hasError: false,
path: "",
},
{
statusCode: 200,
body: `{"test" : "hallo"}`,
hasError: true,
responseBody: &example{},
responseBodyType: &example{},
path: "broken",
},
}
for _, testOject := range testsDoMethod {
testServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
log.Infof("Got call from %s %s", req.Method, req.URL.String())
assert.Equal(t, req.Header.Get("PRIVATE-TOKEN"), "aToken")
assert.Equal(t, req.Header.Get("Accept"), "application/json")
rw.WriteHeader(testOject.statusCode)
rw.Header().Set("Content-Type", "application/json")
if _, err := rw.Write([]byte(testOject.body)); err != nil {
log.Info(err)
}
}))
req, err := http.NewRequest("POST", testServer.URL+testOject.path, nil)
assert.NoError(t, err)
resp, err := util.Do(httpClient, req, testOject.responseBodyType)
assert.Equal(t, testOject.hasError, err != nil)
if !testOject.hasError {
assert.Equal(t, testOject.statusCode, resp.StatusCode)
assert.Equal(t, testOject.responseBody, testOject.responseBodyType)
}
testServer.Close()
}
}