Skip to content

ChangeDependency skips dependencies whose new coordinates don't resolve#7321

Merged
steve-aom-elliott merged 5 commits intomainfrom
fix-change-dependency-glob-validation
Apr 9, 2026
Merged

ChangeDependency skips dependencies whose new coordinates don't resolve#7321
steve-aom-elliott merged 5 commits intomainfrom
fix-change-dependency-glob-validation

Conversation

@steve-aom-elliott
Copy link
Copy Markdown
Contributor

@steve-aom-elliott steve-aom-elliott commented Apr 8, 2026

Summary

When ChangeDependency uses glob patterns (e.g. org.hibernate:hibernate-*org.hibernate.orm), it was incorrectly changing the groupId of artifacts that don't exist under the new group — like hibernate-validator, which belongs to org.hibernate.validator not org.hibernate.orm. It also updated the shared version variable, breaking the unchanged dependency.

All warning suppression and silent-skip behavior is gated on glob pattern usage (* or ? in oldGroupId/oldArtifactId). For non-glob patterns, the original e.warn() behavior is preserved so users still see resolution failures from misconfigured environments.

Gradle ChangeDependency

Core change: track per-artifact resolution failures when using globs. The scanner now records which specific GroupArtifact coordinates fail version resolution in failedResolutions (only when the pattern contains wildcards). This feeds into two places:

  1. canUpdateVariable — returns false when any matching artifact sharing a version variable failed resolution. This prevents the shared variable from being updated, and routes deps through the !canUpdateVariable path where successful deps get hardcoded versions and failed deps are skipped.

  2. updateDependency — checks failedResolutions at the top and returns the original tree for deps whose new coordinates don't exist.

Additional fix: Scanner uses putIfAbsent for exceptions (glob only) so a successful resolution from one artifact isn't overwritten by a failure from another sharing the same variable.

Result: Given hibernateVersion = '5.6.15.Final' shared by hibernate-core and hibernate-validator:

  • hibernate-coreorg.hibernate.orm:hibernate-core:6.0.2.Final (hardcoded, detached from variable)
  • hibernate-validator → unchanged (org.hibernate:hibernate-validator:${hibernateVersion})
  • hibernateVersion → stays at 5.6.15.Final

Maven ChangeDependencyGroupIdAndArtifactId

On resolution failure: returns tag unchanged when glob patterns are in use (artifact doesn't exist under new coordinates). Preserves e.warn(tag) for non-glob patterns.

Maven ChangeManagedDependencyGroupIdAndArtifactId

On resolution failure: returns tag unchanged when glob patterns are in use. Preserves e.warn(t) for non-glob patterns. (Previously returned e.warn(t) which kept the modified groupId/artifactId AND added a warning — the original tag is now returned for the glob case.)

Test plan

  • New test doesNotChangeGroupIdWhenNewCoordinatesDontResolve: Gradle build with hibernateVersion property shared by hibernate-core and hibernate-validator, glob ChangeDependency hardcodes hibernate-core's version, leaves hibernate-validator and the shared property untouched
  • All existing ChangeDependencyTest tests pass
  • All existing ChangeDependencyGroupIdAndArtifactIdTest tests pass
  • All existing ChangeManagedDependencyGroupIdAndArtifactIdTest tests pass

When using glob patterns like `hibernate-*` to change a dependency's
groupId, artifacts that don't exist under the new groupId (e.g.
hibernate-validator under org.hibernate.orm) were incorrectly modified.

Three fixes:
- Scanner: use putIfAbsent for exceptions so a failed resolution from
  one artifact doesn't overwrite a successful resolution from another
  sharing the same version variable
- Edit (!canUpdateVariable path): return the original tree instead of
  adding a warning marker when the new coordinates can't be resolved
- Edit (canUpdateVariable path): verify the new coordinates resolve
  before applying groupId/artifactId changes
ChangeDependencyGroupIdAndArtifactId already reverted the groupId change
on resolution failure (returning `tag` not `t`), but still added a
warning marker via `e.warn(tag)`. Changed to return `tag` unchanged.

ChangeManagedDependencyGroupIdAndArtifactId was worse — it returned
`e.warn(t)` which kept the modified groupId/artifactId AND added a
warning. Changed to return the original `tag`.
@steve-aom-elliott steve-aom-elliott added enhancement New feature or request test provided Already replicated with a unit test, using JUnit pioneer's ExpectedToFail maven gradle labels Apr 8, 2026
…ables

When a glob pattern matches artifacts that don't exist under the new
coordinates (e.g. hibernate-validator under org.hibernate.orm), the
shared version variable should not be updated. Instead, deps that
resolve successfully get their version hardcoded, and deps that fail
are left completely unchanged.

Previously, canUpdateVariable only checked whether all deps sharing a
variable matched the pattern. Now it also checks whether any of those
deps failed version resolution in the scanner. This routes failed deps
through the !canUpdateVariable path where they are skipped, while
successful deps get hardcoded versions and detach from the variable.
@steve-aom-elliott steve-aom-elliott moved this from In Progress to Ready to Review in OpenRewrite Apr 8, 2026
Comment on lines +394 to +395
// New coordinates can't be resolved — leave this dependency unchanged
return tag;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have a small worry here swallowing exceptions when we're running in a new environment that doesn't have credentials or repository access set up correctly. I can understand it if we want to suppress warnings when it's part of wildcard upgrade flow, but might it make sense to make that conditional / explicit here? To only suppress if wildcards are in play? Because if that's not the case as a user I'd want to see the failure. Or what's your view on this?

Same applies elsewhere above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You're correct. I had actually discussed this and asked about it, but it seems to have skipped doing it and I missed it in the last look through. Will get another adjustment to that pushed shortly

When a specific (non-glob) artifact fails to resolve under the new
coordinates, that is a real problem the user should see — e.g. missing
repository credentials or misconfiguration. Only suppress warnings and
skip silently when the pattern contains wildcards, where a resolution
failure is the expected signal that the glob matched an artifact that
doesn't exist under the new group.
Copy link
Copy Markdown
Contributor Author

@steve-aom-elliott steve-aom-elliott left a comment

Choose a reason for hiding this comment

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

Good call Tim — pushed a commit that gates all warning suppression on whether the pattern contains wildcards (* or ?). For non-glob patterns, the original e.warn() behavior is preserved so users still see resolution failures from misconfigured environments.

- Change instanceof Exception to instanceof MavenDownloadingException
  to match the actual cast, since the map only stores String or
  MavenDownloadingException values
- Extract isGlobPattern() helper in all three classes instead of
  inlining the check only in the Maven variants
Copy link
Copy Markdown
Member

@timtebeek timtebeek left a comment

Choose a reason for hiding this comment

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

Thanks for the quick turnaround; should make the downstream recipes easier to write and reason about.

@steve-aom-elliott steve-aom-elliott merged commit ccb7d23 into main Apr 9, 2026
1 check passed
@steve-aom-elliott steve-aom-elliott deleted the fix-change-dependency-glob-validation branch April 9, 2026 13:00
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite Apr 9, 2026
steve-aom-elliott added a commit to openrewrite/rewrite-hibernate that referenced this pull request Apr 9, 2026
…ordinates

With openrewrite/rewrite#7321 merged, ChangeDependency automatically
skips dependencies whose new coordinates don't resolve when using glob
patterns. The hibernate-validator and hibernate-search-* revert entries
are no longer needed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request gradle maven test provided Already replicated with a unit test, using JUnit pioneer's ExpectedToFail

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants