Skip to content

feat(updaters): add Maven pom.xml updater with property indirection - #596

Merged
ruromero merged 2 commits into
guacsec:mainfrom
ruromero:TC-5411
Jul 30, 2026
Merged

feat(updaters): add Maven pom.xml updater with property indirection#596
ruromero merged 2 commits into
guacsec:mainfrom
ruromero:TC-5411

Conversation

@ruromero

@ruromero ruromero commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • New src/updaters/maven_updater.js module with updateMavenVersions() API
  • Position-based string splice preserves all formatting, comments, whitespace
  • Supports ${property} indirection with recursive resolution and cycle detection
  • Handles <dependencyManagement> sections
  • 17 new tests, 6 fixture pom.xml files, 89% line coverage

Implements TC-5411

Test plan

  • Direct version replacement
  • Property-based version replacement
  • Recursive property chain resolution
  • Circular property detection and skip
  • Formatting/comment preservation
  • Malformed XML fail-safe
  • Idempotency verification
  • npm run lint passes
  • npm test passes

Summary by Sourcery

Add a Maven pom.xml updater that performs structure-aware, formatting-preserving dependency version updates with robust handling of property indirection and edge cases, backed by comprehensive tests and fixtures.

New Features:

  • Introduce a Maven pom.xml updater that updates dependency versions by groupId/artifactId while preserving file formatting and comments
  • Support version updates via Maven property references, including recursive property chains and dependencyManagement entries

Enhancements:

  • Detect and skip circular or conflicting property-based version updates, reporting detailed reasons for skipped changes
  • Ensure idempotent behavior and graceful handling of malformed or non-standard pom.xml structures

Tests:

  • Add a comprehensive maven_updater test suite with fixtures covering direct versions, property indirection, recursive and circular properties, formatting preservation, error handling, idempotency, and dependencyManagement support

@sourcery-ai

sourcery-ai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a Maven pom.xml updater that uses fast-xml-parser for structural understanding but applies position-based string replacements to preserve formatting, with support for property-based version indirection (including recursive chains, circular detection, and dependencyManagement) and an accompanying high-coverage test suite with XML fixtures.

Sequence diagram for updateMavenVersions Maven pom.xml update flow

sequenceDiagram
  participant Caller
  participant updateMavenVersions
  participant XMLParser
  participant resolvePropertyChain
  participant findDependencyVersionPosition
  participant findPropertyPosition

  Caller->>updateMavenVersions: updateMavenVersions(pomContent, versionChanges)

  alt no_versionChanges
    updateMavenVersions-->>Caller: {content: pomContent, applied: [], skipped: []}
  else has_versionChanges
    updateMavenVersions->>XMLParser: new XMLParser(options)
    updateMavenVersions->>XMLParser: parse(pomContent)
    alt parse_error
      updateMavenVersions-->>Caller: {content: pomContent, applied: [], skipped: [reason Failed to parse pom.xml]}
    else parse_ok
      updateMavenVersions->>findDependencyVersionPosition: findDependencyVersionPosition(pomContent, groupId, artifactId)
      alt version_not_found
        updateMavenVersions-->>Caller: skipped reason Dependency not found or no version
      else version_found
        updateMavenVersions->>updateMavenVersions: read currentVersion
        alt currentVersion_is_property
          updateMavenVersions->>resolvePropertyChain: resolvePropertyChain(propName, properties)
          alt resolve_error_or_cycle
            updateMavenVersions-->>Caller: skipped reason from resolvePropertyChain
          else resolved_ok
            updateMavenVersions->>findPropertyPosition: findPropertyPosition(pomContent, terminalPropName)
            alt property_position_not_found
              updateMavenVersions-->>Caller: skipped reason Could not locate property
            else property_position_found
              updateMavenVersions->>updateMavenVersions: queue property replacement in replacementsByPosition
            end
          end
        else direct_version
          updateMavenVersions->>updateMavenVersions: queue direct version replacement
        end
        updateMavenVersions->>updateMavenVersions: sort replacementsByPosition descending
        updateMavenVersions->>updateMavenVersions: splice pomContent to apply replacements
        updateMavenVersions-->>Caller: {content: result, applied, skipped}
      end
    end
  end
Loading

File-Level Changes

Change Details Files
Introduce Maven pom.xml updater that performs structure-aware, position-based version updates, including property indirection and dependencyManagement support.
  • Implement helper functions to locate dependency/version and property value spans in raw XML via tag scanning and boundary checks.
  • Add property-chain resolver with visited-set cycle detection and error reporting for missing or circular properties.
  • Implement updateMavenVersions() that parses pom.xml with fast-xml-parser, computes direct vs property-based replacements, deduplicates conflicting property updates, and applies sorted string splices while returning applied/skipped metadata.
src/updaters/maven_updater.js
Add comprehensive tests and fixtures validating updater behavior and formatting preservation.
  • Create maven_updater.test.js covering direct and property-based updates, recursive and circular properties, malformed XML, missing dependencies/properties, idempotency, and dependencyManagement handling.
  • Add fixture pom.xml files modeling direct versions, property references, recursive and circular properties, malformed XML, formatting/comments, and dependencyManagement layouts to support behavioral tests.
test/updaters/maven_updater.test.js
test/updaters/fixtures/pom_with_comments.xml
test/updaters/fixtures/pom_property_versions.xml
test/updaters/fixtures/pom_direct_versions.xml
test/updaters/fixtures/pom_circular_properties.xml
test/updaters/fixtures/pom_recursive_properties.xml
test/updaters/fixtures/pom_malformed.xml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • When multiple versionChanges target the same direct dependency (same groupId/artifactId) with different newVersion values, the last one silently wins; consider adding a conflict check similar to the property case so callers get an explicit skipped reason instead of an implicit override.
  • The string-based tag searches (e.g. findDependencyVersionPosition/findPropertyPosition) assume simple <tag>/</tag> forms without attributes or namespace prefixes, which may break on real-world POMs; consider relaxing these to handle <tag ...> and prefixed tags (or leveraging the parsed XML structure to locate positions more robustly).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- When multiple versionChanges target the same direct dependency (same groupId/artifactId) with different newVersion values, the last one silently wins; consider adding a conflict check similar to the property case so callers get an explicit skipped reason instead of an implicit override.
- The string-based tag searches (e.g. findDependencyVersionPosition/findPropertyPosition) assume simple `<tag>`/`</tag>` forms without attributes or namespace prefixes, which may break on real-world POMs; consider relaxing these to handle `<tag ...>` and prefixed tags (or leveraging the parsed XML structure to locate positions more robustly).

## Individual Comments

### Comment 1
<location path="test/updaters/maven_updater.test.js" line_range="331" />
<code_context>
+		});
+	});
+
+	suite('idempotency', () => {
+
+		/** Verifies that running updateMavenVersions twice with the same input is idempotent. */
</code_context>
<issue_to_address>
**suggestion (testing):** Expand idempotency tests to cover the applied/skipped metadata, not just the final content.

Since callers may depend on `applied`/`skipped` metadata, it would be valuable to assert how those fields behave on the second run—for example, whether we still report the same `applied` entries or instead mark everything as `skipped` once versions already match. Encoding this explicitly in a test will document the intended contract and guard against regressions in this behavior.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread test/updaters/maven_updater.test.js
@codecov-commenter

codecov-commenter commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.01657% with 47 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.84%. Comparing base (b0e2843) to head (dcfb3d3).

Files with missing lines Patch % Lines
src/updaters/maven_updater.js 87.01% 47 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #596      +/-   ##
==========================================
- Coverage   91.01%   90.84%   -0.18%     
==========================================
  Files          38       39       +1     
  Lines        8001     8363     +362     
  Branches     1395     1453      +58     
==========================================
+ Hits         7282     7597     +315     
- Misses        719      766      +47     
Flag Coverage Δ
unit-tests 90.84% <87.01%> (-0.18%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/updaters/maven_updater.js 87.01% <87.01%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@a-oren a-oren left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

ruromero and others added 2 commits July 30, 2026 14:47
Implements TC-5411

Adds a new `updateMavenVersions()` function that modifies dependency
versions in pom.xml files while preserving all formatting, comments,
whitespace, and indentation.

Key capabilities:
- Direct <version> element replacement via position-based string splice
- ${property} indirection: traces property references through
  <properties> and updates the property value instead
- Recursive property chain resolution (${a} -> ${b} -> value)
- Circular property reference detection with skip reporting
- Fail-safe: unreachable dependencies reported in skipped[]
- Idempotent: running twice with same input produces same output
- Covers both <dependencies> and <dependencyManagement> sections

Uses fast-xml-parser (existing dependency) for XML structure
understanding, then performs character-offset string splice to
avoid altering any non-version content.

Assisted-by: Claude Code
The direct-version path silently let the last entry win when the same
dependency appeared twice in versionChanges with different newVersion
values, while reporting both as applied. Align with the property path
by checking replacementsByPosition before inserting and skipping
conflicts with a clear reason.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ruromero
ruromero merged commit 0c4e031 into guacsec:main Jul 30, 2026
5 checks passed
@ruromero
ruromero deleted the TC-5411 branch July 30, 2026 14:16
@ruromero

Copy link
Copy Markdown
Collaborator Author

[sdlc-workflow/verify-pr] Re: @sourcery-ai[bot] review —

  1. "duplicate direct dep conflict check" — Classified as suggestion — already addressed by commit dcfb3d3 which adds dedup checking to the direct-version path, aligning it with the property path. No sub-task created.

  2. "relaxing string-based tag searches" — Classified as suggestion — this proposes a future robustness improvement for namespace-prefixed or attribute-bearing XML tags. No documented CONVENTIONS.md pattern or demonstrated codebase convention matches this suggestion. No sub-task created.

@ruromero

Copy link
Copy Markdown
Collaborator Author

Verification Report for TC-5411 (commit dcfb3d3)

Check Result Details
Review Feedback PASS 3 suggestions from sourcery-ai[bot]; no code change requests
Root-Cause Investigation N/A No sub-tasks created
Scope Containment PASS All 8 PR files within task-specified scope
Diff Size PASS 911 additions across 8 new files; proportionate (39.7% impl, 44.6% tests, 15.7% fixtures)
Commit Traceability WARN Commit 1 (fcda80e) references TC-5411; commit 2 (dcfb3d3) does not
Sensitive Patterns PASS No secrets detected in 768 added lines across 8 files
CI Status PASS All 5 CI checks pass (lint, test Node 22/24, PR title, commit messages, Sourcery)
Acceptance Criteria PASS 8 of 8 criteria met
Test Quality PASS No repetitive tests; all 17 tests have doc comments; Eval Quality: N/A
Test Change Classification ADDITIVE New test file + 6 fixture files; no existing tests modified
Verification Commands PASS npm run lint and npm test pass via CI

Overall: WARN

Commit dcfb3d3 ("fix(updaters): detect conflicting duplicate direct version changes") does not reference TC-5411 in its message. This is a follow-up fix addressing sourcery-ai's review suggestion about duplicate direct dep conflict detection. All other checks pass.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants