NAME¶
JIRA::Client - An extended interface to JIRA's SOAP API.
VERSION¶
version 0.37
SYNOPSIS¶
use JIRA::Client;
my $jira = JIRA::Client->new('http://jira.example.com/jira', 'user', 'passwd');
my $issue = $jira->create_issue(
{
project => 'TST',
type => 'Bug',
summary => 'Summary of the bug',
assignee => 'gustavo',
components => ['compa', 'compb'],
fixVersions => ['1.0.1'],
custom_fields => {Language => 'Perl', Architecture => 'Linux'},
}
);
$issue = eval { $jira->getIssue('TST-123') };
die "Can't getIssue(): $@" if $@;
$jira->set_filter_iterator('my-filter');
while (my $issue = $jira->next_issue()) {
# ...
}
DESCRIPTION¶
JIRA is a proprietary bug tracking system from Atlassian
(<
http://www.atlassian.com/software/jira/>).
This module implements an Object Oriented wrapper around JIRA's SOAP API, which
is specified in
http://docs.atlassian.com/software/jira/docs/api/rpc-jira-plugin/latest/com/atlassian/jira/rpc/soap/JiraSoapService.html
<
http://docs.atlassian.com/software/jira/docs/api/rpc-jira-plugin/latest/com/atlassian/jira/rpc/soap/JiraSoapService.html>.
(This version is known work against JIRA 4.4.)
Moreover, it implements some other methods to make it easier to do some common
operations.
API METHODS¶
With the exception of the API "login" and "logout" methods,
which aren't needed, all other methods are available through the JIRA::Client
object interface. You must call them with the same name as documented in the
specification but you should not pass the "token" argument, because
it is supplied transparently by the JIRA::Client object.
All methods fail by throwing exceptions (croaking, actually). You may want to
guard against this by invoking them within an eval block, like this:
my $issue = eval { $jira->getIssue('TST-123') };
die "Can't getIssue('TST-123'): $@" if $@;
Some of the API methods require hard-to-build data structures as arguments. This
module tries to make them easier to call by accepting simpler structures and
implicitly constructing the more elaborated ones before making the actual SOAP
call. Note that this is an option, i.e, you can either pass the elaborate
structures by yourself or the simpler ones in the call.
The items below are all the implemented implicit conversions. Wherever a
parameter of the type specified first is required (as an rvalue, not as an
lvalue) by an API method you can safely pass a value of the type specified
second.
- A issue key as a string can be specified by a
RemoteIssue object.
- A RemoteComment object can be specified by a
string.
- A filterId as a string can be specified by a
RemoteFilter object.
- A RemoteFieldValue object array can be specified by
a hash mapping field names to values.
This module implements some extra methods to add useful functionality to the
API. They are described below. Note that their names don't follow the
CamelCase convention used by the native API methods but the more Perlish
underscore_separated_words convention so that you can distinguish them and we
can avoid future name clashes.
METHODS¶
new JIRAURL, USER, PASSWD [, <SOAP::Lite
arguments>]¶
The JIRA::Client constructor requires three arguments. JIRAURL is JIRA's base
URL from which will be constructed it's WSDL descriptor as
"$JIRAURL/rpc/soap/jirasoapservice-v2?wsdl". USER and PASSWD are the
credentials that will be used to authenticate into JIRA. Any other arguments
will be passed to the SOAP::Lite object that will be created to talk to JIRA.
create_issue HASH_REF [, SECURITYLEVEL]¶
Creates a new issue given a hash containing the initial values for its fields
and, optionally, a security-level. The hash must specify at least the fields
"project", "summary", and "type".
This is an easier to use version of the createIssue API method. For once it
accepts symbolic values for some of the issue fields that the API method does
not. Specifically:
- "type" can be specified by name instead of
by id.
- "priority" can be specified by name
instead of by id.
- "component" can be specified by a list of
component names or ids instead of a list of
"RemoteComponent" objects.
- "affectsVersions" and "fixVersions" can
be specified by a list of version names or ids instead of a
list of "RemoteVersion" objects.
- "duedate" can be specified by a DateTime object
or by a string in ISO standard format (YYYY-MM-DD...). (Note that up to JIRA
4.3 you could pass a string in the format "d/MMM/yy", which was
passed as is to JIRA, which expected a string SOAP type. However,
since JIRA 4.4 the server expects a date SOAP type, which must be in
the ISO standard format.)
It accepts a 'magic' field called
parent, which specifies the issue key
from which the created issue must be a sub-task.
It accepts another 'magic' field called
custom_fields to make it easy to
set custom fields. It accepts a hash mapping each custom field to its value.
The custom field can be specified by its id (in the format
customfield_NNNNN) or by its name, in which case the method will try to
convert it to its id. Note that to do that conversion the user needs
administrator rights.
A simple custom field value can be specified by a scalar, which will be properly
placed inside an ARRAY in order to satisfy the
RemoteFieldValue's
structure.
Cascading select fields are properly specified like this:
http://tinyurl.com/2bmthoa. The magic short-cut requires a HASH where each
cascading level is indexed by its level number, starting at zero. So, instead
of specifying it like this:
{
id => 'customfield_10011',
values => [ SOAP::Data->type(string => '10031' ) ]
},
{
id => 'customfield_10011:1',
values => [ SOAP::Data->type(string => '10188') ],
},
You can do it like this:
{customfield_10011 => {'0' => 10031, '1' => 10188}},
Note that the original hash keys and values are completely preserved.
update_issue ISSUE_OR_KEY, HASH_REF¶
Update a issue given a hash containing the values for its fields. The first
argument may be an issue key or a RemoteIssue object. The second argument must
be a hash-ref specifying the fields's values just like documented in the
create_issue function above.
This is an easier to use version of the updateIssue API method because it
accepts the same shortcuts that create_issue does.
get_issue_types¶
Returns a hash mapping the server's issue type names to the RemoteIssueType
objects describing them.
get_subtask_issue_types¶
Returns a hash mapping the server's sub-task issue type names to the
RemoteIssueType objects describing them.
get_statuses¶
Returns a hash mapping the server's status names to the RemoteStatus objects
describing them.
get_priorities¶
Returns a hash mapping a server's priorities names to the RemotePriority objects
describing them.
get_resolutions¶
Returns a hash mapping a server's resolution names to the RemoteResolution
objects describing them.
get_security_levels PROJECT-KEY¶
Returns a hash mapping a project's security level names to the
RemoteSecurityLevel objects describing them.
get_custom_fields¶
Returns a hash mapping JIRA's custom field names to the RemoteField representing
them. It's useful since when you get a RemoteIssue object from this API it
doesn't contain the custom field's names, but just their identifiers. From the
RemoteField object you can obtain the field's
id, which is useful when
calling the
updateIssue method.
The method calls the getCustomFields API method the first time and keeps the
custom fields information in a cache.
set_custom_fields HASHREF¶
Passes a hash mapping JIRA's custom field names to the RemoteField representing
them to populate the custom field's cache. This can be useful if you don't
have administrative privileges to the JIRA instance, since only administrators
can call the
getCustomFields API method.
get_components PROJECT_KEY¶
Returns a hash mapping a project's components names to the RemoteComponent
objects describing them.
get_versions PROJECT_KEY¶
Returns a hash mapping a project's versions names to the RemoteVersion objects
describing them.
get_favourite_filters¶
Returns a hash mapping the user's favourite filter names to its filter ids.
set_filter_iterator FILTER [, CACHE_SIZE]¶
Sets up an iterator for the filter identified by FILTER. It must be called
before calls to
next_issue.
FILTER can be either a filter
id or a filter
name, in which case
it's converted to a filter id with a call to "getSavedFilters".
CACHE_SIZE defines the number of issues that will be pre-fetched by
nect_issue using "getIssuesFromFilterWithLimit". If not
specified, a suitable default will be used.
next_issue¶
This must be called after a call to
set_filter_iterator. Each call
returns a reference to the next issue from the filter. When there are no more
issues it returns undef.
progress_workflow_action_safely ISSUE, ACTION, PARAMS¶
This is a safe and easier to use version of the
progressWorkflowAction
API method which is used to progress an issue through a workflow's action
while making edits to the fields that are shown in the action screen. The API
method is dangerous because if you forget to provide new values to all the
fields shown in the screen, then the fields not provided will become undefined
in the issue. The problem has a pending issue on Atlassian's JIRA
http://jira.atlassian.com/browse/JRA-8717
<
http://jira.atlassian.com/browse/JRA-8717>.
This method plays it safe by making sure that all fields shown in the screen
that already have a value are given new (or the same) values so that they
don't get undefined. It calls the
getFieldsForAction API method to grok
all fields that are shown in the screen. If there is any field not set in the
ACTION_PARAMS then it calls
getIssue to grok the missing fields current
values. As a result it constructs the necessary RemoteFieldAction array that
must be passed to progressWorkflowAction.
The method is also easier to use because its arguments are more flexible:
- "ISSUE" can be either an issue key or a
RemoteIssue object returned by a previous call to, e.g.,
"getIssue".
- "ACTION" can be either an action id or an
action name.
- "PARAMS" must be a hash mapping field names to
field values. This hash is treated in the same way as the hash passed to the
function create_issue above.
For example, instead of using this:
my $action_id = somehow_grok_the_id_of('close');
$jira->progressWorkflowAction('PRJ-5', $action_id, [
RemoteFieldValue->new(2, 'new value'),
..., # all fields must be specified here
]);
And risking to forget to pass some field you can do this:
$jira->progress_workflow_action_safely('PRJ-5', 'close', {2 => 'new value'});
get_issue_custom_field_values ISSUE, NAME_OR_IDs¶
This method receives a RemoteField object and a list of names or ids of custom
fields. It returns a list of references to the ARRAYs containing the values of
the ISSUE's custom fields denoted by their NAME_OR_IDs. Returns undef for
custom fields not set on the issue.
In scalar context it returns a reference to the list.
attach_files_to_issue ISSUE, FILES...¶
This method attaches one or more files to an issue. The ISSUE argument may be an
issue key or a
RemoteIssue object. The attachments may be specified in
two ways:
- STRING
- A string denotes a filename to be open and read. In this
case, the attachment name is the file's basename.
- HASHREF
- When you want to specify a different name to the attachment
or when you already have an IO object (a GLOB, a IO::File, or a
FileHandle) you must pass them as values of a hash. The keys of the hash
are taken as the attachment name. You can specify more than one attachment
in each hash.
The method retuns the value returned by the
addBase64EncodedAttachmentsToIssue API method.
In the example below, we attach three files to the issue TST-1. The first is
called "file1.txt" and its contents are read from
"/path/to/file1.txt". The second is called "text.txt" and
its contents are read from "/path/to/file2.txt". the third is called
"me.jpg" and its contents are read from the object refered to by
$fh.
$jira->attach_files_to_issue('TST-1',
'/path/to/file1.txt',
{
'text.txt' => '/path/to/file2.txt',
'me.jpg' => $fh,
},
);
attach_strings_to_issue ISSUE, HASHREF¶
This method attaches one or more strings to an issue. The ISSUE argument may be
an issue key or a
RemoteIssue object. The attachments are specified by
a HASHREF in which the keys denote the file names and the values their
contents.
The method retuns the value returned by the
addBase64EncodedAttachmentsToIssue API method.
filter_issues FILTER [, LIMIT]¶
This method returns a list of RemoteIssue objects from the specified FILTER,
which is a string that is understood in one of these ways (in order):
- A space-separated list of issue keys
- To specify issues explicitly by their keys, which must
match /[A-Z]+-\d+/i. The letters in the key are upcased before being
passed to getIssue. For example:
KEY-123 chave-234 CLAVE-345
- The name of a saved filter
- If FILTER is a single word, it is passed to
getIssuesFromFilterWithLimit as a filter name. For example:
sprint-backlok-filter
- A JQL expression
- As a last resort, FILTER is passed to
getIssuesFromJqlSearch as a JQL expression. For example:
project = CDS AND fixVersion = sprint-5
The optional LIMIT argument specified the maximum number of issues that can be
returned. It has a default limit of 1000, but this can be overridden by the
JIRA server configuration.
This method is meant to be used as a flexible interface for human beings to
request a list of issues. Be warned, however, that you are responsible to
de-taint the FILTER argument before passing it to the method.
The returned list of RemoteIssue objects is sorted by issue key.
RemoteFieldValue->new ID, VALUES¶
The RemoteFieldValue object represents the value of a field of an issue. It
needs two arguments:
- ID
- The field name, which must be a valid key for the ISSUE
hash.
- VALUES
- A scalar or an array of scalars.
RemoteCustomFieldValue->new ID, VALUES¶
The RemoteCustomFieldValue object represents the value of a custom_field of an
issue. It needs two arguments:
- ID
- The field name, which must be a valid custom_field
key.
- VALUES
- A scalar or an array of scalars.
RemoteComponent->new ID, NAME¶
RemoteVersion->new ID, NAME¶
OTHER CONSTRUCTORS¶
The JIRA SOAP API uses several types of objects (i.e., classes) for which the
Perl SOAP interface does not provide the necessary constructors. This module
implements some of them.
EXAMPLES¶
Please, see the examples under the "examples" directory in the module
distribution.
AUTHOR¶
Gustavo L. de M. Chaves <gnustavo@cpan.org>
COPYRIGHT AND LICENSE¶
This software is copyright (c) 2012 by CPqD.
This is free software; you can redistribute it and/or modify it under the same
terms as the Perl 5 programming language system itself.