Skip to content

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.

License

Notifications You must be signed in to change notification settings

ravinderji/maven_upgrade_utility

Repository files navigation

Maven Upgrade Utility

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.

Features

  • Project scan: Recursively finds all pom.xml files 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 .m2 directory, then repositories declared in the project pom.xml, then environment variables.
    • Supports credentials from the settings file (servers matched by id) and Authorization header or tokens via environment variables.
  • 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 properties section (including values inherited from a parent POM located via relativePath)
    • Updates versions in dependencyManagement
    • Updates BOM imports (dependencyManagement entries with type=pom and scope=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.

Requirements

  • 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).

Setup

  • 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 .m2 directory (recommended): place credentials and repo mirror/definition in ~/.m2/settings.xml.
    • Project pom.xml <repositories> entry.
    • Environment variables:
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"

Project layout

  • 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 purpose
  • selected_versions.xlsx: Generated Excel with your final selections

Quick start

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.

Execution

  • Run against a project directory:
python main.py /path/to/your/maven/project
  • Example using the included sample project:
python main.py ./sample-multi-module

During 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 C at 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.

What the tool does

  1. Scans the given directory for pom.xml files and extracts dependencies
  2. 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)
  3. Prompts you to select versions (shows up to 20 most recent, or enter a custom version)
  4. 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
  5. Asks you to continue or abort based on issues/warnings
  6. Updates pom.xml files where versions changed
  7. Writes selected_versions.xlsx with your final selections

FAQ

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.


Organization repository settings

  • Detection order: user settings file in the .m2 directory → repositories declared in the project pom.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.

Compatibility rules

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 }
  }
}

Notes and limitations

  • 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.

Troubleshooting

  • "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.xml files 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.

Output

  • Updated pom.xml files (only where versions changed)
  • selected_versions.xlsx containing: 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.

Sample execution session (abridged)

$ 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)

Sample settings.xml (minimal)

<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>

Understanding and extending compatibility rules

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.

What it is

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.x means “any major version 6”. Exact strings (for example, 2.19.0) match exactly.
  • Directives: required (should align), incompatible (not allowed), warn (advisory).

Sections in the file

  • 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"}
      ]
    }

How the tool uses the rules

  • Aggregates your selections, then:
    • Detects duplicate coordinates with different selected versions (issue)
    • Applies version_patterns (for example, group major spread) and deprecated_versions (if provided)
    • Evaluates inter_dependency_rules across 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.

About the schema

  • The file compatibility_rules.schema.json defines the structure for validation and editor hints.
  • Validate with any JSON Schema tool (for example, ajv, jsonschema).

How to extend for new dependencies

  • Add Java requirements:
    • Put the coordinate under java_version_requirements with a map of version pattern → Java requirement.
  • Add cross‑component rules:
    • Create or extend a set under inter_dependency_rules and include version alignment rules with a compatibility directive.
  • Add app server constraints:
    • Under app_server_rules, add incompatibilities (always issues) or requirements (required/warn/incompatible) entries tying a server/server_version to a dependency coordinate and version pattern.
  • Adjust cross‑cutting patterns:
    • Tune version_patterns.major_version_mismatch.threshold or add deprecations.

Pattern matching and evolution

  • Supported today: major patterns like 6.x and 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.

Good practices

  • Keep rules focused and readable; use description/message for context.
  • Treat the JSON as policy‑as‑code (version control + PR reviews).
  • Start with warn, then move to required/incompatible after validation in real projects.

Field reference: tags, properties, and attributes

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+").
  • 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.
  • version_patterns (object):

    • major_version_mismatch (object, optional):
      • description (string, optional)
      • threshold (integer): Max allowed spread of major versions within the same groupId before 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.
  • 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.
    • requirements (array): Required/warn/incompatible relationships to app servers:
      • entry (object):
        • server (string)
        • server_version (string)
        • dependency (string)
        • version (string)
        • compatibility (string): required, warn, or incompatible.
        • message (string, optional)

Notes:

  • Version pattern semantics: N.x matches any version whose major equals N; exact strings match literally.
  • Component keys in inter_dependency_rules are labels you define; keep them consistent within a rule set.
  • Unknown additional properties are tolerated; see compatibility_rules.schema.json for validation.

Schema (compatibility_rules.schema.json): purpose, usage, and extension

Purpose

  • Acts as the formal contract for compatibility_rules.json so 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.json to 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

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 a compatibility directive (required | incompatible | warn) and optional notes.
  • version_patterns: generic knobs like major_version_mismatch.threshold, optional deprecated_versions list.
  • app_server_rules: incompatibilities (always issues) and requirements (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. Keep version for simple cases to remain backward compatible.
  • More app server expressiveness:
    • Allow multiple dependencies in one rule by extending the schema so dependency accepts an array, or introduce dependencies as an array. Optionally add wildcards (for example, groupId:*).
    • Add requires_feature flags (for example, jakarta_ee_9: true) and map them to server versions in a separate section.
  • Additional domains:
    • Introduce new sections (for example, database_driver_rules, plugin_rules, build_tool_rules) by modeling them like app_server_rules or inter_dependency_rules.
  • Stronger deprecation semantics:
    • Extend deprecated_versions.artifacts[*] with reason, eolDate, replacement to provide better guidance.
  • Versioning and governance:
    • Keep $id in the schema and consider adding a top‑level schemaVersion in compatibility_rules.json. Bump versions when you introduce breaking changes to enable safe rollout.

Guidelines for scaling rules across many projects

  • Start simple (major patterns, targeted rules), then iterate. Use warn first; promote to required/incompatible after 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.

About

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.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages