Hamburger Cross Icon
PagerDuty Collector - Lunar Collector

PagerDuty Collector

Collector Beta Incident Management

Query the PagerDuty API to collect on-call schedule, escalation policy, and current responder data. Normalizes results into the .oncall category for tool-agnostic policy evaluation.

Add pagerduty to your lunar-config.yml:
uses: github://earthly/lunar-lib/collectors/pagerduty@v1.0.5

What This Integration Collects

This integration includes 2 collectors that gather metadata from your systems.

Collector code

oncall

Queries the PagerDuty REST API for the component's service on a code hook — it runs when commits are pushed (PRs and the default branch). Resolves the service ID in order: the component's pagerduty/service-id meta annotation (set by a cataloger via lunar catalog component --meta pagerduty/service-id <id>), then the explicit service_id input, then — when backstage_discovery is enabled — the component's own catalog-info.yaml (read from the fresh checkout the code hook provides, so no clone-code is needed), reading the service ID directly from a pagerduty.com/service-id / pagerduty/service-id annotation. Fetches service details, on-call schedule participants, and escalation policy. Writes normalized data to .oncall.service, .oncall.schedule, .oncall.escalation, and .oncall.summary. Stores the raw API response under .oncall.native.pagerduty.

pagerduty oncall escalation incident management on-call schedule
Book a demo
Collector cron

oncall-cron

Same PagerDuty query as oncall, but on a daily cron instead of on push — it re-collects on a schedule so .oncall stays fresh as on-call schedules and escalation policies rotate between commits (they change on their own clock, independent of code). Resolves the service ID identically and writes the same normalized .oncall.service, .oncall.schedule, .oncall.escalation, and .oncall.summary (raw responses under .oncall.native.pagerduty). clone-code gives it the checkout so backstage_discovery can still read catalog-info.yaml. Include oncall for on-push evaluation, oncall-cron for always-fresh scheduled refresh, or both.

pagerduty oncall escalation incident management on-call schedule cron scheduled
Book a demo

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
1
Collectors Gather Data This Integration
Triggered by code changes or CI pipelines, collectors extract metadata from config files, tool outputs, test results, and scans
2
{ } Centralized as JSON
All data merged into each component's unified metadata document
3
Guardrails Enforce Standards
Real-time feedback in PRs and AI workflows

Example Collected Data

This collector writes structured metadata to the Component JSON. Here's an example of the data it produces:

{ } component.json Component JSON
{
  "oncall": {
    "source": {
      "tool": "pagerduty",
      "integration": "api"
    },
    "service": {
      "id": "PXXXXXX",
      "name": "Payment API",
      "status": "active"
    },
    "schedule": {
      "exists": true,
      "participants": 4,
      "rotation": "weekly"
    },
    "escalation": {
      "exists": true,
      "levels": 3,
      "policy_name": "Payment API Escalation"
    },
    "summary": {
      "has_oncall": true,
      "has_escalation": true,
      "min_participants": 4
    },
    "native": {
      "pagerduty": { "...full PagerDuty API response..." }
    }
  }
}

Configuration

Configure this collector in your lunar-config.yml.

Inputs

