| = 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 === |
| |
| [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. |
| |
| 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 |
| ---- |
| |
| == 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() |
| ---- |
| |
| GERRIT |
| ------ |
| Part of link:index.html[Gerrit Code Review] |
| |
| SEARCHBOX |
| --------- |