Add DevTools build customizers

Using Spring Boot DevTools requires customizers for both the Maven and
the Gradle build. While the library can't have an opinion about the id
of the "devtools" dependency, it can provide the logic with a
configurable dependency identifier.

This commit adds such configurable customizers.

Closes gh-1135
This commit is contained in:
Stephane Nicoll 2020-11-13 16:15:13 +01:00
parent f2accaa7f7
commit e9b3ca74c3
5 changed files with 266 additions and 0 deletions

View File

@ -0,0 +1,67 @@
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.spring.initializr.generator.spring.dependency.devtools;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.gradle.GradleBuild;
import io.spring.initializr.generator.buildsystem.gradle.GradleDependency;
import io.spring.initializr.generator.spring.build.BuildCustomizer;
import io.spring.initializr.generator.version.Version;
import io.spring.initializr.generator.version.VersionParser;
import io.spring.initializr.generator.version.VersionRange;
/**
* Gradle {@link BuildCustomizer} that creates a dedicated "developmentOnly" configuration
* when devtools is selected.
*
* @author Stephane Nicoll
*/
public class DevToolsGradleBuildCustomizer implements BuildCustomizer<GradleBuild> {
private static final VersionRange SPRING_BOOT_2_3_0_RC1_OR_LATER = VersionParser.DEFAULT.parseRange("2.3.0.RC1");
private final Version platformVersion;
private final String devtoolsDependencyId;
/**
* Create a new instance with the requested {@link Version platform version} and the
* identifier for the devtools dependency.
* @param platformVersion the version of the plateform
* @param devtoolsDependencyId the id of the devtools dependency
*/
public DevToolsGradleBuildCustomizer(Version platformVersion, String devtoolsDependencyId) {
this.platformVersion = platformVersion;
this.devtoolsDependencyId = devtoolsDependencyId;
}
@Override
public void customize(GradleBuild build) {
Dependency devtools = build.dependencies().get(this.devtoolsDependencyId);
if (devtools == null) {
return;
}
if (!SPRING_BOOT_2_3_0_RC1_OR_LATER.match(this.platformVersion)) {
build.configurations().add("developmentOnly");
build.configurations().customize("runtimeClasspath",
(runtimeClasspath) -> runtimeClasspath.extendsFrom("developmentOnly"));
}
build.dependencies().add(this.devtoolsDependencyId,
GradleDependency.from(devtools).configuration("developmentOnly"));
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.spring.initializr.generator.spring.dependency.devtools;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.maven.MavenBuild;
import io.spring.initializr.generator.buildsystem.maven.MavenDependency;
import io.spring.initializr.generator.spring.build.BuildCustomizer;
/**
* Maven {@link BuildCustomizer} that sets the "optional" flag when devtools is selected.
*
* @author Stephane Nicoll
*/
public class DevToolsMavenBuildCustomizer implements BuildCustomizer<MavenBuild> {
private final String devtoolsDependencyId;
/**
* Create a new instance with the identifier for the devtools dependency.
* @param devtoolsDependencyId the id of the devtools dependency
*/
public DevToolsMavenBuildCustomizer(String devtoolsDependencyId) {
this.devtoolsDependencyId = devtoolsDependencyId;
}
@Override
public void customize(MavenBuild build) {
Dependency devtools = build.dependencies().get(this.devtoolsDependencyId);
if (devtools != null) {
build.dependencies().add("devtools", MavenDependency.from(devtools).optional(true));
}
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Customizations for Spring Boot DevTools.
*/
package io.spring.initializr.generator.spring.dependency.devtools;

View File

@ -0,0 +1,74 @@
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.spring.initializr.generator.spring.dependency.devtools;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.gradle.GradleBuild;
import io.spring.initializr.generator.buildsystem.gradle.GradleDependency;
import io.spring.initializr.generator.version.Version;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link DevToolsGradleBuildCustomizer}.
*
* @author Stephane Nicoll
*/
class DevToolsGradleBuildCustomizerTests {
private static final Dependency DEVTOOLS_DEPENDENCY = Dependency
.withCoordinates("org.springframework.boot", "spring-boot-devtools").build();
@Test
void gradleWithDevtoolsAndSpringBootPriorTo23RC1CreatesDevelopmentOnlyConfiguration() {
GradleBuild build = new GradleBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
new DevToolsGradleBuildCustomizer(Version.parse("2.3.0.M4"), "devtools").customize(build);
assertThat(build.configurations().names()).containsOnly("developmentOnly");
assertThat(build.configurations().customizations()).singleElement().satisfies((configuration) -> {
assertThat(configuration.getName()).isEqualTo("runtimeClasspath");
assertThat(configuration.getExtendsFrom()).containsOnly("developmentOnly");
});
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(GradleDependency.class);
assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly");
}
@Test
void gradleWithDevtoolsAndSpringBoot23RC1OrLaterDoesNotCreateDevelopmentOnlyConfiguration() {
GradleBuild build = new GradleBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
new DevToolsGradleBuildCustomizer(Version.parse("2.3.0.RC1"), "devtools").customize(build);
assertThat(build.configurations().names()).isEmpty();
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(GradleDependency.class);
assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly");
}
@Test
void gradleWithoutDevtoolsAndSpringBootPriorTo23RC1DoesNotCreateDevelopmentOnlyConfiguration() {
GradleBuild build = new GradleBuild();
build.dependencies().add("web", mock(Dependency.class));
new DevToolsGradleBuildCustomizer(Version.parse("2.3.0.M4"), "devtools").customize(build);
assertThat(build.configurations().names()).isEmpty();
assertThat(build.dependencies().ids()).containsOnly("web");
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.spring.initializr.generator.spring.dependency.devtools;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.maven.MavenBuild;
import io.spring.initializr.generator.buildsystem.maven.MavenDependency;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link DevToolsMavenBuildCustomizer}.
*
* @author Stephane Nicoll
*/
class DevToolsMavenBuildCustomizerTests {
private static final Dependency DEVTOOLS_DEPENDENCY = Dependency
.withCoordinates("org.springframework.boot", "spring-boot-devtools").build();
@Test
void mavenWithDevtoolsSwitchOptionalFlag() {
MavenBuild build = new MavenBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
new DevToolsMavenBuildCustomizer("devtools").customize(build);
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(MavenDependency.class);
assertThat(((MavenDependency) devtools).isOptional()).isTrue();
}
@Test
void mavenWithoutDevtoolsDoesNotChangeDependencies() {
MavenBuild build = new MavenBuild();
build.dependencies().add("web", mock(Dependency.class));
new DevToolsMavenBuildCustomizer("devtools").customize(build);
assertThat(build.dependencies().ids()).containsOnly("web");
}
}