Input Required Default Description
service_id Required PagerDuty service ID to query (e.g. PXXXXXX). Optional if the component has a `pagerduty/service-id` meta annotation set by a cataloger.
pagerduty_base_url Optional https://api.pagerduty.com PagerDuty API base URL
backstage_discovery Optional false When "true", and no service ID is found via component meta or the service_id input, discover it from the component's own catalog-info.yaml: the collector reads the file from the runner's checkout (oncall runs on a code hook, which clones; oncall-cron sets clone-code) and takes the PagerDuty service ID from the annotation keys listed in backstage_annotations. Opt-in, and needs no extra secret — the runner's checkout is used, not a token. Lets the oncall guardrails work off the standard PagerDuty Backstage annotation without a cataloger or component meta.
backstage_annotations Optional pagerduty.com/service-id,pagerduty/service-id Comma-separated annotation keys to read the service ID from, tried in order (first non-empty value across the file's Component entities wins). Defaults to both conventional spellings — PagerDuty's Backstage integration guide uses `pagerduty.com/service-id`; Lunar's meta uses `pagerduty/service-id`. Only used when backstage_discovery is "true".
backstage_catalog_paths Optional catalog-info.yaml,catalog-info.yml Comma-separated catalog-info file paths to try in the checked-out repo (first match wins). Only used when backstage_discovery is "true".

Secrets

This collector requires the following secrets to be configured in Lunar:

Secret Description
PAGERDUTY_API_KEY PagerDuty REST API key (read-only token with service and oncall scopes)

Documentation

View on GitHub

PagerDuty Collector

Collect on-call schedule and escalation data from the PagerDuty API.

Overview

This collector queries the PagerDuty REST API to gather on-call schedule, escalation policy, and service data, writing normalized results to the .oncall category in a tool-agnostic format so the same oncall policy works for PagerDuty, OpsGenie, or any other provider. It ships two trigger variants that run the same query and write the same data — oncall (code hook, on PRs and the default branch) and oncall-cron (daily cron); pick whichever fits (see Collectors below). The service ID is discovered from the component's pagerduty/service-id meta annotation, an explicit service_id input, or — with backstage_discovery enabled — the repo's catalog-info.yaml annotation.

Collected Data

This collector writes to the following Component JSON paths:

Path Type Description
.oncall.source object Tool and integration metadata
.oncall.service object PagerDuty service ID, name, and status
.oncall.schedule object On-call schedule: exists flag, participant count, rotation type
.oncall.escalation object Escalation policy: exists flag, level count, policy name
.oncall.summary object Summary flags for quick policy evaluation
.oncall.native.pagerduty object Raw PagerDuty API responses

Collectors

This integration provides the following collectors — use include to select one (or include both to collect on both triggers). Both run the same query and write the same .oncall data; they differ only in when they run.

Collector Description
oncall Code hook — queries PagerDuty on pushes to PRs and the default branch, so the on-call guardrail is evaluated as part of a commit/PR check
oncall-cron Cron hook — queries PagerDuty daily (04:00 UTC, staggered off the 02:00/03:00 scheduled jobs) and refreshes .oncall so the data stays current as schedules rotate, independent of code changes

Most setups want one or the other. Including both is supported and the normalized .oncall data stays correct either way — but be aware the raw arrays under .oncall.native.pagerduty will carry duplicate entries, because Lunar concatenates arrays written to the same path by different collectors. Guardrail results are unaffected: the oncall policy reads only the normalized scalars.

Installation

Add to your lunar-config.yml (use include to pick a trigger variant):

collectors:
  - uses: github://earthly/lunar-lib/collectors/pagerduty@v1.0.0
    include: [oncall]          # code hook (PRs + default branch); use [oncall-cron] for the daily-cron variant
    on: ["domain:your-domain"]
    # with:
    #   service_id: "PXXXXXX"  # Optional — falls back to catalog meta annotation

Secrets:

  • PAGERDUTY_API_KEY — PagerDuty REST API key (read-only, with service and oncall scopes). Required.

(No GitHub token is needed for backstage_discoveryoncall (code) runs on a fresh checkout and oncall-cron sets clone-code: true, so either way the collector reads catalog-info.yaml from the runner's checkout, not the API.)

Service ID discovery

The collector resolves the PagerDuty service ID in this order:

  1. Catalog meta annotation — reads pagerduty/service-id from the component's lunar catalog meta. Set via lunar catalog component --meta pagerduty/service-id <id>, typically invoked by a company-specific cataloger that knows which components map to which PagerDuty services. This is the recommended approach for orgs where each component has its own service.

  2. Explicit service_id input — set in lunar-config.yml for static org-wide configurations, or when importing the collector multiple times with different on: scopes (e.g. one import per domain, each with its own service ID).

  3. Backstage discovery (opt-in) — when backstage_discovery: "true", the collector reads the component's own catalog-info.yaml from the runner's checkout (the oncall code hook clones automatically; oncall-cron sets clone-code: true) and takes the service ID directly from its annotations (backstage_annotations, default pagerduty.com/service-id,pagerduty/service-id). This lets the oncall guardrails work off the standard PagerDuty Backstage annotation with no cataloger and no component meta — reach for it when your components already carry the PagerDuty annotation and you'd rather read it directly than run a cataloger to copy it into component meta. No GitHub token needed: it reads the runner's checkout, not the API.

    collectors:
      - uses: github://earthly/lunar-lib/collectors/pagerduty@v1.0.0
        on: ["domain:your-domain"]
        with:
          backstage_discovery: "true"
    
  4. None found — the collector exits cleanly with no data written.

Inputs

Input Default Description
service_id (empty — falls back to catalog meta) PagerDuty service ID (e.g. PXXXXXX). Optional if pagerduty/service-id meta annotation is set.
pagerduty_base_url https://api.pagerduty.com PagerDuty API base URL
backstage_discovery "false" When "true", discover the service ID from the component's checked-out catalog-info.yaml annotations if meta/service_id don't provide one. No token needed (uses the runner's clone-code checkout).
backstage_annotations pagerduty.com/service-id,pagerduty/service-id Comma-separated annotation keys to read the service ID from (first non-empty wins), tried in order. Only used when backstage_discovery is "true".
backstage_catalog_paths catalog-info.yaml,catalog-info.yml Comma-separated catalog-info file paths to try in the checked-out repo (first match wins). Only used when backstage_discovery is "true".

Open Source

This collector is open source and available on GitHub. Contribute improvements, report issues, or fork it for your own use.

View Repository

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.

Works with any process
check AI agent rules & prompt files
check Post-mortem action items
check Security & compliance policies
check Testing & quality requirements
Automate Now
Paste your AGENTS.md or manual process doc and get guardrails in minutes
Book a Demo