add release & milestone functionality
parent
be60c693c9
commit
8ce6b18ce6
@ -1,4 +1,17 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/h2non/gock v1.0.9 h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU=
|
||||
github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -0,0 +1,31 @@
|
||||
package bitbucket
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type milestoneService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) List(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package bitbucket
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type releaseService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type milestoneService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/milestones/%d", namespace, name, id)
|
||||
out := new(milestone)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertMilestone(out), res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/milestones%s", namespace, name, encodeMilestoneListOptions(opts))
|
||||
out := []*milestone{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertMilestoneList(out), res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/milestones", namespace, name)
|
||||
in := &milestoneInput{
|
||||
Title: input.Title,
|
||||
Description: input.Description,
|
||||
State: StateOpen,
|
||||
Deadline: input.DueDate,
|
||||
}
|
||||
if input.State == "closed" {
|
||||
in.State = StateClosed
|
||||
}
|
||||
out := new(milestone)
|
||||
res, err := s.client.do(ctx, "POST", path, in, out)
|
||||
return convertMilestone(out), res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/milestones/%d", namespace, name, id)
|
||||
return s.client.do(ctx, "DELETE", path, nil, nil)
|
||||
}
|
||||
|
||||
func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/milestones/%d", namespace, name, id)
|
||||
in := milestoneInput{}
|
||||
if input.Title != "" {
|
||||
in.Title = input.Title
|
||||
}
|
||||
switch input.State {
|
||||
case "open":
|
||||
in.State = StateOpen
|
||||
case "close", "closed":
|
||||
in.State = StateClosed
|
||||
}
|
||||
if input.Description != "" {
|
||||
in.Description = input.Description
|
||||
}
|
||||
if input.DueDate != nil {
|
||||
in.Deadline = input.DueDate
|
||||
}
|
||||
out := new(milestone)
|
||||
res, err := s.client.do(ctx, "PATCH", path, in, out)
|
||||
return convertMilestone(out), res, err
|
||||
}
|
||||
|
||||
// StateType issue state type
|
||||
type StateType string
|
||||
|
||||
const (
|
||||
// StateOpen pr/issue is open
|
||||
StateOpen StateType = "open"
|
||||
// StateClosed pr/issue is closed
|
||||
StateClosed StateType = "closed"
|
||||
// StateAll is all
|
||||
StateAll StateType = "all"
|
||||
)
|
||||
|
||||
type milestone struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
State StateType `json:"state"`
|
||||
OpenIssues int `json:"open_issues"`
|
||||
ClosedIssues int `json:"closed_issues"`
|
||||
Created time.Time `json:"created_at"`
|
||||
Updated *time.Time `json:"updated_at"`
|
||||
Closed *time.Time `json:"closed_at"`
|
||||
Deadline *time.Time `json:"due_on"`
|
||||
}
|
||||
|
||||
type milestoneInput struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
State StateType `json:"state"`
|
||||
Deadline *time.Time `json:"due_on"`
|
||||
}
|
||||
|
||||
func convertMilestoneList(src []*milestone) []*scm.Milestone {
|
||||
var dst []*scm.Milestone
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertMilestone(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func convertMilestone(src *milestone) *scm.Milestone {
|
||||
if src == nil || src.Deadline == nil {
|
||||
return nil
|
||||
}
|
||||
return &scm.Milestone{
|
||||
Number: int(src.ID),
|
||||
ID: int(src.ID),
|
||||
Title: src.Title,
|
||||
Description: src.Description,
|
||||
State: string(src.State),
|
||||
DueDate: src.Deadline,
|
||||
}
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/h2non/gock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMilestoneFind(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Get("/api/v1/repos/jcitizen/my-repo/milestones/1").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/milestone.json")
|
||||
|
||||
client, _ := New("https://try.gitea.io")
|
||||
got, _, err := client.Milestones.Find(context.Background(), "jcitizen/my-repo", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
want := new(scm.Milestone)
|
||||
raw, _ := ioutil.ReadFile("testdata/milestone.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMilestoneList(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Get("/api/v1/repos/jcitizen/my-repo/milestones").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockPageHeaders).
|
||||
File("testdata/milestones.json")
|
||||
|
||||
client, _ := New("https://try.gitea.io")
|
||||
got, res, err := client.Milestones.List(context.Background(), "jcitizen/my-repo", scm.MilestoneListOptions{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
want := []*scm.Milestone{}
|
||||
raw, _ := ioutil.ReadFile("testdata/milestones.json.golden")
|
||||
err = json.Unmarshal(raw, &want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Page", testPage(res))
|
||||
}
|
||||
|
||||
func TestMilestoneCreate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Post("/api/v1/repos/jcitizen/my-repo/milestones").
|
||||
File("testdata/milestone_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/milestone.json")
|
||||
|
||||
client, _ := New("https://try.gitea.io")
|
||||
dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z")
|
||||
input := &scm.MilestoneInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking milestone for version 1.0",
|
||||
State: "open",
|
||||
DueDate: &dueDate,
|
||||
}
|
||||
got, _, err := client.Milestones.Create(context.Background(), "jcitizen/my-repo", input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
want := new(scm.Milestone)
|
||||
raw, _ := ioutil.ReadFile("testdata/milestone.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMilestoneUpdate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Patch("/api/v1/repos/jcitizen/my-repo/milestones").
|
||||
File("testdata/milestone_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/milestone.json")
|
||||
|
||||
client, _ := New("https://try.gitea.io")
|
||||
dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z")
|
||||
input := &scm.MilestoneInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking milestone for version 1.0",
|
||||
State: "open",
|
||||
DueDate: &dueDate,
|
||||
}
|
||||
got, _, err := client.Milestones.Update(context.Background(), "jcitizen/my-repo", 1, input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
want := new(scm.Milestone)
|
||||
raw, _ := ioutil.ReadFile("testdata/milestone.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMilestoneDelete(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Delete("/api/v1/repos/jcitizen/my-repo/milestones/1").
|
||||
Reply(200).
|
||||
Type("application/json")
|
||||
|
||||
client, _ := New("https://try.gitea.io")
|
||||
_, err := client.Milestones.Delete(context.Background(), "jcitizen/my-repo", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
var mockPageHeaders = map[string]string{
|
||||
"Link": `<https://try.gitea.io/v1/resource?page=2>; rel="next",` +
|
||||
`<https://try.gitea.io/v1/resource?page=1>; rel="prev",` +
|
||||
`<https://try.gitea.io/v1/resource?page=1>; rel="first",` +
|
||||
`<https://try.gitea.io/v1/resource?page=5>; rel="last"`,
|
||||
}
|
||||
|
||||
func mockServerVersion() {
|
||||
gock.New("https://try.gitea.io").
|
||||
Get("/api/v1/version").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/version.json")
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type releaseService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/releases/%d", namespace, name, id)
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/releases/tags/%s", namespace, name, tag)
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/releases?%s", namespace, name, encodeReleaseListOptions(opts))
|
||||
out := []*release{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertReleaseList(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/releases", namespace, name)
|
||||
in := &ReleaseInput{
|
||||
TagName: input.Tag,
|
||||
Target: input.Commitish,
|
||||
Title: input.Title,
|
||||
Note: input.Description,
|
||||
IsDraft: input.Draft,
|
||||
IsPrerelease: input.Prerelease,
|
||||
}
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "POST", path, in, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/releases/%d", namespace, name, id)
|
||||
return s.client.do(ctx, "DELETE", path, nil, nil)
|
||||
}
|
||||
|
||||
func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/releases/tags/%s", namespace, name, tag)
|
||||
return s.client.do(ctx, "DELETE", path, nil, nil)
|
||||
}
|
||||
|
||||
func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
namespace, name := scm.Split(repo)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/%s/releases/%d", namespace, name, id)
|
||||
in := &ReleaseInput{
|
||||
TagName: input.Tag,
|
||||
Target: input.Commitish,
|
||||
Title: input.Title,
|
||||
Note: input.Description,
|
||||
IsDraft: input.Draft,
|
||||
IsPrerelease: input.Prerelease,
|
||||
}
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "PATCH", path, in, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
rel, _, err := s.FindByTag(ctx, repo, tag)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return s.Update(ctx, repo, rel.ID, input)
|
||||
}
|
||||
|
||||
type ReleaseInput struct {
|
||||
TagName string `json:"tag_name"`
|
||||
Target string `json:"target_commitish"`
|
||||
Title string `json:"name"`
|
||||
Note string `json:"body"`
|
||||
IsDraft bool `json:"draft"`
|
||||
IsPrerelease bool `json:"prerelease"`
|
||||
}
|
||||
|
||||
// release represents a repository release
|
||||
type release struct {
|
||||
ID int64 `json:"id"`
|
||||
TagName string `json:"tag_name"`
|
||||
Target string `json:"target_commitish"`
|
||||
Title string `json:"name"`
|
||||
Note string `json:"body"`
|
||||
URL string `json:"url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
TarURL string `json:"tarball_url"`
|
||||
ZipURL string `json:"zipball_url"`
|
||||
IsDraft bool `json:"draft"`
|
||||
IsPrerelease bool `json:"prerelease"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
PublishedAt time.Time `json:"published_at"`
|
||||
Publisher *User `json:"author"`
|
||||
Attachments []*Attachment `json:"assets"`
|
||||
}
|
||||
|
||||
type Attachment struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
DownloadCount int64 `json:"download_count"`
|
||||
Created time.Time `json:"created_at"`
|
||||
UUID string `json:"uuid"`
|
||||
DownloadURL string `json:"browser_download_url"`
|
||||
}
|
||||
|
||||
func convertRelease(src *release) *scm.Release {
|
||||
return &scm.Release{
|
||||
ID: int(src.ID),
|
||||
Title: src.Title,
|
||||
Description: src.Note,
|
||||
Link: ConvertAPIURLToHTMLURL(src.URL, src.TagName),
|
||||
Tag: src.TagName,
|
||||
Commitish: src.Target,
|
||||
Draft: src.IsDraft,
|
||||
Prerelease: src.IsPrerelease,
|
||||
Created: src.CreatedAt,
|
||||
Published: src.PublishedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func convertReleaseList(src []*release) []*scm.Release {
|
||||
var dst []*scm.Release
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertRelease(v))
|
||||
}
|
||||
return dst
|
||||
}
|
@ -0,0 +1,342 @@
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/h2non/gock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConvertAPIURLToHTMLURL(t *testing.T) {
|
||||
|
||||
got := ConvertAPIURLToHTMLURL("https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", "v1.0.0")
|
||||
want := "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0"
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
t.Log("got:")
|
||||
t.Log(string(got))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestConvertAPIURLToHTMLURLEmptyLinkWhenURLParseFails(t *testing.T) {
|
||||
|
||||
broken := []string{"http s://try.gitea.com/api/v1/repos/octocat/Hello-World/123", "https://try.gitea.com/api/v1/repos/octocat/Hello-World"}
|
||||
for _, url := range broken {
|
||||
|
||||
got := ConvertAPIURLToHTMLURL(url, "v1.0.0")
|
||||
want := ""
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
t.Log("got:")
|
||||
t.Log(string(got))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestReleaseFind(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Get("/repos/octocat/hello-world/releases/1").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/release.json")
|
||||
|
||||
client, err := New("https://try.gitea.io")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
got, _, err := client.Releases.Find(context.Background(), "octocat/hello-world", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseFindByTag(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Get("/repos/octocat/hello-world/releases/tags/v1.0.0").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/release.json")
|
||||
|
||||
client, err := New("https://try.gitea.io")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
got, _, err := client.Releases.FindByTag(context.Background(), "octocat/hello-world", "v1.0.0")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseList(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Get("/repos/octocat/hello-world/releases").
|
||||
MatchParam("page", "1").
|
||||
MatchParam("limit", "30").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/releases.json")
|
||||
|
||||
client, err := New("https://try.gitea.io")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
got, _, err := client.Releases.List(context.Background(), "octocat/hello-world", scm.ReleaseListOptions{Page: 1, Size: 30, Open: true, Closed: true})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := []*scm.Release{}
|
||||
raw, _ := ioutil.ReadFile("testdata/releases.json.golden")
|
||||
err = json.Unmarshal(raw, &want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestReleaseCreate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Post("/repos/octocat/hello-world/releases").
|
||||
File("testdata/release_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/release.json")
|
||||
|
||||
client, err := New("https://try.gitea.io")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
input := &scm.ReleaseInput{
|
||||
Title: "v1.0.0",
|
||||
Description: "Description of the release",
|
||||
Tag: "v1.0.0",
|
||||
Commitish: "master",
|
||||
Draft: false,
|
||||
Prerelease: false,
|
||||
}
|
||||
|
||||
got, _, err := client.Releases.Create(context.Background(), "octocat/hello-world", input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestReleaseUpdate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Patch("/repos/octocat/hello-world/releases/1").
|
||||
File("testdata/release_update.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/release.json")
|
||||
|
||||
client, err := New("https://try.gitea.io")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
input := &scm.ReleaseInput{
|
||||
Title: "v1.0.0",
|
||||
Description: "Description of the release",
|
||||
Tag: "v1.0.0",
|
||||
Commitish: "master",
|
||||
Draft: false,
|
||||
Prerelease: false,
|
||||
}
|
||||
got, _, err := client.Releases.Update(context.Background(), "octocat/hello-world", 1, input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestReleaseUpdateByTag(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Get("/repos/octocat/hello-world/releases/tags/v1.0.0").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/release.json")
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Patch("/repos/octocat/hello-world/releases/1").
|
||||
File("testdata/release_update.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/release.json")
|
||||
|
||||
client, err := New("https://try.gitea.io")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
input := &scm.ReleaseInput{
|
||||
Title: "v1.0.0",
|
||||
Description: "Description of the release",
|
||||
Tag: "v1.0.0",
|
||||
Commitish: "master",
|
||||
Draft: false,
|
||||
Prerelease: false,
|
||||
}
|
||||
got, _, err := client.Releases.UpdateByTag(context.Background(), "octocat/hello-world", "v1.0.0", input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func TestReleaseDelete(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Delete("/repos/octocat/hello-world/releases/1").
|
||||
Reply(200).
|
||||
Type("application/json")
|
||||
|
||||
client, err := New("https://try.gitea.io")
|
||||
_, err = client.Releases.Delete(context.Background(), "octocat/hello-world", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestReleaseDeleteByTag(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
mockServerVersion()
|
||||
|
||||
gock.New("https://try.gitea.io").
|
||||
Delete("/repos/octocat/hello-world/releases/tags/v1.0.0").
|
||||
Reply(200).
|
||||
Type("application/json")
|
||||
|
||||
client, err := New("https://try.gitea.io")
|
||||
_, err = client.Releases.DeleteByTag(context.Background(), "octocat/hello-world", "v1.0.0")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"closed_at": "2020-09-11T19:32:38.046Z",
|
||||
"closed_issues": 0,
|
||||
"created_at": "2020-09-11T19:32:38.046Z",
|
||||
"description": "string",
|
||||
"due_on": "2020-09-11T19:32:38.046Z",
|
||||
"id": 1,
|
||||
"open_issues": 0,
|
||||
"state": "open",
|
||||
"title": "string",
|
||||
"updated_at": "2020-09-11T19:32:38.046Z"
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Description": "string",
|
||||
"DueDate": "2020-09-11T19:32:38.046Z",
|
||||
"ID": 1,
|
||||
"Number": 1,
|
||||
"State": "open",
|
||||
"Title": "string"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"title": "v1.0",
|
||||
"description": "Tracking milestone for version 1.0",
|
||||
"state": "open",
|
||||
"due_on": "2012-10-09T23:39:01Z"
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"closed_at": "2020-09-11T19:32:38.046Z",
|
||||
"closed_issues": 0,
|
||||
"created_at": "2020-09-11T19:32:38.046Z",
|
||||
"description": "string",
|
||||
"due_on": "2020-09-11T19:32:38.046Z",
|
||||
"id": 1,
|
||||
"open_issues": 0,
|
||||
"state": "open",
|
||||
"title": "string",
|
||||
"updated_at": "2020-09-11T19:32:38.046Z"
|
||||
}
|
||||
]
|
@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"Description": "string",
|
||||
"DueDate": "2020-09-11T19:32:38.046Z",
|
||||
"ID": 1,
|
||||
"Number": 1,
|
||||
"State": "open",
|
||||
"Title": "string"
|
||||
}
|
||||
]
|
@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "v1.0.0",
|
||||
"body": "Description of the release",
|
||||
"url": "https://try.gitea.com/api/v1/repos/octocat/Hello-World/123",
|
||||
"tag_name": "v1.0.0",
|
||||
"target_commitish": "master",
|
||||
"draft": false,
|
||||
"prerelease": false
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
{
|
||||
"ID": 1,
|
||||
"Title": "v1.0.0",
|
||||
"Description": "Description of the release",
|
||||
"Link": "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0",
|
||||
"Tag": "v1.0.0",
|
||||
"Commitish": "master",
|
||||
"Draft": false,
|
||||
"Prerelease": false
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"tag_name": "v1.0.0",
|
||||
"target_commitish": "master",
|
||||
"name": "v1.0.0",
|
||||
"body": "Description of the release",
|
||||
"draft": false,
|
||||
"prerelease": false
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"tag_name": "v1.0.0",
|
||||
"target_commitish": "master",
|
||||
"name": "v1.0.0",
|
||||
"body": "Description of the release",
|
||||
"draft": false,
|
||||
"prerelease": false
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "v1.0.0",
|
||||
"body": "Description of the release",
|
||||
"url": "https://try.gitea.com/api/v1/repos/octocat/Hello-World/123",
|
||||
"tag_name": "v1.0.0",
|
||||
"target_commitish": "master",
|
||||
"draft": false,
|
||||
"prerelease": false
|
||||
}
|
||||
]
|
@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"ID": 1,
|
||||
"Title": "v1.0.0",
|
||||
"Description": "Description of the release",
|
||||
"Link": "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0",
|
||||
"Tag": "v1.0.0",
|
||||
"Commitish": "master",
|
||||
"Draft": false,
|
||||
"Prerelease": false
|
||||
}
|
||||
]
|
@ -0,0 +1,111 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type milestoneService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
type milestone struct {
|
||||
ID int `json:"id"`
|
||||
Number int `json:"number"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
State string `json:"state"`
|
||||
DueOn time.Time `json:"due_on"`
|
||||
URL string `json:"url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
LabelsURL string `json:"labels_url"`
|
||||
Creator user `json:"creator"`
|
||||
OpenIssues int `json:"open_issues"`
|
||||
ClosedIssues int `json:"closed_issues"`
|
||||
NodeID string `json:"node_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ClosedAt time.Time `json:"closed_at"`
|
||||
}
|
||||
|
||||
type milestoneInput struct {
|
||||
Title string `json:"title"`
|
||||
State string `json:"state"`
|
||||
Description string `json:"description"`
|
||||
DueOn time.Time `json:"due_on"`
|
||||
}
|
||||
|
||||
func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/milestones/%d", repo, id)
|
||||
out := new(milestone)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertMilestone(out), res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/milestones?%s", repo, encodeMilestoneListOptions(opts))
|
||||
out := []*milestone{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertMilestoneList(out), res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/milestones", repo)
|
||||
in := &milestoneInput{
|
||||
Title: input.Title,
|
||||
State: input.State,
|
||||
Description: input.Description,
|
||||
DueOn: *input.DueDate,
|
||||
}
|
||||
out := new(milestone)
|
||||
res, err := s.client.do(ctx, "POST", path, in, out)
|
||||
return convertMilestone(out), res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/milestones/%d", repo, id)
|
||||
return s.client.do(ctx, "DELETE", path, nil, nil)
|
||||
}
|
||||
|
||||
func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/milestones/%d", repo, id)
|
||||
in := &milestoneInput{}
|
||||
if input.Title != "" {
|
||||
in.Title = input.Title
|
||||
}
|
||||
if input.State != "" {
|
||||
in.State = input.State
|
||||
}
|
||||
if input.Description != "" {
|
||||
in.Description = input.Description
|
||||
}
|
||||
if input.DueDate != nil {
|
||||
in.DueOn = *input.DueDate
|
||||
}
|
||||
out := new(milestone)
|
||||
res, err := s.client.do(ctx, "PATCH", path, in, out)
|
||||
return convertMilestone(out), res, err
|
||||
}
|
||||
|
||||
func convertMilestoneList(from []*milestone) []*scm.Milestone {
|
||||
var to []*scm.Milestone
|
||||
for _, m := range from {
|
||||
to = append(to, convertMilestone(m))
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertMilestone(from *milestone) *scm.Milestone {
|
||||
return &scm.Milestone{
|
||||
Number: from.Number,
|
||||
ID: from.ID,
|
||||
Title: from.Title,
|
||||
Description: from.Description,
|
||||
Link: from.HTMLURL,
|
||||
State: from.State,
|
||||
DueDate: &from.DueOn,
|
||||
}
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/drone/go-scm/scm"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/h2non/gock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestMilestoneFind(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Get("/repos/octocat/hello-world/milestones/1").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/milestone.json")
|
||||
|
||||
client := NewDefault()
|
||||
got, res, err := client.Milestones.Find(context.Background(), "octocat/hello-world", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Milestone)
|
||||
raw, _ := ioutil.ReadFile("testdata/milestone.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestMilestoneList(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Get("/repos/octocat/hello-world/milestones").
|
||||
MatchParam("page", "1").
|
||||
MatchParam("per_page", "30").
|
||||
MatchParam("state", "all").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/milestones.json")
|
||||
client := NewDefault()
|
||||
got, res, err := client.Milestones.List(context.Background(), "octocat/hello-world", scm.MilestoneListOptions{Page: 1, Size: 30, Open: true, Closed: true})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := []*scm.Milestone{}
|
||||
raw, _ := ioutil.ReadFile("testdata/milestones.json.golden")
|
||||
err = json.Unmarshal(raw, &want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestMilestoneCreate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Post("/repos/octocat/hello-world/milestones").
|
||||
File("testdata/milestone_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/milestone.json")
|
||||
|
||||
client := NewDefault()
|
||||
dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z")
|
||||
input := &scm.MilestoneInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking milestone for version 1.0",
|
||||
State: "open",
|
||||
DueDate: &dueDate,
|
||||
}
|
||||
|
||||
got, res, err := client.Milestones.Create(context.Background(), "octocat/hello-world", input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Milestone)
|
||||
raw, _ := ioutil.ReadFile("testdata/milestone.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestMilestoneUpdate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Patch("/repos/octocat/hello-world/milestones/1").
|
||||
File("testdata/milestone_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/milestone.json")
|
||||
|
||||
client := NewDefault()
|
||||
dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z")
|
||||
input := &scm.MilestoneInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking milestone for version 1.0",
|
||||
State: "open",
|
||||
DueDate: &dueDate,
|
||||
}
|
||||
|
||||
got, res, err := client.Milestones.Update(context.Background(), "octocat/hello-world", 1, input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Milestone)
|
||||
raw, _ := ioutil.ReadFile("testdata/milestone.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestMilestoneDelete(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Delete("/repos/octocat/hello-world/milestones/1").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders)
|
||||
|
||||
client := NewDefault()
|
||||
res, err := client.Milestones.Delete(context.Background(), "octocat/hello-world", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type releaseService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
type release struct {
|
||||
ID int `json:"id"`
|
||||
Title string `json:"name"`
|
||||
Description string `json:"body"`
|
||||
Link string `json:"html_url,omitempty"`
|
||||
Tag string `json:"tag_name,omitempty"`
|
||||
Commitish string `json:"target_commitish,omitempty"`
|
||||
Draft bool `json:"draft"`
|
||||
Prerelease bool `json:"prerelease"`
|
||||
Created time.Time `json:"created_at"`
|
||||
Published time.Time `json:"published_at"`
|
||||
}
|
||||
|
||||
type releaseInput struct {
|
||||
Title string `json:"name"`
|
||||
Description string `json:"body"`
|
||||
Tag string `json:"tag_name"`
|
||||
Commitish string `json:"target_commitish"`
|
||||
Draft bool `json:"draft"`
|
||||
Prerelease bool `json:"prerelease"`
|
||||
}
|
||||
|
||||
func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/releases/%d", repo, id)
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/releases/tags/%s", repo, tag)
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/releases?%s", repo, encodeReleaseListOptions(opts))
|
||||
out := []*release{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertReleaseList(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/releases", repo)
|
||||
in := &releaseInput{
|
||||
Title: input.Title,
|
||||
Commitish: input.Commitish,
|
||||
Description: input.Description,
|
||||
Draft: input.Draft,
|
||||
Prerelease: input.Prerelease,
|
||||
Tag: input.Tag,
|
||||
}
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "POST", path, in, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/releases/%d", repo, id)
|
||||
return s.client.do(ctx, "DELETE", path, nil, nil)
|
||||
}
|
||||
|
||||
func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) {
|
||||
rel, _, _ := s.FindByTag(ctx, repo, tag)
|
||||
return s.Delete(ctx, repo, rel.ID)
|
||||
}
|
||||
|
||||
func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
path := fmt.Sprintf("repos/%s/releases/%d", repo, id)
|
||||
in := &releaseInput{}
|
||||
if input.Title != "" {
|
||||
in.Title = input.Title
|
||||
}
|
||||
if input.Description != "" {
|
||||
in.Description = input.Description
|
||||
}
|
||||
if input.Commitish != "" {
|
||||
in.Commitish = input.Commitish
|
||||
}
|
||||
if input.Tag != "" {
|
||||
in.Tag = input.Tag
|
||||
}
|
||||
in.Draft = input.Draft
|
||||
in.Prerelease = input.Prerelease
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "PATCH", path, in, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
rel, _, _ := s.FindByTag(ctx, repo, tag)
|
||||
return s.Update(ctx, repo, rel.ID, input)
|
||||
}
|
||||
|
||||
func convertReleaseList(from []*release) []*scm.Release {
|
||||
var to []*scm.Release
|
||||
for _, m := range from {
|
||||
to = append(to, convertRelease(m))
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertRelease(from *release) *scm.Release {
|
||||
return &scm.Release{
|
||||
ID: from.ID,
|
||||
Title: from.Title,
|
||||
Description: from.Description,
|
||||
Link: from.Link,
|
||||
Tag: from.Tag,
|
||||
Commitish: from.Commitish,
|
||||
Draft: from.Draft,
|
||||
Prerelease: from.Prerelease,
|
||||
Created: from.Created,
|
||||
Published: from.Published,
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/drone/go-scm/scm"
|
||||
"github.com/h2non/gock"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestReleaseFind(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Get("/repos/octocat/hello-world/releases/1").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/release.json")
|
||||
|
||||
client := NewDefault()
|
||||
got, res, err := client.Releases.Find(context.Background(), "octocat/hello-world", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestReleaseList(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Get("/repos/octocat/hello-world/releases").
|
||||
MatchParam("page", "1").
|
||||
MatchParam("per_page", "30").
|
||||
MatchParam("state", "all").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/releases.json")
|
||||
|
||||
client := NewDefault()
|
||||
got, res, err := client.Releases.List(context.Background(), "octocat/hello-world", scm.ReleaseListOptions{Page: 1, Size: 30, Open: true, Closed: true})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := []*scm.Release{}
|
||||
raw, _ := ioutil.ReadFile("testdata/releases.json.golden")
|
||||
err = json.Unmarshal(raw, &want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestReleaseCreate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Post("/repos/octocat/hello-world/releases").
|
||||
File("testdata/release_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/release.json")
|
||||
|
||||
client := NewDefault()
|
||||
input := &scm.ReleaseInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking release for version 1.0",
|
||||
Tag: "v1.0",
|
||||
}
|
||||
|
||||
got, res, err := client.Releases.Create(context.Background(), "octocat/hello-world", input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestReleaseUpdate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Patch("/repos/octocat/hello-world/releases/1").
|
||||
File("testdata/release_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/release.json")
|
||||
|
||||
client := NewDefault()
|
||||
input := &scm.ReleaseInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking release for version 1.0",
|
||||
Tag: "v1.0",
|
||||
}
|
||||
|
||||
got, res, err := client.Releases.Update(context.Background(), "octocat/hello-world", 1, input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestReleaseDelete(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://api.github.com").
|
||||
Delete("/repos/octocat/hello-world/releases/1").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders)
|
||||
|
||||
client := NewDefault()
|
||||
res, err := client.Releases.Delete(context.Background(), "octocat/hello-world", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
{
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/milestones/1",
|
||||
"html_url": "https://github.com/octocat/Hello-World/milestones/v1.0",
|
||||
"labels_url": "https://api.github.com/repos/octocat/Hello-World/milestones/1/labels",
|
||||
"id": 1002604,
|
||||
"node_id": "MDk6TWlsZXN0b25lMTAwMjYwNA==",
|
||||
"number": 1,
|
||||
"state": "open",
|
||||
"title": "v1.0",
|
||||
"description": "Tracking milestone for version 1.0",
|
||||
"creator": {
|
||||
"login": "octocat",
|
||||
"id": 1,
|
||||
"node_id": "MDQ6VXNlcjE=",
|
||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/octocat",
|
||||
"html_url": "https://github.com/octocat",
|
||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
},
|
||||
"open_issues": 4,
|
||||
"closed_issues": 8,
|
||||
"created_at": "2011-04-10T20:09:31Z",
|
||||
"updated_at": "2014-03-03T18:58:10Z",
|
||||
"closed_at": "2013-02-12T13:22:01Z",
|
||||
"due_on": "2012-10-09T23:39:01Z"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Link": "https://github.com/octocat/Hello-World/milestones/v1.0",
|
||||
"ID": 1002604,
|
||||
"Number": 1,
|
||||
"State": "open",
|
||||
"Title": "v1.0",
|
||||
"Description": "Tracking milestone for version 1.0",
|
||||
"DueDate": "2012-10-09T23:39:01Z"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"state": "open",
|
||||
"title": "v1.0",
|
||||
"description": "Tracking milestone for version 1.0",
|
||||
"due_on": "2012-10-09T23:39:01Z"
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
[
|
||||
{
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/milestones/1",
|
||||
"html_url": "https://github.com/octocat/Hello-World/milestones/v1.0",
|
||||
"labels_url": "https://api.github.com/repos/octocat/Hello-World/milestones/1/labels",
|
||||
"id": 1002604,
|
||||
"node_id": "MDk6TWlsZXN0b25lMTAwMjYwNA==",
|
||||
"number": 1,
|
||||
"state": "open",
|
||||
"title": "v1.0",
|
||||
"description": "Tracking milestone for version 1.0",
|
||||
"creator": {
|
||||
"login": "octocat",
|
||||
"id": 1,
|
||||
"node_id": "MDQ6VXNlcjE=",
|
||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/octocat",
|
||||
"html_url": "https://github.com/octocat",
|
||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
},
|
||||
"open_issues": 4,
|
||||
"closed_issues": 8,
|
||||
"created_at": "2011-04-10T20:09:31Z",
|
||||
"updated_at": "2014-03-03T18:58:10Z",
|
||||
"closed_at": "2013-02-12T13:22:01Z",
|
||||
"due_on": "2012-10-09T23:39:01Z"
|
||||
}
|
||||
]
|
@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"Link": "https://github.com/octocat/Hello-World/milestones/v1.0",
|
||||
"ID": 1002604,
|
||||
"Number": 1,
|
||||
"State": "open",
|
||||
"Title": "v1.0",
|
||||
"Description": "Tracking milestone for version 1.0",
|
||||
"DueDate": "2012-10-09T23:39:01Z"
|
||||
}
|
||||
]
|
@ -0,0 +1,74 @@
|
||||
{
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/releases/1",
|
||||
"html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0",
|
||||
"assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets",
|
||||
"upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}",
|
||||
"tarball_url": "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0",
|
||||
"zipball_url": "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0",
|
||||
"id": 1,
|
||||
"node_id": "MDc6UmVsZWFzZTE=",
|
||||
"tag_name": "v1.0.0",
|
||||
"target_commitish": "master",
|
||||
"name": "v1.0.0",
|
||||
"body": "Description of the release",
|
||||
"draft": false,
|
||||
"prerelease": false,
|
||||
"created_at": "2013-02-27T19:35:32Z",
|
||||
"published_at": "2013-02-27T19:35:32Z",
|
||||
"author": {
|
||||
"login": "octocat",
|
||||
"id": 1,
|
||||
"node_id": "MDQ6VXNlcjE=",
|
||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/octocat",
|
||||
"html_url": "https://github.com/octocat",
|
||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
},
|
||||
"assets": [
|
||||
{
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/releases/assets/1",
|
||||
"browser_download_url": "https://github.com/octocat/Hello-World/releases/download/v1.0.0/example.zip",
|
||||
"id": 1,
|
||||
"node_id": "MDEyOlJlbGVhc2VBc3NldDE=",
|
||||
"name": "example.zip",
|
||||
"label": "short description",
|
||||
"state": "uploaded",
|
||||
"content_type": "application/zip",
|
||||
"size": 1024,
|
||||
"download_count": 42,
|
||||
"created_at": "2013-02-27T19:35:32Z",
|
||||
"updated_at": "2013-02-27T19:35:32Z",
|
||||
"uploader": {
|
||||
"login": "octocat",
|
||||
"id": 1,
|
||||
"node_id": "MDQ6VXNlcjE=",
|
||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/octocat",
|
||||
"html_url": "https://github.com/octocat",
|
||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"ID": 1,
|
||||
"Title": "v1.0.0",
|
||||
"Description": "Description of the release",
|
||||
"Link": "https://github.com/octocat/Hello-World/releases/v1.0.0",
|
||||
"Tag": "v1.0.0",
|
||||
"Commitish": "master",
|
||||
"Draft": false,
|
||||
"Prerelease": false,
|
||||
"Created": "2013-02-27T19:35:32Z",
|
||||
"Published": "2013-02-27T19:35:32Z"
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
[
|
||||
{
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/releases/1",
|
||||
"html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0",
|
||||
"assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets",
|
||||
"upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}",
|
||||
"tarball_url": "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0",
|
||||
"zipball_url": "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0",
|
||||
"id": 1,
|
||||
"node_id": "MDc6UmVsZWFzZTE=",
|
||||
"tag_name": "v1.0.0",
|
||||
"target_commitish": "master",
|
||||
"name": "v1.0.0",
|
||||
"body": "Description of the release",
|
||||
"draft": false,
|
||||
"prerelease": false,
|
||||
"created_at": "2013-02-27T19:35:32Z",
|
||||
"published_at": "2013-02-27T19:35:32Z",
|
||||
"author": {
|
||||
"login": "octocat",
|
||||
"id": 1,
|
||||
"node_id": "MDQ6VXNlcjE=",
|
||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/octocat",
|
||||
"html_url": "https://github.com/octocat",
|
||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
},
|
||||
"assets": [
|
||||
{
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/releases/assets/1",
|
||||
"browser_download_url": "https://github.com/octocat/Hello-World/releases/download/v1.0.0/example.zip",
|
||||
"id": 1,
|
||||
"node_id": "MDEyOlJlbGVhc2VBc3NldDE=",
|
||||
"name": "example.zip",
|
||||
"label": "short description",
|
||||
"state": "uploaded",
|
||||
"content_type": "application/zip",
|
||||
"size": 1024,
|
||||
"download_count": 42,
|
||||
"created_at": "2013-02-27T19:35:32Z",
|
||||
"updated_at": "2013-02-27T19:35:32Z",
|
||||
"uploader": {
|
||||
"login": "octocat",
|
||||
"id": 1,
|
||||
"node_id": "MDQ6VXNlcjE=",
|
||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/octocat",
|
||||
"html_url": "https://github.com/octocat",
|
||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"ID": 1,
|
||||
"Title": "v1.0.0",
|
||||
"Description": "Description of the release",
|
||||
"Link": "https://github.com/octocat/Hello-World/releases/v1.0.0",
|
||||
"Tag": "v1.0.0",
|
||||
"Commitish": "master",
|
||||
"Draft": false,
|
||||
"Prerelease": false,
|
||||
"Created": "2013-02-27T19:35:32Z",
|
||||
"Published": "2013-02-27T19:35:32Z"
|
||||
}
|
||||
]
|
@ -0,0 +1,166 @@
|
||||
package gitlab
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type milestoneService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
// isoTime represents an ISO 8601 formatted date
|
||||
type isoTime time.Time
|
||||
|
||||
// ISO 8601 date format
|
||||
const iso8601 = "2006-01-02"
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface
|
||||
func (t isoTime) MarshalJSON() ([]byte, error) {
|
||||
if y := time.Time(t).Year(); y < 0 || y >= 10000 {
|
||||
// ISO 8901 uses 4 digits for the years
|
||||
return nil, errors.New("json: ISOTime year outside of range [0,9999]")
|
||||
}
|
||||
|
||||
b := make([]byte, 0, len(iso8601)+2)
|
||||
b = append(b, '"')
|
||||
b = time.Time(t).AppendFormat(b, iso8601)
|
||||
b = append(b, '"')
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface
|
||||
func (t *isoTime) UnmarshalJSON(data []byte) error {
|
||||
// Ignore null, like in the main JSON package
|
||||
if string(data) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
isotime, err := time.Parse(`"`+iso8601+`"`, string(data))
|
||||
*t = isoTime(isotime)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// EncodeValues implements the query.Encoder interface
|
||||
func (t *isoTime) EncodeValues(key string, v *url.Values) error {
|
||||
if t == nil || (time.Time(*t)).IsZero() {
|
||||
return nil
|
||||
}
|
||||
v.Add(key, t.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
// String implements the Stringer interface
|
||||
func (t isoTime) String() string {
|
||||
return time.Time(t).Format(iso8601)
|
||||
}
|
||||
|
||||
type milestone struct {
|
||||
ID int `json:"id"`
|
||||
IID int `json:"iid"`
|
||||
ProjectID int `json:"project_id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
State string `json:"state"`
|
||||
DueDate isoTime `json:"due_date"`
|
||||
StartDate isoTime `json:"start_date"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Expired bool `json:"expired"`
|
||||
}
|
||||
|
||||
type milestoneInput struct {
|
||||
Title *string `json:"title"`
|
||||
StateEvent *string `json:"state_event,omitempty"`
|
||||
Description *string `json:"description"`
|
||||
DueDate *isoTime `json:"due_date"`
|
||||
}
|
||||
|
||||
func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/milestones/%d", encode(repo), id)
|
||||
out := new(milestone)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertMilestone(out), res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/milestones?%s", encode(repo), encodeMilestoneListOptions(opts))
|
||||
out := []*milestone{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertMilestoneList(out), res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/milestones", encode(repo))
|
||||
dueDateIso := isoTime(*input.DueDate)
|
||||
in := &milestoneInput{
|
||||
Title: &input.Title,
|
||||
Description: &input.Description,
|
||||
DueDate: &dueDateIso,
|
||||
}
|
||||
out := new(milestone)
|
||||
res, err := s.client.do(ctx, "POST", path, in, out)
|
||||
return convertMilestone(out), res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/milestones/%d", encode(repo), id)
|
||||
res, err := s.client.do(ctx, "DELETE", path, nil, nil)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/milestones/%d", encode(repo), id)
|
||||
in := &milestoneInput{}
|
||||
if input.Title != "" {
|
||||
in.Title = &input.Title
|
||||
}
|
||||
if input.State != "" {
|
||||
if input.State == "open" {
|
||||
activate := "activate"
|
||||
in.StateEvent = &activate
|
||||
} else {
|
||||
in.StateEvent = &input.State
|
||||
}
|
||||
}
|
||||
if input.Description != "" {
|
||||
in.Description = &input.Description
|
||||
}
|
||||
if input.DueDate != nil {
|
||||
dueDateIso := isoTime(*input.DueDate)
|
||||
in.DueDate = &dueDateIso
|
||||
}
|
||||
out := new(milestone)
|
||||
res, err := s.client.do(ctx, "PATCH", path, in, out)
|
||||
return convertMilestone(out), res, err
|
||||
}
|
||||
|
||||
func convertMilestoneList(from []*milestone) []*scm.Milestone {
|
||||
var to []*scm.Milestone
|
||||
for _, m := range from {
|
||||
to = append(to, convertMilestone(m))
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertMilestone(from *milestone) *scm.Milestone {
|
||||
if from == nil || from.Title == "" {
|
||||
return nil
|
||||
}
|
||||
dueDate := time.Time(from.DueDate)
|
||||
return &scm.Milestone{
|
||||
Number: from.ID,
|
||||
ID: from.ID,
|
||||
Title: from.Title,
|
||||
Description: from.Description,
|
||||
State: from.State,
|
||||
DueDate: &dueDate,
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
package gitlab
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/drone/go-scm/scm"
|
||||
"github.com/h2non/gock"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestMilestoneFind(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Get("/api/v4/projects/diaspora/diaspora/milestones/1").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/milestone.json")
|
||||
|
||||
client := NewDefault()
|
||||
got, res, err := client.Milestones.Find(context.Background(), "diaspora/diaspora", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Milestone)
|
||||
raw, err := ioutil.ReadFile("testdata/milestone.json.golden")
|
||||
if err != nil {
|
||||
t.Fatalf("ioutil.ReadFile: %v", err)
|
||||
}
|
||||
if err := json.Unmarshal(raw, want); err != nil {
|
||||
t.Fatalf("json.Unmarshal: %v", err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestMilestoneList(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Get("/api/v4/projects/diaspora/diaspora/milestones").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/milestones.json")
|
||||
|
||||
client := NewDefault()
|
||||
got, res, err := client.Milestones.List(context.Background(), "diaspora/diaspora", scm.MilestoneListOptions{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := []*scm.Milestone{}
|
||||
raw, err := ioutil.ReadFile("testdata/milestones.json.golden")
|
||||
if err != nil {
|
||||
t.Fatalf("ioutil.ReadFile: %v", err)
|
||||
}
|
||||
if err := json.Unmarshal(raw, &want); err != nil {
|
||||
t.Fatalf("json.Unmarshal: %v", err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestMilestoneCreate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Post("/api/v4/projects/diaspora/diaspora/milestones").
|
||||
File("testdata/milestone_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/milestone.json")
|
||||
|
||||
client := NewDefault()
|
||||
dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z")
|
||||
input := &scm.MilestoneInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking milestone for version 1.0",
|
||||
State: "open",
|
||||
DueDate: &dueDate,
|
||||
}
|
||||
got, res, err := client.Milestones.Create(context.Background(), "diaspora/diaspora", input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Milestone)
|
||||
raw, err := ioutil.ReadFile("testdata/milestone.json.golden")
|
||||
if err != nil {
|
||||
t.Fatalf("ioutil.ReadFile: %v", err)
|
||||
}
|
||||
if err := json.Unmarshal(raw, &want); err != nil {
|
||||
t.Fatalf("json.Unmarshal: %v", err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestMilestoneUpdate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Patch("/api/v4/projects/diaspora/diaspora/milestones/1").
|
||||
File("testdata/milestone_update.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/milestone.json")
|
||||
|
||||
client := NewDefault()
|
||||
dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z")
|
||||
input := &scm.MilestoneInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking milestone for version 1.0",
|
||||
State: "close",
|
||||
DueDate: &dueDate,
|
||||
}
|
||||
got, res, err := client.Milestones.Update(context.Background(), "diaspora/diaspora", 1, input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Milestone)
|
||||
raw, err := ioutil.ReadFile("testdata/milestone.json.golden")
|
||||
if err != nil {
|
||||
t.Fatalf("ioutil.ReadFile: %v", err)
|
||||
}
|
||||
if err := json.Unmarshal(raw, &want); err != nil {
|
||||
t.Fatalf("json.Unmarshal: %v", err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestMilestoneDelete(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Delete("/api/v4/projects/diaspora/diaspora/milestones/1").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders)
|
||||
|
||||
client := NewDefault()
|
||||
_, err := client.Milestones.Delete(context.Background(), "diaspora/diaspora", 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package gitlab
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type releaseService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
type release struct {
|
||||
Title string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Tag string `json:"tag_name"`
|
||||
Commit struct {
|
||||
ID string `json:"id"`
|
||||
} `json:"commit"`
|
||||
}
|
||||
|
||||
type releaseInput struct {
|
||||
Title string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Tag string `json:"tag_name"`
|
||||
}
|
||||
|
||||
func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) {
|
||||
// this could be implemented by List and filter but would be to expensive
|
||||
panic("gitlab only allows to find a release by tag")
|
||||
}
|
||||
|
||||
func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/releases/%s", encode(repo), tag)
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/releases", encode(repo))
|
||||
out := []*release{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertReleaseList(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/releases", encode(repo))
|
||||
in := &releaseInput{
|
||||
Title: input.Title,
|
||||
Description: input.Description,
|
||||
Tag: input.Tag,
|
||||
}
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "POST", path, in, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
// this could be implemented by List and filter but would be to expensive
|
||||
panic("gitlab only allows to delete a release by tag")
|
||||
}
|
||||
|
||||
func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/releases/%s", encode(repo), tag)
|
||||
return s.client.do(ctx, "DELETE", path, nil, nil)
|
||||
}
|
||||
|
||||
func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
// this could be implemented by List and filter but would be to expensive
|
||||
panic("gitlab only allows to update a release by tag")
|
||||
}
|
||||
|
||||
func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v4/projects/%s/releases/%s", encode(repo), tag)
|
||||
in := &releaseInput{}
|
||||
if input.Title != "" {
|
||||
in.Title = input.Title
|
||||
}
|
||||
if input.Description != "" {
|
||||
in.Description = input.Description
|
||||
}
|
||||
if input.Tag != "" {
|
||||
in.Tag = input.Tag
|
||||
}
|
||||
out := new(release)
|
||||
res, err := s.client.do(ctx, "PUT", path, in, out)
|
||||
return convertRelease(out), res, err
|
||||
}
|
||||
|
||||
func convertReleaseList(from []*release) []*scm.Release {
|
||||
var to []*scm.Release
|
||||
for _, m := range from {
|
||||
to = append(to, convertRelease(m))
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertRelease(from *release) *scm.Release {
|
||||
return &scm.Release{
|
||||
ID: 0,
|
||||
Title: from.Title,
|
||||
Description: from.Description,
|
||||
Link: "",
|
||||
Tag: from.Tag,
|
||||
Commitish: from.Commit.ID,
|
||||
Draft: false, // not supported by gitlab
|
||||
Prerelease: false, // not supported by gitlab
|
||||
}
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
package gitlab
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/h2non/gock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestReleaseFindByTag(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Get("/api/v4/projects/diaspora/diaspora/releases/v1.0.1").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/release.json")
|
||||
|
||||
client := NewDefault()
|
||||
got, res, err := client.Releases.FindByTag(context.Background(), "diaspora/diaspora", "v1.0.1")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestReleaseList(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Get("/api/v4/projects/diaspora/diaspora/releases").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/releases.json")
|
||||
|
||||
client := NewDefault()
|
||||
got, res, err := client.Releases.List(context.Background(), "diaspora/diaspora", scm.ReleaseListOptions{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := []*scm.Release{}
|
||||
raw, _ := ioutil.ReadFile("testdata/releases.json.golden")
|
||||
err = json.Unmarshal(raw, &want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestReleaseCreate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Post("/api/v4/projects/diaspora/diaspora/releases").
|
||||
File("testdata/release_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/release.json")
|
||||
|
||||
client := NewDefault()
|
||||
input := &scm.ReleaseInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking release for version 1.0",
|
||||
Tag: "v1.0",
|
||||
}
|
||||
|
||||
got, res, err := client.Releases.Create(context.Background(), "diaspora/diaspora", input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
|
||||
data, _ := json.Marshal(got)
|
||||
t.Log("got JSON:")
|
||||
t.Log(string(data))
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestReleaseUpdateByTag(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Put("/api/v4/projects/diaspora/diaspora/releases/v1.0").
|
||||
File("testdata/release_create.json").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders).
|
||||
File("testdata/release.json")
|
||||
|
||||
client := NewDefault()
|
||||
input := &scm.ReleaseInput{
|
||||
Title: "v1.0",
|
||||
Description: "Tracking release for version 1.0",
|
||||
Tag: "v1.0",
|
||||
}
|
||||
|
||||
got, res, err := client.Releases.UpdateByTag(context.Background(), "diaspora/diaspora", "v1.0", input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
want := new(scm.Release)
|
||||
raw, _ := ioutil.ReadFile("testdata/release.json.golden")
|
||||
err = json.Unmarshal(raw, want)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
||||
|
||||
func TestReleaseDeleteByTag(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("https://gitlab.com").
|
||||
Delete("/api/v4/projects/diaspora/diaspora/releases/v1.0").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
SetHeaders(mockHeaders)
|
||||
|
||||
client := NewDefault()
|
||||
res, err := client.Releases.DeleteByTag(context.Background(), "diaspora/diaspora", "v1.0")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Run("Request", testRequest(res))
|
||||
t.Run("Rate", testRate(res))
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": 12,
|
||||
"iid": 3,
|
||||
"project_id": 16,
|
||||
"title": "10.0",
|
||||
"description": "Version",
|
||||
"due_date": "2013-11-29",
|
||||
"start_date": "2013-11-10",
|
||||
"state": "active",
|
||||
"updated_at": "2013-10-02T09:24:18Z",
|
||||
"created_at": "2013-10-02T09:24:18Z",
|
||||
"expired": false
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"ID": 12,
|
||||
"Number": 12,
|
||||
"Title": "10.0",
|
||||
"Description": "Version",
|
||||
"DueDate": "2013-11-29T00:00:00Z",
|
||||
"State": "active"
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "v1.0",
|
||||
"description": "Tracking milestone for version 1.0",
|
||||
"due_date": "2012-10-09"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"title": "v1.0",
|
||||
"description": "Tracking milestone for version 1.0",
|
||||
"state_event": "close",
|
||||
"due_date": "2012-10-09"
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
[
|
||||
{
|
||||
"id": 12,
|
||||
"iid": 3,
|
||||
"project_id": 16,
|
||||
"title": "10.0",
|
||||
"description": "Version",
|
||||
"due_date": "2013-11-29",
|
||||
"start_date": "2013-11-10",
|
||||
"state": "active",
|
||||
"updated_at": "2013-10-02T09:24:18Z",
|
||||
"created_at": "2013-10-02T09:24:18Z",
|
||||
"expired": false
|
||||
}
|
||||
]
|
@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"ID": 12,
|
||||
"Number": 12,
|
||||
"Title": "10.0",
|
||||
"Description": "Version",
|
||||
"DueDate": "2013-11-29T00:00:00Z",
|
||||
"State": "active"
|
||||
}
|
||||
]
|
@ -0,0 +1,100 @@
|
||||
{
|
||||
"tag_name":"v0.1",
|
||||
"description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516",
|
||||
"name":"Awesome app v0.1 alpha",
|
||||
"description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e",
|
||||
"created_at":"2019-01-03T01:55:18.203Z",
|
||||
"released_at":"2019-01-03T01:55:18.203Z",
|
||||
"author":{
|
||||
"id":1,
|
||||
"name":"Administrator",
|
||||
"username":"root",
|
||||
"state":"active",
|
||||
"avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
|
||||
"web_url":"https://gitlab.example.com/root"
|
||||
},
|
||||
"commit":{
|
||||
"id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4",
|
||||
"short_id":"f8d3d94c",
|
||||
"title":"Initial commit",
|
||||
"created_at":"2019-01-03T01:53:28.000Z",
|
||||
"parent_ids":[
|
||||
|
||||
],
|
||||
"message":"Initial commit",
|
||||
"author_name":"Administrator",
|
||||
"author_email":"admin@example.com",
|
||||
"authored_date":"2019-01-03T01:53:28.000Z",
|
||||
"committer_name":"Administrator",
|
||||
"committer_email":"admin@example.com",
|
||||
"committed_date":"2019-01-03T01:53:28.000Z"
|
||||
},
|
||||
"milestones": [
|
||||
{
|
||||
"id":51,
|
||||
"iid":1,
|
||||
"project_id":24,
|
||||
"title":"v1.0-rc",
|
||||
"description":"Voluptate fugiat possimus quis quod aliquam expedita.",
|
||||
"state":"closed",
|
||||
"created_at":"2019-07-12T19:45:44.256Z",
|
||||
"updated_at":"2019-07-12T19:45:44.256Z",
|
||||
"due_date":"2019-08-16T11:00:00.256Z",
|
||||
"start_date":"2019-07-30T12:00:00.256Z",
|
||||
"web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1",
|
||||
"issue_stats": {
|
||||
"total": 98,
|
||||
"closed": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":52,
|
||||
"iid":2,
|
||||
"project_id":24,
|
||||
"title":"v1.0",
|
||||
"description":"Voluptate fugiat possimus quis quod aliquam expedita.",
|
||||
"state":"closed",
|
||||
"created_at":"2019-07-16T14:00:12.256Z",
|
||||
"updated_at":"2019-07-16T14:00:12.256Z",
|
||||
"due_date":"2019-08-16T11:00:00.256Z",
|
||||
"start_date":"2019-07-30T12:00:00.256Z",
|
||||
"web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2",
|
||||
"issue_stats": {
|
||||
"total": 24,
|
||||
"closed": 21
|
||||
}
|
||||
}
|
||||
],
|
||||
"commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a",
|
||||
"tag_path":"/root/awesome-app/-/tags/v0.11.1",
|
||||
"assets":{
|
||||
"count":5,
|
||||
"sources":[
|
||||
{
|
||||
"format":"zip",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip"
|
||||
},
|
||||
{
|
||||
"format":"tar.gz",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz"
|
||||
},
|
||||
{
|
||||
"format":"tar.bz2",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2"
|
||||
},
|
||||
{
|
||||
"format":"tar",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar"
|
||||
}
|
||||
],
|
||||
"links":[
|
||||
{
|
||||
"id":3,
|
||||
"name":"hoge",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/tags/v0.11.1/binaries/linux-amd64",
|
||||
"external":true,
|
||||
"link_type":"other"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
{
|
||||
"ID": 0,
|
||||
"Title": "Awesome app v0.1 alpha",
|
||||
"Description": "## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516",
|
||||
"Link": "",
|
||||
"Tag": "v0.1",
|
||||
"Commitish": "f8d3d94cbd347e924aa7b715845e439d00e80ca4",
|
||||
"Draft": false,
|
||||
"Prerelease": false
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
[
|
||||
{
|
||||
"tag_name":"v0.2",
|
||||
"description":"## CHANGELOG\r\n\r\n- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740\r\n- Prevent private snippets from being embeddable.\r\n- Add subresources removal to member destroy service.",
|
||||
"name":"Awesome app v0.2 beta",
|
||||
"description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eEscape label and milestone titles to prevent XSS in GFM autocomplete. !2740\u003c/li\u003e\n\u003cli\u003ePrevent private snippets from being embeddable.\u003c/li\u003e\n\u003cli\u003eAdd subresources removal to member destroy service.\u003c/li\u003e\n\u003c/ul\u003e",
|
||||
"created_at":"2019-01-03T01:56:19.539Z",
|
||||
"released_at":"2019-01-03T01:56:19.539Z",
|
||||
"author":{
|
||||
"id":1,
|
||||
"name":"Administrator",
|
||||
"username":"root",
|
||||
"state":"active",
|
||||
"avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
|
||||
"web_url":"https://gitlab.example.com/root"
|
||||
},
|
||||
"commit":{
|
||||
"id":"079e90101242458910cccd35eab0e211dfc359c0",
|
||||
"short_id":"079e9010",
|
||||
"title":"Update README.md",
|
||||
"created_at":"2019-01-03T01:55:38.000Z",
|
||||
"parent_ids":[
|
||||
"f8d3d94cbd347e924aa7b715845e439d00e80ca4"
|
||||
],
|
||||
"message":"Update README.md",
|
||||
"author_name":"Administrator",
|
||||
"author_email":"admin@example.com",
|
||||
"authored_date":"2019-01-03T01:55:38.000Z",
|
||||
"committer_name":"Administrator",
|
||||
"committer_email":"admin@example.com",
|
||||
"committed_date":"2019-01-03T01:55:38.000Z"
|
||||
},
|
||||
"milestones": [
|
||||
{
|
||||
"id":51,
|
||||
"iid":1,
|
||||
"project_id":24,
|
||||
"title":"v1.0-rc",
|
||||
"description":"Voluptate fugiat possimus quis quod aliquam expedita.",
|
||||
"state":"closed",
|
||||
"created_at":"2019-07-12T19:45:44.256Z",
|
||||
"updated_at":"2019-07-12T19:45:44.256Z",
|
||||
"due_date":"2019-08-16T11:00:00.256Z",
|
||||
"start_date":"2019-07-30T12:00:00.256Z",
|
||||
"web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1",
|
||||
"issue_stats": {
|
||||
"total": 98,
|
||||
"closed": 76
|
||||
}
|
||||
},
|
||||
{
|
||||
"id":52,
|
||||
"iid":2,
|
||||
"project_id":24,
|
||||
"title":"v1.0",
|
||||
"description":"Voluptate fugiat possimus quis quod aliquam expedita.",
|
||||
"state":"closed",
|
||||
"created_at":"2019-07-16T14:00:12.256Z",
|
||||
"updated_at":"2019-07-16T14:00:12.256Z",
|
||||
"due_date":"2019-08-16T11:00:00.256Z",
|
||||
"start_date":"2019-07-30T12:00:00.256Z",
|
||||
"web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2",
|
||||
"issue_stats": {
|
||||
"total": 24,
|
||||
"closed": 21
|
||||
}
|
||||
}
|
||||
],
|
||||
"commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a",
|
||||
"tag_path":"/root/awesome-app/-/tags/v0.11.1",
|
||||
"assets":{
|
||||
"count":6,
|
||||
"sources":[
|
||||
{
|
||||
"format":"zip",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.zip"
|
||||
},
|
||||
{
|
||||
"format":"tar.gz",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.gz"
|
||||
},
|
||||
{
|
||||
"format":"tar.bz2",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.bz2"
|
||||
},
|
||||
{
|
||||
"format":"tar",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar"
|
||||
}
|
||||
],
|
||||
"links":[
|
||||
{
|
||||
"id":2,
|
||||
"name":"awesome-v0.2.msi",
|
||||
"url":"http://192.168.10.15:3000/msi",
|
||||
"external":true,
|
||||
"link_type":"other"
|
||||
},
|
||||
{
|
||||
"id":1,
|
||||
"name":"awesome-v0.2.dmg",
|
||||
"url":"http://192.168.10.15:3000",
|
||||
"external":true,
|
||||
"link_type":"other"
|
||||
}
|
||||
],
|
||||
"evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.2/evidence.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag_name":"v0.1",
|
||||
"description":"## CHANGELOG\r\n\r\n-Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516",
|
||||
"name":"Awesome app v0.1 alpha",
|
||||
"description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e",
|
||||
"created_at":"2019-01-03T01:55:18.203Z",
|
||||
"released_at":"2019-01-03T01:55:18.203Z",
|
||||
"author":{
|
||||
"id":1,
|
||||
"name":"Administrator",
|
||||
"username":"root",
|
||||
"state":"active",
|
||||
"avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
|
||||
"web_url":"https://gitlab.example.com/root"
|
||||
},
|
||||
"commit":{
|
||||
"id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4",
|
||||
"short_id":"f8d3d94c",
|
||||
"title":"Initial commit",
|
||||
"created_at":"2019-01-03T01:53:28.000Z",
|
||||
"parent_ids":[
|
||||
|
||||
],
|
||||
"message":"Initial commit",
|
||||
"author_name":"Administrator",
|
||||
"author_email":"admin@example.com",
|
||||
"authored_date":"2019-01-03T01:53:28.000Z",
|
||||
"committer_name":"Administrator",
|
||||
"committer_email":"admin@example.com",
|
||||
"committed_date":"2019-01-03T01:53:28.000Z"
|
||||
},
|
||||
"assets":{
|
||||
"count":4,
|
||||
"sources":[
|
||||
{
|
||||
"format":"zip",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip"
|
||||
},
|
||||
{
|
||||
"format":"tar.gz",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz"
|
||||
},
|
||||
{
|
||||
"format":"tar.bz2",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2"
|
||||
},
|
||||
{
|
||||
"format":"tar",
|
||||
"url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar"
|
||||
}
|
||||
],
|
||||
"links":[
|
||||
|
||||
],
|
||||
"evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json"
|
||||
}
|
||||
}
|
||||
]
|
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"Title": "Awesome app v0.2 beta",
|
||||
"Description": "## CHANGELOG\r\n\r\n- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740\r\n- Prevent private snippets from being embeddable.\r\n- Add subresources removal to member destroy service.",
|
||||
"Tag": "v0.2",
|
||||
"Commitish": "079e90101242458910cccd35eab0e211dfc359c0"
|
||||
},
|
||||
{
|
||||
"Title": "Awesome app v0.1 alpha",
|
||||
"Description": "## CHANGELOG\r\n\r\n-Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516",
|
||||
"Tag": "v0.1",
|
||||
"Commitish": "f8d3d94cbd347e924aa7b715845e439d00e80ca4"
|
||||
}
|
||||
]
|
@ -0,0 +1,31 @@
|
||||
package gogs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type milestoneService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package gogs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type releaseService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package stash
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type milestoneService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package stash
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type releaseService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package scm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
// MilestoneInput contains the information needed to create a milestone
|
||||
MilestoneInput struct {
|
||||
Title string
|
||||
Description string
|
||||
State string
|
||||
DueDate *time.Time
|
||||
}
|
||||
|
||||
// MilestoneListOptions provides options for querying a list of repository milestones.
|
||||
MilestoneListOptions struct {
|
||||
Page int
|
||||
Size int
|
||||
Open bool
|
||||
Closed bool
|
||||
}
|
||||
|
||||
// MilestoneService provides access to creating, listing, updating, and deleting milestones
|
||||
MilestoneService interface {
|
||||
// Find returns the milestone for the given number in the given repository
|
||||
Find(context.Context, string, int) (*Milestone, *Response, error)
|
||||
|
||||
// List returns a list of milestones in the given repository
|
||||
List(context.Context, string, MilestoneListOptions) ([]*Milestone, *Response, error)
|
||||
|
||||
// Create creates a milestone in the given repository
|
||||
Create(context.Context, string, *MilestoneInput) (*Milestone, *Response, error)
|
||||
|
||||
// Update updates a milestone in the given repository
|
||||
Update(context.Context, string, int, *MilestoneInput) (*Milestone, *Response, error)
|
||||
|
||||
// Delete deletes a milestone in the given repository
|
||||
Delete(context.Context, string, int) (*Response, error)
|
||||
}
|
||||
)
|
@ -0,0 +1,67 @@
|
||||
package scm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
// Release the release
|
||||
Release struct {
|
||||
ID int
|
||||
Title string
|
||||
Description string
|
||||
Link string
|
||||
Tag string
|
||||
Commitish string
|
||||
Draft bool
|
||||
Prerelease bool
|
||||
Created time.Time
|
||||
Published time.Time
|
||||
}
|
||||
|
||||
// ReleaseInput contains the information needed to create a release
|
||||
ReleaseInput struct {
|
||||
Title string
|
||||
Description string
|
||||
Tag string
|
||||
Commitish string
|
||||
Draft bool
|
||||
Prerelease bool
|
||||
}
|
||||
|
||||
// ReleaseListOptions provides options for querying a list of repository releases.
|
||||
ReleaseListOptions struct {
|
||||
Page int
|
||||
Size int
|
||||
Open bool
|
||||
Closed bool
|
||||
}
|
||||
|
||||
// ReleaseService provides access to creating, listing, updating, and deleting releases
|
||||
ReleaseService interface {
|
||||
// Find returns the release for the given number in the given repository
|
||||
Find(context.Context, string, int) (*Release, *Response, error)
|
||||
|
||||
// FindByTag returns the release for the given tag in the given repository
|
||||
FindByTag(context.Context, string, string) (*Release, *Response, error)
|
||||
|
||||
// List returns a list of releases in the given repository
|
||||
List(context.Context, string, ReleaseListOptions) ([]*Release, *Response, error)
|
||||
|
||||
// Create creates a release in the given repository
|
||||
Create(context.Context, string, *ReleaseInput) (*Release, *Response, error)
|
||||
|
||||
// Update updates a release in the given repository
|
||||
Update(context.Context, string, int, *ReleaseInput) (*Release, *Response, error)
|
||||
|
||||
// UpdateByTag deletes a release in the given repository by tag
|
||||
UpdateByTag(context.Context, string, string, *ReleaseInput) (*Release, *Response, error)
|
||||
|
||||
// Delete deletes a release in the given repository
|
||||
Delete(context.Context, string, int) (*Response, error)
|
||||
|
||||
// DeleteByTag deletes a release in the given repository by tag
|
||||
DeleteByTag(context.Context, string, string) (*Response, error)
|
||||
}
|
||||
)
|
Loading…
Reference in New Issue