Port the build to Gradle

Closes gh-19609
Closes gh-19608
This commit is contained in:
Andy Wilkinson
2020-01-10 13:48:43 +00:00
parent abe95fa8a7
commit ce99db1902
974 changed files with 17108 additions and 26596 deletions

View File

@@ -0,0 +1,195 @@
plugins {
id 'java'
id 'org.springframework.boot.deployed'
id 'org.springframework.boot.conventions'
id 'org.springframework.boot.integration-test'
}
description = "Spring Boot CLI"
configurations {
dependenciesBom
loader
testRepository
}
dependencies {
compileOnly project(':spring-boot-project:spring-boot')
compileOnly 'jakarta.servlet:jakarta.servlet-api'
compileOnly 'org.codehaus.groovy:groovy-templates'
compileOnly 'org.springframework:spring-web'
dependenciesBom project(path: ':spring-boot-project:spring-boot-dependencies', configuration: 'effectiveBom')
implementation enforcedPlatform(project(':spring-boot-project:spring-boot-parent'))
implementation project(':spring-boot-project:spring-boot-tools:spring-boot-loader-tools')
implementation 'com.vaadin.external.google:android-json'
implementation 'jline:jline'
implementation 'net.sf.jopt-simple:jopt-simple'
implementation('org.apache.httpcomponents:httpclient') {
exclude group: 'commons-logging', module: 'commons-logging'
}
implementation 'org.apache.maven:maven-model'
implementation('org.apache.maven:maven-resolver-provider') {
exclude group: 'com.google.guava', module: 'guava'
}
implementation 'org.apache.maven.resolver:maven-resolver-connector-basic'
implementation 'org.apache.maven.resolver:maven-resolver-transport-file'
implementation('org.apache.maven.resolver:maven-resolver-transport-http') {
exclude group: 'org.slf4j', module: 'jcl-over-slf4j'
}
implementation 'org.apache.maven:maven-settings-builder'
implementation 'org.codehaus.groovy:groovy'
implementation 'org.slf4j:slf4j-simple'
implementation 'org.sonatype.plexus:plexus-sec-dispatcher'
implementation('org.sonatype.sisu:sisu-inject-plexus') {
exclude group: 'javax.enterprise', module: 'cdi-api'
exclude group: 'org.sonatype.sisu', module: 'sisu-inject-bean'
}
implementation 'org.springframework:spring-core'
implementation 'org.springframework.security:spring-security-crypto'
intTestImplementation enforcedPlatform(project(':spring-boot-project:spring-boot-dependencies'))
intTestImplementation project(':spring-boot-project:spring-boot-tools:spring-boot-loader-tools')
intTestImplementation project(':spring-boot-project:spring-boot-tools:spring-boot-test-support')
intTestImplementation 'org.assertj:assertj-core'
intTestImplementation 'org.junit.jupiter:junit-jupiter'
intTestImplementation 'org.springframework:spring-core'
loader project(':spring-boot-project:spring-boot-tools:spring-boot-loader')
testImplementation project(':spring-boot-project:spring-boot')
testImplementation project(':spring-boot-project:spring-boot-tools:spring-boot-test-support')
testImplementation project(':spring-boot-project:spring-boot-test')
testImplementation 'org.assertj:assertj-core'
testImplementation 'org.codehaus.groovy:groovy-templates'
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.mockito:mockito-core'
testImplementation 'org.springframework:spring-test'
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-actuator', configuration: 'mavenRepository')
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-amqp', configuration: 'mavenRepository')
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-aop', configuration: 'mavenRepository')
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-artemis', configuration: 'mavenRepository')
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-batch', configuration: 'mavenRepository')
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-data-jpa', configuration: 'mavenRepository')
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-jdbc', configuration: 'mavenRepository')
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-integration', configuration: 'mavenRepository')
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-security', configuration: 'mavenRepository')
testRepository project(path: ':spring-boot-project:spring-boot-starters:spring-boot-starter-web', configuration: 'mavenRepository')
}
task syncSpringBootDependenciesBom(type: Sync) {
destinationDir = file("$buildDir/generated-resources/org/springframework/boot/cli/compiler/dependencies")
from configurations.dependenciesBom
}
task syncTestRepository(type: Sync) {
destinationDir = file("${buildDir}/test-repository")
from configurations.testRepository
}
sourceSets {
main {
output.dir("$buildDir/generated-resources", builtBy: 'syncSpringBootDependenciesBom')
}
}
test {
dependsOn syncTestRepository
useJUnitPlatform()
}
task fullJar(type: Jar) {
classifier = 'full'
entryCompression = 'stored'
from(configurations.runtimeClasspath) {
into 'BOOT-INF/lib'
}
from(sourceSets.main.output) {
into 'BOOT-INF/classes'
}
into("") {
from zipTree(configurations.loader.singleFile)
}
manifest {
attributes(
'Class-Loader': 'groovy.lang.GroovyClassLoader',
'Main-Class': 'org.springframework.boot.loader.JarLauncher',
'Start-Class': 'org.springframework.boot.cli.SpringCli'
)
}
}
def configureArchive(archive) {
archive.classifier = 'bin'
archive.into "spring-${project.version}"
archive.from(fullJar) {
rename {
it.replace("-full", "")
}
into 'lib/'
}
archive.from(file('src/main/content')) {
eachFile { it.mode = it.directory ? 0x755 : 0x644 }
}
archive.from(file('src/main/executablecontent')) {
eachFile { it.mode = 0x755 }
}
}
task zip(type: Zip) {
classifier = 'bin'
configureArchive it
}
intTest {
dependsOn syncTestRepository, zip
}
task tar(type: Tar) {
compression = 'gzip'
archiveExtension = 'tar.gz'
configureArchive it
}
task scoopManifest(type: org.springframework.boot.build.cli.ScoopManifest) {
dependsOn zip
outputDir = file("$buildDir/scoop")
template = file('src/main/scoop/springboot.json')
archive = zip.archiveFile
}
def scoopManifestArtifact = artifacts.add('archives', file("$buildDir/scoop/springboot.json")) {
type 'json'
classifier 'scoop'
builtBy 'scoopManifest'
}
task homebrewFormula(type: org.springframework.boot.build.cli.HomebrewFormula) {
dependsOn tar
outputDir = file("$buildDir/homebrew")
template = file('src/main/homebrew/springboot.rb')
archive = tar.archiveFile
}
def homebrewFormulaArtifact = artifacts.add('archives', file("$buildDir/homebrew/springboot.rb")) {
type 'rb'
classifier 'homebrew'
builtBy 'homebrewFormula'
}
publishing {
publications {
getByName('maven') {
artifact fullJar
artifact tar
artifact zip
artifact scoopManifestArtifact
artifact homebrewFormulaArtifact
}
}
}

