From 30161c01b68d1577c8a136a744e81b771b757bc7 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Tue, 23 Mar 2021 14:24:57 +0000 Subject: [PATCH] fix: refactor the label comment code so we can reuse the comment label logic for bitbucket cloud too --- scm/driver/bitbucket/issue.go | 21 +++++++++---- scm/driver/bitbucket/pr.go | 27 +++++++++++++---- scm/driver/stash/issue.go | 14 ++++----- scm/driver/stash/pr.go | 52 ++++++-------------------------- scm/labels/labels.go | 56 +++++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 63 deletions(-) create mode 100644 scm/labels/labels.go diff --git a/scm/driver/bitbucket/issue.go b/scm/driver/bitbucket/issue.go index 28023927c..1b7f0b947 100644 --- a/scm/driver/bitbucket/issue.go +++ b/scm/driver/bitbucket/issue.go @@ -7,6 +7,8 @@ package bitbucket import ( "context" + "github.com/jenkins-x/go-scm/scm/labels" + "github.com/jenkins-x/go-scm/scm" ) @@ -30,17 +32,26 @@ func (s *issueService) ListEvents(context.Context, string, int, scm.ListOptions) return nil, nil, scm.ErrNotSupported } -func (s *issueService) ListLabels(context.Context, string, int, scm.ListOptions) ([]*scm.Label, *scm.Response, error) { - // TODO - return nil, nil, nil +func (s *issueService) ListLabels(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Label, *scm.Response, error) { + // Get all comments, parse out labels (removing and added based off time) + cs, res, err := s.ListComments(ctx, repo, number, opts) + if err == nil { + l, err := labels.ConvertLabelComments(cs) + return l, res, err + } + return nil, res, err } func (s *issueService) AddLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelAddComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err } func (s *issueService) DeleteLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelRemoveComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err } func (s *issueService) Find(ctx context.Context, repo string, number int) (*scm.Issue, *scm.Response, error) { diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index 8e0fcfc2f..f0eb3e2f6 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -11,6 +11,8 @@ import ( "strings" "time" + "github.com/jenkins-x/go-scm/scm/labels" + "github.com/jenkins-x/go-scm/scm" ) @@ -55,17 +57,30 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, return convertDiffstats(out), res, err } -func (s *pullService) ListLabels(context.Context, string, int, scm.ListOptions) ([]*scm.Label, *scm.Response, error) { - // TODO - return nil, nil, nil +func (s *pullService) ListLabels(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Label, *scm.Response, error) { + // Get all comments, parse out labels (removing and added based off time) + cs, res, err := s.ListComments(ctx, repo, number, opts) + if err == nil { + l, err := labels.ConvertLabelComments(cs) + return l, res, err + } + return nil, res, err } -func (s *pullService) ListEvents(context.Context, string, int, scm.ListOptions) ([]*scm.ListedIssueEvent, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *pullService) AddLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { + input := labels.CreateLabelAddComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err } func (s *pullService) DeleteLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + input := labels.CreateLabelRemoveComment(label) + _, res, err := s.CreateComment(ctx, repo, number, input) + return res, err +} + +func (s *pullService) ListEvents(context.Context, string, int, scm.ListOptions) ([]*scm.ListedIssueEvent, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported } func (s *pullService) Merge(ctx context.Context, repo string, number int, options *scm.PullRequestMergeOptions) (*scm.Response, error) { diff --git a/scm/driver/stash/issue.go b/scm/driver/stash/issue.go index f68c26ed5..d2a87c43b 100644 --- a/scm/driver/stash/issue.go +++ b/scm/driver/stash/issue.go @@ -8,6 +8,8 @@ import ( "context" "fmt" + "github.com/jenkins-x/go-scm/scm/labels" + "github.com/jenkins-x/go-scm/scm" ) @@ -35,26 +37,20 @@ func (s *issueService) ListLabels(ctx context.Context, repo string, number int, // Get all comments, parse out labels (removing and added based off time) cs, res, err := s.ListComments(ctx, repo, number, opts) if err == nil { - l, err := convertLabelComments(cs) + l, err := labels.ConvertLabelComments(cs) return l, res, err } return nil, res, err } func (s *issueService) AddLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - // Add a comment with /jx-label - input := &scm.CommentInput{ - Body: fmt.Sprintf("%s%s", addLabel, label), - } + input := labels.CreateLabelAddComment(label) _, res, err := s.CreateComment(ctx, repo, number, input) return res, err } func (s *issueService) DeleteLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - // Add a comment with /jx-label remove - input := &scm.CommentInput{ - Body: fmt.Sprintf("%s%s%s", addLabel, label, removeLabel), - } + input := labels.CreateLabelRemoveComment(label) _, res, err := s.CreateComment(ctx, repo, number, input) return res, err } diff --git a/scm/driver/stash/pr.go b/scm/driver/stash/pr.go index 18263a18f..5014ae0ce 100644 --- a/scm/driver/stash/pr.go +++ b/scm/driver/stash/pr.go @@ -9,10 +9,11 @@ import ( "fmt" "net/http" "net/url" - "sort" "strings" "time" + "github.com/jenkins-x/go-scm/scm/labels" + "github.com/jenkins-x/go-scm/scm" ) @@ -20,10 +21,6 @@ type pullService struct { client *wrapper } -const addLabel = "/jx-label " -const removeLabel = " remove" -const emptyString = "" - func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.PullRequest, *scm.Response, error) { namespace, name := scm.Split(repo) path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests/%d", namespace, name, number) @@ -64,63 +61,32 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, return convertDiffstats(out), res, err } -func convertLabelComments(cs []*scm.Comment) ([]*scm.Label, error) { - sort.SliceStable(cs, func(i, j int) bool { - return cs[i].Created.UnixNano() < cs[j].Created.UnixNano() - }) - m := make(map[string]bool) - for _, com := range cs { - if strings.HasPrefix(com.Body, addLabel) { - t := strings.ReplaceAll(com.Body, addLabel, emptyString) - if strings.HasSuffix(t, removeLabel) { - t = strings.ReplaceAll(t, removeLabel, emptyString) - m[t] = true - } else { - m[t] = false - } - } - } - var ls []*scm.Label - for l, i := range m { - if i == false { - ls = append(ls, &scm.Label{Name: l}) - } - } - return ls, nil -} - func (s *pullService) ListLabels(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Label, *scm.Response, error) { // Get all comments, parse out labels (removing and added based off time) cs, res, err := s.ListComments(ctx, repo, number, opts) if err == nil { - l, err := convertLabelComments(cs) + l, err := labels.ConvertLabelComments(cs) return l, res, err } return nil, res, err } -func (s *pullService) ListEvents(context.Context, string, int, scm.ListOptions) ([]*scm.ListedIssueEvent, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported -} - func (s *pullService) AddLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - // Add a comment with /jx-label - input := &scm.CommentInput{ - Body: fmt.Sprintf("%s%s", addLabel, label), - } + input := labels.CreateLabelAddComment(label) _, res, err := s.CreateComment(ctx, repo, number, input) return res, err } func (s *pullService) DeleteLabel(ctx context.Context, repo string, number int, label string) (*scm.Response, error) { - // Add a comment with /jx-label remove - input := &scm.CommentInput{ - Body: fmt.Sprintf("%s%s%s", addLabel, label, removeLabel), - } + input := labels.CreateLabelRemoveComment(label) _, res, err := s.CreateComment(ctx, repo, number, input) return res, err } +func (s *pullService) ListEvents(context.Context, string, int, scm.ListOptions) ([]*scm.ListedIssueEvent, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + func (s *pullService) ListComments(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { // TODO(bradrydzewski) the challenge with comments is that we need to use // the activities endpoint, which returns entries that may or may not be diff --git a/scm/labels/labels.go b/scm/labels/labels.go new file mode 100644 index 000000000..ba0391f01 --- /dev/null +++ b/scm/labels/labels.go @@ -0,0 +1,56 @@ +package labels + +import ( + "fmt" + "sort" + "strings" + + "github.com/jenkins-x/go-scm/scm" +) + +const ( + addLabel = "/jx-label " + removeLabel = " remove" + emptyString = "" +) + +// ConvertLabelComments converts comments to labels for git providers which don't support native labels +func ConvertLabelComments(cs []*scm.Comment) ([]*scm.Label, error) { + sort.SliceStable(cs, func(i, j int) bool { + return cs[i].Created.UnixNano() < cs[j].Created.UnixNano() + }) + m := make(map[string]bool) + for _, com := range cs { + if strings.HasPrefix(com.Body, addLabel) { + t := strings.ReplaceAll(com.Body, addLabel, emptyString) + if strings.HasSuffix(t, removeLabel) { + t = strings.ReplaceAll(t, removeLabel, emptyString) + m[t] = true + } else { + m[t] = false + } + } + } + var ls []*scm.Label + for l, i := range m { + if i == false { + ls = append(ls, &scm.Label{Name: l}) + } + } + return ls, nil +} + +// CreateLabelAddComment creates a label comment for git providers which don't support labels with comment with /jx-label +func CreateLabelAddComment(label string) *scm.CommentInput { + return &scm.CommentInput{ + Body: fmt.Sprintf("%s%s", addLabel, label), + } +} + +// CreateLabelRemoveComment adds a comment with /jx-label remove +func CreateLabelRemoveComment(label string) *scm.CommentInput { + input := &scm.CommentInput{ + Body: fmt.Sprintf("%s%s%s", addLabel, label, removeLabel), + } + return input +}