Plugin Portal Outage Followup

On June 23rd, 2023, at 9:00 UTC, Gradle users started experiencing issues resolving artifacts from the Gradle Plugin Portal because of changes to artifacts hosted on JCenter by JFrog. JCenter stopped serving files directly and redirected all requests to Maven Central. This was an unannounced change.

We contacted JFrog, and they replied it was a test and they would revert back to having JCenter serve artifacts.

Around 18:30 UTC, JCenter returned to normal behavior.

This post describes the effect this outage had on builds, ways to recover from similar outages, and what we will do to eliminate the dependency on JCenter in the future.

Users still directly using JCenter should also refer to our original blog post about the shutdown of JCenter on Gradle builds in general.

Effects on Gradle plugins usage in builds

When JFrog stopped serving artifacts from JCenter, all requests were redirected to Maven Central. This can impact builds in different ways. In this blog post, we focus on the resolution of Gradle plugins from the Plugin Portal.

Background information

The Plugin Portal only hosts artifacts related to Gradle plugins. The Plugin Portal redirects Gradle builds to JCenter to resolve transitive dependencies required by plugins. Some of these transitive dependencies are hosted by JCenter and some are mirrored from Maven Central.

Additionally, some very old versions of Gradle plugins are also hosted on JCenter. This is because they were historically hosted on JFrog’s Bintray service. Following Bintray’s shutdown in May 2021, we removed the Plugin Portal’s integration with Bintray, but we kept redirecting to JCenter for those artifacts because JFrog committed to keeping JCenter read-only indefinitely.

When changes are made to JCenter, the Plugin Portal may no longer serve some artifacts or serve different artifacts.

Missing artifacts

Any artifacts only available on JCenter become unavailable when JCenter stops serving artifacts.

For example, a library published to JCenter 10 years ago and never published to Maven Central would no longer be available.

As a consequence, Gradle builds may fail when trying to resolve dependencies from the Plugin Portal. This includes:

  1. Builds that rely on very old versions of plugins. Those plugins may have been only hosted on JCenter, and that version of the plugin may no longer be available.
  2. Builds that rely on plugins that transitively depend on other libraries hosted elsewhere. Libraries that were only hosted by JCenter may no longer be available.

Different versions

Any plugin that relies on artifacts that are published to both JCenter and Maven Central may resolve to different versions when using dynamic versions.

For example, a library published to JCenter and later published to Maven Central only has the versions published to Maven Central available.

Gradle builds may not fail to resolve dependencies, but the build may resolve different versions.

Different artifacts

Any plugin that relies on artifacts that are published to both JCenter and Maven Central may behave differently.

For example, a library published to JCenter and later published to Maven Central could have different dependencies, even for the same version. A library may have been built for Java 6 on JCenter and Java 8 on Maven Central. Signed artifacts may be affected and signed by different keys.

Gradle builds may not fail to resolve dependencies, but the behavior of those dependencies may have changed.

Builds using dependency verification should fail with verification failures because of these differences. These failures require manual intervention when the upstream repository is serving different artifacts.

Recovering from broken builds

Gradle does not have control over changes to JCenter. This kind of outage may occur again before we are able to migrate away from JCenter.

There are a few things you can do to recover:

  1. Identify builds that directly use JCenter for build logic and change them to use Maven Central.
  2. Identify build logic dependencies that are being served by JCenter.

If you have dependencies that come from JCenter:

  1. Update to latest plugin version, as it may no longer require JCenter only dependencies.
  2. Remove unused direct dependencies.
  3. Switch to updated coordinates. Some dependencies may have migrated to new coordinates on Maven Central.
  4. Migrate to alternative libraries. Some dependencies may have alternatives that are hosted on Maven Central.
  5. For transitive dependencies, exclude dependencies that are not necessary.

Note that most of the above can also be applied to application dependencies that are JCenter only.

What Gradle is doing

Gradle will be analyzing the most recent version of each plugin and determine which require a transitive dependency that is only available on JCenter. Our goal is to migrate away from JCenter with as little disruption to the community as possible to prevent unexpected changes like this again.

Based on that information, Gradle will publish a follow-up blog post with next steps and reach out to affected plugin authors to see if they can publish a version of their plugin that only requires dependencies hosted on Maven Central.

Plugins that already fail to resolve with a working JCenter, that is, plugins that have dependencies hosted in another repository, will not be part of that analysis.

Feedback

Let us know if you have any questions on our forums or Gradle Community Slack.