| = Gerrit Code Review - Building plugins | |
| 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.xml` from | |
| `2.8-SNAPSHOT` to `2.8.1` and repeat step 1 above. | |
| * build and install `SNAPSHOT` version 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 === | |
| 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. | |
| To support multiple plugins, include their `external_plugin_deps.MODULE.bazel` | |
| files. | |
| For example, to import external dependencies for the `oauth` and `javamelody` | |
| plugins, add the following lines to `plugins/external_plugin_deps.MODULE.bazel`: | |
| ---- | |
| include("//plugins/javamelody:external_plugin_deps.MODULE.bazel") | |
| include("//plugins/oauth:external_plugin_deps.MODULE.bazel") | |
| ---- | |
| [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, | |
| 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 | |
| ---- | |
| GERRIT | |
| ------ | |
| Part of link:index.html[Gerrit Code Review] | |
| SEARCHBOX | |
| --------- |