Associate property to bom version

This commit allows to specify a property for the version of a BOM. If
that value is defined, a version property is automatically added to the
build to allow to easily configure the value.

Closes gh-181
This commit is contained in:
Stephane Nicoll 2016-07-20 11:53:35 +02:00
parent d9c65a5a07
commit fb7b8eb5cb
9 changed files with 191 additions and 15 deletions

View File

@ -222,13 +222,11 @@ class ProjectGenerator {
def dependencyIds = dependencies.collect { it.id }
log.info("Processing request{type=$request.type, dependencies=$dependencyIds}")
request.properties.each { model[it.key] = it.value }
if (isMavenBuild(request)) {
ParentPom parentPom = metadata.configuration.env.maven.resolveParentPom(request.bootVersion)
if (parentPom.includeSpringBootBom && !request.boms['spring-boot']) {
request.buildProperties.versions['spring-boot.version'] = { request.bootVersion }
request.boms['spring-boot'] = metadata.createSpringBootBom('${spring-boot.version}')
request.boms['spring-boot'] = metadata.createSpringBootBom(
request.bootVersion, 'spring-boot.version')
}
model['mavenParentGroupId'] = parentPom.groupId
@ -242,6 +240,12 @@ class ProjectGenerator {
model['providedDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_PROVIDED)
model['testDependencies'] = filterDependencies(dependencies, Dependency.SCOPE_TEST)
request.boms.each { k, v ->
if (v.versionProperty) {
request.buildProperties.versions[v.versionProperty] = { v.version }
}
}
// Add various versions
model['dependencyManagementPluginVersion'] = metadata.configuration.env.gradle.dependencyManagementPluginVersion
model['kotlinVersion'] = metadata.configuration.env.kotlin.version
@ -260,6 +264,9 @@ class ProjectGenerator {
// New Servlet Initializer location
model['newServletInitializer'] = isNewServletInitializerAvailable(request)
// Append the project request to the model
request.properties.each { model[it.key] = it.value }
model
}

View File

@ -41,6 +41,13 @@ class BillOfMaterials {
*/
String version
/**
* The property to use to externalize the version of the BOM. When this is set,
* a version property is automatically added rather than setting the version
* in the bom declaration itself.
*/
String versionProperty
/**
* The BOM(s) that should be automatically included if this BOM is required. Can be
* {@code null} if it is provided via a mapping.
@ -55,6 +62,15 @@ class BillOfMaterials {
final List<Mapping> mappings = []
/**
* Determine the version placeholder to use for this instance. If a version
* property is defined, this returns the reference for the property. Otherwise
* this returns the plain {@link #version}
*/
String determineVersionToken() {
return (versionProperty ? '${' + versionProperty + '}' : version)
}
void validate() {
if (!version && !mappings) {
throw new InvalidInitializrMetadataException("No version available for $this");
@ -81,7 +97,7 @@ class BillOfMaterials {
for (Mapping mapping : mappings) {
if (mapping.range.match(bootVersion)) {
def resolvedBom = new BillOfMaterials(groupId: groupId, artifactId: artifactId,
version: mapping.version)
version: mapping.version, versionProperty: versionProperty)
resolvedBom.repositories += mapping.repositories ?: repositories
resolvedBom.additionalBoms += mapping.additionalBoms ?: additionalBoms
return resolvedBom

View File

@ -147,9 +147,9 @@ class InitializrMetadata {
/**
* Create a {@link BillOfMaterials} for the spring boot BOM.
*/
BillOfMaterials createSpringBootBom(String bootVersion) {
BillOfMaterials createSpringBootBom(String bootVersion, String versionProperty) {
new BillOfMaterials(groupId: 'org.springframework.boot', artifactId: 'spring-boot-dependencies',
version: bootVersion)
version: bootVersion, versionProperty: versionProperty)
}
/**

View File

@ -51,8 +51,8 @@ dependencies {<% compileDependencies.each { %>
}
<% if (boms) { %>
dependencyManagement {
imports { <% boms.values().each { %>
mavenBom "${it.groupId}:${it.artifactId}${it.version ? ":$it.version" : ""}" <% } %>
imports {<% boms.values().each { %>
mavenBom "${it.groupId}:${it.artifactId}:${it.determineVersionToken()}"<% } %>
}
}
<% } %>

View File

@ -73,13 +73,13 @@
<dependency>
<groupId>${it.groupId}</groupId>
<artifactId>${it.artifactId}</artifactId>
<version>${it.version}</version>
<version>${it.determineVersionToken()}</version>
<type>pom</type>
<scope>import</scope>
</dependency><% } %>
</dependencies>
</dependencyManagement>
<% } %>
<% } %>
<build><% if (language=='kotlin') { %>
<sourceDirectory>\${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>\${project.basedir}/src/test/kotlin</testSourceDirectory><% } %>

View File

@ -16,6 +16,9 @@
package io.spring.initializr.generator
import io.spring.initializr.metadata.BillOfMaterials
import io.spring.initializr.metadata.Dependency
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@ -69,7 +72,6 @@ class ProjectGeneratorBuildTests extends AbstractProjectGeneratorTests {
private void testStandardJar(def language) {
def request = createProjectRequest()
request.language = language
request.type = "$build-project"
def project = generateProject(request)
project.sourceCodeAssert("$fileName")
.equalsTo(new ClassPathResource("project/$language/standard/$assertFileName"))
@ -94,7 +96,6 @@ class ProjectGeneratorBuildTests extends AbstractProjectGeneratorTests {
def request = createProjectRequest('web')
request.packaging = 'war'
request.language = language
request.type = "$build-project"
def project = generateProject(request)
project.sourceCodeAssert("$fileName")
.equalsTo(new ClassPathResource("project/$language/war/$assertFileName"))
@ -103,7 +104,6 @@ class ProjectGeneratorBuildTests extends AbstractProjectGeneratorTests {
@Test
public void versionOverride() {
def request = createProjectRequest('web')
request.type = "$build-project"
request.buildProperties.versions['spring-foo.version'] = {'0.1.0.RELEASE'}
request.buildProperties.versions['spring-bar.version'] = {'0.2.0.RELEASE'}
def project = generateProject(request)
@ -111,4 +111,26 @@ class ProjectGeneratorBuildTests extends AbstractProjectGeneratorTests {
.equalsTo(new ClassPathResource("project/$build/version-override-$assertFileName"))
}
@Test
public void bomWithVersionProperty() {
def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', bom: 'the-bom')
def bom = new BillOfMaterials(groupId: 'org.acme', artifactId: 'foo-bom',
version: '1.3.3', versionProperty: 'foo.version')
def metadata = InitializrMetadataTestBuilder.withDefaults()
.addDependencyGroup('foo', foo)
.addBom('the-bom', bom).build()
applyMetadata(metadata)
def request = createProjectRequest('foo')
def project = generateProject(request)
project.sourceCodeAssert("$fileName")
.equalsTo(new ClassPathResource("project/$build/bom-property-$assertFileName"))
}
@Override
ProjectRequest createProjectRequest(String... styles) {
def request = super.createProjectRequest(styles)
request.type = "$build-project"
request
}
}

View File

@ -22,6 +22,7 @@ import org.junit.Test
import org.junit.rules.ExpectedException
import static org.hamcrest.CoreMatchers.equalTo
import static org.hamcrest.CoreMatchers.nullValue
import static org.hamcrest.CoreMatchers.sameInstance
import static org.junit.Assert.assertThat
@ -45,7 +46,8 @@ class BillOfMaterialsTests {
@Test
void resolveSimpleRange() {
BillOfMaterials bom = new BillOfMaterials(groupId: 'com.example', artifactId: 'bom',
version: '1.0.0', repositories: ['repo-main'], additionalBoms: ['bom-main'])
version: '1.0.0', versionProperty: "bom.version",
repositories: ['repo-main'], additionalBoms: ['bom-main'])
bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)',
version: '1.1.0')
bom.validate()
@ -53,6 +55,7 @@ class BillOfMaterialsTests {
assertThat(resolved.groupId, equalTo('com.example'))
assertThat(resolved.artifactId, equalTo('bom'))
assertThat(resolved.version, equalTo('1.1.0'))
assertThat(resolved.versionProperty, equalTo('bom.version'))
assertThat(resolved.repositories.size(), equalTo(1))
assertThat(resolved.repositories[0], equalTo('repo-main'))
assertThat(resolved.additionalBoms.size(), equalTo(1))
@ -70,12 +73,27 @@ class BillOfMaterialsTests {
assertThat(resolved.groupId, equalTo('com.example'))
assertThat(resolved.artifactId, equalTo('bom'))
assertThat(resolved.version, equalTo('1.1.0'))
assertThat(resolved.versionProperty, nullValue())
assertThat(resolved.repositories.size(), equalTo(1))
assertThat(resolved.repositories[0], equalTo('repo-foo'))
assertThat(resolved.additionalBoms.size(), equalTo(1))
assertThat(resolved.additionalBoms[0], equalTo('bom-foo'))
}
@Test
void resolveRangeOverrideAndMapping() {
BillOfMaterials bom = new BillOfMaterials(groupId: 'com.example',
artifactId: 'bom', version: '1.0.0', versionProperty: 'example.version')
bom.mappings << new BillOfMaterials.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)',
version: '1.1.0')
bom.validate()
BillOfMaterials resolved = bom.resolve(Version.parse('1.2.3.RELEASE'))
assertThat(resolved.groupId, equalTo('com.example'))
assertThat(resolved.artifactId, equalTo('bom'))
assertThat(resolved.version, equalTo('1.1.0'))
assertThat(resolved.versionProperty, equalTo('example.version'))
}
@Test
void noRangeAvailable() {
BillOfMaterials bom = new BillOfMaterials(groupId: 'com.example', artifactId: 'bom')

View File

@ -0,0 +1,50 @@
buildscript {
ext {
springBootVersion = '1.2.3.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath('io.spring.gradle:dependency-management-plugin:0.5.1.RELEASE')
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
apply plugin: 'io.spring.dependency-management'
jar {
baseName = 'demo'
version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
ext['foo.version'] = '1.3.3'
dependencies {
compile('org.acme:foo')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
mavenBom "org.acme:foo-bom:${foo.version}"
}
}
eclipse {
classpath {
containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
}
}

View File

@ -0,0 +1,63 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<foo.version>1.3.3</foo.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.acme</groupId>
<artifactId>foo</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.acme</groupId>
<artifactId>foo-bom</artifactId>
<version>${foo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>