Skip to content
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
7 changes: 7 additions & 0 deletions examples/demoapp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,13 @@ java_test(
deps = [":demoapp_lib"] + test_deps + springboottest_deps,
)

java_test(
name = "PackagingTest",
srcs = ["src/test/java/com/salesforce/rules_spring/PackagingTest.java"],
data = [":demoapp"],
deps = [":demoapp_lib"] + test_deps,
)

licenses_used(
name = "demoapp_licenses",
out = "demoapp_licenses.json",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2021, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
package com.salesforce.rules_spring;

import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import static org.junit.Assert.*;

/**
*/
public class PackagingTest {

File springbootJarFile = null;

// file contents
String gitPropertiesContents = null;
String buildPropertiesContents = null;
String applicationPropertiesContents = null;

// file existence
boolean exists_lib1 = false;
boolean exists_lib2 = false;
boolean exists_lib3_neverlink = false;

@Before
public void setup() throws Exception {
springbootJarFile = new File("./examples/demoapp/demoapp.jar");
if (!springbootJarFile.exists()) {
throw new IllegalStateException("Missing demoapp springboot jar; looked in path: " +
springbootJarFile.getAbsolutePath());
}
extractFilesFromSpringBootJar();
}

@Test
public void gitPropertiesFileTest() {
assertNotNull(gitPropertiesContents);
assertTrue(gitPropertiesContents.contains("git.commit"));
}

@Test
public void buildPropertiesFileTest() {
assertNotNull(buildPropertiesContents);
assertTrue(buildPropertiesContents.contains("build.number"));
}

@Test
public void applicationPropertiesFileTest() {
assertNotNull(applicationPropertiesContents);
assertTrue(applicationPropertiesContents.contains("demoapp.config.internal"));
}

@Test
public void internalLibsAreIncludedTest() {
assertTrue(this.exists_lib1);
assertTrue(this.exists_lib2);
}

@Test
public void neverlinkLibsAreExcludedTest() {
assertFalse(this.exists_lib3_neverlink);
}

private void extractFilesFromSpringBootJar() throws Exception {
try (ZipFile sbZip = new ZipFile(springbootJarFile)) {
Enumeration<? extends ZipEntry> entries = sbZip.entries();
for (Iterator<? extends ZipEntry> it = entries.asIterator(); it.hasNext(); ) {
ZipEntry entry = it.next();
String name = entry.getName();
System.out.println(" zipentry: "+name);
if (name.equals("BOOT-INF/classes/git.properties")) {
InputStream is = sbZip.getInputStream(entry);
gitPropertiesContents = new String(is.readAllBytes(), StandardCharsets.UTF_8);
} else if (name.equals("BOOT-INF/classes/META-INF/build-info.properties")) {
InputStream is = sbZip.getInputStream(entry);
buildPropertiesContents = new String(is.readAllBytes(), StandardCharsets.UTF_8);
} else if (name.equals("BOOT-INF/classes/application.properties")) {
InputStream is = sbZip.getInputStream(entry);
applicationPropertiesContents = new String(is.readAllBytes(), StandardCharsets.UTF_8);
} else if (name.equals("BOOT-INF/lib/examples/demoapp/libs/lib1/liblib1.jar")) {
exists_lib1 = true;
} else if (name.equals("BOOT-INF/lib/examples/demoapp/libs/lib2/liblib2.jar")) {
exists_lib2 = true;
} else if (name.contains("neverlink")) {
// we have a lib named lib3_neverlink that has neverlink = True, which means it should NOT be
// included in the springboot jar
exists_lib3_neverlink = true;
}
}
}
}
}
91 changes: 41 additions & 50 deletions springboot/springboot.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ def _banneddeps_rule_impl(ctx):

if found_banned:
ctx.actions.write(output, "FAIL", is_executable = False)
fail("Found banned jars in the springboot rule [" + ctx.label.name
+ "] dependency list. Filenames:\n" + banned_filenames
+ "\nYou can ignore these by setting deps_banned = [] on the springboot() rule.\n")
fail("Found banned jars in the springboot rule [" + ctx.label.name +
"] dependency list. Filenames:\n" + banned_filenames +
"\nYou can ignore these by setting deps_banned = [] on the springboot() rule.\n")
else:
ctx.actions.write(output, "SUCCESS", is_executable = False)
return [DefaultInfo(files = depset(outputs))]
Expand All @@ -237,11 +237,9 @@ _banneddeps_rule = rule(
"deps_banned": attr.string_list(),
"deps": attr.label_list(),
"out": attr.string(),
}
},
)



