From build process perspective there are three types of plugins:
-
Maven driven
-
Bazel tree driven
-
Bazel standalone
These types can be combined: if both files in plugin’s root directory exist:
-
BUILD -
pom.xml
the plugin can be built with both Bazel and Maven.
Maven driven build
If plugin contains pom.xml file, it can be built with Maven as usually:
mvn clean package
Exceptions from the rule above:
Exception 1:
Plugin’s pom.xml references snapshot version of plugin API:
2.8-SNAPSHOT. In this case there are two possibilities:
-
switch to release API. Change plugin API version in
pom.xmlfrom2.8-SNAPSHOTto2.8.1and repeat step 1 above. -
build and install
SNAPSHOTversion of plugin API in local Maven repository:
./tools/maven/api.sh install
Exception 2:
Plugin’s pom.xml references other own or foreign (unpublished) libraries or
even other Gerrit plugins. These libraries and/or plugins must be built and
installed in local Maven repository. Clone the related projects and issue
mvn install
Repeat step 1. above.
Bazel in tree driven
The fact that plugin contains BUILD file doesn’t mean that building this
plugin from the plugin directory works.
Bazel in tree driven means it can only be built from within Gerrit tree. Clone or link the plugin into gerrit/plugins directory:
cd gerrit bazel build plugins/<plugin-name>:<plugin-name>
The output can be normally found in the following directory:
bazel-bin/plugins/<plugin-name>/<plugin-name>.jar
Some plugins describe their build process in src/main/resources/Documentation/build.md
file. It may worth checking.
Error Prone checks
Error Prone checks are enabled by default for core Gerrit and all core plugins. To
enable the checks for custom plugins, add it in the error_prone_packages group
in tools/BUILD.
Plugins with external dependencies
|
Note
|
As of Gerrit 3.14 using the external_plugin_deps.bzl file for adding external
dependencies of plugins to the build has been deprecated. This feature will be
removed with Gerrit 3.15. Please migrate to using Bazel modules as described
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, 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")
bazel_dep(name = "rules_jvm_external", version = "6.10")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
name = "oauth_plugin_deps",
artifacts = [
"com.fasterxml.jackson.core:jackson-databind:2.10.2",
"com.github.scribejava:scribejava-apis:6.9.0",
"com.sap.cloud.security:java-security:3.6.0",
],
duplicate_version_warning = "error",
excluded_artifacts = [
"commons-io:commons-io",
"com.github.ben-manes.caffeine:caffeine",
"org.slf4j:slf4j-api",
],
fail_if_repin_required = True,
fail_on_missing_checksum = True,
fetch_sources = True,
lock_file = "//:oauth_plugin_deps.lock.json",
repositories = [
"https://repo1.maven.org/maven2",
],
version_conflict_policy = "pinned",
)
use_repo(maven, "oauth_plugin_deps")
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")
local_path_override(
module_name = "gerrit-plugin-oauth",
path = "plugins/oauth",
)
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 release.war artifact,
add them to the CUSTOM_PLUGINS list in tools/bzl/plugins.bzl.
Example of tools/bzl/plugins.bzl with custom plugin my-plugin:
CORE_PLUGINS = [
"commit-message-length-validator",
"download-commands",
"hooks",
"replication",
"reviewnotes",
"singleusergroup",
]
CUSTOM_PLUGINS = [
"my-plugin",
]
CUSTOM_PLUGINS_TEST_DEPS = [
# Add custom core plugins with tests deps here
]
|
Note
|
Since tools/bzl/plugins.bzl is part of Gerrit’s source code and the version of
the war is based on the state of the git repository that is built; you should
commit this change before building, otherwise the version will be marked as
'dirty'.
|
Bazel standalone driven
Only few plugins support that mode for now:
cd reviewers bazel build reviewers
Managing external dependencies using external_plugin_deps.bzl
|
Note
|
This functionality has been deprecated. |
If the plugin has external dependencies, then they can be included from Gerrit’s
own WORKSPACE file. This can be achieved by including them in external_plugin_deps.bzl.
During the build in Gerrit tree, this file must be copied over the dummy one in
plugins directory.
Example for content of external_plugin_deps.bzl file:
load("//tools/bzl:maven_jar.bzl", "maven_jar")
def external_plugin_deps():
maven_jar(
name = 'org_apache_tika_tika_core',
artifact = 'org.apache.tika:tika-core:1.12',
sha1 = '5ab95580d22fe1dee79cffbcd98bb509a32da09b',
)
If the plugin(s) being bundled in the release have external dependencies, include them
in plugins/external_plugin_deps. Create symbolic link from plugin’s own
external_plugin_deps() file in plugins directory and prefix the file with
plugin name, e.g.:
$ cd plugins $ ln -s oauth/external_plugin_deps.bzl oauth_external_plugin_deps.bzl $ ln -s uploadvalidator/external_plugin_deps.bzl uploadvalidator_external_plugin_deps.bzl
Now the plugin specific dependency files can be imported:
load(":oauth_external_plugin_deps.bzl", oauth_deps="external_plugin_deps")
load(":uploadvalidator_external_plugin_deps.bzl", uploadvalidator_deps="external_plugin_deps")
def external_plugin_deps():
oauth_deps()
uploadvalidator_deps()
Part of Gerrit Code Review