Ticket Valid + Jira Collector
Enforce Ticket Valid using data collected by Jira Collector. Automatically check devex build and ci standards on every PR.
How Jira Collector Powers This Guardrail
The Jira Collector gathers metadata from your vcs systems. This data flows into Lunar's Component JSON, where the Ticket Valid guardrail evaluates it against your standards.
When enabled, this check runs automatically on every PR and in AI coding workflows, providing real-time enforcement with actionable feedback.
Quick Start Configuration
Add both the collector and policy to your lunar-config.yml to enable this guardrail.
# Step 1: Enable the Jira Collector
collectors:
- uses: github://earthly/lunar-lib/collectors/jira@v1.0.0
# with: ...
# Step 2: Enable the Ticket Guardrails
policies:
- uses: github://earthly/lunar-lib/policies/ticket@v1.0.0
include: [ticket-valid]
# with: ...
What Jira Collector Collects
This collector gathers the following data that the Ticket Valid guardrail evaluates.
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.
Example Data Flow
Here's an example of the data that Jira Collector writes to the Component JSON, which Ticket Valid then evaluates.
{
"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 Options
Jira Collector 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 |
Ticket Guardrails Inputs
| Input | Required | Default | Description |
|---|---|---|---|
allowed_sources |
Required | — | Comma-separated list of allowed ticket sources (e.g. "jira,linear"). Empty = any. |
allowed_statuses |
Required | — | Comma-separated list of allowed ticket statuses (empty = any) |
disallowed_statuses |
Required | — | Comma-separated list of disallowed ticket statuses (empty = none) |
allowed_types |
Required | — | Comma-separated list of allowed issue types (empty = any) |
max_ticket_reuse |
Optional |
3
|
Maximum number of other PRs allowed to reference the same ticket |
Ready to Automate Your Standards?
See how Lunar can turn your engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 100+ built-in guardrails.