# ***************************************************************
# Outer launcher script for "bazel run"

Expand Down Expand Up @@ -297,21 +295,21 @@ def _springboot_rule_impl(ctx):
# into the _bazelrun_script_template text defined above
outer_bazelrun_script_contents = _bazelrun_script_template \
.replace("%bazelrun_script%", ctx.attr.bazelrun_script.files.to_list()[0].short_path) \
.replace("%name%", ctx.attr.name)
.replace("%name%", ctx.attr.name)

# the bazelrun_java_toolchain optional, if set, we use it as the jvm for bazel run
if ctx.attr.bazelrun_java_toolchain != None:
# lookup the path to selected java toolchain, and string sub it into the bazel run script
# text _bazelrun_script_template defined above
java_runtime = ctx.attr.bazelrun_java_toolchain[java_common.JavaToolchainInfo].java_runtime
java_bin = [f for f in java_runtime.files.to_list() if f.path.endswith("bin/java") or f.path.endswith("bin/java.exe")][0]
outer_bazelrun_script_contents = outer_bazelrun_script_contents \
.replace("%java_toolchain_attr%", java_bin.path)
outer_bazelrun_script_contents = outer_bazelrun_script_contents \
.replace("%java_toolchain_name_attr%", ctx.attr.bazelrun_java_toolchain.label.name)
# lookup the path to selected java toolchain, and string sub it into the bazel run script
# text _bazelrun_script_template defined above
java_runtime = ctx.attr.bazelrun_java_toolchain[java_common.JavaToolchainInfo].java_runtime
java_bin = [f for f in java_runtime.files.to_list() if f.path.endswith("bin/java") or f.path.endswith("bin/java.exe")][0]
outer_bazelrun_script_contents = outer_bazelrun_script_contents \
.replace("%java_toolchain_attr%", java_bin.path)
outer_bazelrun_script_contents = outer_bazelrun_script_contents \
.replace("%java_toolchain_name_attr%", ctx.attr.bazelrun_java_toolchain.label.name)
else:
outer_bazelrun_script_contents = outer_bazelrun_script_contents \
.replace("%java_toolchain_attr%", "")
outer_bazelrun_script_contents = outer_bazelrun_script_contents \
.replace("%java_toolchain_attr%", "")

outer_bazelrun_script_file = ctx.actions.declare_file("%s" % ctx.label.name)
ctx.actions.write(outer_bazelrun_script_file, outer_bazelrun_script_contents, is_executable = True)
Expand All @@ -323,9 +321,9 @@ def _springboot_rule_impl(ctx):

# and add any data files to runfiles
if ctx.attr.bazelrun_data != None:
for data_target in ctx.attr.bazelrun_data:
for data_target in data_target.files.to_list():
runfiles_list.append(data_target)
for data_target in ctx.attr.bazelrun_data:
for data_target in data_target.files.to_list():
runfiles_list.append(data_target)

