forked from go-jira/jira
-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.go
143 lines (125 loc) · 3.82 KB
/
search.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package jira
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"github.com/go-jira/jira/jiradata"
)
type SearchProvider interface {
ProvideSearchRequest() *jiradata.SearchRequest
}
type SearchOptions struct {
Assignee string `yaml:"assignee,omitempty" json:"assignee,omitempty"`
Query string `yaml:"query,omitempty" json:"query,omitempty"`
QueryFields string `yaml:"query-fields,omitempty" json:"query-fields,omitempty"`
Project string `yaml:"project,omitempty" json:"project,omitempty"`
Component string `yaml:"component,omitempty" json:"component,omitempty"`
IssueType string `yaml:"issue-type,omitempty" json:"issue-type,omitempty"`
Watcher string `yaml:"watcher,omitempty" json:"watcher,omitempty"`
Reporter string `yaml:"reporter,omitempty" json:"reporter,omitempty"`
Status string `yaml:"status,omitempty" json:"status,omitempty"`
Sort string `yaml:"sort,omitempty" json:"sort,omitempty"`
MaxResults int `yaml:"max-results,omitempty" json:"max-results,omitempty"`
}
func (o *SearchOptions) ProvideSearchRequest() *jiradata.SearchRequest {
req := &jiradata.SearchRequest{}
if o.Query == "" {
qbuff := bytes.NewBufferString("resolution = unresolved")
if o.Project != "" {
qbuff.WriteString(fmt.Sprintf(" AND project = '%s'", o.Project))
}
if o.Component != "" {
qbuff.WriteString(fmt.Sprintf(" AND component = '%s'", o.Component))
}
if o.Assignee != "" {
qbuff.WriteString(fmt.Sprintf(" AND assignee = '%s'", o.Assignee))
}
if o.IssueType != "" {
qbuff.WriteString(fmt.Sprintf(" AND issuetype = '%s'", o.IssueType))
}
if o.Watcher != "" {
qbuff.WriteString(fmt.Sprintf(" AND watcher = '%s'", o.Watcher))
}
if o.Reporter != "" {
qbuff.WriteString(fmt.Sprintf(" AND reporter = '%s'", o.Reporter))
}
if o.Status != "" {
qbuff.WriteString(fmt.Sprintf(" AND status = '%s'", o.Status))
}
if o.Sort != "" {
qbuff.WriteString(fmt.Sprintf(" ORDER BY %s", o.Sort))
}
req.JQL = qbuff.String()
} else {
req.JQL = o.Query
}
req.Fields = append(req.Fields, "summary")
if o.QueryFields != "" {
fields := strings.Split(o.QueryFields, ",")
req.Fields = append(req.Fields, fields...)
}
req.StartAt = 0
req.MaxResults = o.MaxResults
return req
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/search-searchUsingSearchRequest
func (j *Jira) Search(sp SearchProvider, opts ...SearchOpt) (*jiradata.SearchResults, error) {
return Search(j.UA, j.Endpoint, sp, opts...)
}
type searchConfig struct {
autoPaginate bool
}
type SearchOpt func(*searchConfig)
func WithAutoPagination() SearchOpt {
return func(c *searchConfig) {
c.autoPaginate = true
}
}
func Search(ua HttpClient, endpoint string, sp SearchProvider, opts ...SearchOpt) (*jiradata.SearchResults, error) {
c := &searchConfig{}
for _, opt := range opts {
opt(c)
}
req := sp.ProvideSearchRequest()
limit := req.MaxResults
if limit == 0 {
// max page size is 100
req.MaxResults = 100
}
issues := jiradata.Issues{}
for {
encoded, err := json.Marshal(req)
if err != nil {
return nil, err
}
uri := URLJoin(endpoint, "rest/api/2/search")
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, responseError(resp)
}
page := &jiradata.SearchResults{}
err = json.NewDecoder(resp.Body).Decode(page)
if err != nil {
return nil, err
}
if !c.autoPaginate {
return page, nil
}
issues = append(issues, page.Issues...)
// if we are done paginating just force all issues onto current
// response and return
if (limit > 0 && len(issues) >= limit) || len(issues) >= page.Total {
page.Issues = issues
return page, nil
}
req.StartAt = len(issues)
if len(issues)+req.MaxResults > limit {
req.MaxResults = limit - len(issues)
}
}
}