Skip to content

feat(ENG-15139): set up the Cloudsmith Maven tools for Maven, Gradle, and sbt - #520

Open
cloudsmith-iduffy wants to merge 32 commits into
masterfrom
iduffy/credential-helper-jvm
Open

cloudsmith-iduffy wants to merge 32 commits into
masterfrom
iduffy/credential-helper-jvm

Conversation

@cloudsmith-iduffy

@cloudsmith-iduffy cloudsmith-iduffy commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Description

The Cloudsmith Maven tools let Maven, Gradle, and sbt builds authenticate to Cloudsmith with no credentials in settings.xml, gradle.properties, or build.sbt. The tools are a Maven extension, a Gradle plugin, and an sbt plugin. Each one gets its credential from the generic credential helper, cloudsmith credential-helper generic, and sends it only to Cloudsmith hosts.

This PR adds three commands that set up the tools:

cloudsmith credential-helper install maven
cloudsmith credential-helper install gradle
cloudsmith credential-helper install sbt

By default, each command sets up every build of the user. Each command installs the newest release from the public cloudsmith/maven-tools repository and writes that exact version.

Command Changes Applies to
install maven Puts the extension JAR and POM in ~/.m2/repository, and adds the extension to ~/.m2/extensions.xml Every build with Maven 3.10 or later
install maven --local Puts the extension in ~/.m2/repository, and adds the extension to .mvn/extensions.xml The Maven project in the current directory, with Maven 3.8 or later
install maven --mavenrc Puts the extension in ~/.m2/repository, and adds a block to ~/.mavenrc that sets maven.ext.class.path Every build that starts with the mvn or mvnw script, with any Maven version
install gradle Writes ~/.gradle/init.d/cloudsmith.init.gradle.kts (or $GRADLE_USER_HOME/init.d) Every Gradle build
install sbt Writes ~/.sbt/1.0/plugins/cloudsmith.sbt Every sbt 1 build
install sbt --local Writes project/cloudsmith.sbt The sbt project in the current directory

The commands add to existing files. Other extensions in extensions.xml and other lines in ~/.mavenrc stay as they are. uninstall removes only what install added. --dry-run and list work for all three tools.

Prerequisites

  • Java 17 or later, and Maven, Gradle, or sbt.

  • A private Cloudsmith Maven repository with Maven Central as an upstream. The examples use WORKSPACE and REPOSITORY as placeholders for its workspace and repository names.

  • The CLI from this branch, signed in. The plugins also run this CLI to get the credential.

    gh pr checkout 520
    uv sync
    source .venv/bin/activate
    cloudsmith whoami

Example: Maven

Step 1: Install the extension

cloudsmith credential-helper install maven

The command downloads the extension and adds it to ~/.m2/extensions.xml:

downloaded cloudsmith-maven-extension-0.1.0.jar to /Users/me/.m2/repository/io/cloudsmith/cloudsmith-maven-extension/0.1.0
downloaded cloudsmith-maven-extension-0.1.0.pom to /Users/me/.m2/repository/io/cloudsmith/cloudsmith-maven-extension/0.1.0
added version 0.1.0 to /Users/me/.m2/extensions.xml

Note: Maven 3.9 and earlier ignore ~/.m2/extensions.xml. When mvn -v reports one of these versions, the command shows a warning. Use --local or --mavenrc instead. See Use Maven 3.9 or earlier.

Step 2: Make a project

Make a directory with this pom.xml. The POM has no credentials, and settings.xml needs no <server> entry.

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>maven-demo</artifactId>
  <version>1.0.0</version>

  <repositories>
    <repository>
      <id>cloudsmith</id>
      <url>https://dl.cloudsmith.io/basic/WORKSPACE/REPOSITORY/maven/</url>
    </repository>
  </repositories>

  <dependencies>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.17.0</version>
    </dependency>
  </dependencies>
</project>

Step 3: Resolve the dependency through Cloudsmith

mvn -X dependency:resolve | grep -E "Using the cloudsmith CLI credential|Downloaded from cloudsmith.*commons-lang3-3.17.0.jar|BUILD"

The extension adds the credential for the Cloudsmith repository, and Maven downloads Commons Lang through it:

[DEBUG] Using the cloudsmith CLI credential for https://dl.cloudsmith.io/basic/WORKSPACE/REPOSITORY/maven/
Downloaded from cloudsmith: https://dl.cloudsmith.io/basic/WORKSPACE/REPOSITORY/maven/org/apache/commons/commons-lang3/3.17.0/commons-lang3-3.17.0.jar (674 kB at 6.9 MB/s)
[INFO] BUILD SUCCESS

