NAME
Rmv::JIRA - JIRA REST API v3 client for Raku
SYNOPSIS
use Rmv::JIRA::Client;
my $jira = Rmv::JIRA::Client.from-env;
# Fetch a ticket (all fields + human-readable names)
my %issue = $jira.get-ticket('PROJ-123');
say %issue<fields><summary>;
# Fetch specific fields only
my %issue = $jira.get-ticket('PROJ-123', fields => <summary status assignee>);
# Search with JQL
my %results = $jira.search-tickets('project = PROJ AND status = "In Progress"');
for %results<issues>.list -> %t {
say "%t<key>: %t<fields><summary>";
}
DESCRIPTION
Rmv::JIRA is a thin Raku client for the JIRA REST API v3. It supports
fetching issues (all fields or a subset), JQL search, issue creation, and
structured error handling.
INSTALLATION
zef install --/precompile-install Rmv::JIRA
Note: the --/precompile-install flag is needed when dependencies are
installed in the user-level ~/.raku repository rather than the
system/rakubrew site repository.
CONFIGURATION
Authentication uses HTTP Basic auth with your Atlassian email and an API
token. Set these environment variables before use:
| Variable | Description |
|---|
JIRA_URL | Base URL of your JIRA instance, e.g. https://your-org.atlassian.net |
JIRA_EMAIL | Your Atlassian account email address |
JIRA_TOKEN | An Atlassian API token (not your password) |
Generate an API token at https://id.atlassian.com/manage-profile/security/api-tokens.
METHODS
Rmv::JIRA::Client.from-env()
Constructs a client from JIRA_URL, JIRA_EMAIL, and JIRA_TOKEN. Dies if
any variable is missing.
my $jira = Rmv::JIRA::Client.from-env;
Rmv::JIRA::Client.new(:server-url, :email, :token)
Constructs a client with explicit credentials.
my $jira = Rmv::JIRA::Client.new(
server-url => 'https://your-org.atlassian.net',
email => 'you@example.com',
token => 'your-api-token',
);
get-ticket(Str $key, :@fields --> Hash)
Fetches a single issue by key. By default returns all fields (*all) and
expands the names map so you can look up human-readable field labels.
Pass :fields to restrict to a subset.
my %issue = $jira.get-ticket('PROJ-123');
my %names = %issue<names>; # field-id => display name
my %fields = %issue<fields>; # all field values
# Specific fields only
my %issue = $jira.get-ticket('PROJ-123', fields => <summary status assignee>);
search-tickets(Str $jql, :@fields, Int :$max-results = 50, Str :$next-page-token --> Hash)
Searches issues using JQL via POST /rest/api/3/search/jql. Returns the
JIRA search response (issues, isLast, optional nextPageToken, etc.).
The legacy /rest/api/3/search endpoint is no longer available on Jira Cloud.
my %res = $jira.search-tickets(
'project = PROJ AND status != Done ORDER BY created DESC',
max-results => 20,
);
say "Found: %res<total>";
for %res<issues>.list -> %t { say %t<key> }
create-ticket(:%fields --> Hash)
Creates an issue via POST /rest/api/2/issue/. Pass JIRA field values as a
hash; they are wrapped as { fields: { ... } }. Returns the create response
(key, id, self). Field keys and values must match what the target
project's issue screen accepts (components, custom fields, etc. are caller
responsibility). Create uses the v2 endpoint so plain-string description
values work without Atlassian Document Format.
my %created = $jira.create-ticket(
project => { key => 'PROJ' },
summary => 'Fix the widget',
description => 'Steps to reproduce...',
issuetype => { name => 'Task' },
);
say %created<key>; # PROJ-99
request(Str $endpoint, Str :$method = 'GET', :$body, :%params --> Hash)
Low-level method for arbitrary JIRA REST API v3 calls.
my %me = $jira.request('/rest/api/3/myself');
say %me<displayName>;
ERROR HANDLING
Non-2xx responses throw X::Rmv::JIRA::Api:
my %issue = $jira.get-ticket('PROJ-123');
CATCH {
when X::Rmv::JIRA::Api {
say "HTTP $_.status(): $_.body()";
}
}
AUTHOR
Rui Vieira ruidevieira@googlemail.com
COPYRIGHT AND LICENSE
Copyright 2026 Rui Vieira
Licensed under the Apache License, Version 2.0. See LICENSE for the full license text.