Installation & Configuration¶
Requirements¶
- Python 3.13+
- uv (recommended) or pip
- A KeePass database holding your Jira credentials
Install¶
This installs all runtime dependencies declared in pyproject.toml.
Settings (settings.toml)¶
Settings are loaded with Dynaconf from settings.toml in the project root. The file has a [default] section plus one section per environment: [development], [staging] and [production]. An environment section only needs the keys that differ from [default].
[default]
# ── Required ─────────────────────────────────────────────────────────────────
JIRA_BASE_URL = "https://your-domain.atlassian.net"
# KeePass database that stores the Jira credentials
KEEPASS_DB = "C:/keepass/Database.kdbx"
KEEPASS_KEY = "C:/keepass/Database.key"
KEEPASS_ENTRY = "Jira Entry Name"
# ── Concurrency ──────────────────────────────────────────────────────────────
JIRA_MAX_CONCURRENCY = 10 # simultaneous API requests
PHASE2_WORKERS = 15 # concurrent issue transitions in Phase 2
# ── Retry ────────────────────────────────────────────────────────────────────
JIRA_MAX_RETRIES = 3
JIRA_RETRY_BACKOFF_MIN = 2.0 # seconds
JIRA_RETRY_BACKOFF_MAX = 30.0 # seconds
# ── Rate limiting (HTTP 429) ─────────────────────────────────────────────────
JIRA_RATE_LIMIT_MAX_RETRIES = 10 # retries per request for HTTP 429
JIRA_RATE_LIMIT_MAX_WAIT = 300 # seconds; fail if Jira asks to wait longer
# ── Status classification ────────────────────────────────────────────────────
DONE_STATUSES = ["Done", "Cancelled", "Closed"]
BUG_ISSUE_TYPES = ["Bug", "UAT Defect", "Production Defect"] # case-insensitive
PRIORITY_STATUSES = ["Closed", "Done", "Cancelled"] # smart-default order
# ── Mandatory field (Phase 2) ────────────────────────────────────────────────
# Set before transitioning these issue types if empty. Skipped in --dry-run.
# Use MANDATORY_FIELD_ID = "" to disable.
MANDATORY_FIELD_ID = "customfield_10000"
MANDATORY_FIELD_VALUE = "Some value"
MANDATORY_FIELD_ISSUE_TYPES = ["Bug", "UAT Defect"]
[development]
JIRA_BASE_URL = "https://your-sandbox.atlassian.net"
PHASE2_WORKERS = 2
[staging]
JIRA_BASE_URL = "https://your-sandbox.atlassian.net"
[production]
KEEPASS_ENTRY = "Jira (prod)"
Choosing the environment¶
The active environment comes from JIRA_ENV and defaults to development. Set it in a .env file in the project root (see .env.example) or in the shell:
The CLI logs the active environment and Jira URL at startup, and the GUI shows them under Global settings.
Overrides¶
Highest precedence wins:
settings.toml, the[default]section, then the active environment's section.secrets.toml(optional, git-ignored, same layout), for values you don't want committedJTR_-prefixed environment variables, including those in.env, e.g.JTR_PHASE2_WORKERS=5orJTR_DONE_STATUSES='["Done", "Closed"]'
settings.toml is read from the current directory if it has one, otherwise from the project root. Set JTR_SETTINGS_DIR to use another directory.
Workflow Configuration (transition.yaml)¶
Define per-project workflows. Each project maps issue types to workflows, and each workflow lists named transitions with from, to, and Jira transition id.
projects:
PROJ:
projectId: '10000'
workflowSchemeId: 10001
issueTypes:
Story:
workflow: Story_Workflow
transitions:
open_to_in_progress:
id: '11'
name: Start Progress
from: Open
to: In Progress
in_progress_to_done:
id: '21'
name: Done
from: In Progress
to: Done
Tip
You can find transition IDs in Jira by navigating to Project Settings → Workflows and inspecting the transition links, or by calling GET /rest/api/3/issue/{key}/transitions.
Logging Configuration (logging_config.yaml)¶
The default config logs WARNING+ to the console and DEBUG+ to rotating files:
formatters:
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: WARNING
formatter: simple
file:
class: logging.handlers.RotatingFileHandler
level: DEBUG
filename: jira_transition_runner.log
maxBytes: 10485760 # 10 MB
backupCount: 5
formatter: simple
Pass a custom config at runtime: