Created jira script
[clearscm.git] / lib / JIRA.pm
1
2 =pod
3
4 =head1 NAME $RCSfile: JIRA.pm,v $
5
6 Minimal module to talk to JIRA and get a few fields
7
8 =head1 VERSION
9
10 =over
11
12 =item Author
13
14 Andrew DeFaria <Andrew.DeFaria@WebPros.com>
15
16 =item Revision
17
18 $Revision: 1.0 $
19
20 =item Created
21
22 Monday, April 25 2022
23
24 =item Modified
25
26 Monday, April 25 2022
27
28 =back
29
30 =cut
31
32 package JIRA;
33
34 use strict;
35 use warnings;
36
37 use feature 'say';
38 use experimental qw(signatures);
39
40 use Display;
41 use Carp;
42
43 use JIRA::REST;
44
45 my %findQuery;
46
47 sub new ( $class, %opts ) {
48     croak "JIRA::new: Username not specified" unless $opts{username};
49     croak "JIRA::new: Password not specified" unless $opts{password};
50     croak "JIRA::new: Server not specified"   unless $opts{server};
51
52 =pod
53
54 =head2 new ()
55
56 Create a new JIRA object connecting to the JIRA database
57
58 Parameters:
59
60 =for html <blockquote>
61
62 =over
63
64 =item $opts{username}
65
66 Username to authenticate with
67
68 =item $opts{password}
69
70 Password to authenticate with
71
72 =item $opts{server}
73
74 JIRA server to connect to
75
76 =back
77
78 =for html </blockquote>
79
80 Returns:
81
82 =for html <blockquote>
83
84 =over
85
86 =item $jira
87
88 JIRA Object
89
90 =back
91
92 =for html </blockquote>
93
94 =cut
95
96     $opts{URL} = "http://$opts{server}/rest/api/latest";
97
98     $opts{rest} = JIRA::REST->new( $opts{URL}, $opts{username}, $opts{password} );
99
100     return bless \%opts, $class;
101 }
102
103 sub findIssues ( $self, $condition, @fields ) {
104
105 =pod
106
107 =head2 findIssues ()
108
109 Set up a find for JIRA issues based on a condition
110
111 Parameters:
112
113 =for html <blockquote>
114
115 =over
116
117 =item $condition
118
119 Condition to use. JQL is supported
120
121 =item @fields
122
123 List of fields to retrieve data for
124
125 =back
126
127 =for html </blockquote>
128
129 Returns:
130
131 =for html <blockquote>
132
133 =over
134
135 =item <nothing>
136
137 =back
138
139 =for html </blockquote>
140
141 =cut
142
143     push @fields, '*all' unless @fields;
144
145     $findQuery{jql}        = $condition || '';
146     $findQuery{startAt}    = 0;
147     $findQuery{maxResults} = 1;
148     $findQuery{fields}     = join ',', @fields;
149
150     return;
151 }    # findIssues
152
153 sub getNextIssue ($self) {
154     my $result;
155
156 =pod
157
158 =head2 getNextIssue ()
159
160 Get next qualifying issue. Call findIssues first
161
162 Parameters:
163
164 =for html <blockquote>
165
166 =over
167
168 =item <none>
169
170 =back
171
172 =for html </blockquote>
173
174 Returns:
175
176 =for html <blockquote>
177
178 =over
179
180 =item %issue
181
182 Perl hash of the fields in the next JIRA issue
183
184 =back
185
186 =for html </blockquote>
187
188 =cut
189
190     eval { $result = $self->{rest}->GET( '/search/', \%findQuery ) };
191
192     $findQuery{startAt}++;
193
194     # Move id and key into fields
195     return unless @{ $result->{issues} };
196
197     $result->{issues}[0]{fields}{id}  = $result->{issues}[0]{id};
198     $result->{issues}[0]{fields}{key} = $result->{issues}[0]{key};
199
200     return %{ $result->{issues}[0]{fields} };
201 }    # getNextIssue
202
203 sub getIssues ( $self, $condition, $start, $max, @fields ) {
204
205 =pod
206
207 =head2 getIssues ()
208
209 Get the @fields of JIRA issues based on a condition. Note that JIRA limits the
210 amount of entries returned to 1000. You can get fewer. Or you can use $start
211 to continue from where you've left off. 
212
213 Parameters:
214
215 =for html <blockquote>
216
217 =over
218
219 =item $condition
220
221 JQL condition to apply
222
223 =item $start
224
225 Starting point to get issues from
226
227 =item $max
228
229 Max number of entrist to get
230
231 =item @fields
232
233 List of fields to retrieve
234
235 =back
236
237 =for html </blockquote>
238
239 Returns:
240
241 =for html <blockquote>
242
243 =over
244
245 =item @issues
246
247 Perl array of hashes of JIRA issue records
248
249 =back
250
251 =for html </blockquote>
252
253 =cut
254
255     push @fields, '*all' unless @fields;
256
257     my ( $result, %query );
258
259     $query{jql}        = $condition || '';
260     $query{startAt}    = $start     || 0;
261     $query{maxResults} = $max       || 50;
262     $query{fields}     = join ',', @fields;
263
264     eval { $result = $self->{rest}->GET( '/search/', \%query ) };
265
266     # We sometimes get an error here when $result->{issues} is undef.
267     # I suspect this is when the number of issues just happens to be
268     # an even number like on a $query{maxResults} boundry. So when
269     # $result->{issues} is undef we assume it's the last of the issues.
270     # (I should really verify this).
271     if ( $result->{issues} ) {
272         return @{ $result->{issues} };
273     }
274     else {
275         return;
276     }    # if
277 }    # getIssues
278
279 sub getIssue ( $self, $issue, @fields ) {
280
281 =pod
282
283 =head2 getIssue ()
284
285 Get individual JIRA issue
286
287 Parameters:
288
289 =for html <blockquote>
290
291 =over
292
293 =item $issue
294
295 Issue ID
296
297 =item @fields
298
299 List of fields to retrieve
300
301 =back
302
303 =for html </blockquote>
304
305 Returns:
306
307 =for html <blockquote>
308
309 =over
310
311 =item %issue
312
313 Perl hash of JIRA issue
314
315 =back
316
317 =for html </blockquote>
318
319 =cut
320
321     my $fields = @fields ? "?fields=" . join ',', @fields : '';
322
323     return $self->{rest}->GET("/issue/$issue$fields");
324 }    # getIssue
325
326 1;