Coder Social home page Coder Social logo

salesforce / rules_spring Goto Github PK

View Code? Open in Web Editor NEW
217.0 15.0 44.0 864 KB

Bazel rule for building Spring Boot apps as a deployable jar

License: BSD 3-Clause "New" or "Revised" License

Python 19.95% Shell 26.68% Starlark 38.58% Java 14.79%

rules_spring's Introduction

Salesforce Spring Rules for Bazel

This repository contains the Spring Boot rule for the Bazel build system. It enables Bazel to build Spring Boot applications and package them as an executable jar file. The executable jar is the best way to deploy your Spring Boot application in production environments.

The Salesforce springboot rule can be found, along with documentation, in this directory:

  • springboot: a Bazel extension to build and package Spring Boot applications

Support and Ongoing Development

This rule was developed and is supported by Salesforce. If you have any issues with this repository, please create a GitHub Issue. We will try to quickly address problems and answer questions. Note that we do not yet support running these rules on Windows.

Ongoing development is planned and tracked using this GitHub repository's Project Manager. To see what bug fixes and new features are planned, consult the roadmaps located there.

:octocat: Please do us a huge favor. If you think this project could be useful for you, now or in the future, please hit the Star button at the top. That helps us advocate for more time and resources on this project. Thanks!

Loading the Spring Rules in your WORKSPACE

Before you can use the rule in your BUILD files, you need to add it to your workspace.

Reference an official release This loads a pre-built version of this rule into your workspace during the build. This is the recommended approach for most users.

http_archive(
    name = "rules_spring",
    sha256 = "87b337f95f9c09a2e5875f0bca533b050c9ccb8b0d2c92915e290520b79d0912",
    urls = [
        "https://github.com/salesforce/rules_spring/releases/download/2.3.2/rules-spring-2.3.2.zip",
    ],
)

Do not use a git_repository rule with our main branch If you choose not to use an official release, you may be tempted to use a git_repository workspace rule to point to our main branch, Please do not do this, as we use main for ongoing work. We may check breaking changes into main at any time.

Alternate Approach for Building and Running Spring Boot Applications

If you don't need to create a runnable executable jar file, there is an alternate approach to Spring Boot in the rules_jvm_external repository. That approach is sufficient if Bazel and your Bazel workspace (i.e. source code) are available in all environments that launch the application.

At Salesforce, Bazel is not available in production environments, and so this alternate approach is not viable.

Upgrades

This section contains notes for specific upgrade steps needed to adopt newer versions of rules-spring. Starting with the 1.1.x line, we strive to adhere to SemVer. This Git repository was renamed from bazel-springboot-rule to rules_spring on March 17, 2021. This was done to comply with required Bazel naming conventions for external rules.

2.0.0: March 13, 2021

This release refactored the rule with the standardized Bazel rule layout conventions. When the Spring Boot rule was originally written, the conventions did not exist. This repackaging makes the rule more modern.

For rule 1.x users upgrading to 2.0.0, you will need to do the following:

  • All WORKSPACE and BUILD file references to bazel_springboot_rule must be changed to rules_spring
  • All BUILD and .bzl file references to //tools/springboot must be changed to //springboot

See Repackaging work item for more details.

rules_spring's People

Contributors

aditya-2001 avatar arturdryomov avatar bendavini avatar btbuxton avatar bwsalesforce avatar dnishant-zz avatar dylanshark avatar fmeum avatar hjellek avatar invader35 avatar kriscfoster avatar marcus-rosti avatar mohitbhar avatar plaird avatar simontoens avatar svc-scm avatar vertexwahn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rules_spring's Issues

Support passing arguments to bazel run for Spring Boot application

bazel run does not pass the arguments to the Spring Boot executable:

$ java -jar bazel-bin/samples/helloworld/helloworld.jar one two three
Launching the sample SpringBoot demo application...
Command line args: one two three

$ bazel run //samples/helloworld one two three
Launching the sample SpringBoot demo application...
Command line args:

Make springboot rule customizable with extension code

