Author: Ravinderjeet Singh Nagpal
Requirements:
- All Python dependencies are listed in
requirements.txt. - Install them with:
pip install -r requirements.txt
License:
- This project is licensed under the MIT License.
- See the LICENSE file for full details.
- The MIT License is a permissive open source license that allows you to use, modify, and distribute the software with minimal restrictions, as long as you include the copyright notice.
A Python CLI that scans a Maven project for pom.xml files, lists current dependencies, discovers available versions, lets you interactively pick target versions (including custom versions), performs compatibility checks, updates the pom.xml files, and saves your selections to an Excel sheet.
- Project scan: Recursively finds all
pom.xmlfiles and extracts dependencies. - Organization repository first: Reads versions from your organization’s Maven repository first, then optionally falls back to Maven Central (asks once per run).
- Auto-detects repository settings in this order: user settings file in the
.m2directory, then repositories declared in the projectpom.xml, then environment variables. - Supports credentials from the settings file (servers matched by id) and Authorization header or tokens via environment variables.
- Auto-detects repository settings in this order: user settings file in the
- Version discovery: Uses repository metadata to list available versions.
- Interactive selection: Pick versions per dependency with auto-apply for duplicates across modules.
- Custom version entry: For any dependency, you can always enter a custom version not listed in the fetched versions. The tool will prompt for confirmation if the version is not in the fetched list, ensuring you don't accidentally select a typo or unavailable version.
- Compatibility checks: Dynamic rules (Spring Boot with Spring Framework/Hibernate, Spring with Jackson), Java version requirements, major version mismatches, and newer-version notices.
- Comprehensive upgrades:
- Updates explicit dependency version elements
- Updates versions defined via properties in a
propertiessection (including values inherited from a parent POM located viarelativePath) - Updates versions in
dependencyManagement - Updates BOM imports (
dependencyManagemententries withtype=pomandscope=import)
- Safe upgrade flow: Shows issues and warnings, asks you to continue or abort, then updates the POM files.
- Audit trail: Exports all selections to an Excel file for review.
- Python 3.8 or later
- Internet access to query repositories
- Python packages: requests, openpyxl
Install the required packages using your preferred method (for example, a virtual environment and pip).
- Create and activate a Python virtual environment and install dependencies:
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install requests openpyxl- Optional: configure organization repository access (pick one; the tool auto-detects in this order):
- User settings file in the
.m2directory (recommended): place credentials and repo mirror/definition in~/.m2/settings.xml. - Project
pom.xml<repositories>entry. - Environment variables:
- User settings file in the
export ORG_MAVEN_REPO_URL="https://artifactory.example.com/artifactory/libs-release-local"
export ORG_MAVEN_AUTH_HEADER_NAME="Authorization"
export ORG_MAVEN_AUTH_HEADER_VALUE="Bearer YOUR_TOKEN"
# Optional: point to a non-default Maven settings location
export MAVEN_SETTINGS_XML="/custom/path/to/settings.xml"main.py: CLI workflow (scan → select versions → compatibility checks → confirm → upgrade → export)compatibility_rules.json: Optional rules file (if absent, built-in defaults are used)sample-multi-module/: Example multi-module project with simple dependencies for testing purposeselected_versions.xlsx: Generated Excel with your final selections
Run the utility against a Maven project root (your own project or the provided sample directory). You will be prompted per dependency to choose a version (or keep current). Duplicate groupId:artifactId entries across modules will auto-apply your first choice.
You can always enter a custom version for any dependency by typing C at the prompt. If the version is not in the fetched list, the tool will prompt you to confirm before accepting it. This ensures you can safely use pre-releases, snapshots, or private versions.
- Run against a project directory:
python main.py /path/to/your/maven/project- Example using the included sample project:
python main.py ./sample-multi-moduleDuring execution the tool will:
- Read your custom repository settings (settings file → project pom → environment variables)
- Query your org repository first; if nothing is found, ask once whether to fall back to Maven Central for the remainder of the run
- Prompt interactively for version selections, show compatibility checks, and ask for confirmation before applying edits
- Allow you to enter a custom version for any dependency by typing
Cat the prompt. If the version is not in the fetched list, you will be asked to confirm before it is accepted. This is a safe way to use pre-releases, snapshots, or private versions.
- Scans the given directory for
pom.xmlfiles and extracts dependencies - Fetches available versions from your organization repository first; if none are found, it can fall back to Maven Central (the tool asks once per run)
- Prompts you to select versions (shows up to 20 most recent, or enter a custom version)
- Runs compatibility checks and shows detailed analysis
- Inter-dependency rules (e.g., Spring Boot ↔ Spring Framework / Hibernate)
- Java version requirements (e.g., Spring 6.x → Java 17+)
- Major version mismatches within the same group
- Newer version available notifications
- Asks you to continue or abort based on issues/warnings
- Updates
pom.xmlfiles where versions changed - Writes
selected_versions.xlsxwith your final selections
Q: Can I use a version that is not listed in the fetched versions?
A: Yes! When prompted for a version, type C to enter a custom version. If the version you enter is not in the fetched list, the tool will prompt you to confirm before accepting it. This allows you to use pre-releases, snapshots, or versions from private repositories, and helps prevent typos or mistakes.
- Detection order: user settings file in the
.m2directory → repositories declared in the projectpom.xml→ environment variables. - Credentials: the tool reads server credentials from the settings file when the server id matches the selected repository. It also supports setting an Authorization header or token through environment variables.
- Behavior when not configured: if no local repository settings are found anywhere, the tool informs you and switches to Maven Central.
The tool loads rules from compatibility_rules.json if present; otherwise it falls back to sensible defaults. You can extend these rules to suit your organization’s policies.
Sample compatibility_rules.json:
{
"java_version_requirements": {
"org.springframework.boot:spring-boot-starter-web": { "3.x": "Java 17+", "2.x": "Java 8+" },
"org.springframework:spring-context": { "6.x": "Java 17+", "5.x": "Java 8+" }
},
"inter_dependency_rules": {
"spring_boot_spring_framework": {
"description": "Spring Boot version compatibility with Spring Framework",
"rules": [
{ "spring_boot": "3.x", "spring_framework": "6.x", "compatibility": "required" },
{ "spring_boot": "2.x", "spring_framework": "5.x", "compatibility": "required" }
]
}
},
"version_patterns": {
"major_version_mismatch": { "threshold": 1 }
}
}- The upgrader now updates: explicit dependency versions, property-backed versions, dependencyManagement entries, and BOM imports. It follows parent POMs discovered via local
relativePath(e.g.,../pom.xml) so child POMs can inherit and update values defined in parents. - Remote parent POMs not present locally are not resolved. Profiles, plugin versions, and pluginManagement are currently out of scope.
- Settings file parsing supports mirrors, active profiles’ repositories, and basic server credential mapping. Complex authentication setups may require environment overrides.
- XML namespaces are handled for typical POM layouts; ensure POMs are well-formed.
- Sorting of versions is heuristic for common SemVer-like formats; non-standard qualifiers might affect ordering.
- Network connectivity to Maven Central is required for version discovery and some compatibility info.
- "No versions found": The artifact may not be in the selected repository, the group/artifact coordinates may be unusual, or there is a network issue.
- Namespace-related parsing issues: Ensure
pom.xmlfiles are valid and use standard Maven POM schemas. - Upgrades not applied: If a dependency lacks an explicit
<version>(e.g., managed by a BOM), the tool will log it and skip changing it.
- Updated
pom.xmlfiles (only where versions changed) selected_versions.xlsxcontaining:groupId,artifactId,currentVersion,selectedVersion,pomFile
For non-interactive or CI usage, consider scripting a selections file and extending main.py to read preselected versions and skip prompts.
$ python main.py ./sample-multi-module
🚀 Maven Upgrade Utility
============================================================
Scanning Maven project: ./sample-multi-module
Found 3 pom.xml file(s)
Found 4 dependencies in ./sample-multi-module/module-a/pom.xml
Found 5 dependencies in ./sample-multi-module/module-b/pom.xml
Found 9 unique dependencies
Fetching available versions...
Fetching versions for org.springframework:spring-context...
Found 20 versions
...
DEPENDENCY VERSION SELECTION
============================================================
Dependency: org.springframework:spring-context
Current Version: 5.2.0.RELEASE
Available versions (showing 20 most recent):
1. 6.1.18
2. 6.1.17
...
Select version [1-20] (Enter for current: 5.2.0.RELEASE): 1
COMPATIBILITY CHECK
============================================================
⚠️ COMPATIBILITY WARNINGS
Requires Java 17+
CONFIRMATION REQUIRED
Do you want to:
1. Continue with the upgrade (proceed despite issues/warnings)
2. Abort the upgrade (go back and select different versions)<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<mirrors>
<mirror>
<id>corp-repo</id>
<name>Corporate Mirror</name>
<url>https://artifactory.example.com/artifactory/maven-proxy</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<servers>
<server>
<id>corp-repo</id>
<username>my-service-user</username>
<password>Bearer my-token-or-password</password>
</server>
</servers>
<activeProfiles>
<activeProfile>corp</activeProfile>
</activeProfiles>
<profiles>
<profile>
<id>corp</id>
<repositories>
<repository>
<id>corp-repo</id>
<url>https://artifactory.example.com/artifactory/libs-release</url>
</repository>
</repositories>
</profile>
</profiles>
</settings>This section explains the purpose and structure of compatibility_rules.json, how the tool applies it, and how to scale it to new dependencies and servers.
compatibility_rules.json is a policy file that encodes your organization’s version guidance. The tool reads it at runtime, reports issues/warnings, and asks you whether to proceed.
Key ideas:
- Maven coordinate:
groupId:artifactId(for example,org.springframework:spring-context). - Version patterns:
6.xmeans “any major version 6”. Exact strings (for example,2.19.0) match exactly. - Directives:
required(should align),incompatible(not allowed),warn(advisory).
- java_version_requirements: minimum Java runtime per dependency version.
- Example:
"java_version_requirements": { "org.springframework:spring-context": { "6.x": "Java 17+", "5.x": "Java 8+" } }
- inter_dependency_rules: how components must line up (for example, Spring Boot ↔ Spring Framework).
- Example:
"inter_dependency_rules": { "spring_boot_spring_framework": { "description": "Spring Boot vs Spring Framework", "rules": [ {"spring_boot": "3.x", "spring_framework": "6.x", "compatibility": "required"} ] } }
- version_patterns: cross‑cutting checks (for example, major version spread, deprecations).
- Example:
"version_patterns": { "major_version_mismatch": { "threshold": 1 } }
- app_server_rules: compatibility of selected dependencies with application servers (for example, Tomcat/WebLogic/WildFly).
- Example:
"app_server_rules": { "incompatibilities": [ {"server": "tomcat", "server_version": "9.x", "dependency": "org.springframework:spring-context", "version": "6.x", "message": "Spring 6.x is incompatible with Tomcat 9.x (javax.*)"} ], "requirements": [ {"server": "tomcat", "server_version": "10.x", "dependency": "org.springframework.boot:spring-boot-starter-web", "version": "3.x", "compatibility": "required", "message": "Use Boot 3.x with Tomcat 10.x"} ] }
- Aggregates your selections, then:
- Detects duplicate coordinates with different selected versions (issue)
- Applies
version_patterns(for example, group major spread) anddeprecated_versions(if provided) - Evaluates
inter_dependency_rulesacross selections - If an app server is provided (env or prompt), evaluates
app_server_rules - Warns if a newer version exists in the repository
- Prints issues/warnings and asks whether to proceed or abort.
- The file
compatibility_rules.schema.jsondefines the structure for validation and editor hints. - Validate with any JSON Schema tool (for example,
ajv,jsonschema).
- Add Java requirements:
- Put the coordinate under
java_version_requirementswith a map of version pattern → Java requirement.
- Put the coordinate under
- Add cross‑component rules:
- Create or extend a set under
inter_dependency_rulesand include version alignment rules with acompatibilitydirective.
- Create or extend a set under
- Add app server constraints:
- Under
app_server_rules, addincompatibilities(always issues) orrequirements(required/warn/incompatible) entries tying aserver/server_versionto a dependency coordinate and version pattern.
- Under
- Adjust cross‑cutting patterns:
- Tune
version_patterns.major_version_mismatch.thresholdor add deprecations.
- Tune
- Supported today: major patterns like
6.xand exact version strings. - To support richer ranges later (for example,
>=6.1,<6.4), extend the schema and matcher; start with major patterns to keep rules readable.
- Keep rules focused and readable; use
description/messagefor context. - Treat the JSON as policy‑as‑code (version control + PR reviews).
- Start with
warn, then move torequired/incompatibleafter validation in real projects.
Top‑level object (compatibility_rules.json):
-
java_version_requirements (object):
- key (string): Maven coordinate
groupId:artifactId. - value (object): Map of version pattern → Java requirement string.
- version pattern (string):
N.x(major match) or exact version. - requirement (string): Human guidance (for example, "Java 17+").
- version pattern (string):
- key (string): Maven coordinate
-
inter_dependency_rules (object):
- key (string): Rule set name (for readability; any unique name).
- value (object):
- description (string, optional): What this rule set covers.
- rules (array): Each rule enforces alignment between components.
- rule (object):
- component keys (string → string): Arbitrary component labels (for example,
spring_boot,spring_framework,hibernate,spring,jackson) whose values are version patterns. - compatibility (string): One of
required,incompatible,warn. - notes (string, optional): Extra context.
- component keys (string → string): Arbitrary component labels (for example,
- rule (object):
-
version_patterns (object):
- major_version_mismatch (object, optional):
- description (string, optional)
- threshold (integer): Max allowed spread of major versions within the same
groupIdbefore warning.
- deprecated_versions (object, optional):
- description (string, optional)
- artifacts (array): Explicitly deprecated versions.
- artifact (object):
- groupId (string)
- artifactId (string)
- versions (array of string): Version list to warn on.
- artifact (object):
- major_version_mismatch (object, optional):
-
app_server_rules (object):
- incompatibilities (array): Hard conflicts with application servers (always reported as issues):
- entry (object):
- server (string): App server name (lowercase recommended, for example,
tomcat,weblogic,wildfly). - server_version (string): Server version pattern (for example,
10.x). - dependency (string): Maven coordinate
groupId:artifactId. - version (string): Dependency version pattern (for example,
6.x). - message (string, optional): Human-readable reason.
- server (string): App server name (lowercase recommended, for example,
- entry (object):
- requirements (array): Required/warn/incompatible relationships to app servers:
- entry (object):
- server (string)
- server_version (string)
- dependency (string)
- version (string)
- compatibility (string):
required,warn, orincompatible. - message (string, optional)
- entry (object):
- incompatibilities (array): Hard conflicts with application servers (always reported as issues):
Notes:
- Version pattern semantics:
N.xmatches any version whose major equals N; exact strings match literally. - Component keys in
inter_dependency_rulesare labels you define; keep them consistent within a rule set. - Unknown additional properties are tolerated; see
compatibility_rules.schema.jsonfor validation.
Purpose
- Acts as the formal contract for
compatibility_rules.jsonso editors and CI can validate structure. - Enables IDE IntelliSense/auto‑complete and early error detection (missing keys, wrong types).
- Documents allowed sections and fields, keeping policy-as-code consistent across repos.
How to use
- Reference the schema at the top of your
compatibility_rules.jsonto enable IDE validation:{ "$schema": "./compatibility_rules.schema.json", "java_version_requirements": { } } - Validate in CI (examples):
- Using Node ajv-cli:
npx ajv validate -s compatibility_rules.schema.json -d compatibility_rules.json
- Using Python jsonschema:
python - <<'PY' import json, sys from jsonschema import validate schema = json.load(open('compatibility_rules.schema.json')) data = json.load(open('compatibility_rules.json')) validate(data, schema) print('OK') PY
- Using Node ajv-cli:
What it covers today
java_version_requirements: coordinates → { version pattern → Java requirement string }.inter_dependency_rules: named sets of rules; each rule defines component keys (for example, spring_boot, spring_framework, hibernate) with version patterns plus acompatibilitydirective (required|incompatible|warn) and optionalnotes.version_patterns: generic knobs likemajor_version_mismatch.threshold, optionaldeprecated_versionslist.app_server_rules:incompatibilities(always issues) andrequirements(directive-driven) tying app servers (server,server_version) to dependency coordinates and version patterns.
How to extend the schema for future needs
- Richer version ranges:
- Today rules use major patterns (for example,
6.x) or exact strings. To support ranges (for example,>=6.1,<6.4), add a new field to rules (for example,version_range) with a structured object and update the tool’s matcher to parse ranges. Keepversionfor simple cases to remain backward compatible.
- Today rules use major patterns (for example,
- More app server expressiveness:
- Allow multiple dependencies in one rule by extending the schema so
dependencyaccepts an array, or introducedependenciesas an array. Optionally add wildcards (for example,groupId:*). - Add
requires_featureflags (for example,jakarta_ee_9: true) and map them to server versions in a separate section.
- Allow multiple dependencies in one rule by extending the schema so
- Additional domains:
- Introduce new sections (for example,
database_driver_rules,plugin_rules,build_tool_rules) by modeling them likeapp_server_rulesorinter_dependency_rules.
- Introduce new sections (for example,
- Stronger deprecation semantics:
- Extend
deprecated_versions.artifacts[*]withreason,eolDate,replacementto provide better guidance.
- Extend
- Versioning and governance:
- Keep
$idin the schema and consider adding a top‑levelschemaVersionincompatibility_rules.json. Bump versions when you introduce breaking changes to enable safe rollout.
- Keep
Guidelines for scaling rules across many projects
- Start simple (major patterns, targeted rules), then iterate. Use
warnfirst; promote torequired/incompatibleafter proven. - Keep component key names consistent across repos (for example, always use
spring_boot,spring_framework,hibernate). - Co-locate the schema and rules in each repo or centralize them and reference via a URL for shared org policy.
- Enforce validation in CI to stop schema drift and catch typos early.