Jira Collector
Extract Jira ticket references from pull request titles, validate them against the Jira REST API, and detect ticket reuse across PRs.
jira to your lunar-config.yml:uses: github://earthly/lunar-lib/collectors/jira@v1.0.5
What This Integration Collects
This integration includes 2 collectors that gather metadata from your systems.
ticket
Extracts Jira ticket ID from PR title, fetches issue metadata from the Jira REST API, and writes normalized ticket data to .vcs.pr.ticket and native Jira data to .vcs.pr.ticket.native.jira.
ticket-history
Queries the Lunar SQL database to count how many other PRs reference the same ticket. Writes .vcs.pr.ticket.reuse_count for policy evaluation. Detects ticket recycling abuse.
How Collectors Fit into Lunar
Lunar watches your code and CI/CD systems to collect SDLC data from config files, test results, IaC, deployment configurations, security scans, and more.
Collectors are the automatic data-gathering layer. They extract structured metadata from your repositories and pipelines, feeding it into Lunar's centralized database where guardrails evaluate it to enforce your engineering standards.
Learn How Lunar Works →Example Collected Data
This collector writes structured metadata to the Component JSON. Here's an example of the data it produces:
{
"vcs": {
"pr": {
"ticket": {
"id": "ABC-123",
"source": { "tool": "jira", "integration": "api" },
"url": "https://acme.atlassian.net/browse/ABC-123",
"valid": true,
"status": "In Progress",
"type": "Story",
"summary": "Implement payment validation",
"assignee": "jane@acme.com",
"reuse_count": 0,
"native": {
"jira": { "...full Jira API response..." }
}
}
}
}
}
Configuration
Configure this collector in your lunar-config.yml.
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
ticket_prefix
|
Required | — | Character(s) before the ticket ID in PR titles (empty = match anywhere) |
ticket_suffix
|
Required | — | Character(s) after the ticket ID in PR titles (empty = match anywhere) |
ticket_pattern
|
Optional |
[A-Za-z][A-Za-z0-9]+-[0-9]+
|
Regex pattern for ticket ID (without prefix/suffix) |
jira_base_url
|
Required | — | Jira instance base URL (e.g. https://acme.atlassian.net) |
jira_user
|
Required | — | Jira user email for API authentication |
Secrets
This collector requires the following secrets to be configured in Lunar:
| Secret | Description |
|---|---|
JIRA_TOKEN
|
Jira API token for authentication |
GH_TOKEN
|
GitHub token for reading PR metadata |
Documentation
View on GitHubJira Collector
Extract Jira ticket references from pull request titles and validate them against the Jira REST API.
Overview
This collector parses PR titles for Jira ticket IDs (e.g. [ABC-123] Fix bug), validates the ticket against the Jira REST API, and writes normalized ticket data to .vcs.pr.ticket and native Jira data to .vcs.pr.ticket.native.jira. It also detects ticket reuse across PRs by querying the Lunar SQL database.
The normalized .vcs.pr.ticket paths match the Linear collector's shape, so the shared ticket policy works regardless of which issue tracker provided the data.
Collected Data
This collector writes to the following Component JSON paths:
| Path | Type | Description |
|---|---|---|
.vcs.pr.ticket.id |
string | Ticket key extracted from PR title (e.g. ABC-123) |
.vcs.pr.ticket.source |
object | Source metadata ({tool: "jira", integration: "api"}) |
.vcs.pr.ticket.url |
string | Direct link to the ticket on the Jira instance |
.vcs.pr.ticket.valid |
boolean | true when the Jira API returned the ticket |
.vcs.pr.ticket.status |
string | Ticket status name (e.g. In Progress) |
.vcs.pr.ticket.type |
string | Issue type name (e.g. Story, Bug) |
.vcs.pr.ticket.summary |
string | Ticket summary |
.vcs.pr.ticket.assignee |
string | Assignee email (subject to Atlassian email visibility) |
.vcs.pr.ticket.reuse_count |
number | Count of other PRs referencing the same ticket |
.vcs.pr.ticket.native.jira |
object | Full raw Jira API response |
Collectors
This integration provides the following collectors (use include to select a subset):
| Collector | Description |
|---|---|
ticket |
Extracts ticket ID from PR title and fetches Jira issue metadata via the Jira REST API |
ticket-history |
Queries Lunar SQL for ticket reuse count across PRs (no Jira API call) |
Installation
Add to your lunar-config.yml:
collectors:
- uses: github://earthly/lunar-lib/collectors/jira
on: ["domain:your-domain"]
with:
jira_base_url: "https://acme.atlassian.net"
jira_user: "user@acme.com"
Required secrets:
| Secret | Purpose |
|---|---|
JIRA_TOKEN |
Atlassian API token used with HTTP Basic auth to read the ticket via GET /rest/api/3/issue/{key} |
GH_TOKEN |
GitHub token used to read the PR title via GET /repos/{owner}/{repo}/pulls/{number} |
JIRA_TOKEN
Use a classic Atlassian API token. Steps:
- Sign in to Atlassian as the user whose account will own the token.
- Open https://id.atlassian.com/manage-profile/security/api-tokens.
- Click Create API token (the plain button — not "Create API token with scopes").
- Enter a label (e.g.
lunar-jira-collector) and click Create. - Click Copy to copy the token, then paste it into your secret store as
JIRA_TOKEN. - In Jira, make sure that same user has the Browse Projects permission on every project whose tickets appear in your PR titles.
Set jira_user to that user's Atlassian email — the collector uses HTTP Basic auth (email:token) against {jira_base_url}/rest/api/3/issue/{key}. This is the path Atlassian themselves recommend for our shape of integration: per Basic auth for REST APIs, "We recommend using it for simple scripts and manual calls to the REST APIs." This collector is exactly that — a small script doing one GET /issue/{key} per PR.
Note: Granular ("fine-grained") Atlassian API tokens — the ones created via Create API token with scopes — are not currently supported. Atlassian's scoped tokens require a separate
api.atlassian.com/ex/jira/{cloudId}/...gateway, and even when all the right scopes are attached, Beta-state granular scopes don't reliably grant project-level visibility (verified empirically againstearthly.atlassian.net). Atlassian's own OAuth 2.0 scopes guidance also says: "When choosing your scopes, the recommendation is to use classic scopes" — i.e.read:jira-work— rather than the granular ones. Stick with the classic API token above.
assignee.emailAddress honors each Jira user's email-visibility setting (Account → Profile → Contact); API tokens cannot override it.
GH_TOKEN
Needs read access to the PR (GET /repos/{owner}/{repo}/pulls/{number}).
- Classic PAT:
repofor private repos, no scope for public - Fine-grained PAT or GitHub App:
Metadata: Read+Pull requests: Read - GitHub Actions
GITHUB_TOKEN: works as-is
Open Source
This collector is open source and available on GitHub. Contribute improvements, report issues, or fork it for your own use.
Common Use Cases
Explore guardrails that use data from Jira Collector.
Ready to Automate Your Standards?
See how Lunar can turn your AGENTS.md, engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 200+ built-in guardrails.