Note: Maven downloads only the files that are not in ~/.m2/repository. If the Downloaded from cloudsmith line does not appear, delete ~/.m2/repository/org/apache/commons/commons-lang3/3.17.0 and run the command again.

Use Maven 3.9 or earlier

Choose one of these options:

  • One project: Run the command in the root directory of the project. The command adds the extension to .mvn/extensions.xml. Commit this file so that the whole team gets the extension. Each machine that builds the project, including CI, must also run the command to get the JAR into its local repository.

    cloudsmith credential-helper install maven --local
  • Every build: The command adds this block to ~/.mavenrc, after the lines that are already there. The mvn and mvnw scripts read the file. Maven that runs inside an IDE does not read it.

    cloudsmith credential-helper install maven --mavenrc
    # >>> cloudsmith credential-helper install maven >>>
    MAVEN_OPTS="$MAVEN_OPTS -Dmaven.ext.class.path=/Users/me/.m2/repository/io/cloudsmith/cloudsmith-maven-extension/0.1.0/cloudsmith-maven-extension-0.1.0.jar"
    # <<< cloudsmith credential-helper install maven <<<

Example: Gradle

Step 1: Install the plugin

cloudsmith credential-helper install gradle
wrote /Users/me/.gradle/init.d/cloudsmith.init.gradle.kts for version 0.1.0

The init script applies the plugin to the settings of every Gradle build. The build files need no change.

Step 2: Make a project

settings.gradle.kts:

rootProject.name = "gradle-demo"

dependencyResolutionManagement {
    repositories {
        maven { url = uri("https://dl.cloudsmith.io/basic/WORKSPACE/REPOSITORY/maven/") }
    }
}

build.gradle.kts:

plugins {
    java
}

dependencies {
    implementation("org.apache.commons:commons-lang3:3.17.0")
}

Step 3: Resolve the dependency through Cloudsmith

gradle dependencies --configuration compileClasspath --info | grep -E "cloudsmith CLI credential|commons-lang3:|BUILD"
Using the cloudsmith CLI credential for https://dl.cloudsmith.io/basic/WORKSPACE/REPOSITORY/maven/
\--- org.apache.commons:commons-lang3:3.17.0
BUILD SUCCESSFUL in 9s

Note: Gradle has no init scripts for one build, so install gradle has no --local option. To set up one build, apply the io.cloudsmith.gradle-plugin plugin in settings.gradle.kts.

Example: sbt

Step 1: Install the plugin

cloudsmith credential-helper install sbt
wrote /Users/me/.sbt/1.0/plugins/cloudsmith.sbt for version 0.1.0

To set up only the project in the current directory, use --local. The command writes project/cloudsmith.sbt, and the other files of the build stay as they are.

Step 2: Make a project

project/build.properties:

sbt.version=1.13.0

build.sbt:

resolvers += "cloudsmith" at "https://dl.cloudsmith.io/basic/WORKSPACE/REPOSITORY/maven/"
libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.17.0"

Step 3: Resolve the dependency and check the credential

sbt -batch update "show csrConfiguration" | grep -oE "DirectCredentials\([^)]*\)|\[success\]"

The plugin adds a credential for the Cloudsmith host. sbt does not show the token.

[success]
DirectCredentials(host=dl.cloudsmith.io, username=token)
[success]

Remove the setup

cloudsmith credential-helper uninstall maven           # ~/.m2/extensions.xml and ~/.mavenrc
cloudsmith credential-helper uninstall maven --local   # .mvn/extensions.xml of the current project
cloudsmith credential-helper uninstall gradle
cloudsmith credential-helper uninstall sbt
cloudsmith credential-helper uninstall sbt --local

uninstall deletes a file only when nothing else is left in it. It keeps the JAR in ~/.m2/repository, because other projects can use it.

Troubleshooting

The build fails with 401 Unauthorized

The build did not get a credential. Run cloudsmith whoami to confirm that the CLI is signed in. Then run cloudsmith domains list to confirm that the repository host is in the list.

The credential line does not appear

A credential in the build takes precedence. Remove a <server> entry with the same id from ~/.m2/settings.xml, credentials from the Gradle repository, or an entry for the host from the sbt credentials.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Refactoring
  • Other (please describe)

