Skip to content

Add ChangeRepository recipe for Gradle build scripts#6785

Draft
Jenson3210 wants to merge 5 commits intomainfrom
change-gradle-repository
Draft

Add ChangeRepository recipe for Gradle build scripts#6785
Jenson3210 wants to merge 5 commits intomainfrom
change-gradle-repository

Conversation

@Jenson3210
Copy link
Contributor

Summary

  • Adds a new ChangeRepository recipe to replace or remove repository declarations in build.gradle and build.gradle.kts files
  • Enables organizations to standardize repository usage across all projects (e.g. migrate from jcenter to mavenCentral, consolidate internal Nexus URLs)
  • Handles deduplication: if the target repository already exists, removes the old one instead of creating a duplicate

Solution

All four parameters are optional, supporting flexible matching and replacement:

Parameter Description
oldType Match by type (jcenter, maven, etc.). Omit to match any type.
oldUrl Match by URL. Omit to match any URL of the given type.
newType Replacement type. Omit (with no newUrl) to remove the match.
newUrl Replacement URL.

Supported transformations:

  • Named → Named: jcenter()mavenCentral()
  • Named → Custom: jcenter()maven { url = "https://..." }
  • Custom → Named: maven { url = "..." }mavenCentral()
  • Custom → Custom: URL change while keeping the type
  • Remove: match and delete without replacement
  • Both Groovy and Kotlin DSL

Example usage for org-wide uniformity

type: specs.openrewrite.org/v1beta/recipe
name: com.myorg.StandardizeRepositories
recipeList:
  - org.openrewrite.gradle.ChangeRepository:
      oldType: jcenter
      newType: mavenCentral
  - org.openrewrite.gradle.ChangeRepository:
      oldUrl: https://old-nexus.internal.com/releases
      newType: maven
      newUrl: https://artifactory.myorg.com/releases

Test plan

  • 23 tests covering all transformation types, both DSLs, idempotency, deduplication, URL-only matching, and removal mode

Adds a new recipe to replace or remove repository declarations in
build.gradle and build.gradle.kts files, enabling organizations to
standardize repository usage.

Supports all combinations: named-to-named (jcenter to mavenCentral),
named-to-custom-maven, custom-maven-to-named, and URL changes.
Automatically deduplicates when the target repository already exists.
All four parameters (oldType, oldUrl, newType, newUrl) are optional,
allowing matching by type, URL, or both, and either replacing or
removing the matched repository.
When newType is null but newUrl is set, keep the matched repository's
type and only change the URL. Previously this would incorrectly enter
remove mode. Also refactored to use effectiveNewType throughout the
visitor to eliminate null checks on newType.
public TreeVisitor<?, ExecutionContext> getVisitor() {
MethodMatcher repoMatcher = new MethodMatcher("org.gradle.api.artifacts.dsl.RepositoryHandler " + (oldType != null ? oldType : "*") + "(..)", true);

return Preconditions.check(new IsBuildGradle<>(), new JavaIsoVisitor<ExecutionContext>() {
Copy link
Contributor

Choose a reason for hiding this comment

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

optional: We have a couple of recipes now that interact with repositories. Should we consider wrapping the discovery portion of this up into a Trait instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that is definitely a possibility here.
Just wondering if we should do this in this PR or in a next one.
We have a customer usecase atm for this functionality where a trait might take a larger refactor/bigger PR/ longer throughput.
So thinking we could potentially split the Trait in a different PR and already release the recipe functionality. Internal kitchen of it can still change.

@Jenson3210
Copy link
Contributor Author

Thanks for the early review @shanman190! Was a draft as I did not look at CC's output before heading into the weekend. Will take this into account when asking him to "do more"! 🙏

@shanman190
Copy link
Contributor

No worries at all; I figured that I'd just write up some comments to help out. 🙂

- Use field-level = syntax for displayName/description per convention
- Remove explicit removal mode (RemoveRepository already covers that)
- Add validate() to ensure old != new and at least one of newType/newUrl
- Update description and @option docs to not reference removal
- Remove related removal tests; keep dedup removal tests
@Jenson3210 Jenson3210 marked this pull request as ready for review February 23, 2026 08:58
@Jenson3210 Jenson3210 requested a review from timtebeek February 23, 2026 08:58
Verify that credentials, authentication blocks, and other repository
properties (name, allowInsecureProtocol) are preserved when changing
URLs within the same repository type.
@Jenson3210 Jenson3210 marked this pull request as draft February 24, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants