Hamburger Cross Icon
Ticket Present
+
Linear Collector

Ticket Present + Linear Collector

Guardrail Collector Stable Devex Build And Ci

Enforce Ticket Present using data collected by Linear Collector. Automatically check devex build and ci standards on every PR.

Guardrail: Ensures PRs reference an issue tracker ticket in the title.
Data Source: Extract Linear ticket references from pull request titles, validate them against the Linear GraphQL API, and detect ticket reuse across PRs.

How Linear Collector Powers This Guardrail

The Linear Collector gathers metadata from your vcs systems. This data flows into Lunar's Component JSON, where the Ticket Present 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.

1
Linear Collector Gathers Data Collector
Extracts metadata from code, configs, and tool outputs
2
{ } Component JSON
Data centralized in structured format for evaluation
3
Ticket Present Checks Guardrail
Pass/fail result with actionable feedback in PRs

Quick Start Configuration

Add both the collector and policy to your lunar-config.yml to enable this guardrail.

📄 lunar-config.yml
# Step 1: Enable the Linear Collector
collectors:
  - uses: github://earthly/lunar-lib/collectors/linear@v1.0.0
    # with: ...

# Step 2: Enable the Ticket Guardrails
policies:
  - uses: github://earthly/lunar-lib/policies/ticket@v1.0.0
    include: [ticket-present]
    # with: ...

What Linear Collector Collects

This collector gathers the following data that the Ticket Present guardrail evaluates.

Collector code

ticket

Extracts Linear ticket ID from PR title, fetches issue metadata from the Linear GraphQL API, and writes normalized ticket data to .vcs.pr.ticket and native Linear data to .vcs.pr.ticket.native.linear.

Collector code

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 Linear Collector writes to the Component JSON, which Ticket Present then evaluates.

{ } component.json From Linear Collector
{
  "vcs": {
    "pr": {
      "ticket": {
        "id": "ENG-123",
        "source": { "tool": "linear", "integration": "api" },
        "url": "https://linear.app/acme/issue/ENG-123/add-payment-validation",
        "valid": true,
        "status": "In Progress",
        "type": "bug",
        "summary": "Add payment validation",
        "assignee": "jane@acme.com",
        "reuse_count": 0,
        "native": {
          "linear": {
            "id": "abc123",
            "identifier": "ENG-123",
            "title": "Add payment validation",
            "url": "https://linear.app/acme/issue/ENG-123/add-payment-validation",
            "state": { "name": "In Progress", "type": "started" },
            "assignee": { "email": "jane@acme.com", "displayName": "Jane" },
            "labels": { "nodes": [{ "name": "bug" }] },
            "priority": 2,
            "priorityLabel": "High",
            "team": { "key": "ENG", "name": "Engineering" }
          }
        }
      }
    }
  }
}

Configuration Options

Linear 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)
type_labels Required Comma-separated label names to treat as issue types (e.g. "bug,feature,chore"). If the Linear issue has a matching label, it is written as .vcs.pr.ticket.type. Empty means no type extraction from labels.

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.

Works with any process
check Infrastructure conventions
check Post-mortem action items
check Security & compliance policies
check Testing & quality requirements
Automate Now
Turn any process doc into guardrails
Book a Demo