Bazel: Use plugin-scoped Maven repositories for in-tree plugin builds When Bazel module support (Bzlmod) is enabled, in-tree plugins may contribute `maven.install()` tags that are merged by the rules_jvm_external module extension. Plugins have been updated to declare their bundled runtime dependencies in plugin-scoped repositories (for example `oauth_plugin_deps`) that own their lock files. This avoids conflicts when multiple in-tree plugins contribute pinned runtime dependencies: if plugins share the same Maven repository name, rules_jvm_external merges their `maven.install()` tags and rejects multiple `lock_file` declarations for the same repository. Using plugin-scoped Maven repositories allows multiple plugins with independent dependency lock files to coexist in a single in-tree build. Document the required configuration for plugin modules and the workflow for updating Maven and Bzlmod lock files. Gerrit provides the file `plugins/external_plugin_deps.MODULE.bazel` which is included from the root `MODULE.bazel` and can be used to wire plugin Bazel modules into the in-tree build. Release-Notes: skip Change-Id: Ib6566007f6ebbbf328f9a80bf3c2892a9c50a5f4
diff --git a/Documentation/dev-build-plugins.txt b/Documentation/dev-build-plugins.txt index 3b4a259..cddade7 100644 --- a/Documentation/dev-build-plugins.txt +++ b/Documentation/dev-build-plugins.txt
@@ -90,10 +90,12 @@ below. The documentation of the deprecated `external_plugin_deps.bzl` functionality has been moved to a dedicated section below. -If a plugin requires external Java dependencies, they can install those in its -`MODULE.bazel` using rules_jvm_external. The bazel repository for the maven -dependencies has to be plugin specific, e.g. `oauth_plugin_deps`. -Such a `MODULE.bazel`-file might look as follows: +If a plugin requires external Java dependencies, it can install them in its +`MODULE.bazel` using `rules_jvm_external`. The Maven repository containing the +plugin runtime dependencies must be plugin-scoped (for example +`<plugin>_plugin_deps`) and must not use a shared repository name across +plugins when built in-tree with Bzlmod. Such a `MODULE.bazel` file +might look as follows: ---- module(name = "gerrit-oauth-provider") @@ -124,22 +126,16 @@ ], version_conflict_policy = "pinned", ) + use_repo(maven, "oauth_plugin_deps") ---- -After creating the `MODULE.bazel`-file create and update the lock-file for the -plugin: - ----- -cd plugins/oauth -touch oauth_plugin_deps.lock.json -bazelisk run @oauth_plugin_deps//:pin -bazelisk mod deps --lockfile_mode=update ----- - -If the plugin has external dependencies, then they must be included from Gerrit's -own MODULE.bazel file. This can be achieved by loading the plugin's bazel module -in Gerrit's own module (`MODULE.bazel`-file), e.g.: +If the plugin has external dependencies, its Bazel module must be loaded from +Gerrit's own `MODULE.bazel` file and the plugin-scoped Maven repository +imported via `use_repo()`. Gerrit must not define a `maven.install()` for +plugin runtime dependencies, as plugins may contribute their own lock files. +This can be achieved by loading the plugin's Bazel module in Gerrit's own +module (`MODULE.bazel` file), e.g.: ---- bazel_dep(name = "gerrit-plugin-oauth") @@ -151,6 +147,76 @@ use_repo(maven, "oauth_plugin_deps") ---- +After creating the `MODULE.bazel` file, create and update the plugin’s Maven +lock file: + +---- +cd plugins/oauth +touch oauth_plugin_deps.lock.json +bazelisk run @oauth_plugin_deps//:pin +---- + +The generated Maven lock file (for example `oauth_plugin_deps.lock.json`) is owned +by the plugin and must be checked into the plugin repository. + +When the plugin is built in-tree, Gerrit imports the plugin-scoped Maven +repository via `use_repo()`, but does not resolve or repin its +dependencies. The plugin Maven lock file remains owned and maintained by +the plugin in both standalone and in-tree build modes. + +If Bazel module lockfile mode is enabled (for example via +`--lockfile_mode=error`), the Bzlmod module graph lock file +(`MODULE.bazel.lock`) must be updated from the workspace root: + +---- +cd plugins/oauth +bazelisk mod deps --lockfile_mode=update +---- + +==== Wiring plugin modules into the in-tree build + +Plugins that declare external dependencies via `rules_jvm_external` +must expose their Maven repository to Gerrit's root Bazel module when +built in-tree. + +Gerrit provides the file `plugins/external_plugin_deps.MODULE.bazel` +which is included from the root `MODULE.bazel`. Plugin modules can be +wired into the in-tree build by referencing their module and importing +their plugin-scoped Maven repository. + +Example for the `oauth` plugin: + +---- +bazel_dep(name = "gerrit-plugin-oauth") +local_path_override( + module_name = "gerrit-plugin-oauth", + path = "plugins/oauth", +) + +use_repo(maven, "oauth_plugin_deps") +---- + +Plugins may provide their own `external_plugin_deps.MODULE.bazel` +fragment containing these declarations. When building locally, the +fragment can be linked into the Gerrit tree: + +---- +cd gerrit/plugins +rm external_plugin_deps.MODULE.bazel +ln -s oauth/external_plugin_deps.MODULE.bazel external_plugin_deps.MODULE.bazel +---- + +This makes the plugin's Bazel module and its plugin-scoped Maven +repository visible to Gerrit's root module. + +[NOTE] +When multiple plugins are built in-tree, `rules_jvm_external` merges +`maven.install()` tags with the same name across all modules. Plugin runtime +dependencies must therefore be declared in plugin-scoped repositories +(e.g. `<plugin>_plugin_deps`) that own their lock files. Shared repository +names must not define a `lock_file` in more than one module, otherwise the +build will fail during module extension evaluation. + === Bundle custom plugin in release.war === To bundle custom plugin(s) in the link:dev-bazel.html#release[release.war] artifact,
diff --git a/MODULE.bazel b/MODULE.bazel index a0e4b79..2debe0b 100644 --- a/MODULE.bazel +++ b/MODULE.bazel
@@ -41,3 +41,6 @@ # External dependency wiring is split out. include("//tools:java_deps.MODULE.bazel") + +# Wiring for external dependencies contributed by in-tree plugins. +include("//plugins:external_plugin_deps.MODULE.bazel")
diff --git a/plugins/external_plugin_deps.MODULE.bazel b/plugins/external_plugin_deps.MODULE.bazel new file mode 100644 index 0000000..4c07678 --- /dev/null +++ b/plugins/external_plugin_deps.MODULE.bazel
@@ -0,0 +1,4 @@ +# Module fragment used to wire plugin Bazel modules into the Gerrit +# in-tree build. Plugins that declare external dependencies can expose +# their repositories (e.g. repositories created via rules_jvm_external) +# through this file.