View File

@@ -1,469 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-parent</artifactId>
<version>${revision}</version>
<relativePath>../spring-boot-parent</relativePath>
</parent>
<artifactId>spring-boot-cli</artifactId>
<name>Spring Boot CLI</name>
<description>Spring Boot CLI</description>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
<start-class>org.springframework.boot.cli.SpringCli</start-class>
<spring.profiles.active>default</spring.profiles.active>
<generated.pom.dir>${project.build.directory}/generated-resources/org/springframework/boot/cli/compiler/dependencies</generated.pom.dir>
</properties>
<scm>
<url>${git.url}</url>
<connection>${git.connection}</connection>
<developerConnection>${git.developerConnection}</developerConnection>
</scm>
<dependencies>
<!-- Compile -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader-tools</artifactId>
</dependency>
<dependency>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</dependency>
<dependency>
<groupId>jline</groupId>
<artifactId>jline</artifactId>
</dependency>
<dependency>
<groupId>net.sf.jopt-simple</groupId>
<artifactId>jopt-simple</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
</dependency>
<dependency>
<groupId>org.sonatype.plexus</groupId>
<artifactId>plexus-sec-dispatcher</artifactId>
</dependency>
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
<exclusions>
<exclusion>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-bean</artifactId>
</exclusion>
<exclusion>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-settings-builder</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-file</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<exclusions>
<exclusion>
<artifactId>jcl-over-slf4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- Provided -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<type>effective-pom</type>
<scope>provided</scope>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-templates</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${project.build.directory}/generated-resources</directory>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>${project.build.directory}/generated-resources</additionalClasspathElement>
</additionalClasspathElements>
<systemPropertyVariables>
<spring.profiles.active>${spring.profiles.active}</spring.profiles.active>
</systemPropertyVariables>
</configuration>
</plugin>
<!-- Build an executable JAR manually since we can't easily depend on
a maven plugin that is part of the reactor -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-effective-pom</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<type>effective-pom</type>
<overWrite>true</overWrite>
<outputDirectory>${generated.pom.dir}</outputDirectory>
<destFileName>effective-pom.xml</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
<version>${project.version}</version>
<type>jar</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/assembly</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/assembly/BOOT-INF/lib</outputDirectory>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/jar-with-dependencies.xml</descriptor>
</descriptors>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<mainClass>org.springframework.boot.loader.JarLauncher</mainClass>
</manifest>
<manifestEntries>
<Start-Class>${start-class}</Start-Class>
<Class-Loader>groovy.lang.GroovyClassLoader</Class-Loader>
</manifestEntries>
</archive>
</configuration>
</execution>
<execution>
<id>bin-package</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/bin-package.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<dependencies>
<dependency>
<groupId>ant-contrib</groupId>
<artifactId>ant-contrib</artifactId>
<version>1.0b3</version>
<exclusions>
<exclusion>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-nodeps</artifactId>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>org.tigris.antelope</groupId>
<artifactId>antelopetasks</artifactId>
<version>3.2.10</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>homebrew</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<inherited>false</inherited>
<configuration>
<target>
<taskdef
resource="net/sf/antcontrib/antcontrib.properties" />
<taskdef name="stringutil"
classname="ise.antelope.tasks.StringUtilTask" />
<var name="version-type" value="${project.version}" />
<propertyregex property="version-type"
override="true" input="${version-type}" regexp=".*\.(.*)"
replace="\1" />
<propertyregex property="version-type"
override="true" input="${version-type}" regexp="(M)\d+"
replace="MILESTONE" />
<propertyregex property="version-type"
override="true" input="${version-type}" regexp="(RC)\d+"
replace="MILESTONE" />
<propertyregex property="version-type"
override="true" input="${version-type}" regexp="BUILD-(.*)"
replace="SNAPSHOT" />
<stringutil string="${version-type}" property="repo">
<lowercase />
</stringutil>
<checksum algorithm="sha-256"
file="${project.build.directory}/spring-boot-cli-${project.version}-bin.tar.gz"
property="checksum" />
<echo
message="Customizing homebrew for ${project.version} with checksum ${checksum} in ${repo} repo" />
<copy file="${basedir}/src/main/homebrew/springboot.rb"
tofile="${project.build.directory}/homebrew/springboot.rb"
overwrite="true">
<filterchain>
<expandproperties />
</filterchain>
</copy>
<attachartifact
file="${project.build.directory}/homebrew/springboot.rb"
classifier="homebrew" type="rb" />
</target>
</configuration>
</execution>
<execution>
<id>scoop</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<inherited>false</inherited>
<configuration>
<target>
<taskdef
resource="net/sf/antcontrib/antcontrib.properties" />
<taskdef name="stringutil"
classname="ise.antelope.tasks.StringUtilTask" />
<var name="scoop-version" value="${project.version}" />
<propertyregex property="scoop-version"
override="true" input="${scoop-version}" regexp="(.*)\..*"
replace="\1" />
<var name="version-type" value="${project.version}" />
<propertyregex property="version-type"
override="true" input="${version-type}" regexp=".*\.(.*)"
replace="\1" />
<propertyregex property="version-type"
override="true" input="${version-type}" regexp="(M)\d+"
replace="MILESTONE" />
<propertyregex property="version-type"
override="true" input="${version-type}" regexp="(RC)\d+"
replace="MILESTONE" />
<propertyregex property="version-type"
override="true" input="${version-type}" regexp="BUILD-(.*)"
replace="SNAPSHOT" />
<stringutil string="${version-type}" property="repo">
<lowercase />
</stringutil>
<checksum algorithm="sha-256"
file="${project.build.directory}/spring-boot-cli-${project.version}-bin.zip"
property="hash" />
<echo
message="Customizing scoop for ${project.version} with hash ${hash} in ${repo} repo" />
<copy file="${basedir}/src/main/scoop/springboot.json"
tofile="${project.build.directory}/scoop/springboot.json"
overwrite="true">
<filterchain>
<expandproperties>
<propertyset>
<propertyref name="scoop-version" />
<propertyref name="hash" />
<propertyref name="repo" />
<propertyref name="project.version" />
</propertyset>
</expandproperties>
</filterchain>
</copy>
<attachartifact
file="${project.build.directory}/scoop/springboot.json"
classifier="scoop" type="json" />
</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-test-source</id>
<phase>process-resources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/it/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>integration</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring.profiles.active>integration</spring.profiles.active>
</properties>
</profile>
<profile>
<id>java9+</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<dependencies>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