return [DefaultInfo(
files = outs,
Expand All @@ -347,10 +345,8 @@ _springboot_rule = rule(
"javaxdetect_rule": attr.label(),
"banneddeps_rule": attr.label(),
"apprun_rule": attr.label(),

"bazelrun_script": attr.label(allow_files=True),
"bazelrun_data": attr.label_list(allow_files=True),

"bazelrun_script": attr.label(allow_files = True),
"bazelrun_data": attr.label_list(allow_files = True),
"bazelrun_java_toolchain": attr.label(
mandatory = False,
default = "@bazel_tools//tools/jdk:current_java_toolchain",
Expand All @@ -368,7 +364,7 @@ def springboot(
boot_app_class,
boot_launcher_class = "org.springframework.boot.loader.JarLauncher",
deps = None,
deps_banned = [ "junit", "mockito", ], # detects common mistake of test dep pollution
deps_banned = ["junit", "mockito"], # detects common mistake of test dep pollution
deps_exclude = None,
deps_exclude_paths = None,
deps_index_file = None,
Expand All @@ -377,7 +373,7 @@ def springboot(
dupeclassescheck_ignorelist = None,
javaxdetect_enable = None,
javaxdetect_ignorelist = None,
include_git_properties_file=True,
include_git_properties_file = True,
bazelrun_java_toolchain = None,
bazelrun_script = None,
bazelrun_jvm_flags = None,
Expand All @@ -391,17 +387,16 @@ def springboot(
visibility = None,
bazelrun_addopens = [],
bazelrun_addexports = [],
jartools_toolchains = ["@bazel_tools//tools/jdk:current_host_java_runtime"], # Issue 250
exclude = [], # deprecated
classpath_index = "@rules_spring//springboot:empty.txt", # deprecated
use_build_dependency_order = True, # deprecated
fail_on_duplicate_classes = False, # deprecated
duplicate_class_allowlist = None, # deprecated
jvm_flags = "", # deprecated
data = [], # deprecated
jartools_toolchains = ["@bazel_tools//tools/jdk:current_host_java_runtime"], # Issue 250
exclude = [], # deprecated
classpath_index = "@rules_spring//springboot:empty.txt", # deprecated
use_build_dependency_order = True, # deprecated
fail_on_duplicate_classes = False, # deprecated
duplicate_class_allowlist = None, # deprecated
jvm_flags = "", # deprecated
data = [], # deprecated
restricted_to = None,
target_compatible_with = [],
):
target_compatible_with = []):
"""Bazel rule for packaging an executable Spring Boot application.

Note that the rule README has more detailed usage instructions for each attribute.
Expand Down Expand Up @@ -610,22 +605,20 @@ def springboot(
visibility = visibility,
)



# SUBRULE 3B: GENERATE THE ENV VARIABLES USED BY THE BAZELRUN LAUNCHER SCRIPT
genbazelrunenv_out = name + "_bazelrun_env.sh"
native.genrule(
name = genbazelrunenv_rule,
srcs = bazelrun_data,
cmd = "$(location @rules_spring//springboot:write_bazelrun_env.sh) " + name + " " + _get_springboot_jar_file_name(name)
+ " " + _get_relative_package_path() + " $@ " + _convert_starlarkbool_to_bashbool(bazelrun_background)
+ " $(SRCS)"
+ " start_flags"
+ " " + " ".join(["--add-exports=" + element for element in bazelrun_addexports])
+ " " + " ".join(["--add-opens=" + element for element in bazelrun_addopens])
+ " " + bazelrun_jvm_flags
+ " start_envs"
+ " " + bazelrun_env_flags,
cmd = "$(location @rules_spring//springboot:write_bazelrun_env.sh) " + name + " " + _get_springboot_jar_file_name(name) +
" " + _get_relative_package_path() + " $@ " + _convert_starlarkbool_to_bashbool(bazelrun_background) +
" $(SRCS)" +
" start_flags" +
" " + " ".join(["--add-exports=" + element for element in bazelrun_addexports]) +
" " + " ".join(["--add-opens=" + element for element in bazelrun_addopens]) +
" " + bazelrun_jvm_flags +
" start_envs" +
" " + bazelrun_env_flags,
# message = "SpringBoot rule is writing the bazel run launcher env...",
tools = ["@rules_spring//springboot:write_bazelrun_env.sh"],
outs = [genbazelrunenv_out],
Expand Down Expand Up @@ -727,10 +720,8 @@ def springboot(
dupecheck_rule = dupecheck_rule_label,
javaxdetect_rule = javaxdetect_rule_label,
apprun_rule = ":" + apprun_rule,

bazelrun_script = bazelrun_script,
bazelrun_data = bazelrun_data,

tags = tags,
testonly = testonly,
restricted_to = restricted_to,
Expand All @@ -747,7 +738,7 @@ def _get_springboot_jar_file_name(name):

def _convert_starlarkbool_to_bashbool(starlarkbool):
if starlarkbool:
return "true"
return "true"
return "false"

def _get_relative_package_path():
Expand Down
2 changes: 1 addition & 1 deletion springboot/springboot_pkg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ echo "DEBUG: finished copying transitives into BOOT-INF/lib, elapsed time (secon
if [[ "$include_git_properties_file" == true ]]; then
echo "DEBUG: adding git.properties" >> $debugfile
cat $ruledir/$gitpropsfile >> $debugfile
cp -f $ruledir/$gitpropsfile $working_dir/BOOT-INF/classes
cp -f $ruledir/$gitpropsfile $working_dir/BOOT-INF/classes/git.properties
fi

# Inject the classpath index (unless it is the default empty.txt file). Requires Spring Boot version 2.3+
Expand Down