Automating CMJ Migrations at Scale: An Open-Source Python Toolkit
TL;DR: After managing multiple large-scale Jira migrations using Configuration Manager for Jira (CMJ), I built a Python toolkit that automates the tedious parts—mapping validation, conflict detection, template generation, and post-migration cleanup. The code is open source on GitHub. This article shares the approach and lessons learned.
The Problem: CMJ Migrations at Scale
If you’ve ever done a Jira Data Center migration using CMJ, you know the pain:
For a single small project, this is manageable. For enterprise migrations with thousands of objects across multiple projects, it becomes a full-time job.
The Solution: An 11-Step Automated Pipeline
I built a Python toolkit that wraps around CMJ to automate the repetitive work while keeping humans in the loop for decisions that matter.
The Pipeline at a Glance
Phase | Steps | What Happens |
Pre-Deployment | 1–6 | Convert data, process mappings, validate, generate CMJ templates |
Customer Review | Between 3–4 | Customer reviews and approves mapping decisions |
CMJ Deployment | Manual | Import templates, deploy snapshot |
Post-Deployment | 7–11 | Generate cleanup scripts, validate before/after deletion |
Key Automation Features
The toolkit handles four categories of work that are tedious and error-prone when done manually:
The toolkit automatically matches source objects to target objects using:
Match Results:
EXACT_MATCH: 234 objects (auto-mapped)
FUZZY_MATCH: 45 objects (suggested, needs review)
NO_MATCH: 28 objects (will be created)
Multiple source objects mapping to the same target? The toolkit catches it before it reaches CMJ:
CONFLICTS DETECTED:
Target 'Approved' ← Sources: ['Approved', 'APPROVED', 'approved']
Target 'In Progress' ← Sources: ['In Progress', 'InProgress']
Before generating CMJ templates, the toolkit validates the customer-reviewed spreadsheet:
Check | Example Error |
Leading/trailing spaces | " Status Name " → trim it |
Copied suggestion text | "Status Name (85%)" → remove percentage |
Invalid actions | "map" → should be "MAP" |
Typos in target names | "Aproved" vs "Approved" in target |
Duplicate targets | Two sources → same target (conflict) |
The generated Groovy cleanup script doesn’t blindly delete. It verifies first:
// Before deleting a status, verify no issues use it
def jql = "status = \"Old Status Name\""
def issueCount = countIssues(jql)
if (issueCount > 0) {
println "SKIPPED: ${statusName} - ${issueCount} issues use this status"
} else {
// Safe to delete
statusManager.removeStatus(statusId)
}
Real-World Results
On a recent migration project:
Metric | Manual Approach | With Toolkit |
Objects processed | 500+ | 500+ |
Time to generate mappings | ~8 hours | ~10 minutes |
Human errors caught | Found in UAT | Found before CMJ import |
Cleanup confidence | “Hope nothing breaks” | JQL-validated, audited |
Getting Started
The toolkit is open source and available at GitHub.
Prerequisites
Quick Start
# Clone the toolkit
git clone <repository-url>
cd cmj_template
# Install dependencies
pip install -r requirements.txt
# Validate your setup
python3 scripts/run_migration.py --validate
# Run interactively
python3 scripts/run_migration.py
The Workflow in Practice
Pre-Deployment: Data Collection (Steps 1–2)
Export data from source and target Jira instances, converting to Excel for the audit trail:
python3 run_migration.py --step 1 # Convert source data
python3 run_migration.py --step 2 # Convert target data
Output: Excel workbooks with all objects, IDs, and metadata—easy to review and share.
Pre-Deployment: Process & Validate (Steps 3–5)
python3 run_migration.py --step 3 # Process customer mapping
# → Customer reviews the PROCESSED.xlsx file
python3 run_migration.py --step 4 # Validate reviewed file
python3 run_migration.py --step 5 # Filter for CMJ template
The validation step is critical. It catches mistakes before they become CMJ import failures.
Pre-Deployment: Generate CMJ Templates (Step 6)
python3 run_migration.py --step 6 # Generate CMJ XML templates
Output: Two CMJ template files ready for import:
These templates are generated directly from the validated mapping spreadsheet, ensuring every MAP operation has been reviewed and approved before it touches CMJ. No more manual XML editing or copy-paste errors.
CMJ Deployment
Import both templates into CMJ and deploy your snapshot. This step remains manual—the toolkit hands off cleanly-formatted, validated input so the CMJ deployment itself is straightforward.
Post-Deployment Cleanup (Steps 7–11)
After CMJ deployment, export the new target state and generate the cleanup script:
python3 run_migration.py --step 7 # Convert post-import data
python3 run_migration.py --step 8 # Generate cleanup report
python3 run_migration.py --step 9 # Generate Groovy cleanup script
python3 run_migration.py --step 10 # Validate dryrun output
python3 run_migration.py --step 11 # Validate liverun output
The two-phase validation (dryrun then liverun) ensures nothing gets deleted that shouldn’t be.
Lessons Learned
The #1 cause of CMJ failures in our experience: bad input data. A typo in a target name, an extra space, a copied suggestion with “(85%)” still attached. Catching these before CMJ import saves hours of debugging.
Objects that existed in the target before migration should never be deleted. The toolkit tracks pre-import state and protects those objects during cleanup.
Even after careful planning, always verify with JQL before deleting:
Automation handles the tedious work. Humans make the decisions:
None of This Works Without the Right Customer
Tools like this don’t get built—or validated—in a vacuum. A critical ingredient in making this toolkit production-ready was having a customer who was genuinely invested in getting it right.
Ryan Stroup dedicated real time and attention to this effort: reviewing mapping spreadsheets, testing the pipeline against his projects’ actual data, surfacing edge cases that only appear in production environments, and validating that every requirement was met before sign-off. That kind of engaged partnership is what separates a toolkit that works in theory from one you can trust on a live migration.
If you’re planning to adopt this approach, I’d strongly encourage the same model: identify a customer stakeholder who will roll up their sleeves and test alongside you. The automation handles the tedious work—but a willing, thorough collaborator on the customer side is what gives you confidence the output is actually correct.
Built with AI: A Claude Code Story
Full disclosure: this toolkit was built collaboratively with Claude Code, Anthropic’s AI-powered CLI assistant.
What started as a few helper scripts evolved into a comprehensive 11-step pipeline through iterative development with AI assistance. Claude Code helped with:
The experience reinforced something important: AI doesn’t replace domain expertise—it amplifies it. I knew what CMJ migrations needed; Claude Code helped me build it faster and with fewer bugs than I could have alone.
If you’re on the fence about using AI tools for Jira administration work, I’d encourage you to try it. The combination of your Jira knowledge and AI’s coding assistance is genuinely powerful.
Conclusion
CMJ is a powerful tool, but it’s only as good as the data you feed it. This toolkit fills the gap between “we have a mapping spreadsheet” and “CMJ templates are ready to import” with:
Whether you’re migrating one project or fifty, having a repeatable, validated process makes all the difference.
The code is on GitHub. If you run into issues or have improvements, feel free to open an issue or PR.
Questions or feedback? Drop a comment below or reach out directly. I’m always interested in hearing how others are tackling Jira migrations—and whether you’re using AI to help.