View File

@@ -43,39 +43,40 @@ class CommandLineIT {
this.cli = new CommandLineInvoker(tempDir);
}
@Test void hintProducesListOfValidCommands()
throws IOException, InterruptedException {
@Test
void hintProducesListOfValidCommands() throws IOException, InterruptedException {
Invocation cli = this.cli.invoke("hint");
assertThat(cli.await()).isEqualTo(0);
assertThat(cli.getErrorOutput()).isEmpty();
assertThat(cli.getStandardOutputLines()).hasSize(11);
}
@Test void invokingWithNoArgumentsDisplaysHelp()
throws IOException, InterruptedException {
@Test
void invokingWithNoArgumentsDisplaysHelp() throws IOException, InterruptedException {
Invocation cli = this.cli.invoke();
assertThat(cli.await()).isEqualTo(1);
assertThat(cli.getErrorOutput()).isEmpty();
assertThat(cli.getStandardOutput()).startsWith("usage:");
}
@Test void unrecognizedCommandsAreHandledGracefully()
throws IOException, InterruptedException {
@Test
void unrecognizedCommandsAreHandledGracefully() throws IOException, InterruptedException {
Invocation cli = this.cli.invoke("not-a-real-command");
assertThat(cli.await()).isEqualTo(1);
assertThat(cli.getErrorOutput())
.contains("'not-a-real-command' is not a valid command");
assertThat(cli.getErrorOutput()).contains("'not-a-real-command' is not a valid command");
assertThat(cli.getStandardOutput()).isEmpty();
}
@Test void version() throws IOException, InterruptedException {
@Test
void version() throws IOException, InterruptedException {
Invocation cli = this.cli.invoke("version");
assertThat(cli.await()).isEqualTo(0);
assertThat(cli.getErrorOutput()).isEmpty();
assertThat(cli.getStandardOutput()).startsWith("Spring CLI v");
}
@Test void help() throws IOException, InterruptedException {
@Test
void help() throws IOException, InterruptedException {
Invocation cli = this.cli.invoke("help");
assertThat(cli.await()).isEqualTo(1);
assertThat(cli.getErrorOutput()).isEmpty();

View File

@@ -37,8 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
class JarCommandIT {
private static final boolean JAVA_9_OR_LATER = isClassPresent(
"java.security.cert.URICertStoreParameters");
private static final boolean JAVA_9_OR_LATER = isClassPresent("java.security.cert.URICertStoreParameters");
private CommandLineInvoker cli;
@@ -46,31 +45,32 @@ class JarCommandIT {
@BeforeEach
void setup(@TempDir File tempDir) {
this.cli = new CommandLineInvoker(new File("src/it/resources/jar-command"),
tempDir);
this.cli = new CommandLineInvoker(new File("src/intTest/resources/jar-command"), tempDir);
this.tempDir = tempDir;
}
@Test void noArguments() throws Exception {
@Test
void noArguments() throws Exception {
Invocation invocation = this.cli.invoke("jar");
invocation.await();
assertThat(invocation.getStandardOutput()).isEqualTo("");
assertThat(invocation.getErrorOutput()).contains("The name of the "
+ "resulting jar and at least one source file must be specified");
assertThat(invocation.getErrorOutput())
.contains("The name of the " + "resulting jar and at least one source file must be specified");
}
@Test void noSources() throws Exception {
@Test
void noSources() throws Exception {
Invocation invocation = this.cli.invoke("jar", "test-app.jar");
invocation.await();
assertThat(invocation.getStandardOutput()).isEqualTo("");
assertThat(invocation.getErrorOutput()).contains("The name of the "
+ "resulting jar and at least one source file must be specified");
assertThat(invocation.getErrorOutput())
.contains("The name of the " + "resulting jar and at least one source file must be specified");
}
@Test void jarCreationWithGrabResolver() throws Exception {
@Test
void jarCreationWithGrabResolver() throws Exception {
File jar = new File(this.tempDir, "test-app.jar");
Invocation invocation = this.cli.invoke("run", jar.getAbsolutePath(),
"bad.groovy");
Invocation invocation = this.cli.invoke("run", jar.getAbsolutePath(), "bad.groovy");
invocation.await();
if (!JAVA_9_OR_LATER) {
assertThat(invocation.getErrorOutput()).isEqualTo("");
@@ -82,8 +82,7 @@ class JarCommandIT {
}
assertThat(jar).exists();
Process process = new JavaExecutable()
.processBuilder("-jar", jar.getAbsolutePath()).start();
Process process = new JavaExecutable().processBuilder("-jar", jar.getAbsolutePath()).start();
invocation = new Invocation(process);
invocation.await();
@@ -92,9 +91,33 @@ class JarCommandIT {
}
}
@Test void jarCreation() throws Exception {
@Test
void jarCreation() throws Exception {
File jar = new File(this.tempDir, "test-app.jar");
Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(),
Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(), "jar.groovy");
invocation.await();
if (!JAVA_9_OR_LATER) {
assertThat(invocation.getErrorOutput()).isEmpty();
}
assertThat(jar).exists();
Process process = new JavaExecutable().processBuilder("-jar", jar.getAbsolutePath()).start();
invocation = new Invocation(process);
invocation.await();
if (!JAVA_9_OR_LATER) {
assertThat(invocation.getErrorOutput()).isEqualTo("");
}
assertThat(invocation.getStandardOutput()).contains("Hello World!")
.contains("/BOOT-INF/classes!/public/public.txt").contains("/BOOT-INF/classes!/resources/resource.txt")
.contains("/BOOT-INF/classes!/static/static.txt").contains("/BOOT-INF/classes!/templates/template.txt")
.contains("/BOOT-INF/classes!/root.properties").contains("Goodbye Mama");
}
@Test
void jarCreationWithIncludes() throws Exception {
File jar = new File(this.tempDir, "test-app.jar");
Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(), "--include", "-public/**,-resources/**",
"jar.groovy");
invocation.await();
if (!JAVA_9_OR_LATER) {
@@ -102,42 +125,14 @@ class JarCommandIT {
}
assertThat(jar).exists();
Process process = new JavaExecutable()
.processBuilder("-jar", jar.getAbsolutePath()).start();
Process process = new JavaExecutable().processBuilder("-jar", jar.getAbsolutePath()).start();
invocation = new Invocation(process);
invocation.await();
if (!JAVA_9_OR_LATER) {
assertThat(invocation.getErrorOutput()).isEqualTo("");
}
assertThat(invocation.getStandardOutput()).contains("Hello World!")
.contains("/BOOT-INF/classes!/public/public.txt")
.contains("/BOOT-INF/classes!/resources/resource.txt")
.contains("/BOOT-INF/classes!/static/static.txt")
.contains("/BOOT-INF/classes!/templates/template.txt")
.contains("/BOOT-INF/classes!/root.properties").contains("Goodbye Mama");
}
@Test void jarCreationWithIncludes() throws Exception {
File jar = new File(this.tempDir, "test-app.jar");
Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(), "--include",
"-public/**,-resources/**", "jar.groovy");
invocation.await();
if (!JAVA_9_OR_LATER) {
assertThat(invocation.getErrorOutput()).isEmpty();
}
assertThat(jar).exists();
Process process = new JavaExecutable()
.processBuilder("-jar", jar.getAbsolutePath()).start();
invocation = new Invocation(process);
invocation.await();
if (!JAVA_9_OR_LATER) {
assertThat(invocation.getErrorOutput()).isEqualTo("");
}
assertThat(invocation.getStandardOutput()).contains("Hello World!")
.doesNotContain("/public/public.txt")
assertThat(invocation.getStandardOutput()).contains("Hello World!").doesNotContain("/public/public.txt")
.doesNotContain("/resources/resource.txt").contains("/static/static.txt")
.contains("/templates/template.txt").contains("Goodbye Mama");
}

View File

@@ -43,25 +43,22 @@ class WarCommandIT {
@BeforeEach
void setup(@TempDir File tempDir) {
this.cli = new CommandLineInvoker(new File("src/it/resources/war-command"),
tempDir);
this.cli = new CommandLineInvoker(new File("src/intTest/resources/war-command"), tempDir);
this.tempDir = tempDir;
}
@Test void warCreation() throws Exception {
@Test
void warCreation() throws Exception {
File war = new File(this.tempDir, "test-app.war");
Invocation invocation = this.cli.invoke("war", war.getAbsolutePath(),
"war.groovy");
Invocation invocation = this.cli.invoke("war", war.getAbsolutePath(), "war.groovy");
invocation.await();
assertThat(war.exists()).isTrue();
Process process = new JavaExecutable()
.processBuilder("-jar", war.getAbsolutePath(), "--server.port=0").start();
Process process = new JavaExecutable().processBuilder("-jar", war.getAbsolutePath(), "--server.port=0").start();
invocation = new Invocation(process);
invocation.await();
assertThat(invocation.getOutput()).contains("onStart error");
assertThat(invocation.getOutput()).contains("Tomcat started");
assertThat(invocation.getOutput())
.contains("/WEB-INF/lib-provided/tomcat-embed-core");
assertThat(invocation.getOutput()).contains("/WEB-INF/lib-provided/tomcat-embed-core");
assertThat(invocation.getOutput()).contains("WEB-INF/classes!/root.properties");
process.destroy();
}

View File

@@ -25,6 +25,10 @@ import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -63,19 +67,22 @@ public final class CommandLineInvoker {
}
private Process runCliProcess(String... args) throws IOException {
Path m2 = this.temp.toPath().resolve(".m2");
Files.createDirectories(m2);
Files.copy(Paths.get("src", "intTest", "resources", "settings.xml"), m2.resolve("settings.xml"),
StandardCopyOption.REPLACE_EXISTING);
List<String> command = new ArrayList<>();
command.add(findLaunchScript().getAbsolutePath());
command.addAll(Arrays.asList(args));
ProcessBuilder processBuilder = new ProcessBuilder(command)
.directory(this.workingDirectory);
processBuilder.environment().remove("JAVA_OPTS");
ProcessBuilder processBuilder = new ProcessBuilder(command).directory(this.workingDirectory);
processBuilder.environment().put("JAVA_OPTS", "-Duser.home=" + this.temp);
return processBuilder.start();
}
private File findLaunchScript() throws IOException {
File unpacked = new File(this.temp, "unpacked-cli");
if (!unpacked.isDirectory()) {
File zip = new BuildOutput(getClass()).getRootLocation()
File zip = new File(new BuildOutput(getClass()).getRootLocation(), "distributions")
.listFiles((pathname) -> pathname.getName().endsWith("-bin.zip"))[0];
try (ZipInputStream input = new ZipInputStream(new FileInputStream(zip))) {
ZipEntry entry;
@@ -99,8 +106,7 @@ public final class CommandLineInvoker {
File bin = new File(unpacked.listFiles()[0], "bin");
File launchScript = new File(bin, isWindows() ? "spring.bat" : "spring");
Assert.state(launchScript.exists() && launchScript.isFile(),
() -> "Could not find CLI launch script "
+ launchScript.getAbsolutePath());
() -> "Could not find CLI launch script " + launchScript.getAbsolutePath());
return launchScript;
}
@@ -125,10 +131,10 @@ public final class CommandLineInvoker {
public Invocation(Process process) {
this.process = process;
this.streamReaders.add(new Thread(new StreamReadingRunnable(
this.process.getErrorStream(), this.err, this.combined)));
this.streamReaders.add(new Thread(new StreamReadingRunnable(
this.process.getInputStream(), this.out, this.combined)));
this.streamReaders
.add(new Thread(new StreamReadingRunnable(this.process.getErrorStream(), this.err, this.combined)));
this.streamReaders
.add(new Thread(new StreamReadingRunnable(this.process.getInputStream(), this.out, this.combined)));
for (Thread streamReader : this.streamReaders) {
streamReader.start();
}
@@ -162,10 +168,8 @@ public final class CommandLineInvoker {
}
private List<String> getLines(StringBuffer buffer) {
BufferedReader reader = new BufferedReader(
new StringReader(buffer.toString()));
return reader.lines().filter((line) -> !line.startsWith("Picked up "))
.collect(Collectors.toList());
BufferedReader reader = new BufferedReader(new StringReader(buffer.toString()));
return reader.lines().filter((line) -> !line.startsWith("Picked up ")).collect(Collectors.toList());
}
public int await() throws InterruptedException {

View File

@@ -0,0 +1,23 @@
<settings>
<localRepository>../../../../build/local-m2-repository</localRepository>
<profiles>
<profile>
<id>cli-test-repo</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>local.central</id>
<url>file:../../../../build/test-repository</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
</settings>

View File

@@ -4,7 +4,7 @@ class Springboot < Formula
homepage 'https://spring.io/projects/spring-boot'
url 'https://repo.spring.io/${repo}/org/springframework/boot/spring-boot-cli/${project.version}/spring-boot-cli-${project.version}-bin.tar.gz'
version '${project.version}'
sha256 '${checksum}'
sha256 '${hash}'
head 'https://github.com/spring-projects/spring-boot.git'
if build.head?

View File

@@ -42,8 +42,8 @@ public class SpringBootDependenciesDependencyManagement extends MavenModelDepend
modelProcessor.setModelReader(new DefaultModelReader());
try {
return modelProcessor.read(
SpringBootDependenciesDependencyManagement.class.getResourceAsStream("effective-pom.xml"), null);
return modelProcessor.read(SpringBootDependenciesDependencyManagement.class
.getResourceAsStream("spring-boot-dependencies-effective-bom.xml"), null);
}
catch (IOException ex) {
throw new IllegalStateException("Failed to build model from effective pom", ex);

View File

@@ -17,7 +17,6 @@
package org.springframework.boot.cli.compiler.maven;
import java.io.File;
import java.lang.reflect.Field;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
@@ -83,21 +82,7 @@ public class MavenSettingsReader {
}
private SettingsDecrypter createSettingsDecrypter() {
SettingsDecrypter settingsDecrypter = new DefaultSettingsDecrypter();
setField(DefaultSettingsDecrypter.class, "securityDispatcher", settingsDecrypter,
new SpringBootSecDispatcher());
return settingsDecrypter;
}
private void setField(Class<?> sourceClass, String fieldName, Object target, Object value) {
try {
Field field = sourceClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to set field '" + fieldName + "' on '" + target + "'", ex);
}
return new DefaultSettingsDecrypter(new SpringBootSecDispatcher());
}
private class SpringBootSecDispatcher extends DefaultSecDispatcher {

View File

@@ -1,11 +1,11 @@
{
"homepage": "https://projects.spring.io/spring-boot/",
"version": "${scoop-version}",
"version": "${scoopVersion}",
"license": "Apache 2.0",
"hash": "${hash}",
"url": "https://repo.spring.io/${repo}/org/springframework/boot/spring-boot-cli/${project.version}/spring-boot-cli-${project.version}-bin.zip",
"extract_dir": "spring-${project.version}",
"bin": "bin\\spring.bat",
"bin": "bin\\\\spring.bat",
"suggest": {
"JDK": [
"java/oraclejdk",
@@ -14,13 +14,13 @@
},
"checkver": {
"github": "https://github.com/spring-projects/spring-boot",
"re": "/releases/tag/(?:v)?(2[\\d.]+)\\.RELEASE"
"re": "/releases/tag/(?:v)?(2[\\d.]+)\\\\.RELEASE"
},
"autoupdate": {
"url": "https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/$version.RELEASE/spring-boot-cli-$version.RELEASE-bin.zip",
"extract_dir": "spring-$version.RELEASE",
"url": "https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/\$version.RELEASE/spring-boot-cli-\$version.RELEASE-bin.zip",
"extract_dir": "spring-\$version.RELEASE",
"hash": {
"url": "$url.sha256"
"url": "\$url.sha256"
}
}
}

View File

@@ -96,12 +96,14 @@ public class CliTester implements BeforeEachCallback, AfterEachCallback {
for (String arg : args) {
if (arg.startsWith("--classpath=")) {
arg = arg + ":" + this.buildOutput.getTestClassesLocation().getAbsolutePath();
arg = arg + ":" + this.buildOutput.getTestResourcesLocation().getAbsolutePath();
classpathUpdated = true;
}
updatedArgs.add(arg);
}
if (!classpathUpdated) {
updatedArgs.add("--classpath=.:" + this.buildOutput.getTestClassesLocation().getAbsolutePath());
updatedArgs.add("--classpath=.:" + this.buildOutput.getTestClassesLocation().getAbsolutePath() + ":"
+ this.buildOutput.getTestResourcesLocation().getAbsolutePath());
}
Future<RunCommand> future = submitCommand(new RunCommand(), StringUtils.toStringArray(updatedArgs));
this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS));
@@ -134,6 +136,8 @@ public class CliTester implements BeforeEachCallback, AfterEachCallback {
"org.springframework.boot.cli.CliTesterSpringApplication");
this.serverPortFile = new File(this.temp, "server.port");
System.setProperty("portfile", this.serverPortFile.getAbsolutePath());
String userHome = System.getProperty("user.home");
System.setProperty("user.home", "src/test/resources/cli-tester");
try {
command.run(sources);
return command;
@@ -142,6 +146,7 @@ public class CliTester implements BeforeEachCallback, AfterEachCallback {
System.clearProperty("server.port");
System.clearProperty("spring.application.class.name");
System.clearProperty("portfile");
System.setProperty("user.home", userHome);
Thread.currentThread().setContextClassLoader(loader);
}
});

View File

@@ -57,15 +57,12 @@ class GrabCommandIntegrationTests {
@Test
void grab() throws Exception {
System.setProperty("grape.root", this.cli.getTemp().getAbsolutePath());
System.setProperty("groovy.grape.report.downloads", "true");
// Use --autoconfigure=false to limit the amount of downloaded dependencies
String output = this.cli.grab("grab.groovy", "--autoconfigure=false");
assertThat(new File(this.cli.getTemp(), "repository/joda-time/joda-time")).isDirectory();
// Should be resolved from local repository cache
assertThat(output.contains("Downloading: file:")).isTrue();
assertThat(output).contains("Downloading: ");
}
@Test

View File

@@ -42,7 +42,7 @@ class RunCommandIntegrationTests {
CliTester cli;
RunCommandIntegrationTests(CapturedOutput output) {
this.cli = new CliTester("src/it/resources/run-command/", output);
this.cli = new CliTester("src/test/resources/run-command/", output);
}
private Properties systemProperties = new Properties();

View File

@@ -19,7 +19,6 @@ package org.springframework.boot.cli.compiler.dependencies;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.empty;
/**
* Tests for {@link SpringBootDependenciesDependencyManagement}
@@ -45,7 +44,7 @@ class SpringBootDependenciesDependencyManagementTests {
@Test
void getDependencies() {
assertThat(this.dependencyManagement.getDependencies()).isNotEqualTo(empty());
assertThat(this.dependencyManagement.getDependencies()).isNotEmpty();
}
}

View File

@@ -47,9 +47,12 @@ class AetherGrapeEngineTests {
private final GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
private final RepositoryConfiguration springMilestones = new RepositoryConfiguration("spring-milestones",
private final RepositoryConfiguration springMilestone = new RepositoryConfiguration("spring-milestone",
URI.create("https://repo.spring.io/milestone"), false);
private final RepositoryConfiguration springSnaphot = new RepositoryConfiguration("spring-snapshot",
URI.create("https://repo.spring.io/snapshot"), true);
private AetherGrapeEngine createGrapeEngine(RepositoryConfiguration... additionalRepositories) {
List<RepositoryConfiguration> repositoryConfigurations = new ArrayList<>();
repositoryConfigurations
@@ -64,7 +67,7 @@ class AetherGrapeEngineTests {
@Test
void dependencyResolution() {
Map<String, Object> args = new HashMap<>();
createGrapeEngine(this.springMilestones).grab(args,
createGrapeEngine(this.springMilestone, this.springSnaphot).grab(args,
createDependency("org.springframework", "spring-jdbc", null));
assertThat(this.groovyClassLoader.getURLs()).hasSize(5);
}
@@ -104,7 +107,7 @@ class AetherGrapeEngineTests {
Map<String, Object> args = new HashMap<>();
args.put("excludes", Arrays.asList(createExclusion("org.springframework", "spring-core")));
createGrapeEngine(this.springMilestones).grab(args,
createGrapeEngine(this.springMilestone, this.springSnaphot).grab(args,
createDependency("org.springframework", "spring-jdbc", "3.2.4.RELEASE"),
createDependency("org.springframework", "spring-beans", "3.2.4.RELEASE"));
@@ -126,7 +129,7 @@ class AetherGrapeEngineTests {
GroovyClassLoader customClassLoader = new GroovyClassLoader();
args.put("classLoader", customClassLoader);
createGrapeEngine(this.springMilestones).grab(args,
createGrapeEngine(this.springMilestone, this.springSnaphot).grab(args,
createDependency("org.springframework", "spring-jdbc", null));
assertThat(this.groovyClassLoader.getURLs()).isEmpty();

View File

@@ -2,7 +2,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>build/local-m2-repository</localRepository>
<mirrors>
<mirror>
<id>central-mirror</id>
@@ -10,7 +10,6 @@
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<servers>
<server>
<id>central-mirror</id>
@@ -18,7 +17,6 @@
<password>password</password>
</server>
</servers>
<proxies>
<proxy>
<active>true</active>
@@ -29,5 +27,4 @@
<password>password</password>
</proxy>
</proxies>
</settings>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<localRepository>build/local-m2-repository</localRepository>
<profiles>
<profile>
<id>cli-test-repo</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>local.central</id>
<url>file:build/test-repository</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshot</id>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/milestone</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
</settings>

View File

@@ -0,0 +1,10 @@
package org.test
@Component
class Example implements CommandLineRunner {
void run(String... args) {
print "Ssshh"
}
}