Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add release & milestone functionality #121

Merged
merged 10 commits into from
Oct 1, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/drone/go-scm
require (
github.com/google/go-cmp v0.2.0
github.com/h2non/gock v1.0.9
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 // indirect
)

go 1.13
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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=
8 changes: 5 additions & 3 deletions scm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ type (
// ListOptions specifies optional pagination
// parameters.
ListOptions struct {
URL string
Page int
Size int
URL string
Page int
Size int
eoinmcafee00 marked this conversation as resolved.
Show resolved Hide resolved
}

// Client manages communication with a version control
Expand All @@ -93,8 +93,10 @@ type (
Git GitService
Organizations OrganizationService
Issues IssueService
Milestones MilestoneService
PullRequests PullRequestService
Repositories RepositoryService
Releases ReleaseService
Reviews ReviewService
Users UserService
Webhooks WebhookService
Expand Down
2 changes: 2 additions & 0 deletions scm/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,5 @@ func (v Visibility) String() (s string) {
return "unknown"
}
}

const SearchTimeFormat = "2006-01-02T15:04:05Z"
2 changes: 2 additions & 0 deletions scm/driver/bitbucket/bitbucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ func New(uri string) (*scm.Client, error) {
client.Contents = &contentService{client}
client.Git = &gitService{client}
client.Issues = &issueService{client}
client.Milestones = &milestoneService{client}
client.Organizations = &organizationService{client}
client.PullRequests = &pullService{&issueService{client}}
client.Repositories = &repositoryService{client}
client.Releases = &releaseService{client}
client.Reviews = &reviewService{client}
client.Users = &userService{client}
client.Webhooks = &webhookService{client}
Expand Down
31 changes: 31 additions & 0 deletions scm/driver/bitbucket/milestone.go
Original file line number Diff line number Diff line change
@@ -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.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
}
43 changes: 43 additions & 0 deletions scm/driver/bitbucket/release.go
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 2 additions & 0 deletions scm/driver/gitea/gitea.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ func New(uri string) (*scm.Client, error) {
client.Contents = &contentService{client}
client.Git = &gitService{client}
client.Issues = &issueService{client}
client.Milestones = & milestoneService{client}
client.Organizations = &organizationService{client}
client.PullRequests = &pullService{client}
client.Repositories = &repositoryService{client}
client.Releases = &releaseService{client}
client.Reviews = &reviewService{client}
client.Users = &userService{client}
client.Webhooks = &webhookService{client}
Expand Down
22 changes: 21 additions & 1 deletion scm/driver/gitea/gitea_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
// package gitea implements a Gogs client.
package gitea

import "testing"
import (
"github.com/drone/go-scm/scm"
"testing"
)

func TestClient(t *testing.T) {
client, err := New("https://try.gitea.io")
Expand Down Expand Up @@ -33,3 +36,20 @@ func TestClient_Error(t *testing.T) {
t.Errorf("Expect error when invalid URL")
}
}

func testPage(res *scm.Response) func(t *testing.T) {
return func(t *testing.T) {
if got, want := res.Page.Next, 2; got != want {
t.Errorf("Want next page %d, got %d", want, got)
}
if got, want := res.Page.Prev, 1; got != want {
t.Errorf("Want prev page %d, got %d", want, got)
}
if got, want := res.Page.First, 1; got != want {
t.Errorf("Want first page %d, got %d", want, got)
}
if got, want := res.Page.Last, 5; got != want {
t.Errorf("Want last page %d, got %d", want, got)
}
}
}
130 changes: 130 additions & 0 deletions scm/driver/gitea/milestone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package gitea

import (
"context"
"fmt"

"github.com/drone/go-scm/scm"
"github.com/drone/go-scm/scm/driver/internal/null"
)

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: null.NewTime(input.DueDate, true),
eoinmcafee00 marked this conversation as resolved.
Show resolved Hide resolved
}
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.IsZero() {
in.Deadline = null.TimeFrom(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"
eoinmcafee00 marked this conversation as resolved.
Show resolved Hide resolved
)

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 null.Time `json:"created_at"`
eoinmcafee00 marked this conversation as resolved.
Show resolved Hide resolved
Updated null.Time `json:"updated_at"`
Closed null.Time `json:"closed_at"`
Deadline null.Time `json:"due_on"`
}

type milestoneInput struct {
Title string `json:"title"`
Description string `json:"description"`
State stateType `json:"state"`
Deadline null.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.IsZero() {
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.ValueOrZero(),
}
}
Loading