blob: 3a9af789460e29fbb687cdf118f01689e0ead4ba [file]
load(":maven_bom_fragment.bzl", "MavenBomFragmentInfo")
load(":maven_publish.bzl", "maven_publish")
load(":maven_utils.bzl", "generate_pom", "unpack_coordinates")
def _label(label_or_string):
if type(label_or_string) == "Label":
return label_or_string
if type(label_or_string) == "string":
# We may have a target of the form: `@bar//foo`, `//foo`, `//foo:foo`, `:foo`, `foo`
if label_or_string.startswith("@"):
# We have an absolute target. Great!
return Label(label_or_string)
elif label_or_string.startswith("//"):
return Label("@%s" % label_or_string)
else:
if label_or_string.startswith(":"):
label_or_string = label_or_string[1:]
return Label("@//%s:%s" % (native.package_name(), label_or_string))
fail("Can only convert either labels or strings: %s" % label_or_string)
def _maven_bom_impl(ctx):
fragments = [f[MavenBomFragmentInfo] for f in ctx.attr.fragments]
combined_deps = depset(transitive = [f.maven_info.maven_deps for f in fragments])
bom = generate_pom(
ctx,
coordinates = ctx.attr.maven_coordinates,
versioned_dep_coordinates = [f[MavenBomFragmentInfo].coordinates for f in ctx.attr.fragments],
pom_template = ctx.file.pom_template,
out_name = "%s.xml" % ctx.label.name,
)
return [
DefaultInfo(files = depset([bom])),
]
_maven_bom = rule(
_maven_bom_impl,
doc = """Create a Maven BOM file (`pom.xml`) for the given targets.""",
attrs = {
"maven_coordinates": attr.string(
mandatory = True,
),
"pom_template": attr.label(
doc = "Template file to use for the BOM pom.xml",
default = "//private/templates:bom.tpl",
allow_single_file = True,
),
"fragments": attr.label_list(
providers = [
[MavenBomFragmentInfo],
],
),
},
)
def _maven_dependencies_bom_impl(ctx):
fragments = [f[MavenBomFragmentInfo] for f in ctx.attr.fragments]
combined_deps = depset(transitive = [f.maven_info.maven_deps for f in fragments])
unpacked = unpack_coordinates(ctx.attr.maven_coordinates)
dependencies_bom = generate_pom(
ctx,
coordinates = ctx.attr.maven_coordinates,
versioned_dep_coordinates = combined_deps.to_list() + ["%s:%s:pom:import:%s" % (unpacked.groupId, unpacked.artifactId, unpacked.version)],
pom_template = ctx.file.pom_template,
out_name = "%s.xml" % ctx.label.name,
indent = 12,
)
return [
DefaultInfo(files = depset([dependencies_bom])),
]
_maven_dependencies_bom = rule(
_maven_dependencies_bom_impl,
doc = """Create a Maven dependencies `pom.xml` for the given targets.""",
attrs = {
"maven_coordinates": attr.string(
mandatory = True,
),
"pom_template": attr.label(
doc = "Template file to use for the pom.xml",
default = "//private/templates:dependencies-bom.tpl",
allow_single_file = True,
),
"fragments": attr.label_list(
providers = [
[MavenBomFragmentInfo],
],
),
},
)
def maven_bom(
name,
maven_coordinates,
java_exports,
bom_pom_template = None,
dependencies_maven_coordinates = None,
dependencies_pom_template = None,
tags = None,
testonly = None,
visibility = None):
"""Generates a Maven BOM `pom.xml` file and an optional "dependencies" `pom.xml`.
The generated BOM will contain a list of all the coordinates of the
`java_export` targets in the `java_exports` parameters. An optional
dependencies artifact will be created if the parameter
`dependencies_maven_coordinates` is set.
Both the BOM and dependencies artifact can be templatised to support
customisation, but a sensible default template will be used if none is
provided. The template used is derived from the (optional)
`pom_template` argument, and the following substitutions are performed on
the template file:
* `{groupId}`: Replaced with the maven coordinates group ID.
* `{artifactId}`: Replaced with the maven coordinates artifact ID.
* `{version}`: Replaced by the maven coordinates version.
* `{dependencies}`: Replaced by a list of maven dependencies directly relied upon
by java_library targets within the artifact.
To publish, call the implicit `*.publish` target(s).
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.
Generated rules:
* `name`: The BOM file itself.
* `name.publish`: To be executed by `bazel run` to publish the BOM to a maven repo
* `name-dependencies`: The BOM file for the dependencies `pom.xml`. Only generated if `dependencies_maven_coordinates` is set.
* `name-dependencies.publish`: To be executed by `bazel run` to publish the dependencies `pom.xml` to a maven rpo. Only generated if `dependencies_maven_coordinates` is set.
Args:
name: A unique name for this rule.
maven_coordinates: The maven coordinates of this BOM in `groupId:artifactId:version` form.
bom_pom_template: A template used for generating the `pom.xml` of the BOM at `maven_coordinates` (optional)
dependencies_maven_coordinates: The maven coordinates of a dependencies artifact to generate in GAV format. If empty, none will be generated. (optional)
dependencies_pom_template: A template used for generating the `pom.xml` of the dependencies artifact at `dependencies_maven_coordinates` (optional)
java_exports: A list of `java_export` targets that are used to generate the BOM.
"""
fragments = []
labels = [_label(je) for je in java_exports]
fragments = ["%s.bom-fragment" % str(l) for l in labels]
_maven_bom(
name = name,
maven_coordinates = maven_coordinates,
pom_template = bom_pom_template,
fragments = fragments,
tags = tags,
testonly = testonly,
visibility = visibility,
)
maven_publish(
name = "%s.publish" % name,
coordinates = maven_coordinates,
pom = name,
tags = tags,
testonly = testonly,
visibility = visibility,
)
if dependencies_maven_coordinates:
_maven_dependencies_bom(
name = "%s-dependencies" % name,
maven_coordinates = dependencies_maven_coordinates,
pom_template = dependencies_pom_template,
fragments = fragments,
tags = tags,
testonly = testonly,
visibility = visibility,
)
maven_publish(
name = "%s-dependencies.publish" % name,
coordinates = dependencies_maven_coordinates,
pom = "%s-dependencies" % name,
tags = tags,
testonly = testonly,
visibility = visibility,
)