After we migrate the rule implementation to Java (see Issue #3) it wouldn't be hard to provide plug points for customizations. For example, we have the exclude (aka exclude_deps) attribute that is a static list of deps that should not be packaged. If a user wants to do something more custom, it would be nice if they could provide a class that implements an interface that we would invoke with a method:

boolean acceptDependency(String depName);

And other important steps in the packaging would have the same treatment like:

List<String> customizeManifest(List<String> manifestLines);

This would allow us to avoid implementing one-off requirements by users. We could just point them to this facility, and they can customize it themselves. If the customization is popular, we could then turn it into an official feature.

The rule user would need to provide the Java class(es) via a new attribute (? or think of a better solution), like:

springboot(
   ...
   extension_deps = [ "//tools/acme/springboot:acme_springboot_custom_whizbang"],
)

Support rules_jvm_external deps

Description

As rules_jvm_external lays out deps differently to the native.maven_jar repo rule used in the example, things don't work right now if you use the former.

I collected the SRCS passed into write_manifest.sh to show this:

com.book.store.api.Application bazel-out/darwin-fastbuild/bin/store-api/src/main/java/com/book/store/api/MANIFEST.MF bazel-out/darwin-fastbuild/bin/external/maven/v1/https/repo1.maven.org/maven2/org/springframework/boot/spring-boot/2.1.3.RELEASE/stamped_spring-boot-2.1.3.RELEASE.jar 
bazel-out/darwin-fastbuild/bin/external/maven/v1/https/repo1.maven.org/maven2/org/springframework/spring-aop/5.1.5.RELEASE/stamped_spring-aop-5.1.5.RELEASE.jar 
bazel-out/darwin-fastbuild/bin/external/maven/v1/https/repo1.maven.org/maven2/org/springframework/spring-core/5.1.5.RELEASE/stamped_spring-core-5.1.5.RELEASE.jar 
bazel-out/darwin-fastbuild/bin/external/maven/v1/https/repo1.maven.org/maven2/org/springframework/spring-jcl/5.1.5.RELEASE/stamped_spring-jcl-5.1.5.RELEASE.jar 
bazel-out/darwin-fastbuild/bin/external/maven/v1/https/repo1.maven.org/maven2/org/springframework/spring-beans/5.1.5.RELEASE/stamped_spring-beans-5.1.5.RELEASE.jar 
bazel-out/darwin-fastbuild/bin/external/maven/v1/https/repo1.maven.org/maven2/org/springframework/spring-context/5.1.5.RELEASE/stamped_spring-context-5.1.5.RELEASE.jar 
bazel-out/darwin-fastbuild/bin/external/maven/v1/https/repo1.maven.org/maven2/org/springframework/spring-expression/5.1.5.RELEASE/stamped_spring-expression-5.1.5.RELEASE.jar 
....

The first ERROR you get is:

ERROR: //tools/springboot/write_manifest.sh could not find spring-boot jar

Fortunately it was quite easy to get at least the basics working with rules_jvm_external by make 2 changes to pattern matching lines here and here.

At thundergolfer/example-bazel-monorepo@dc7d2c6 I can now get this rule working I think, as doing bazel run //store-api/src/main/java/com/book/store/api:deployable works ๐Ÿ‘.


Note, this may be a dupe/sibling of #4

Windows support for Spring Boot rule

Currently, with a bash implementation, the rule is not portable natively to Windows. It seems like there is weak support for running Bazel from cygwin, but that isn't a real solution.

https://docs.bazel.build/versions/master/windows.html#bazel-build-without-bash

There is already an issue #3 to reimplement the bash script in another language for maintainability reasons. Please track the bash migration discussions there.

This issue tracks testing, and fixing any other issues found while running this rule on Windows.

Support bazel 2.0

Firstly, thank you for putting together this awesome tool!

My issue:
As a bazel user
I would like to be able to build a spring boot project with bazel 2.0 and bazel-spring-boot without errors
So that I can use the default google cloud build bazel task for building spring boot applications
And so that I don't have to use an out of date, regressed 0.29.1 bazel task

To Reproduce:

On MacOS 10.15.2, using bazel 2.0 (I believe the same error is given on any bazel version after 0.29.1)

when building the samples/helloworld spring boot application

bazel build //samples/helloworld

Starting local Bazel server and connecting to it...
ERROR: /Users/me/src/bazel-springboot-rule/WORKSPACE:9:1: name 'maven_server' is not defined
ERROR: error loading package '': Encountered error while reading extension file 'tools/build_defs/repo/http.bzl': no such package '@bazel_tools//tools/build_defs/repo': error loading package 'external': Could not load //external package
ERROR: error loading package '': Encountered error while reading extension file 'tools/build_defs/repo/http.bzl': no such package '@bazel_tools//tools/build_defs/repo': error loading package 'external': Could not load //external package
INFO: Elapsed time: 2.291s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (0 packages loaded)

Allow BUILD file to override the default launcher script for bazel run

We have the launcher script that is invoked when a user issues a run command via bazel:

bazel run //projects/myservice

It is hardcoded in springboot.bzl. We have a couple of open issues related to the contents #16 and #91. While those are small updates, it would be nice for users to be able to replace it and make any changes they would like. For example, to run custom steps prior to launch of the Spring Boot app.

For this issue, allow the user to pass in a file as a rule attribute.

Add ability to configure workspace specific defaults for springboot rule

As a user of the springboot rule
I would like to be able to override the rule's defaults for my workspace to suit my preferences
Such that I can force default dupeclassescheck_enable=True (and other features) on all usages within my Bazel workspace

Background:
As rule authors, we decided on defaults for the various features supported by our rule.
Our default of dupeclassescheck_enable = False is the most notable.
We set our defaults to be user friendly for new users; enabling fail on duplicates by default could be an annoyance for new users.
We allow each usage of the rule to override these defaults as desired using the rule attributes.

But it would be nice (as we are seeing in an internal workspace of ours) to be able to globally (within the workspace) override the default. In our particular case, to enable dupe class checking by default.
Other attributes that could benefit from this treatment include deps_exclude, deps_use_starlark_order, tags, visibility.

The right time to do this is when working #30 since this will likely require backwards incompatible changes to the way the rule is loaded in WORKSPACe.

Provide a Docker/OCI packaging example

Internally at Salesforce, we don't do anything super elaborate when we package up Spring Boot services into Docker containers. But we have some nice idioms that could be helpful for others.

We probably shouldn't create anything we will maintain, but having some code samples/docs would be nice. We have about a dozen attributes we pass into our docker packaging rule.

In addition, there are two specific techniques for Spring Boot applications in Docker images. This article explains them:

  • Spring Boot apps should be extracted upon copy into the Docker image. Running from the executable jar is slower.
  • Once we implement the layer layout for the springboot rule (#69) we should suggest how to write the Dockerfile to take advantage of that

I think it would be best to do this example in a new branch, much like the Kotlin example branch.

Also consider an alternate example that uses the CloudNative buildpack for Spring Boot:

Implement dep bundles for Spring Boot starters

As a SpringBoot rule user
I would like to have an easy idiom for including an open source Spring Boot starter (e.g. jetty, web)
Such that I do not have to list all the transitive deps for that starter in my BUILD file
Such that the dep list corresponds with the version of SpringBoot I have chosen

Acceptance:

  • double down on our current approach, or research and switch to something else
  • create/use a tool that can create a bundle for each open source starter at each spring boot version
  • publish those bundles somewhere in this repo

Background:
Internally at Salesforce, we have internal Bazel BUILD packages that wrap each open source starter that we use (a small subset of the ones in open source) for a variety of reasons. Those packages list the transitive deps for the SpringBoot starter they each wrap. We also standardize on one Spring Boot version at a given time. So our internal use case is simpler than the general public and is easily curated by hand.

But the general public will use a wider variety of starters, and could be on any of the public Spring Boot releases. We have a crude solution in place for this open source distro here:
https://github.com/salesforce/bazel-springboot-rule/tree/master/tools/springboot/import_bundles

But we should solve this in a more maintainable and comprehensive way.
rules_jvm_external uses a different scheme with maven_install.json files, perhaps consider that. https://github.com/bazelbuild/rules_jvm_external

Add attribute for providing Classpath index file in executable jar

Some newer features of Spring Boot executable jar file format are not available in the Bazel Spring Boot jar rule yet.

  • Classpath index file
  • Layer index file

https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-executable-jar-format.html#executable-jar-war-index-files-classpath

This issue is only for the classpath index file. The layer index file is more involved and will be covered in another issue.

I don't think we should do anything magical here (i.e. auto-generating these files). Just allow the user to specify existing workspace files as attributes in the rule.

Support Code Coverage with Spring Boot Rule

We have some old code in the packaging script that is supposed to support code coverage statistics. It was implemented on an early version of Bazel. The status of that feature is not well known.

  • does it work?
  • document how to use it

Formal releases for the rule

Right now we just suggest users copy the tools/springboot directory into their workspace (vendoring). Since it is small and self contained seems like good advice.

But there are other options. Especially with the the addition of the buildstamp work, we should invest some time into it. It would also be nice to have actual releases of the rule (e.g. 1.0.0), which may need to correspond to Bazel releases or Federation releases.

Consider especially this best practice, which is to zip up the current state of the repo as a .zip file:
https://docs.bazel.build/versions/master/external.html#repository-rules

WARNING: moving maven_jar() support to a maintenance branch

NOTE: If you are importing this rule with git_repository() and only specify the master branch (not commit id) you will break soon. I plan to remove support for maven_jar() in the master branch since it no longer exists in Bazel 2.0. Please rewrite your import to use a git commit id.

Plan:
We have a couple of work items in flight: https://github.com/salesforce/bazel-springboot-rule/projects/1

After those are merged, I plan to cut a ceremonial 1.0 release. We don't actually release binaries, so it isn't a real release, but most importantly I will cut a 1.x branch. maven_jar() usage will travel there.

master branch will soon after migrate away from maven_jar, see #7

I hope to support maven_install and jvm_maven_import_external in parallel in master, but it will require moving some furniture around. Protect your CI build by using git_repository() with a commit id, so you can manage any necessary changes at your leisure.

Use the correct build JDK details when writing the Spring Boot MANIFEST.MF file

See write_manifest.sh. It helpfully inscribes the version of the JDK that was used to build the code in the generated Spring Boot application. Unfortunately, the value that is being written today is incorrect in many cases.

https://github.com/salesforce/bazel-springboot-rule/blob/master/tools/springboot/write_manifest.sh#L28

We need to inject this information from the actual JDK used to build the source (the toolchain), not the JDK that is in path while the genrule executes.

Drop support for Bazel 1.x

This is a marker Issue. Not much work is needed aside from some small doc edits, a release note, and update the Bazelisk .bazelversion file. This is filed as an issue mostly so we can be intentional about when to do this.

Thoughts:

  • Spring Boot rule release 1.1.0 will continue to support Bazel 1.2.1.
  • We will try to implement as many features/bug fixes as possible before dropping Bazel 1.2.1 support so that users can remain on 1.2.1 if they choose and be happy
  • Issue #16 is the one I am thinking of that could encourage us to drop 1.2.1 sooner rather than later
  • Consider timeline for dropping Bazel 2.x support. I don't think it is as urgent, but that is just guessing.

Insert order into executable jar is not deterministic, causes classloading differences

We had some issues with classes being classloaded in a different order, depending on the platform that built the Spring Boot jar. We believe this is caused by the springboot rule packaging step not specifying the insert order into the spring boot jar between:

  • spring boot loader
  • BOOT-INF/classes
  • BOOT-INF/lib

We want the order to be as depicted above.

Packaged application cannot start if there are no app-specific auto configs

Reported from the community:

$ java -jar bazel-bin/src/main/java/hello/app_deploy.jar

. ____ _ __ _ _
/\ / ' __ _ () __ __ _ \ \ \
( ( )_
_ | '_ | '| | ' / ` | \ \ \
\/ )| |)| | | | | || (| | ) ) ) )
' |
| .__|| ||| |_, | / / / /
=========|
|==============|/=////
:: Spring Boot ::

2019-12-19 22:39:36.964 INFO 52947 --- [ main] hello.Application : Starting Application on jingwen-macbookpro1.roam.corp.google.com with PID 52947 (/private/var/tmp/_bazel_jingwen/520ef5ee3324f7f06fb7919a7112f262/execroot/main/bazel-out/darwin-fastbuild/bin/src/main/java/hello/app_deploy.jar started by jingwen in /Users/jingwen/code/rules_jvm_external/examples/spring_boot)
2019-12-19 22:39:36.966 INFO 52947 --- [ main] hello.Application : No active profile set, falling back to default profiles: default
2019-12-19 22:39:37.172 ERROR 52947 --- [ main] o.s.boot.SpringApplication : Application run failed

java.lang.IllegalArgumentException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.
at org.springframework.util.Assert.notEmpty(Assert.java:464) ~[app_deploy.jar:na]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getCandidateConfigurations(AutoConfigurationImportSelector.java:183) ~[app_deploy.jar:na]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getAutoConfigurationEntry(AutoConfigurationImportSelector.java:119) ~[app_deploy.jar:na]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.process(AutoConfigurationImportSelector.java:420) ~[app_deploy.jar:na]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:878) ~[app_deploy.jar:na]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:804) ~[app_deploy.jar:na]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:774) ~[app_deploy.jar:na]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:185) ~[app_deploy.jar:na]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:315) ~[app_deploy.jar:na]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232) ~[app_deploy.jar:na]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) ~[app_deploy.jar:na]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) ~[app_deploy.jar:na]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705) ~[app_deploy.jar:na]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531) ~[app_deploy.jar:na]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[app_deploy.jar:na]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [app_deploy.jar:na]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [app_deploy.jar:na]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [app_deploy.jar:na]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [app_deploy.jar:na]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [app_deploy.jar:na]
at hello.Application.main(Application.java:15) [app_deploy.jar:na]

