Skip to content

Commit

Permalink
Create a Maven BOM (#731)
Browse files Browse the repository at this point in the history
In multi-project Maven repos, it's common to create a
Bill of Materials (BOM) `pom.xml` that shares the common
dependencies the project uses, pinned at specific versions.

The `maven_bom` rule gathers multiple `java_export` targets
into a single unit, and creates the BOM from them. The
dependencies included in the BOM are:

 - Ones that appear as dependencies of two or more of the
  `java_export`s the BOM is being created for.
 - Are not one of the `java_export`s the BOM is being
   created for.
  • Loading branch information
shs96c committed Aug 25, 2022
1 parent 3957fdc commit 8a9bcd9
Show file tree
Hide file tree
Showing 23 changed files with 723 additions and 80 deletions.
4 changes: 4 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ stardoc(
symbol_names = [
"javadoc",
"java_export",
"maven_bom",
"maven_install",
],
deps = ["//:implementation"],
Expand Down Expand Up @@ -50,9 +51,12 @@ bzl_library(
"//private/rules:jetifier.bzl",
"//private/rules:jetifier_maven_map.bzl",
"//private/rules:jvm_import.bzl",
"//private/rules:maven_bom.bzl",
"//private/rules:maven_bom_fragment.bzl",
"//private/rules:maven_install.bzl",
"//private/rules:maven_project_jar.bzl",
"//private/rules:maven_publish.bzl",
"//private/rules:maven_utils.bzl",
"//private/rules:pom_file.bzl",
"//settings:stamp_manifest.bzl",
],
Expand Down
2 changes: 2 additions & 0 deletions defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ load("//private/rules:artifact.bzl", _artifact = "artifact", _maven_artifact = "
load("//private/rules:has_maven_deps.bzl", _read_coordinates = "read_coordinates")
load("//private/rules:java_export.bzl", _java_export = "java_export")
load("//private/rules:javadoc.bzl", _javadoc = "javadoc")
load("//private/rules:maven_bom.bzl", _maven_bom = "maven_bom")
load("//private/rules:maven_install.bzl", _maven_install = "maven_install")
load("//private/rules:maven_publish.bzl", _MavenPublishInfo = "MavenPublishInfo")
load("//private/rules:pom_file.bzl", _pom_file = "pom_file")
Expand All @@ -27,6 +28,7 @@ artifact = _artifact
java_export = _java_export
javadoc = _javadoc
maven_artifact = _maven_artifact
maven_bom = _maven_bom
maven_install = _maven_install
pom_file = _pom_file
read_coordinates = _read_coordinates
Expand Down
52 changes: 50 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [Basic functions](#basic-functions)
- [javadoc](#javadoc)
- [java_export](#java_export)
- [maven_bom](#maven_bom)
- [maven_install](#maven_install)
- [Maven specification functions](#maven-specification-functions)
- [maven.repository](#mavenrepository)
Expand Down Expand Up @@ -49,7 +50,7 @@ Generate a javadoc from all the `deps`
## java_export

<pre>
java_export(<a href="#java_export-name">name</a>, <a href="#java_export-maven_coordinates">maven_coordinates</a>, <a href="#java_export-deploy_env">deploy_env</a>, <a href="#java_export-pom_template">pom_template</a>, <a href="#java_export-visibility">visibility</a>, <a href="#java_export-tags">tags</a>, <a href="#java_export-kwargs">kwargs</a>)
java_export(<a href="#java_export-name">name</a>, <a href="#java_export-maven_coordinates">maven_coordinates</a>, <a href="#java_export-deploy_env">deploy_env</a>, <a href="#java_export-pom_template">pom_template</a>, <a href="#java_export-visibility">visibility</a>, <a href="#java_export-tags">tags</a>, <a href="#java_export-testonly">testonly</a>, <a href="#java_export-kwargs">kwargs</a>)
</pre>

Extends `java_library` to allow maven artifacts to be uploaded.
Expand All @@ -73,7 +74,8 @@ the template file:
* `{artifactId}`: Replaced with the maven coordinates artifact ID.
* `{version}`: Replaced by the maven coordinates version.
* `{type}`: Replaced by the maven coordinates type, if present (defaults to "jar")
* `{scope}`: Replaced by the maven coordinates scope, if present (defaults to "compile")
* `{scope}`: Replaced by the maven coordinates type, if present (defaults to "compile")
* `{parent}`: Replaced by a `<groupId>`, `<artifactId>`, and `<version>` set of tags.
* `{dependencies}`: Replaced by a list of maven dependencies directly relied upon
by java_library targets within the artifact.

Expand Down Expand Up @@ -105,9 +107,55 @@ Generated rules:
| pom_template | The template to be used for the pom.xml file. | <code>None</code> |
| visibility | The visibility of the target | <code>None</code> |
| tags | <p align="center"> - </p> | <code>[]</code> |
| testonly | <p align="center"> - </p> | <code>None</code> |
| kwargs | These are passed to [<code>java_library</code>](https://docs.bazel.build/versions/master/be/java.html#java_library), and so may contain any valid parameter for that rule. | none |


<a name="#maven_bom"></a>

## maven_bom

<pre>
maven_bom(<a href="#maven_bom-name">name</a>, <a href="#maven_bom-maven_coordinates">maven_coordinates</a>, <a href="#maven_bom-java_exports">java_exports</a>, <a href="#maven_bom-tags">tags</a>, <a href="#maven_bom-testonly">testonly</a>, <a href="#maven_bom-visibility">visibility</a>)
</pre>

Generates a Maven BOM `pom.xml` file.

The generated BOM will contain maven dependencies that are shared between two
or more of the `java_exports`. This will also generate `pom.xml` files for
each of the `java_exports`. Within those `pom.xml`s, only dependencies that are
unique to the `java_export` will have the `version` tag. Dependencies which are
listed in the BOM will omit the `version` tag.

The maven repository may accessed locally using a `file://` URL, or
remotely using an `https://` URL. The following flags may be set
using `--define`:

gpg_sign: Whether to sign artifacts using GPG
maven_repo: A URL for the repo to use. May be "https" or "file".
maven_user: The user name to use when uploading to the maven repository.
maven_password: The password to use when uploading to the maven repository.

When signing with GPG, the current default key is used.

Args:
name: A unique name for this rule.
maven_coordinates: The maven coordinates of this BOM in `groupId:artifactId:version` form.
java_exports: A list of `java_export` targets that are used to generate the BOM.

**PARAMETERS**


| Name | Description | Default Value |
| :-------------: | :-------------: | :-------------: |
| name | <p align="center"> - </p> | none |
| maven_coordinates | <p align="center"> - </p> | none |
| java_exports | <p align="center"> - </p> | none |
| tags | <p align="center"> - </p> | <code>None</code> |
| testonly | <p align="center"> - </p> | <code>None</code> |
| visibility | <p align="center"> - </p> | <code>None</code> |


<a name="#maven_install"></a>

## maven_install
Expand Down
11 changes: 10 additions & 1 deletion examples/java-export/BUILD
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
load("@rules_jvm_external//:defs.bzl", "java_export")
load("@rules_jvm_external//:defs.bzl", "java_export", "maven_bom")

# To export the file, run:
#
Expand All @@ -14,3 +14,12 @@ java_export(
"//src/main/java/com/github/bazelbuild/rulesjvmexternal/example/export",
],
)

maven_bom(
name = "bom",
java_exports = [
":example-export",
"//src/main/java/com/github/bazelbuild/rulesjvmexternal/example/io",
],
maven_coordinates = "com.example:bazel-example-bom:0.0.1",
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ load("@rules_jvm_external//:defs.bzl", "artifact")

java_library(
name = "export",
srcs = glob(["Main.java"]),
srcs = glob(["*.java"]),
visibility = [
"//:__pkg__",
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("@rules_jvm_external//:defs.bzl", "artifact", "java_export")

java_export(
name = "io",
srcs = glob(["*.java"]),
maven_coordinates = "com.example:bazel-io:0.0.1",
visibility = [
"//:__pkg__",
],
deps = [
artifact("com.google.guava:guava"),
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.github.bazelbuild.rulesjvmexternal.example.io;

import com.google.common.collect.ImmutableList;

import java.util.List;


public class Printer {

public void showGreeting(String personToGreet) {
// We take a dep on guava so that we can show off BOM generation.
// No-one sensible would write this code normally.
List<String> messages = ImmutableList.of("Hello, ", personToGreet, "!");

for (String item : messages) {
System.out.print(item);
}
System.out.print("\n");
}

}
3 changes: 3 additions & 0 deletions private/rules/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ exports_files([
"jetifier_maven_map.bzl",
"jvm_import.bzl",
"kt_jvm_export.bzl",
"maven_bom.bzl",
"maven_bom_fragment.bzl",
"maven_install.bzl",
"maven_project_jar.bzl",
"maven_publish.bzl",
"maven_utils.bzl",
"pom_file.bzl",
])
27 changes: 21 additions & 6 deletions private/rules/java_export.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
load("//private/rules:javadoc.bzl", "javadoc")
load("//private/rules:maven_project_jar.bzl", "maven_project_jar")
load("//private/rules:maven_publish.bzl", "maven_publish")
load("//private/rules:pom_file.bzl", "pom_file")
load(":javadoc.bzl", "javadoc")
load(":maven_bom_fragment.bzl", "maven_bom_fragment")
load(":maven_project_jar.bzl", "maven_project_jar")
load(":maven_publish.bzl", "maven_publish")
load(":pom_file.bzl", "pom_file")

def java_export(
name,
Expand Down Expand Up @@ -34,6 +35,7 @@ def java_export(
* `{version}`: Replaced by the maven coordinates version.
* `{type}`: Replaced by the maven coordinates type, if present (defaults to "jar")
* `{scope}`: Replaced by the maven coordinates type, if present (defaults to "compile")
* `{parent}`: Replaced by a `<groupId>`, `<artifactId>`, and `<version>` set of tags.
* `{dependencies}`: Replaced by a list of maven dependencies directly relied upon
by java_library targets within the artifact.
Expand Down Expand Up @@ -87,7 +89,7 @@ def java_export(
tags,
testonly,
lib_name,
javadocopts
javadocopts,
)

def maven_export(
Expand All @@ -101,7 +103,6 @@ def maven_export(
testonly,
lib_name,
javadocopts):

"""Helper rule to reuse this code for both java_export and kt_jvm_export.
After a library has already been created (either a kt_jvm_library or
Expand Down Expand Up @@ -181,6 +182,20 @@ def maven_export(
testonly = testonly,
)

# We may want to aggregate several `java_export` targets into a single Maven BOM POM
# https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#bill-of-materials-bom-poms
maven_bom_fragment(
name = "%s.bom-fragment" % name,
maven_coordinates = maven_coordinates,
artifact = ":%s" % lib_name,
src_artifact = "%s-maven-source" % name,
javadoc_artifact = None if "no-javadocs" in tags else "%s-docs" % name,
pom_template = pom_template,
testonly = testonly,
tags = tags,
visibility = visibility,
)

# Finally, alias the primary output
native.alias(
name = name,
Expand Down
Loading

0 comments on commit 8a9bcd9

Please sign in to comment.