Skip to content

Commit

Permalink
Add support of release list for GitLab
Browse files Browse the repository at this point in the history
  • Loading branch information
minamijoyo committed Feb 24, 2020
1 parent a55e235 commit 66aba94
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 21 deletions.
9 changes: 0 additions & 9 deletions release/github.go
Expand Up @@ -167,12 +167,3 @@ func (r *GitHubRelease) List(ctx context.Context, maxLength int) ([]string, erro
}
return versions, nil
}

func tagNameToVersion(tagName string) string {
// if a tagName starts with `v`, remove it.
if tagName[0] == 'v' {
return tagName[1:]
}

return tagName
}
42 changes: 33 additions & 9 deletions release/gitlab.go
Expand Up @@ -2,7 +2,6 @@ package release

import (
"context"
"errors"
"fmt"
"net/url"
"strings"
Expand All @@ -15,6 +14,9 @@ import (
type GitLabAPI interface {
// ProjectGetLatestRelease fetches the latest published release for the project.
ProjectGetLatestRelease(ctx context.Context, owner, project string) (*gitlab.Release, *gitlab.Response, error)

// ProjectListReleases gets a pagenated of releases accessible by the authenticated user.
ProjectListReleases(ctx context.Context, owner, project string, opt *gitlab.ListReleasesOptions) ([]*gitlab.Release, *gitlab.Response, error)
}

// GitLabConfig is a set of configurations for GitLabRelease..
Expand Down Expand Up @@ -71,6 +73,11 @@ func (c *GitLabClient) ProjectGetLatestRelease(ctx context.Context, owner, proje
return latest, response, err
}

// ProjectListReleases gets a pagenated of releases accessible by the authenticated user.
func (c *GitLabClient) ProjectListReleases(ctx context.Context, owner, project string, opt *gitlab.ListReleasesOptions) ([]*gitlab.Release, *gitlab.Response, error) {
return c.client.Releases.ListReleases(owner+"/"+project, opt, gitlab.WithContext(ctx))
}

// GitLabRelease is a release implementation which provides version information with GitLab Release.
type GitLabRelease struct {
// api is an instance of GitLabAPI interface.
Expand Down Expand Up @@ -120,17 +127,34 @@ func (r *GitLabRelease) Latest(ctx context.Context) (string, error) {
}

// Use TagName because some releases do not have Name.
tagName := release.TagName

// if a tagName starts with `v`, remove it.
if tagName[0] == 'v' {
return tagName[1:], nil
}
v := tagNameToVersion(release.TagName)

return tagName, nil
return v, nil
}

// List returns a list of versions.
func (r *GitLabRelease) List(ctx context.Context, maxLength int) ([]string, error) {
return nil, errors.New("not impplemented yet")
versions := []string{}
opt := &gitlab.ListReleasesOptions{}
for {
releases, resp, err := r.api.ProjectListReleases(ctx, r.owner, r.project, opt)

if err != nil {
return versions, fmt.Errorf("failed to list releases for %s/%s: %s", r.owner, r.project, err)
}

for _, release := range releases {
v := tagNameToVersion(release.TagName)
versions = append(versions, v)
}
if resp.NextPage == 0 || len(versions) >= maxLength {
break
}
opt.Page = resp.NextPage
}

if maxLength < len(versions) {
return versions[:maxLength], nil
}
return versions, nil
}
93 changes: 90 additions & 3 deletions release/gitlab_test.go
Expand Up @@ -3,6 +3,7 @@ package release
import (
"context"
"errors"
"reflect"
"testing"

"github.com/davecgh/go-spew/spew"
Expand All @@ -11,16 +12,22 @@ import (

// mockGitLabClient is a mock GitLabAPI implementation.
type mockGitLabClient struct {
projectRelease *gitlab.Release
response *gitlab.Response
err error
projectRelease *gitlab.Release
projectReleases []*gitlab.Release
response *gitlab.Response
err error
}

// ProjectGetLatestRelease returns the latest release for the mockGitLabClient.
func (c *mockGitLabClient) ProjectGetLatestRelease(ctx context.Context, owner, project string) (*gitlab.Release, *gitlab.Response, error) {
return c.projectRelease, c.response, c.err
}

// ProjectListReleases returns a list of releases for the mockGitLabClient.
func (c *mockGitLabClient) ProjectListReleases(ctx context.Context, owner, repo string, opt *gitlab.ListReleasesOptions) ([]*gitlab.Release, *gitlab.Response, error) {
return c.projectReleases, c.response, c.err
}

// Test of NewGitLabClient(config GitLabConfig)
func TestNewGitLabClient(t *testing.T) {
cases := []struct {
Expand Down Expand Up @@ -220,3 +227,83 @@ func TestGitLabReleaseLatest(t *testing.T) {
}
}
}

// Test of GitLabRelease.List(ctx context.Context, maxLength int)
func TestGitLabReleaseList(t *testing.T) {
tagv := []string{"v0.3.0", "v0.2.0", "v0.1.0"}
tag := []string{"0.3.0", "0.2.0", "0.1.0"}
cases := []struct {
client *mockGitLabClient
maxLength int
want []string
ok bool
}{ // test len(versions) < maxLength
{
client: &mockGitLabClient{
projectReleases: []*gitlab.Release{
&gitlab.Release{TagName: tagv[0]},
&gitlab.Release{TagName: tagv[1]},
&gitlab.Release{TagName: tagv[2]},
},
response: &gitlab.Response{},
err: nil,
},
maxLength: 5,
want: tag,
ok: true,
},
// test len(versions) > maxLength
{
client: &mockGitLabClient{
projectReleases: []*gitlab.Release{
&gitlab.Release{TagName: tagv[0]},
&gitlab.Release{TagName: tagv[1]},
&gitlab.Release{TagName: tagv[2]},
},
response: &gitlab.Response{},
err: nil,
},
maxLength: 2,
want: tag[:2],
ok: true,
},
// test unreachable/invalid project
{
client: &mockGitLabClient{
projectReleases: nil,
response: &gitlab.Response{},
// Actual error response type is *gitlab.ErrorResponse,
// but we are not interested in the internal structure.
err: errors.New(`GET https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab/releases: 404 Not Found []`),
},
want: []string{},
ok: false,
},
}

source := "gitlab-org/gitlab"
for _, tc := range cases {
// Set a mock client
config := GitLabConfig{
api: tc.client,
}
r, err := NewGitLabRelease(source, config)
if err != nil {
t.Fatalf("failed to NewGitLabRelease(%s, %#v): %s", source, config, err)
}

got, err := r.List(context.Background(), tc.maxLength)

if tc.ok && err != nil {
t.Errorf("(*GitLabRelease).List() with r = %s, maxLength = %d returns unexpected err: %+v", spew.Sdump(r), tc.maxLength, err)
}

if !tc.ok && err == nil {
t.Errorf("(*GitLabRelease).List() with r = %s, maxLength = %d expects to return an error, but no error", spew.Sdump(r), tc.maxLength)
}

if !reflect.DeepEqual(got, tc.want) {
t.Errorf("(*GitLabRelease).List() with r = %s, maxLength = %d returns %s, but want = %s", spew.Sdump(r), tc.maxLength, got, tc.want)
}
}
}
10 changes: 10 additions & 0 deletions release/version.go
@@ -0,0 +1,10 @@
package release

func tagNameToVersion(tagName string) string {
// if a tagName starts with `v`, remove it.
if tagName[0] == 'v' {
return tagName[1:]
}

return tagName
}

0 comments on commit 66aba94

Please sign in to comment.