springboot rule doesn't work when the java_library attribute references a kt_jvm_library target

This is with rules kotlin version v1.5.0-alpha-3

The error is, when running the springboot jar:

Error: Invalid or corrupt jarfile path-to-jar

This error is caused by a corrupt jar manifest.

In springboot.bzl, when we use a genrule to call springboot_pkg.sh, we use the $(SRCS) syntax. For the java_library attribute, when it references a kt_jvm_library target, we get more than one file path although we expect only one. The first one we get is the jar produced by kt_jvm_library as expected. But the next one is a .jdeps file, which is unexpected. When springboot_pkg.sh runs, since it uses positional arguments, the jdeps file replaces the manifest file, and things go downhill from there.
See around here: https://github.com/salesforce/bazel-springboot-rule/blob/master/tools/springboot/springboot.bzl#L350

There is a workaround - add a java_library target indirection between the kt_jvm_library target and the springboot target.

java_library(
    name = "springboot_lib",
    runtime_deps = [":<kt_jvm_library_name>"],
)
springboot(
    java_library = ":springboot_lib",
    ...

We are currently testing this workaround internally. If it works as expected, we can encapsulate this within springboot.bzl

Standardize naming of springboot rule attributes

In hindsight, the attribute name duplicate_class_allowlist is not the best. Something like duplicate_class_ignorelist would be better.

Also, exclude would be better as exclude_deps.

When implementing this, continue to support the old attribute names but log a warning message that the old style is deprecated.

Running app_springboot.jar in a container

First and foremost, many thanks for publishing these rules.

I'm trying to run the output jar in a container, and am running into the following error when Spring serves static content.

java.io.FileNotFoundException: class path resource [static/index.html] cannot be resolved in the file system for resolving its last-modified timestamp
	at org.springframework.core.io.AbstractResource.lastModified(AbstractResource.java:155) ~[spring-core-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
	at org.springframework.core.io.AbstractFileResolvingResource.lastModified(AbstractFileResolvingResource.java:169) ~[spring-core-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]

Looking at the Spring source, I found this section in AbstractResource.java.

if (lastModified == 0L) {
  throw new FileNotFoundException(getDescription() +
      " cannot be resolved in the file system for resolving its last-modified timestamp");
}

I assume this is tripped because Bazel wants deterministic builds and sets file timestamps to zero. Does anyone know how to work around this?

Apps built by springboot rule fail launch from IntelliJ due to git.properties

Repro:

  • Import your Bazel workspace into IntelliJ using the IJ plugin
  • Navigate to the springboot app main java file in intellij.
  • Right click and 'Run as Bazel target' (or debug, doesn't matter).
  • Notice the following stack trace:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.info.GitProperties' available: expected at least 1 bean which qualifies as autowire candidate

The workaround is to create an empty git.properties file in src/main/resources

Bazel Build failing

https://github.com/rajrajenln/bazel-springboot-rule/tree/master
Hello @plaird ,

Thanks for putting together the bazel-springboot-rule.

I am trying to use your bazel scripts , I used the https://github.com/spring-guides/gs-rest-service/tree/master/complete source file inside the
https://github.com/rajrajenln/bazel-springboot-rule/tree/master/samples/src folder

Then adjusted certain BUILD , WORKSPACE files as per the README notes.

But when i create the bazelbuild from /Users/rajasekar.rajendran/raj/rajgithub/bazel-springboot-rule folder

ladmins-MacBook-Pro-4:bazel-springboot-rule rajasekar.rajendran$ bazel build //samples:samples
ERROR: /Users/rajasekar.rajendran/raj/rajgithub/bazel-springboot-rule/samples/BUILD:48:1: in deps attribute of _depaggregator_rule rule //samples:samples_deps: file '//samples:lib/myhello.jar' is misplaced here (expected no files). Since this rule was created by the macro 'springboot', the error might have been caused by the macro implementation in /Users/rajasekar.rajendran/raj/rajgithub/bazel-springboot-rule/tools/springboot/springboot.bzl:114:13
ERROR: Analysis of target '//samples:samples' failed; build aborted: Analysis of target '//samples:samples_deps' failed; build aborted
INFO: Elapsed time: 0.179s
FAILED: Build did NOT complete successfully (0 packages loaded)
ladmins-MacBook-Pro-4:bazel-springboot-rule rajasekar.rajendran$

I am sure , there must be a best way to accomplish the build without copying the tools folder content into the samples folder or vice versa..

Provide a list of packaged files (BOM) as an output

In addition to the executable jar, the rule should produce a Bill of Materials that lists everything packaged into the jar. This would allow rule users to use the BOM as an input into other rules, such as custom validation rules.

For example, we just discovered a service that was packaging 125 unnecessary dependencies. I have been thinking about how to add validation to signal this (e.g. should we error if BOOT-INF/lib count > 300?) and I think it would be better to externalize this instead of adding more logic to the springboot rule. If we write the BOM as a proper output, we could implement custom logic as we like.

Create a Kotlin example for Spring Boot

We are doing this internally, we should also have an example in the public repo.

To start with, let's do this in a dedicated kotlin_example branch instead of master/1.1.x. We will need to remember to refresh it now and then.

SpringBoot rule should pull through deps and runtime_deps from java_library

Given my base lib definition here:

java_library(
    name = "base_lib",
    srcs = glob(["src/main/java/**/*.java"]),
    resources = glob(["src/main/resources/**"]),
    deps = deps,
    runtime_deps = runtime_deps,
)

I have to construct the deps attribute for my springboot rule invocation like this:

springboot(
    name = "test-service",
    boot_app_class = "com.salesforce.services.test.TestServiceMain",
    java_library = ":base_lib",
    deps = deps + runtime_deps,
)

I shouldn't have to provide the deps or runtime_deps in the deps attribute, the rule should do that automatically.

bazel run doesn't honor --javabase, uses internal Java version

I'm using Java 11 and therefore have the following in my .bazelrc:
run --javabase=@bazel_tools//tools/jdk:remote_jdk11

For java_binary rules, this works great, causing them to run with JDK 11. However, when I do a bazel run on a springboot target, it always uses Java 1.8. I believe the reason is that it looks at JAVA_HOME, which is not taken from my environment but rather from the environment internal to the bazel server. I confirmed this by modifying springboot.bzl to echo JAVA_HOME. It gave me jdk1.8 even though my JAVA_HOME is pointing to jdk-11.

Refactor MANIFEST.MF generation code

When working on switching to singlejar for the final packaging step in #19 I left some tech debt there around manifest generation. We are actually now generating the manifest twice - once for the old jar packager, and once for the new singlejar packager. I was torn on whether to leave the door open to allow people to switch back to using jar to do the final packaging.

In the end, I didn't make the singlejar packager an option - it is hard wired. So we should refactor that area and make it clean.

jar manifest
https://github.com/salesforce/bazel-springboot-rule/blob/master/tools/springboot/springboot_pkg.sh#L187

singlejar manifest
https://github.com/salesforce/bazel-springboot-rule/blob/master/tools/springboot/springboot_pkg.sh#L195

Goals:

  • write the manifest just once
  • populate the manifest with legit values (spring boot version, build jdk version, etc)
  • provide a spring boot rule attribute (list of strings?) for adding additional custom lines to the manifest

Support maven_install and jvm_import style dependencies

As a Spring Boot rule new user
I would like to have an organized list of Maven dependencies to add to my WORKSPACE
Such that adding Spring Boot is not a painful ordeal.
Such that I can use Bazel 2.0 without issue (no use of maven_jar).
Such that I can use maven_install or jvm_maven_import_external

The problem is seen by looking at https://github.com/salesforce/bazel-springboot-rule/blob/master/external_deps.bzl
It is a mess.

This needs to worked in conjunction with the import bundles work item:
#4

To achieve this, we need to also migrate to this standard:
https://docs.bazel.build/versions/master/skylark/deploying.html

Spike: Generate SpringNative applications for Bazel SpringBoot (GraalVM, AOT)

Spike support for generating a SpringNative/GraalVM Spring Boot application with AOT features. The outcome of this issue is to create the 5-10 work items for actually implementing this feature.

This looks to be a really big item. This is an epic, and probably will be its own major release. It may even surface that it will be best to implement as an entirely different rule (e.g. springboot_native). But it would be really nice to have.

Spring Native References:

Output jar includes timestamps, not hermetic (want singlejar)

The packaging step uses jar. That creates an archive with time stamps, yielding the artifact not hermetic. Bazel internally uses singlejar to package up jars which sets timestamps to a fixed value.

Have you considered using singlejar for its packaging (or another packaging tool), or somehow create a jar that has fixed timestamps and other varying bytes removed.

BOOT-INF/lib jars are pathed using Bazel internal directory structures

Dependency jars should be nested directly under BOOT-INF/lib. But currently we are constructing the spring boot jar with internal details of the build in the form of deeply nested path structures. Spring Boot seems to be able to handle it, but it is poor form.

For maven_install deps, we see paths like:
BOOT-INF/lib/bazel-out/darwin-fastbuild/bin/external/maven/v1/https/nexus-proxy-prd.soma.salesforce.com/nexus/content/groups/public/com/fasterxml/jackson/core/jackson-annotations/2.10.5/jackson-annotations-2.10.5.jar

For internal deps, we see paths like:
BOOT-INF/lib/bazel-out/darwin-fastbuild/bin/projects/libs/acme/blue_lib/liblue_lib.jar

Implement Docker/OCI layer index file support

Spring Boot 2.3 added the ability to supply a layer index file that optimizes the writing of the Spring Boot jar for container use cases. It splits the jar into multiple layers.

Much like the classpath index file #33, we need to add an attribute so the user can supply the layer index. I don't think we should do anything magical here (i.e. auto-generating these files). Just allow the user to specify an existing workspace file as an attribute in the rule. This would be optional as the default layout seems sufficient for most use cases.

But then the writing of the spring boot jar file needs to honor the layers. This will involve having an alternate layout. This article explains everything pretty well:

To make this useful, the user would then need to create a docker image from the layered jar. This involves the -Djarmode=layertools tool. It is questionable if we should provide docker image creation support for this or not. At this point, I am more in favor of just showing examples.

This work may require changing the springboot rule signature in some incompatible way, so assigning to a major release for now.

SpringBoot rule output jar should be aware of the data files from the upstream java_library

The files mentioned in the data attribute are not copied into the jar by bazel instead they are linked by bazel at runtime into the runfiles directory. These files are not handled correctly as part of the springboot rule. The springboot rule in it's current state ignores the data attributes of the base_library.

Potential solutions:

  • Check if the library passed in the springboot rule has a data attribute and fail if it does. (Add docs to mention, data attr is not supported)
  • Add support for data attribute in the springboot rule
  • The user could add data attributes to the library and use them for tests, however when that library is used in a springboot rule you warn the users, that none of the data files will be part of the jar and instead you must add them as resources.

Cleanup tasks prior to 1.1 release

Running list of small things to cleanup before the next big release:

  • tags attribute should be passed down to the subrules in the macro
  • buildstamp has sfdc specific references in the comments, clean those up
  • rescan for legal headers, copyright extend to 2021
  • state the supported version(s) of Bazel (1.2.1?, 2.x?, 3.x)
  • run BUILD formatter

Expand the available examples

As a Spring Boot rule user
I would like more examples that show how to use the rule
Such that I can see how to use the Bazel springboot rule
Such that we have some coverage on different use cases for testing the rule
Such that we have a strong test case for the dependency bundling issue #4

Details:
There are about 50 official starters for Spring Boot. It would be great if we had a handful of examples under the //samples directory that showed different use cases. Perhaps borrow from an existing curated list of projects?

https://www.springboottutorial.com/spring-boot-projects-with-code-examples

When doing this, I think it will directly lead to addressing the module packaging issue #4 as it will be difficult to work this ticket without having at least some solution in place for that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.