Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add exclusion info to pom.xml #2

Merged
merged 2 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion private/rules/has_maven_deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ def _has_maven_deps_impl(target, ctx):
return _EMPTY_INFO

coordinates = read_coordinates(ctx.rule.attr.tags)
label_to_javainfo = {target.label: target[JavaInfo]}

gathered = _gathered(
all_infos = [],
Expand Down
18 changes: 18 additions & 0 deletions private/rules/java_export.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ load(":maven_bom_fragment.bzl", "maven_bom_fragment")
load(":maven_project_jar.bzl", "DEFAULT_EXCLUDED_WORKSPACES", "maven_project_jar")
load(":maven_publish.bzl", "maven_publish")
load(":pom_file.bzl", "pom_file")
load("//:specs.bzl", "parse", _json = "json")

def java_export(
name,
maven_coordinates,
manifest_entries = {},
deploy_env = [],
excluded_workspaces = {name: None for name in DEFAULT_EXCLUDED_WORKSPACES},
exclusions = {},
pom_template = None,
visibility = None,
tags = [],
Expand Down Expand Up @@ -70,6 +72,9 @@ def java_export(
that should not be included in the maven jar to a `Label` pointing to the dependency
that workspace should be replaced by, or `None` if the exclusion shouldn't be replaced
with an extra dependency.
exclusions: Mapping of target labels to a list of exclusions to be added to the POM file.
Each label must correspond to a direct maven dependency of this target.
Each exclusion is represented as a `group:artifact` string.
classifier_artifacts: A dict of classifier -> artifact of additional artifacts to publish to Maven.
doc_deps: Other `javadoc` targets that are referenced by the generated `javadoc` target
(if not using `tags = ["no-javadoc"]`)
Expand Down Expand Up @@ -104,6 +109,7 @@ def java_export(
manifest_entries = manifest_entries,
deploy_env = deploy_env,
excluded_workspaces = excluded_workspaces,
exclusions = exclusions,
pom_template = pom_template,
visibility = visibility,
tags = tags,
Expand All @@ -122,6 +128,7 @@ def maven_export(
manifest_entries = {},
deploy_env = [],
excluded_workspaces = {},
exclusions = {},
pom_template = None,
visibility = None,
tags = [],
Expand Down Expand Up @@ -185,6 +192,9 @@ def maven_export(
that should not be included in the maven jar to a `Label` pointing to the dependency
that workspace should be replaced by, or `None` if the exclusion shouldn't be replaced
with an extra dependency.
exclusions: Mapping of target labels to a list of exclusions to be added to the POM file.
Each label must correspond to a direct maven dependency of this target.
Each exclusion is represented as a `group:artifact` string.
doc_deps: Other `javadoc` targets that are referenced by the generated `javadoc` target
(if not using `tags = ["no-javadoc"]`)
doc_url: The URL at which the generated `javadoc` will be hosted (if not using
Expand Down Expand Up @@ -267,6 +277,13 @@ def maven_export(
)
classifier_artifacts.setdefault("javadoc", docs_jar)

exclusions_dict_json_strings = {
target: _json.write_exclusion_spec_list(
parse.parse_exclusion_spec_list(targetExclusions),
)
for target, targetExclusions in exclusions.items()
}

pom_file(
name = "%s-pom" % name,
target = ":%s" % lib_name,
Expand All @@ -276,6 +293,7 @@ def maven_export(
tags = tags,
testonly = testonly,
toolchains = toolchains,
exclusions = exclusions_dict_json_strings,
)

maven_publish(
Expand Down
34 changes: 30 additions & 4 deletions private/rules/maven_utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def _whitespace(indent):
whitespace = whitespace + " "
return whitespace

def format_dep(unpacked, indent = 8, include_version = True):
def format_dep(unpacked, indent = 8, include_version = True, exclusions = {}):
whitespace = _whitespace(indent)

dependency = [
Expand Down Expand Up @@ -70,6 +70,27 @@ def format_dep(unpacked, indent = 8, include_version = True):
" <scope>%s</scope>\n" % unpacked.scope,
])

if exclusions:
dependency.extend([
whitespace,
" <exclusions>\n",
])
for exclusion in exclusions:
dependency.extend([
whitespace,
" <exclusion>\n",
whitespace,
" <groupId>%s</groupId>\n" % exclusion["group"],
whitespace,
" <artifactId>%s</artifactId>\n" % exclusion["artifact"],
whitespace,
" </exclusion>\n",
])
dependency.extend([
whitespace,
" </exclusions>\n",
])

dependency.extend([
whitespace,
"</dependency>",
Expand All @@ -85,7 +106,8 @@ def generate_pom(
parent = None,
versioned_dep_coordinates = [],
unversioned_dep_coordinates = [],
indent = 8):
indent = 8,
exclusions = {}):
unpacked_coordinates = unpack_coordinates(coordinates)
substitutions = {
"{groupId}": unpacked_coordinates.groupId,
Expand All @@ -95,6 +117,10 @@ def generate_pom(
"{scope}": unpacked_coordinates.scope or "compile",
}

for key in exclusions:
if key not in versioned_dep_coordinates and key not in unversioned_dep_coordinates:
fail("Key %s in exclusions does not occur in versioned_dep_coordinates or unversioned_dep_coordinates" % key)

if parent:
# We only want the groupId, artifactID, and version
unpacked_parent = unpack_coordinates(parent)
Expand All @@ -113,10 +139,10 @@ def generate_pom(
deps = []
for dep in sorted(versioned_dep_coordinates):
unpacked = unpack_coordinates(dep)
deps.append(format_dep(unpacked, indent = indent))
deps.append(format_dep(unpacked, indent = indent, exclusions = exclusions.get(dep, {})))
for dep in sorted(unversioned_dep_coordinates):
unpacked = unpack_coordinates(dep)
deps.append(format_dep(unpacked, indent = indent, include_version = False))
deps.append(format_dep(unpacked, indent = indent, exclusions = exclusions.get(dep, {}), include_version = False))

substitutions.update({"{dependencies}": "\n".join(deps)})

Expand Down
22 changes: 21 additions & 1 deletion private/rules/pom_file.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ def _pom_file_impl(ctx):
artifact_jars = calculate_artifact_jars(info)
additional_deps = determine_additional_dependencies(artifact_jars, ctx.attr.additional_dependencies)

def get_coordinates(target):
if not info.label_to_javainfo.get(target.label):
fail("exclusions key %s not found in dependencies %s" % (target, info.label_to_javainfo.keys()))
else:
return ctx.expand_make_variables("exclusions", target[MavenInfo].coordinates, ctx.var)

exclusions = {
get_coordinates(target): json.decode(targetExclusions)
for target, targetExclusions in ctx.attr.exclusions.items()
}

all_maven_deps = info.maven_deps.to_list()
for dep in additional_deps:
for coords in dep[MavenInfo].as_maven_dep.to_list():
Expand All @@ -30,6 +41,7 @@ def _pom_file_impl(ctx):
versioned_dep_coordinates = sorted(expanded_maven_deps),
pom_template = ctx.file.pom_template,
out_name = "%s.xml" % ctx.label.name,
exclusions = exclusions,
)

return [
Expand All @@ -54,7 +66,8 @@ The following substitutions are performed on the template file:
{type}: Replaced by the maven coordinates type, if present (defaults to "jar")
{scope}: Replaced by the maven coordinates type, if present (defaults to "compile")
{dependencies}: Replaced by a list of maven dependencies directly relied upon
by java_library targets within the artifact.
by java_library targets within the artifact. Dependencies have exclusions
for any transitive dependencies that are occur in deploy_env.
""",
attrs = {
"pom_template": attr.label(
Expand Down Expand Up @@ -82,5 +95,12 @@ The following substitutions are performed on the template file:
has_maven_deps,
],
),
"exclusions": attr.label_keyed_string_dict(
doc = "Mapping of dependency labels to a list of exclusions (encoded as a json string). Each exclusion is a dict with a group and an artifact.",
allow_empty = True,
aspects = [
has_maven_deps,
],
),
},
)
7 changes: 7 additions & 0 deletions specs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ def _exclusion_spec_to_json(exclusion_spec):
"""
return "{ \"group\": \"" + exclusion_spec["group"] + "\", \"artifact\": \"" + exclusion_spec["artifact"] + "\" }"

def _exclusion_spec_list_to_json(exclusion_spec):
"""
Given a list of artifact exclusion spec, returns its json serialization.
"""
return "[" + ", ".join([_exclusion_spec_to_json(spec) for spec in exclusion_spec]) + "]"

def _override_license_types_spec_to_json(override_license_types_spec):
"""
Given an override license types spec, returns the json serialization of the object.
Expand Down Expand Up @@ -246,6 +252,7 @@ json = struct(
write_repository_credentials_spec = _repository_credentials_spec_to_json,
write_repository_spec = _repository_spec_to_json,
write_exclusion_spec = _exclusion_spec_to_json,
write_exclusion_spec_list = _exclusion_spec_list_to_json,
write_override_license_types_spec = _override_license_types_spec_to_json,
write_artifact_spec = _artifact_spec_to_json,
)
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/specs_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,25 @@ def _exclusion_spec_to_json_test_impl(ctx):

exclusion_spec_to_json_test = unittest.make(_exclusion_spec_to_json_test_impl)

def _exclusion_spec_list_to_json_test_impl(ctx):
env = unittest.begin(ctx)
asserts.equals(
env,
"[" +
"{ \"group\": \"org.eclipse.aether\", \"artifact\": \"aether-api\" }, " +
"{ \"group\": \"org.eclipse.aether\", \"artifact\": \"aether-util\" }" +
"]",
json.write_exclusion_spec_list(
[
{"group": "org.eclipse.aether", "artifact": "aether-api"},
{"group": "org.eclipse.aether", "artifact": "aether-util"},
],
),
)
return unittest.end(env)

exclusion_spec_list_to_json_test = unittest.make(_exclusion_spec_list_to_json_test_impl)

def _override_license_types_to_json_test_impl(ctx):
env = unittest.begin(ctx)
asserts.equals(
Expand Down Expand Up @@ -383,6 +402,7 @@ def artifact_specs_test_suite():
repository_credentials_spec_to_json_test,
repository_spec_to_json_test,
exclusion_spec_to_json_test,
exclusion_spec_list_to_json_test,
override_license_types_spec_to_json_test,
artifact_spec_to_json_test,
)
Expand Down