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