Jira Integration (Optional)¶
issue-processor is an optional fourth service that unlocks two
independent capabilities, sourced from Jira:
- Change failure rate / MTTR -- the two DORA metrics
git-processor/pr-processoralone can't compute, since they need an incident tracker, not just git/PR history. Shows up inreport.py's PDF and the/v1/change-failure-rate//v1/mttrAPI endpoints. - Investment allocation -- how work breaks down by category
(feature/bug/tech-debt/etc.), story points, and cycle time. Shows up
in the separate
allocation_report.pyPDF (see Generating Reports) and the/v1/investment-allocationAPI endpoint.
Enable one, the other, or both -- they're independently configured.
issue-processor idles cleanly if neither is set up (same "empty
queue -> clean exit -> restart" pattern as git-processor/
pr-processor), so it's safe to leave running in your compose bundle
even before you configure this.
Jira Cloud only
Jira Server/Data Center isn't supported -- its REST API differs enough (different auth, no v3 endpoint parity) to be a separate follow-up.
Shared credentials¶
Both flows authenticate the same way. Add to .env:
JIRA_BASE_URL=https://yourcompany.atlassian.net
JIRA_EMAIL=you@yourcompany.com
JIRA_API_TOKEN=...
JIRA_API_TOKEN is a Jira Cloud API token,
used as the password half of Basic auth (JIRA_EMAIL:JIRA_API_TOKEN).
Change failure rate / MTTR¶
Linkage works via Jira's Fix Version field: an incident counts against a deployment if its Fix Version exactly matches that deployment's git tag name, scoped per repo (see DORA Metrics for which tags count as deployments). This requires your Jira project's Fix Versions to already agree with your git tag naming -- there's no fuzzy matching or time-window fallback (same "no fabricated proxy" philosophy as deployment frequency/lead time above).
-
Add to
.env:JIRA_INCIDENT_ISSUE_TYPES=Incident,BugComma-separated Jira issue-type names that count as an "incident." Required to enable this flow, no default -- an unfiltered list (every issue counted as an incident) would silently corrupt both metrics.
-
Map each Jira project to the repo whose tags its Fix Versions apply to. Copy
jira_project_map.example.yamlto/var/lib/eng-metrics-suite/jira_project_map.yamland edit it, then seed the queue:docker compose run --rm --entrypoint python3 issue-processor discover_jira_projects.py \ --config /var/lib/eng-metrics-suite/jira_project_map.yamlThis is a hand-maintained mapping, not auto-discovered -- there's no Jira API that can derive which project's Fix Versions apply to which repo. Safe to re-run later to add more mappings.
Once issue-processor has imported some incidents, report.py's PDF
and the /v1/change-failure-rate//v1/mttr API endpoints return real
numbers instead of "not configured."
Untracking a project: remove_jira_project.py permanently deletes
the mapping and its incidents:
docker compose run --rm --entrypoint python3 issue-processor remove_jira_project.py <project_key> \
--repo-identity-key "github.com/owner/repo" \
--actor "you@company.com" --reason "decommissioned" --yes
Same preview-first/--yes/--allow-readd contract as
remove_repo.py -- once
removed, discover_jira_projects.py won't silently re-add this
project/repo pairing until you deliberately lift the guard.
Investment allocation¶
A separate flow with no repo relationship at all -- Jira tickets aren't
tied to a specific git repo the way incidents are tied (via Fix
Version) to a deployment, so this doesn't even require
git-processor's schema to exist first.
-
Add to
.env:JIRA_ALLOCATION_ISSUE_TYPES=Story,Task,BugComma-separated Jira issue-type names that count as "work" for this report. Required to enable this flow, no default -- an unfiltered list would mix in issue types (e.g. Epics, Sub-tasks) that don't belong in a ticket-level breakdown.
Two more variables are optional:
JIRA_CATEGORY_FIELD=customfield_10032 JIRA_STORY_POINTS_FIELD=customfield_10016JIRA_CATEGORY_FIELD-- the custom field ID holding each issue's investment category. If unset, every issue's category is its Jira issue type instead (a global fallback, not evaluated per-issue).JIRA_STORY_POINTS_FIELD-- the custom field ID holding story points (varies per Jira instance, no universal default). If unset, story-point figures show "n/a"; ticket counts are unaffected.
-
List which Jira projects to track -- no repo mapping needed. Copy
allocation_projects.example.yamlto/var/lib/eng-metrics-suite/allocation_projects.yamland edit it, then seed the queue:docker compose run --rm --entrypoint python3 issue-processor discover_allocation_projects.py \ --config /var/lib/eng-metrics-suite/allocation_projects.yaml
Once imported, generate the report:
docker compose run --rm eng-reports allocation_report.py --output /out/allocation.pdf
or query /v1/investment-allocation if you're on the Team/Enterprise
API plan (see API Access).
Untracking a project: remove_allocation_project.py permanently
deletes it and its work items:
docker compose run --rm --entrypoint python3 issue-processor remove_allocation_project.py <project_key> \
--actor "you@company.com" --reason "decommissioned" --yes
Same preview-first/--yes/--allow-readd contract as
remove_repo.py -- no
--repo-identity-key needed here, since this flow has no repo
relationship at all.
Changing your Jira settings¶
issue-processor only fetches issues that changed since its last run.
So if you change JIRA_INCIDENT_ISSUE_TYPES, JIRA_ALLOCATION_ISSUE_TYPES,
JIRA_CATEGORY_FIELD or JIRA_STORY_POINTS_FIELD, the change only
reaches issues updated after it. To apply it to everything you've
already imported, restart issue-processor and then re-import.
These settings apply to every project, so re-import all projects in the flow you changed:
docker compose up -d issue-processor
docker compose run --rm --entrypoint python3 issue-processor reingest_jira_project.py --all --flow incident --yes
Use --flow allocation after changing the allocation issue types or
either field, or leave --flow out to re-import both.
If something changed in just one Jira project (for example, an issue type was removed from it), re-import only that project:
docker compose run --rm --entrypoint python3 issue-processor reingest_jira_project.py <project_key> --yes
Re-importing fetches every matching issue again and removes issues whose
type is no longer in your settings, so dropping a type takes those
issues out of your reports. Run it without --yes first to see which
projects it will touch and how many issues it will remove. A project
that's mid-import is skipped; run the command again once it finishes.
Further reading¶
See issue-processor's
own README for the full schema, the claim-queue/retry mechanics shared
with git-processor/pr-processor, and known limitations (Fix Version
exact-match only, category fallback semantics, cycle time being full
ticket lifecycle rather than active-work time, logged time being a
report-period snapshot rather than a weekly trend).
Next: Running Workers once you've configured
either flow above -- issue-processor picks up whatever you've queued
the same way git-processor/pr-processor do.