Additional Notes

Implementation

  • credential_helpers/maven/: the Maven installer, the extensions.xml edits, and the ~/.mavenrc block. The edits change the text in place, so other content and formatting stay. The extensions.xml edits ignore XML comments.
  • credential_helpers/gradle/ and credential_helpers/sbt/: small subclasses of ConfigFileInstaller in credential_helpers/maven_tools.py, which also gets the newest version and downloads files.
  • manage.py: registers the three installers and adds --local (Maven and sbt) and --mavenrc (Maven). Each option is a HelperOption, a click.Option that names the helpers that accept it. For another helper, Click shows a usage error before the installer runs. Click also rejects --local together with --mavenrc.
  • install maven marks the extension files as installed in _remote.repositories. Maven does not load a build extension that this file records as downloaded from a repository. Without the mark, a copy that Maven downloaded earlier stopped every Maven build in the project.

Tests

  • Unit tests in cloudsmith_cli/cli/tests/test_credential_helper_maven_tools.py. The full unit suite and pre-commit pass.
  • End to end in CI: the maven-tools workflow installs this branch and signs in with GitHub OIDC through cloudsmith-cli-action@v3. Each of six jobs runs credential-helper install, downloads a package from a private repository, publishes a new version to it, and runs credential-helper uninstall. The jobs cover maven (Maven 3.10), maven --mavenrc and maven --local (Maven 3.9), gradle, sbt, and sbt --local.
  • I ran the examples above against a private repository with Maven 3.10.0, Gradle 9.8.1, and sbt 1.13.0, in a separate home directory. The outputs above come from these runs. I also checked these cases:
    • --mavenrc with Maven 3.10.0: Maven loaded the extension from maven.ext.class.path, and uninstall restored the original ~/.mavenrc.
    • install sbt --local: sbt added the credential with no global plugin.
    • A JAR that Maven recorded as downloaded from a repository: after install maven, Maven loaded the extension offline.

Open questions

  • install maven always uses ~/.m2/repository. It ignores <localRepository> in settings.xml and -Dmaven.repo.local.
  • --mavenrc writes a POSIX shell block. It does not write %USERPROFILE%\mavenrc_pre.cmd for Windows, and a home directory path with spaces breaks the MAVEN_OPTS line.
  • sbt 2 is not covered. Its global plugin directory moved to $XDG_CONFIG_HOME/sbt/2/plugins on sbt's development branch, and I did not confirm which release uses it.
  • list shows the config file in the launcher field, because these tools have no launcher.
  • --bin-dir and --domain have no effect for these tools.

🤖 Generated with Claude Code

…, and sbt

`credential-helper install maven|gradle|sbt` sets up the Maven extension
and the Gradle and sbt plugins, which get repository credentials from
`cloudsmith credential-helper generic`. Each install takes the newest
release from the public cloudsmith/maven-tools repository.

- maven: puts the extension in ~/.m2/repository and adds it to
  .mvn/extensions.xml of the project in the current directory. Maven 3.9
  has no user-wide extensions, and loads a build extension only from
  Maven Central or the local repository.
- gradle: writes an init script to ~/.gradle/init.d that applies the
  plugin to every build.
- sbt: writes a global plugin to ~/.sbt/1.0/plugins for every sbt 1
  build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 22, 2026 16:46
`install maven` found the Cloudsmith extension inside an XML comment and
changed the version there. The file then had no active entry, but the
command reported success. A groupId or artifactId with spaces inside the
tag was not found, so the command added a second entry.

The search now replaces comments with spaces before it looks for the
extension, its <version>, and the <extensions> element. The offsets do not
change, so the edit still keeps the rest of the file as it is. The
groupId and artifactId match with spaces around the value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟡 Changes recommended

Maven XML handling can delete unrelated configuration or falsely report installation, and downloads bypass the command’s selected TLS settings.

3 open issues
What changed in this PR

Adds installation support for Cloudsmith’s Maven, Gradle, and sbt tools, which obtain repository credentials through the existing generic credential helper.

Changes:

  • Adds project-level Maven extension installation and global Gradle/sbt plugin configuration.
  • Resolves and pins release versions, with uninstall, status, and dry-run support.
  • Registers the installers and adds unit tests and changelog documentation.
