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

switched away from deprecated GetCreateIssueMeta to get the list of p… #849

Merged
merged 1 commit into from
Jul 13, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
19 changes: 3 additions & 16 deletions server/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"mime/multipart"
"net/http"
"net/url"
"path"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -54,7 +55,7 @@ type UserService interface {
// ProjectService is the interface for project-related APIs.
type ProjectService interface {
GetProject(key string) (*jira.Project, error)
GetAllProjectKeys() ([]string, error)
ListProjects(query string, limit int) (jira.ProjectList, error)
}

// SearchService is the interface for search-related APIs.
Expand Down Expand Up @@ -167,20 +168,6 @@ func (client JiraClient) RESTPostAttachment(issueID string, data []byte, name st
return attachments[0], nil
}

func (client JiraClient) GetAllProjectKeys() ([]string, error) {
projectlist, resp, err := client.Jira.Project.GetList()
if err != nil {
return nil, userFriendlyJiraError(resp, err)
}

keys := make([]string, 0, len(*projectlist))
for _, project := range *projectlist {
keys = append(keys, project.Key)
}

return keys, nil
}

// GetProject returns a Project by key.
func (client JiraClient) GetProject(key string) (*jira.Project, error) {
project, resp, err := client.Jira.Project.Get(key)
Expand Down Expand Up @@ -405,7 +392,7 @@ func endpointURL(endpoint string) (string, error) {
}
if parsedURL.Scheme == "" {
// relative path
endpoint = fmt.Sprintf("/rest/api/%s", endpoint)
endpoint = path.Join("/rest/api", endpoint)
}
return endpoint, nil
}
Expand Down
48 changes: 48 additions & 0 deletions server/client_cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package main

import (
"encoding/json"
"strconv"

jira "github.com/andygrunwald/go-jira"
"github.com/pkg/errors"
Expand Down Expand Up @@ -66,3 +67,50 @@ func (client jiraCloudClient) GetUserGroups(connection *Connection) ([]*jira.Use
}
return groups, nil
}

func (client jiraCloudClient) ListProjects(query string, limit int) (jira.ProjectList, error) {
type searchResult struct {
Values jira.ProjectList `json:"values"`
StartAt int `json:"startAt"`
MaxResults int `json:"maxResults"`
Total int `json:"total"`
IsLast bool `json:"isLast"`
}

remaining := 50
Copy link

@catalintomai catalintomai Mar 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@levb - just to confirm, this value looks to be useful only when limit is 0. Since we use only "-1" as a value in the negative spectrum, maybe we could've used limit = 0 to indicate fetchAll and only pass >= 0 values for limit instead. 0/5

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the default. The limit is not currently used anywhere, we always use -1 to get all projects.

Copy link
Contributor Author

@levb levb Mar 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, when we fetch all (-1), we do it 50 at a time.

fetchAll := false
if limit > 0 {
remaining = limit
}
if limit < 0 {
fetchAll = true
}

var out jira.ProjectList
for {
opts := map[string]string{
"startAt": strconv.Itoa(len(out)),
"maxResults": strconv.Itoa(remaining),
"expand": "issueTypes",
}
var result searchResult
err := client.RESTGet("/3/project/search", opts, &result)
if err != nil {
return nil, err
}
if len(result.Values) > remaining {
result.Values = result.Values[:remaining]
}
out = append(out, result.Values...)
remaining -= len(result.Values)

if !fetchAll && remaining == 0 {
// Got enough.
return out, nil
}
if len(result.Values) == 0 || result.IsLast {
// Ran out of results.
return out, nil
}
}
}
15 changes: 15 additions & 0 deletions server/client_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,18 @@ func (client jiraServerClient) GetUserGroups(connection *Connection) ([]*jira.Us
}
return result.Groups.Items, nil
}

func (client jiraServerClient) ListProjects(query string, limit int) (jira.ProjectList, error) {
plist, resp, err := client.Jira.Project.GetList()
if err != nil {
return nil, userFriendlyJiraError(resp, err)
}
if plist == nil {
return jira.ProjectList{}, nil
}
result := *plist
if limit > 0 && len(result) > limit {
result = result[:limit]
}
return result, nil
}
27 changes: 13 additions & 14 deletions server/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,13 +502,13 @@ func (p *Plugin) httpGetJiraProjectMetadata(w http.ResponseWriter, r *http.Reque

instanceID := r.FormValue("instance_id")

cimd, connection, err := p.GetJiraProjectMetadata(types.ID(instanceID), types.ID(mattermostUserID))
plist, connection, err := p.ListJiraProjects(types.ID(instanceID), types.ID(mattermostUserID))
if err != nil {
return respondErr(w, http.StatusInternalServerError,
errors.WithMessage(err, "failed to GetProjectMetadata"))
}

if len(cimd.Projects) == 0 {
if len(plist) == 0 {
_, err = respondJSON(w, map[string]interface{}{
"error": "You do not have permission to create issues in any projects. Please contact your Jira admin.",
})
Expand All @@ -518,21 +518,20 @@ func (p *Plugin) httpGetJiraProjectMetadata(w http.ResponseWriter, r *http.Reque
}
}

type option = utils.ReactSelectOption
projects := make([]option, 0, len(cimd.Projects))
issues := make(map[string][]option, len(cimd.Projects))
for _, prj := range cimd.Projects {
projects = append(projects, option{
projects := []utils.ReactSelectOption{}
issues := map[string][]utils.ReactSelectOption{}
for _, prj := range plist {
projects = append(projects, utils.ReactSelectOption{
Value: prj.Key,
Label: prj.Name,
})
issueTypes := make([]option, 0, len(prj.IssueTypes))
issueTypes := []utils.ReactSelectOption{}
for _, issue := range prj.IssueTypes {
if issue.Subtasks {
if issue.Subtask {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting change here

continue
}
issueTypes = append(issueTypes, option{
Value: issue.Id,
issueTypes = append(issueTypes, utils.ReactSelectOption{
Value: issue.ID,
Label: issue.Name,
})
}
Expand All @@ -546,16 +545,16 @@ func (p *Plugin) httpGetJiraProjectMetadata(w http.ResponseWriter, r *http.Reque
})
}

func (p *Plugin) GetJiraProjectMetadata(instanceID, mattermostUserID types.ID) (*jira.CreateMetaInfo, *Connection, error) {
func (p *Plugin) ListJiraProjects(instanceID, mattermostUserID types.ID) (jira.ProjectList, *Connection, error) {
client, _, connection, err := p.getClient(instanceID, mattermostUserID)
if err != nil {
return nil, nil, err
}
metainfo, err := client.GetCreateMeta(nil)
plist, err := client.ListProjects("", -1)
if err != nil {
return nil, nil, err
}
return metainfo, connection, nil
return plist, connection, nil
}

var reJiraIssueKey = regexp.MustCompile(`^([[:alnum:]]+)-([[:digit:]]+)$`)
Expand Down
5 changes: 3 additions & 2 deletions server/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,12 +351,13 @@ func (p *Plugin) AddAutolinksForCloudInstance(ci *cloudInstance) error {
return fmt.Errorf("unable to get jira client for server: %w", err)
}

keys, err := JiraClient{Jira: client}.GetAllProjectKeys()
plist, err := jiraCloudClient{JiraClient{Jira: client}}.ListProjects("", -1)
if err != nil {
return fmt.Errorf("unable to get project keys: %w", err)
}

for _, key := range keys {
for _, proj := range plist {
key := proj.Key
err = p.AddAutolinks(key, ci.BaseURL)
}
if err != nil {
Expand Down