File Description
cloudsmith_cli/​credential_helpers/​sbt/​installer.py Configures the global sbt 1 plugin.
cloudsmith_cli/​credential_helpers/​sbt/​__init__.py Introduces the sbt installer package.
cloudsmith_cli/​credential_helpers/​maven/​installer.py Downloads Maven artifacts and manages project configuration.
cloudsmith_cli/​credential_helpers/​maven/​extensions.py Adds and removes Maven extension entries.
cloudsmith_cli/​credential_helpers/​maven/​__init__.py Introduces the Maven installer package.
cloudsmith_cli/​credential_helpers/​maven_tools.py Shares release lookup, downloads, and config-file operations.
cloudsmith_cli/​credential_helpers/​gradle/​installer.py Generates the global Gradle initialization script.
cloudsmith_cli/​credential_helpers/​gradle/​__init__.py Introduces the Gradle installer package.
cloudsmith_cli/​cli/​tests/​test_credential_helper_maven_tools.py Tests installers, XML editing, downloads, and CLI wiring.
cloudsmith_cli/​cli/​commands/​credential_helper/​manage.py Registers installers and handles Maven installation errors.
CHANGELOG.md Documents the three new installation targets.

Review effort: Balanced

… and --mavenrc

`install maven`, `install gradle`, and `install sbt` now set up every build
of the user by default.

- maven: lists the extension in ~/.m2/extensions.xml, which Maven 3.10 and
  later read. When `mvn -v` reports an earlier Maven, install shows a
  warning that names the two options below.
- maven --local: lists the extension in .mvn/extensions.xml of the project,
  as before.
- maven --mavenrc: adds a marked block to ~/.mavenrc that sets
  maven.ext.class.path. The mvn and mvnw scripts of every Maven version read
  it. The other lines of the file stay, and uninstall removes only the block.
- sbt --local: writes project/cloudsmith.sbt, so the build's own files stay
  as they are.
- gradle --local: fails with the settings.gradle.kts plugin block to add.
- Other helpers reject --local and --mavenrc with a usage error.

Install also marks the extension files as installed in
_remote.repositories. Maven does not load a build extension that it
records as downloaded from a repository, so a copy that Maven downloaded
earlier stopped every build in the project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudsmith-iduffy cloudsmith-iduffy changed the title feat(no-ticket): install the Cloudsmith Maven tools for Maven, Gradle, and sbt feat(no-ticket): set up the Cloudsmith Maven tools for Maven, Gradle, and sbt Oct 22, 2026
cloudsmith-iduffy added a commit to cloudsmith-iduffy/cloudsmith-cli-oidc-test that referenced this pull request Oct 22, 2026
Adds worked examples of the Maven extension and the Gradle and sbt
plugins, set up by `cloudsmith credential-helper install` from
cloudsmith-io/cloudsmith-cli#520. Each example downloads from and
publishes to iduffy-demo/default through GitHub OIDC, and fails unless
the build used the CLI credential for both URLs.

The examples cover every build of the user (global) and one project
(local): Maven through ~/.m2/extensions.xml, ~/.mavenrc, and
.mvn/extensions.xml; Gradle through an init script and the settings
plugin block; and sbt through a global plugin and project/cloudsmith.sbt.

mise installs Java, Maven, Gradle, sbt, and uv, and runs each example as
a task.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cloudsmith-iduffy and others added 3 commits October 22, 2026 19:14
… settings

Addresses the review of #520.

- Uninstall deleted .mvn/extensions.xml when the other extensions had
  spaces before the > of a tag, such as `<extension >`. The block pattern
  now allows these spaces. Before uninstall deletes the file, it parses
  what is left, and keeps the file if an <extension> element remains or
  if the rest is not valid XML.
- The downloads of the Maven tools used a default session, so
  --proxy, --without-ssl-verify, and --without-ssl-verify-strict did not
  apply to them. `install` now passes a session with these settings to
  the installers that download files. The session does not get the
  --api-headers, because the public repository is not the API host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
--local and --mavenrc now name the helpers that accept them. The install
and uninstall commands show a usage error for another helper before the
installer runs. Click also rejects --local together with --mavenrc.

`install gradle --local` is now a usage error. It no longer gets the
latest version only to show a settings.gradle.kts block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudsmith-bot
cloudsmith-bot marked this pull request as ready for review October 28, 2026 13:39
@cloudsmith-bot
cloudsmith-bot requested a review from a team as a code owner October 28, 2026 13:39
@cloudsmith-iduffy

Copy link
Copy Markdown
Collaborator Author

@copilot resolve the merge conflicts in this pull request

…elper-jvm

# Conflicts:
#	cloudsmith_cli/cli/commands/credential_helper/manage.py

Co-authored-by: cloudsmith-iduffy <178375997+cloudsmith-iduffy@users.noreply.github.com>

Copilot AI commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved in 383554c by merging the latest master. Kept helper-option forwarding and both uninstall error handlers. All 1,979 non-integration tests and pre-commit checks for the resolved file passed.

* origin/master:
  fix(ENG-15484): accept --color on click versions before 8.2 (#582)
@cloudsmith-iduffy cloudsmith-iduffy changed the title feat(no-ticket): set up the Cloudsmith Maven tools for Maven, Gradle, and sbt feat(ENG-15139): set up the Cloudsmith Maven tools for Maven, Gradle, and sbt Nov 3, 2026
@cloudsmith-iduffy
cloudsmith-iduffy requested a balanced review from Copilot November 3, 2026 10:30

Copilot AI 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.

🟡 Changes recommended

Installation and removal can destroy unrelated Gradle/sbt configuration, while Maven setup overrides existing extension paths and silently disables other extensions.

3 open issues
3 resolved since last review

Review effort: Balanced

cloudsmith-iduffy and others added 3 commits November 3, 2026 10:43
The JVM uses only the last -Dmaven.ext.class.path value. The ~/.mavenrc
block now adds the JAR to that value instead of a second option.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Install and uninstall now stop with an error when the config file has
content other than the file that install writes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Status now also checks project/cloudsmith.sbt, so list reports an
install that used --local.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟡 Changes recommended

The duplicate check can leave the Cloudsmith extension unloaded when classpath properties are overridden, while whitespace handling in valid XML can cause installation failures or duplicate entries.

1 open issue
2 previously missed issues

In code that hasn't changed since last review

Medium severity Allow whitespace before XML child-element tag closers

cloudsmith_cli/​credential_helpers/​maven/​extensions.py:23

An existing Cloudsmith entry with valid XML such as <version >0.1.0</version > causes installation to report that the version is missing. Spaced groupId or artifactId tags instead hide the entry from install, uninstall, and status, so installation adds a duplicate. Allow whitespace before > on both opening and closing child-element tags.

Medium severity Allow whitespace before the closing extensions tag

cloudsmith_cli/​credential_helpers/​maven/​extensions.py:92

A valid existing file ending in </extensions > or with a newline before > fails installation here with "The file has no element." XML permits that whitespace, but the literal search cannot find the insertion point. Match the closing root tag with optional whitespace and use its start offset for insertion.

3 resolved since last review

Review effort: Balanced

Copilot AI 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.

🔵 Needs a closer look

Human assessment is needed because valid namespace-prefixed Maven extension files can be rejected, causing installation to fail.

No open issues 🎉

Review effort: Balanced

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🔵 Needs a closer look

Human assessment is needed because requiring build.sbt can reject valid sbt projects and prevent listing or uninstalling local installations after the build file is renamed.

No open issues 🎉

Review effort: Balanced

sbt reads any .sbt file in the root and the project/ directory. Maven finds
the project root by its .mvn directory, whatever the POM is called.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🔵 Needs a closer look

Human assessment is needed because Maven option parsing can add the Cloudsmith JAR to a nested argLine value rather than the extension class path, leaving the extension unloaded.

No open issues 🎉

Review effort: Balanced

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟡 Changes recommended

MAVEN_OPTS arguments separated by tabs or newlines can cause a duplicate extension-path property that overrides the user's existing extensions, requiring whitespace-aware parsing and regression coverage.

1 open issue

Review effort: Balanced

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🔵 Needs a closer look

Human assessment is needed because uninstall can delete comments and commented-out third-party extensions from extensions.xml, and the current test expects that content loss.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

…extension

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🔵 Needs a closer look

Human assessment is needed because switching installation modes can leave both Maven activations in place, potentially loading different versions on Maven 3.10+.

No open issues 🎉

Review effort: Balanced

Maven 3.10 reads both ~/.m2/extensions.xml and ~/.mavenrc, so only one of
them loads the extension.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🔵 Needs a closer look

Human assessment is needed because an unpublished compatibility finding indicates that local installation rejects some valid sbt project layouts.

No open issues 🎉

Review effort: Balanced

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟢 Approval recommended

The review identifies no active issues in the Maven, Gradle, and sbt credential-helper changes.

No open issues 🎉

Review effort: Balanced

This branch has not been deployed

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants