Include the Spring Build Conventions Gradle Plugins in Gradle buildSrc.

Include the Spring Maven Gradle Plugin in Gradle buildSrc.

Include the Spring PropDeps Gradle Plugin in Gradle buildSrc.

Include the Spring Sagan (spring.io website) Gradle Plugin in Gradle buildSrc.

(Optional?) Include the Spring GitHub Milestone Gradle Plugin in Gradle buildSrc.
This commit is contained in:
John Blum
2021-11-16 17:10:49 -08:00
parent dd3389f8f4
commit 7bf623894f
68 changed files with 2980 additions and 0 deletions

86
buildSrc/build.gradle Normal file
View File

@@ -0,0 +1,86 @@
plugins {
id "java-gradle-plugin"
id "java"
id "groovy"
}
sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
gradlePluginPortal()
maven { url 'https://repo.spring.io/plugins-release/' }
}
sourceSets {
main {
java {
srcDirs = []
}
groovy {
srcDirs += ["src/main/java"]
}
}
}
gradlePlugin {
plugins {
managementConfiguration {
id = "io.spring.convention.management-configuration"
implementationClass = "io.spring.gradle.convention.ManagementConfigurationPlugin"
}
sagan {
id = "org.springframework.security.sagan"
implementationClass = "org.springframework.gradle.sagan.SaganPlugin"
}
githubMilestone {
id = "org.springframework.github.milestone"
implementationClass = "org.springframework.gradle.github.milestones.GitHubMilestonePlugin"
}
propdeps {
id = "org.springframework.propdeps"
implementationClass = "org.springframework.gradle.propdeps.PropDepsPlugin"
}
}
}
configurations {
implementation {
exclude module: 'groovy-all'
}
}
dependencies {
implementation 'com.google.code.gson:gson:2.8.8'
implementation 'net.sourceforge.saxon:saxon:9.1.0.8'
implementation localGroovy()
implementation 'io.github.gradle-nexus:publish-plugin:1.1.0'
implementation 'io.spring.gradle:dependency-management-plugin:1.0.10.RELEASE'
implementation 'io.projectreactor:reactor-core:3.4.11'
implementation 'com.apollographql.apollo:apollo-runtime:2.4.5'
implementation 'com.github.ben-manes:gradle-versions-plugin:0.38.0'
implementation 'com.github.spullara.mustache.java:compiler:0.9.10'
implementation 'io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.15'
implementation 'io.spring.nohttp:nohttp-gradle:0.0.9'
implementation 'net.sourceforge.htmlunit:htmlunit:2.55.0'
implementation 'org.hidetake:gradle-ssh-plugin:2.10.1'
implementation 'org.jfrog.buildinfo:build-info-extractor-gradle:4.24.20'
implementation 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
testImplementation platform('org.junit:junit-bom:5.8.1')
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.jupiter:junit-jupiter-params"
testImplementation "org.junit.jupiter:junit-jupiter-engine"
testImplementation 'org.apache.commons:commons-io:1.3.2'
testImplementation 'org.assertj:assertj-core:3.21.0'
testImplementation 'org.mockito:mockito-core:4.0.0'
testImplementation 'org.mockito:mockito-junit-jupiter:3.12.4'
testImplementation 'com.squareup.okhttp3:mockwebserver:3.14.9'
}
test {
onlyIf { !project.hasProperty("buildSrc.skipTests") }
useJUnitPlatform()
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2002-2021 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.gradle
import groovy.transform.CompileStatic
import groovy.transform.TypeChecked
import groovy.transform.TypeCheckingMode
import org.gradle.api.DefaultTask
import org.gradle.api.Task
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
/**
* Checkout a project template from a git repository.
*
* @author Marcus Da Coregio
*/
@CompileStatic
abstract class IncludeRepoTask extends DefaultTask {
private static final String DEFAULT_URI_PREFIX = 'https://github.com/'
/**
* Git repository to use. Will be prefixed with {@link #DEFAULT_URI_PREFIX} if it isn't already
* @return
*/
@Input
abstract Property<String> getRepository();
/**
* Git reference to use.
*/
@Input
abstract Property<String> getRef()
/**
* Directory where the project template should be copied.
*/
@OutputDirectory
final File outputDirectory = project.file("$project.buildDir/$name")
@TaskAction
void checkoutAndCopy() {
outputDirectory.deleteDir()
File checkoutDir = checkout(this, getRemoteUri(), ref.get())
moveToOutputDir(checkoutDir, outputDirectory)
}
private static File cleanTemporaryDir(Task task, File tmpDir) {
if (tmpDir.exists()) {
task.project.delete(tmpDir)
}
return tmpDir
}
static File checkout(Task task, String remoteUri, String ref) {
checkout(task, remoteUri, ref, task.getTemporaryDir())
}
@TypeChecked(TypeCheckingMode.SKIP)
static File checkout(Task task, String remoteUri, String ref, File checkoutDir) {
cleanTemporaryDir(task, checkoutDir)
task.project.exec {
commandLine = ["git", "clone", "--no-checkout", remoteUri, checkoutDir.absolutePath]
errorOutput = System.err
}
task.project.exec {
commandLine = ["git", "checkout", ref]
workingDir = checkoutDir
errorOutput = System.err
}
return checkoutDir
}
private static void moveToOutputDir(File tmpDir, File outputDirectory) {
File baseDir = tmpDir
baseDir.renameTo(outputDirectory)
}
private String getRemoteUri() {
String remoteUri = this.repository.get()
if (remoteUri.startsWith(DEFAULT_URI_PREFIX)) {
return remoteUri
}
return DEFAULT_URI_PREFIX + remoteUri
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2002-2016 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.gradle.convention;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.GroovyPlugin;
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.PluginManager;
import org.gradle.plugins.ide.eclipse.EclipseWtpPlugin;
import org.gradle.plugins.ide.idea.IdeaPlugin;
import org.springframework.gradle.CopyPropertiesPlugin
import org.springframework.gradle.propdeps.PropDepsEclipsePlugin
import org.springframework.gradle.propdeps.PropDepsIdeaPlugin
import org.springframework.gradle.propdeps.PropDepsPlugin;
/**
* @author Rob Winch
*/
public abstract class AbstractSpringJavaPlugin implements Plugin<Project> {
@Override
public final void apply(Project project) {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(JavaPlugin.class);
pluginManager.apply(ManagementConfigurationPlugin.class)
if (project.file("src/main/groovy").exists()
|| project.file("src/test/groovy").exists()
|| project.file("src/integration-test/groovy").exists()) {
pluginManager.apply(GroovyPlugin.class);
}
pluginManager.apply("io.spring.convention.repository");
pluginManager.apply(EclipseWtpPlugin);
pluginManager.apply(IdeaPlugin);
pluginManager.apply(PropDepsPlugin);
pluginManager.apply(PropDepsEclipsePlugin);
pluginManager.apply(PropDepsIdeaPlugin);
pluginManager.apply("io.spring.convention.tests-configuration");
pluginManager.apply("io.spring.convention.integration-test");
pluginManager.apply("io.spring.convention.springdependencymangement");
pluginManager.apply("io.spring.convention.javadoc-options");
pluginManager.apply("io.spring.convention.checkstyle");
pluginManager.apply(CopyPropertiesPlugin);
project.jar {
manifest.attributes["Created-By"] =
"${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})"
manifest.attributes["Implementation-Title"] = project.name
manifest.attributes["Implementation-Version"] = project.version
manifest.attributes["Automatic-Module-Name"] = project.name.replace('-', '.')
}
project.test {
useJUnitPlatform()
}
additionalPlugins(project);
}
protected abstract void additionalPlugins(Project project);
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2017 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.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
class ArtifactoryPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.plugins.apply('com.jfrog.artifactory')
String name = Utils.getProjectName(project);
boolean isSnapshot = Utils.isSnapshot(project);
boolean isMilestone = Utils.isMilestone(project);
project.artifactory {
contextUrl = 'https://repo.spring.io'
publish {
repository {
repoKey = isSnapshot ? 'libs-snapshot-local' : isMilestone ? 'libs-milestone-local' : 'libs-release-local'
if(project.hasProperty('artifactoryUsername')) {
username = artifactoryUsername
password = artifactoryPassword
}
}
defaults {
publications('mavenJava')
}
}
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2016-2021 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.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
/**
* Adds and configures Checkstyle plugin.
*
* @author Vedran Pavic
*/
class CheckstylePlugin implements Plugin<Project> {
final CHECKSTYLE_DIR = 'etc/checkstyle'
@Override
void apply(Project project) {
project.plugins.withType(JavaPlugin) {
def checkstyleDir = project.rootProject.file(CHECKSTYLE_DIR)
if (checkstyleDir.exists() && checkstyleDir.directory) {
project.getPluginManager().apply('checkstyle')
project.dependencies.add('checkstyle', 'io.spring.javaformat:spring-javaformat-checkstyle:0.0.29')
project.dependencies.add('checkstyle', 'io.spring.nohttp:nohttp-checkstyle:0.0.3.RELEASE')
project.checkstyle {
configDirectory = checkstyleDir
toolVersion = '8.21'
}
}
}
}
}

View File

@@ -0,0 +1,61 @@
package io.spring.gradle.convention
import org.gradle.api.Project
import org.gradle.api.artifacts.component.ModuleComponentSelector
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.Properties;
import org.gradle.api.DefaultTask;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.tasks.TaskAction;
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension;
public class DependencyManagementExportTask extends DefaultTask {
@Internal
def projects;
@Input
String getProjectNames() {
return projects*.name
}
@TaskAction
public void dependencyManagementExport() throws IOException {
def projects = this.projects ?: project.subprojects + project
def configurations = projects*.configurations*.findAll { ['testRuntime','integrationTestRuntime','grettyRunnerTomcat8','ajtools'].contains(it.name) }
def dependencyResults = configurations*.incoming*.resolutionResult*.allDependencies.flatten()
def moduleVersionVersions = dependencyResults.findAll { r -> r.requested instanceof ModuleComponentSelector }.collect { r-> r.selected.moduleVersion }
def projectDependencies = projects.collect { p-> "${p.group}:${p.name}:${p.version}".toString() } as Set
def dependencies = moduleVersionVersions.collect { d ->
"${d.group}:${d.name}:${d.version}".toString()
}.sort() as Set
println ''
println ''
println 'dependencyManagement {'
println '\tdependencies {'
dependencies.findAll { d-> !projectDependencies.contains(d)}.each {
println "\t\tdependency '$it'"
}
println '\t}'
println '}'
println ''
println ''
println 'TIP Use this to find duplicates:\n$ sort gradle/dependency-management.gradle| uniq -c | grep -v \'^\\s*1\''
println ''
println ''
}
void setOutputFile(File file) throws IOException {
this.output = new FileOutputStream(file);
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2002-2017 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.gradle.convention
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.Plugin
import org.gradle.api.Project
public class DeployDocsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPluginManager().apply('org.hidetake.ssh')
project.ssh.settings {
knownHosts = allowAnyHosts
}
project.remotes {
docs {
role 'docs'
if (project.hasProperty('deployDocsHost')) {
host = project.findProperty('deployDocsHost')
} else {
host = 'docs.af.pivotal.io'
}
retryCount = 5 // retry 5 times (default is 0)
retryWaitSec = 10 // wait 10 seconds between retries (default is 0)
user = project.findProperty('deployDocsSshUsername')
if (project.hasProperty('deployDocsSshKeyPath')) {
identity = project.file(project.findProperty('deployDocsSshKeyPath'))
} else if (project.hasProperty('deployDocsSshKey')) {
identity = project.findProperty('deployDocsSshKey')
}
if(project.hasProperty('deployDocsSshPassphrase')) {
passphrase = project.findProperty('deployDocsSshPassphrase')
}
}
}
project.task('deployDocs') {
dependsOn 'docsZip'
doFirst {
project.ssh.run {
session(project.remotes.docs) {
def now = System.currentTimeMillis()
def name = project.rootProject.name
def version = project.rootProject.version
def tempPath = "/tmp/${name}-${now}-docs/".replaceAll(' ', '_')
execute "mkdir -p $tempPath"
project.tasks.docsZip.outputs.each { o ->
put from: o.files, into: tempPath
}
execute "unzip $tempPath*.zip -d $tempPath"
def extractPath = "/var/www/domains/spring.io/docs/htdocs/autorepo/docs/${name}/${version}/"
execute "rm -rf $extractPath"
execute "mkdir -p $extractPath"
execute "mv $tempPath/docs/* $extractPath"
execute "chmod -R g+w $extractPath"
}
}
}
}
}
}

View File

@@ -0,0 +1,45 @@
package io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.PluginManager
import org.gradle.api.tasks.bundling.Zip
/**
* Aggregates asciidoc, javadoc, and deploying of the docs into a single plugin
*/
public class DocsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(BasePlugin);
pluginManager.apply(DeployDocsPlugin);
pluginManager.apply(JavadocApiPlugin);
Task docsZip = project.tasks.create('docsZip', Zip) {
dependsOn 'api'
group = 'Distribution'
archiveBaseName = project.rootProject.name
archiveClassifier = 'docs'
description = "Builds -${classifier} archive containing all " +
"Docs for deployment at docs.spring.io"
from(project.tasks.api.outputs) {
into 'api'
}
into 'docs'
duplicatesStrategy 'exclude'
}
Task docs = project.tasks.create("docs") {
group = 'Documentation'
description 'An aggregator task to generate all the documentation'
dependsOn docsZip
}
project.tasks.assemble.dependsOn docs
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2002-2021 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.gradle.convention
import io.spring.gradle.IncludeRepoTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.api.tasks.GradleBuild
import org.gradle.api.tasks.TaskProvider
/**
* Adds a set of tasks that make easy to clone a remote repository and perform some task
*
* @author Marcus Da Coregio
*/
class IncludeCheckRemotePlugin implements Plugin<Project> {
@Override
void apply(Project project) {
IncludeCheckRemoteExtension extension = project.extensions.create('includeCheckRemote', IncludeCheckRemoteExtension)
TaskProvider<IncludeRepoTask> includeRepoTask = project.tasks.register('includeRepo', IncludeRepoTask) { IncludeRepoTask it ->
it.repository = extension.repository
it.ref = extension.ref
}
project.tasks.register('checkRemote', GradleBuild) {
it.dependsOn 'includeRepo'
it.dir = includeRepoTask.get().outputDirectory
it.tasks = extension.getTasks()
}
}
abstract static class IncludeCheckRemoteExtension {
/**
* Git repository to clone
*/
String repository;
/**
* Git ref to checkout
*/
String ref
/**
* Task to run in the repository
*/
List<String> tasks = ['check']
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2016-2018 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.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.GroovyPlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.testing.Test
import org.gradle.plugins.ide.eclipse.EclipsePlugin
import org.gradle.plugins.ide.idea.IdeaPlugin
import org.springframework.gradle.propdeps.PropDepsPlugin
/**
*
* Adds support for integration tests to java projects.
*
* <ul>
* <li>Adds integrationTestCompile and integrationTestRuntime configurations</li>
* <li>A new source test folder of src/integration-test/java has been added</li>
* <li>A task to run integration tests named integrationTest is added</li>
* <li>If Groovy plugin is added a new source test folder src/integration-test/groovy is added</li>
* </ul>
*
* @author Rob Winch
*/
public class IntegrationTestPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.plugins.withType(JavaPlugin.class) {
applyJava(project)
}
}
private applyJava(Project project) {
if(!project.file('src/integration-test/').exists()) {
// ensure we don't add if no tests to avoid adding Gretty
return
}
project.configurations {
integrationTestCompile {
extendsFrom testImplementation
}
integrationTestRuntime {
extendsFrom integrationTestCompile, testRuntime, testRuntimeOnly
}
}
project.sourceSets {
integrationTest {
java.srcDir project.file('src/integration-test/java')
resources.srcDir project.file('src/integration-test/resources')
compileClasspath = project.sourceSets.main.output + project.sourceSets.test.output + project.configurations.integrationTestCompile
runtimeClasspath = output + compileClasspath + project.configurations.integrationTestRuntime
}
}
Task integrationTestTask = project.tasks.create("integrationTest", Test) {
group = 'Verification'
description = 'Runs the integration tests.'
dependsOn 'jar'
testClassesDirs = project.sourceSets.integrationTest.output.classesDirs
classpath = project.sourceSets.integrationTest.runtimeClasspath
shouldRunAfter project.tasks.test
useJUnitPlatform()
}
project.tasks.check.dependsOn integrationTestTask
project.plugins.withType(IdeaPlugin) {
project.idea {
module {
testSourceDirs += project.file('src/integration-test/java')
scopes.TEST.plus += [ project.configurations.integrationTestCompile ]
}
}
}
project.plugins.withType(GroovyPlugin) {
project.sourceSets {
integrationTest {
groovy.srcDirs project.file('src/integration-test/groovy')
}
}
project.plugins.withType(IdeaPlugin) {
project.idea {
module {
testSourceDirs += project.file('src/integration-test/groovy')
}
}
}
}
project.plugins.withType(PropDepsPlugin) {
project.configurations {
integrationTestCompile {
extendsFrom optional, provided
}
}
}
project.plugins.withType(EclipsePlugin) {
project.eclipse.classpath {
plusConfigurations += [ project.configurations.integrationTestCompile ]
}
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2016-2018 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.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
/**
* Adds a version of jacoco to use and makes check depend on jacocoTestReport.
*
* @author Rob Winch
*/
class JacocoPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.plugins.withType(JavaPlugin) {
project.getPluginManager().apply("jacoco")
project.tasks.check.dependsOn project.tasks.jacocoTestReport
project.jacoco {
toolVersion = '0.8.2'
}
}
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2002-2016 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.gradle.convention;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.gradle.api.Action;
import org.gradle.api.JavaVersion
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Rob Winch
*/
public class JavadocApiPlugin implements Plugin<Project> {
Logger logger = LoggerFactory.getLogger(getClass());
Set<Pattern> excludes = Collections.singleton(Pattern.compile("test"));
@Override
public void apply(Project project) {
logger.info("Applied");
Project rootProject = project.getRootProject();
//Task docs = project.getTasks().findByPath("docs") ?: project.getTasks().create("docs");
Javadoc api = project.getTasks().create("api", Javadoc);
api.setGroup("Documentation");
api.setDescription("Generates aggregated Javadoc API documentation.");
api.doLast {
if (JavaVersion.current().isJava11Compatible()) {
project.copy({ copy -> copy
.from(api.destinationDir)
.into(api.destinationDir)
.include("element-list")
.rename("element-list", "package-list")
});
}
}
Set<Project> subprojects = rootProject.getSubprojects();
for (Project subproject : subprojects) {
addProject(api, subproject);
}
if (subprojects.isEmpty()) {
addProject(api, project);
}
api.setMaxMemory("1024m");
api.setDestinationDir(new File(project.getBuildDir(), "api"));
project.getPluginManager().apply("io.spring.convention.javadoc-options");
}
public void setExcludes(String... excludes) {
if(excludes == null) {
this.excludes = Collections.emptySet();
}
this.excludes = new HashSet<Pattern>(excludes.length);
for(String exclude : excludes) {
this.excludes.add(Pattern.compile(exclude));
}
}
private void addProject(final Javadoc api, final Project project) {
for(Pattern exclude : excludes) {
if(exclude.matcher(project.getName()).matches()) {
logger.info("Skipping {} because it is excluded by {}", project, exclude);
return;
}
}
logger.info("Try add sources for {}", project);
project.getPlugins().withType(SpringModulePlugin.class).all(new Action<SpringModulePlugin>() {
@Override
public void execute(SpringModulePlugin plugin) {
logger.info("Added sources for {}", project);
JavaPluginConvention java = project.getConvention().getPlugin(JavaPluginConvention.class);
SourceSet mainSourceSet = java.getSourceSets().getByName("main");
api.setSource(api.getSource().plus(mainSourceSet.getAllJava()));
project.getTasks().withType(Javadoc.class).all(new Action<Javadoc>() {
@Override
public void execute(Javadoc projectJavadoc) {
api.setClasspath(api.getClasspath().plus(projectJavadoc.getClasspath()));
}
});
}
});
}
}

View File

@@ -0,0 +1,15 @@
package io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.javadoc.Javadoc
public class JavadocOptionsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().withType(Javadoc).all { t->
t.options.addStringOption('Xdoclint:none', '-quiet')
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2002-2021 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.gradle.convention;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaTestFixturesPlugin;
import org.gradle.api.plugins.PluginContainer;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import org.springframework.gradle.propdeps.PropDepsPlugin;
/**
* Creates a Management configuration that is appropriate for adding a platform to that is not exposed externally. If
* the JavaPlugin is applied, the compileClasspath, runtimeClasspath, testCompileClasspath, and testRuntimeClasspath
* will extend from it.
* @author Rob Winch
*/
public class ManagementConfigurationPlugin implements Plugin<Project> {
public static final String MANAGEMENT_CONFIGURATION_NAME = "management";
@Override
public void apply(Project project) {
ConfigurationContainer configurations = project.getConfigurations();
configurations.create(MANAGEMENT_CONFIGURATION_NAME, (management) -> {
management.setVisible(false);
management.setCanBeConsumed(false);
management.setCanBeResolved(false);
PluginContainer plugins = project.getPlugins();
plugins.withType(JavaPlugin.class, (javaPlugin) -> {
configurations.getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management);
configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management);
configurations.getByName(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management);
configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management);
});
plugins.withType(JavaTestFixturesPlugin.class, (javaTestFixturesPlugin) -> {
configurations.getByName("testFixturesCompileClasspath").extendsFrom(management);
configurations.getByName("testFixturesRuntimeClasspath").extendsFrom(management);
});
plugins.withType(MavenPublishPlugin.class, (mavenPublish) -> {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getPublications().withType(MavenPublication.class, (mavenPublication -> {
mavenPublication.versionMapping((versions) ->
versions.allVariants(versionMapping -> versionMapping.fromResolutionResult())
);
}));
});
plugins.withType(PropDepsPlugin.class, (propDepsPlugin -> {
configurations.getByName("optional").extendsFrom(management);
configurations.getByName("provided").extendsFrom(management);
}));
});
}
}

View File

@@ -0,0 +1,18 @@
package io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlatformPlugin
import org.sonarqube.gradle.SonarQubePlugin
import org.springframework.gradle.CopyPropertiesPlugin
import org.springframework.gradle.maven.SpringMavenPlugin
public class MavenBomPlugin implements Plugin<Project> {
static String MAVEN_BOM_TASK_NAME = "mavenBom"
public void apply(Project project) {
project.plugins.apply(JavaPlatformPlugin)
project.plugins.apply(SpringMavenPlugin)
project.plugins.apply(CopyPropertiesPlugin)
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2016-2018 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.gradle.convention;
import org.gradle.api.Plugin
import org.gradle.api.Project
class RepositoryConventionPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
String[] forceMavenRepositories = ((String) project.findProperty("forceMavenRepositories"))?.split(',')
boolean isImplicitSnapshotRepository = forceMavenRepositories == null && Utils.isSnapshot(project)
boolean isImplicitMilestoneRepository = forceMavenRepositories == null && Utils.isMilestone(project)
boolean isSnapshot = isImplicitSnapshotRepository || forceMavenRepositories?.contains('snapshot')
boolean isMilestone = isImplicitMilestoneRepository || forceMavenRepositories?.contains('milestone')
project.repositories {
if (forceMavenRepositories?.contains('local')) {
mavenLocal()
}
mavenCentral()
jcenter() {
content {
includeGroup "org.gretty"
}
}
if (isSnapshot) {
maven {
name = 'artifactory-snapshot'
if (project.hasProperty('artifactoryUsername')) {
credentials {
username project.artifactoryUsername
password project.artifactoryPassword
}
}
url = 'https://repo.spring.io/snapshot/'
}
}
if (isSnapshot || isMilestone) {
maven {
name = 'artifactory-milestone'
if (project.hasProperty('artifactoryUsername')) {
credentials {
username project.artifactoryUsername
password project.artifactoryPassword
}
}
url = 'https://repo.spring.io/milestone/'
}
}
maven {
name = 'artifactory-release'
if (project.hasProperty('artifactoryUsername')) {
credentials {
username project.artifactoryUsername
password project.artifactoryPassword
}
}
url = 'https://repo.spring.io/release/'
}
maven {
name = 'shibboleth'
url = 'https://build.shibboleth.net/nexus/content/repositories/releases/'
}
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2016-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.gradle.convention
import io.spring.nohttp.gradle.NoHttpPlugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.PluginManager
import org.springframework.gradle.maven.SpringNexusPublishPlugin
class RootProjectPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
PluginManager pluginManager = project.getPluginManager()
pluginManager.apply(BasePlugin)
pluginManager.apply(SchemaPlugin)
pluginManager.apply(NoHttpPlugin)
pluginManager.apply(SpringNexusPublishPlugin)
pluginManager.apply("org.sonarqube")
project.repositories.mavenCentral()
project.allprojects {
configurations.all {
resolutionStrategy {
cacheChangingModulesFor 0, "seconds"
cacheDynamicVersionsFor 0, "seconds"
}
}
}
String projectName = Utils.getProjectName(project)
project.sonarqube {
properties {
property "sonar.java.coveragePlugin", "jacoco"
property "sonar.projectName", projectName
property "sonar.jacoco.reportPath", "${project.buildDir.name}/jacoco.exec"
property "sonar.links.homepage", "https://spring.io/${projectName}"
property "sonar.links.ci", "https://jenkins.spring.io/job/${projectName}/"
property "sonar.links.issue", "https://github.com/spring-projects/${projectName}/issues"
property "sonar.links.scm", "https://github.com/spring-projects/${projectName}"
property "sonar.links.scm_dev", "https://github.com/spring-projects/${projectName}.git"
}
}
project.tasks.create("dependencyManagementExport", DependencyManagementExportTask)
def finalizeDeployArtifacts = project.task("finalizeDeployArtifacts")
if (Utils.isRelease(project) && project.hasProperty("ossrhUsername")) {
finalizeDeployArtifacts.dependsOn project.tasks.closeAndReleaseOssrhStagingRepository
}
}
}

View File

@@ -0,0 +1,71 @@
package io.spring.gradle.convention
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.Plugin
import org.gradle.api.Project
public class SchemaDeployPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPluginManager().apply('org.hidetake.ssh')
project.ssh.settings {
knownHosts = allowAnyHosts
}
project.remotes {
docs {
role 'docs'
if (project.hasProperty('deployDocsHost')) {
host = project.findProperty('deployDocsHost')
} else {
host = 'docs.af.pivotal.io'
}
retryCount = 5 // retry 5 times (default is 0)
retryWaitSec = 10 // wait 10 seconds between retries (default is 0)
user = project.findProperty('deployDocsSshUsername')
if(project.hasProperty('deployDocsSshKeyPath')) {
identity = project.file(project.findProperty('deployDocsSshKeyPath'))
} else if (project.hasProperty('deployDocsSshKey')) {
identity = project.findProperty('deployDocsSshKey')
}
if(project.hasProperty('deployDocsSshPassphrase')) {
passphrase = project.findProperty('deployDocsSshPassphrase')
}
}
}
project.task('deploySchema') {
dependsOn 'schemaZip'
doFirst {
project.ssh.run {
session(project.remotes.docs) {
def now = System.currentTimeMillis()
def name = project.rootProject.name
def version = project.rootProject.version
def tempPath = "/tmp/${name}-${now}-schema/".replaceAll(' ', '_')
execute "mkdir -p $tempPath"
project.tasks.schemaZip.outputs.each { o ->
println "Putting $o.files"
put from: o.files, into: tempPath
}
execute "unzip $tempPath*.zip -d $tempPath"
def extractPath = "/var/www/domains/spring.io/docs/htdocs/autorepo/schema/${name}/${version}/"
execute "rm -rf $extractPath"
execute "mkdir -p $extractPath"
execute "rm -f $tempPath*.zip"
execute "rm -rf $extractPath*"
execute "mv $tempPath/* $extractPath"
execute "chmod -R g+w $extractPath"
}
}
}
}
}
}

View File

@@ -0,0 +1,15 @@
package io.spring.gradle.convention
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.Plugin
import org.gradle.api.Project
public class SchemaPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPluginManager().apply(SchemaZipPlugin)
project.getPluginManager().apply(SchemaDeployPlugin)
}
}

View File

@@ -0,0 +1,43 @@
package io.spring.gradle.convention
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.Plugin
import org.gradle.api.Project
public class SchemaZipPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
Zip schemaZip = project.tasks.create('schemaZip', Zip)
schemaZip.group = 'Distribution'
schemaZip.archiveBaseName = project.rootProject.name
schemaZip.archiveClassifier = 'schema'
schemaZip.description = "Builds -${schemaZip.archiveClassifier} archive containing all " +
"XSDs for deployment at static.springframework.org/schema."
project.rootProject.subprojects.each { module ->
module.getPlugins().withType(JavaPlugin.class).all {
def Properties schemas = new Properties();
module.sourceSets.main.resources.find {
it.path.endsWith('META-INF/spring.schemas')
}?.withInputStream { schemas.load(it) }
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
assert shortName != key
File xsdFile = module.sourceSets.main.resources.find {
it.path.endsWith(schemas.get(key))
}
assert xsdFile != null
schemaZip.into (shortName) {
duplicatesStrategy 'exclude'
from xsdFile.path
}
}
}
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2002-2017 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.gradle.convention;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
/**
* A Properties which sorts they keys so that they can be written to a File with
* the keys sorted.
*
* @author Rob Winch
*
*/
class SortedProperties extends Properties {
private static final long serialVersionUID = -6199017589626540836L;
public Enumeration<Object> keys() {
Enumeration<Object> keysEnum = super.keys();
List<Object> keyList = new ArrayList<Object>();
while (keysEnum.hasMoreElements()) {
keyList.add(keysEnum.nextElement());
}
Collections.sort(keyList, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return o1.toString().compareTo(o2.toString());
}
});
return Collections.enumeration(keyList);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2016-2021 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.gradle.convention
import io.spring.gradle.dependencymanagement.DependencyManagementPlugin
import org.gradle.api.Plugin
import org.gradle.api.Project
/**
* Adds and configures {@link DependencyManagementPlugin}.
* <p>
* Additionally, if 'gradle/dependency-management.gradle' file is present it will be
* automatically applied file for configuring the dependencies.
*/
class SpringDependencyManagementConventionPlugin implements Plugin<Project> {
static final String DEPENDENCY_MANAGEMENT_RESOURCE = "gradle/dependency-management.gradle"
@Override
void apply(Project project) {
project.getPluginManager().apply(ManagementConfigurationPlugin)
project.getPluginManager().apply(DependencyManagementPlugin)
project.dependencyManagement {
resolutionStrategy {
cacheChangingModulesFor 0, "seconds"
}
}
File rootDir = project.rootDir
List<File> dependencyManagementFiles = [project.rootProject.file(DEPENDENCY_MANAGEMENT_RESOURCE)]
for (File dir = project.projectDir; dir != rootDir; dir = dir.parentFile) {
dependencyManagementFiles.add(new File(dir, DEPENDENCY_MANAGEMENT_RESOURCE))
}
dependencyManagementFiles.each { f ->
if (f.exists()) {
project.apply from: f.absolutePath
}
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2016-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.gradle.convention;
import org.gradle.api.Project
import org.gradle.api.plugins.JavaLibraryPlugin;
import org.gradle.api.plugins.MavenPlugin;
import org.gradle.api.plugins.PluginManager
import org.springframework.gradle.maven.SpringMavenPlugin;
/**
* @author Rob Winch
*/
class SpringModulePlugin extends AbstractSpringJavaPlugin {
@Override
void additionalPlugins(Project project) {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(JavaLibraryPlugin.class)
pluginManager.apply(SpringMavenPlugin.class);
pluginManager.apply("io.spring.convention.jacoco");
def deployArtifacts = project.task("deployArtifacts")
deployArtifacts.group = 'Deploy tasks'
deployArtifacts.description = "Deploys the artifacts to either Artifactory or Maven Central"
if (!Utils.isRelease(project)) {
deployArtifacts.dependsOn project.tasks.artifactoryPublish
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2002-2021 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.gradle.convention
import org.gradle.api.Project
import org.gradle.api.plugins.PluginManager
/**
* @author Rob Winch
*/
public class SpringSampleBootPlugin extends SpringSamplePlugin {
@Override
public void additionalPlugins(Project project) {
super.additionalPlugins(project);
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply("org.springframework.boot");
project.repositories {
maven { url 'https://repo.spring.io/snapshot' }
maven { url 'https://repo.spring.io/milestone' }
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2021 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.gradle.convention;
import org.gradle.api.Project
import org.sonarqube.gradle.SonarQubePlugin;
/**
* @author Rob Winch
*/
public class SpringSamplePlugin extends AbstractSpringJavaPlugin {
@Override
public void additionalPlugins(Project project) {
project.plugins.withType(SonarQubePlugin) {
project.sonarqube.skipProject = true
}
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2016-2021 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.gradle.convention
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.PluginManager
import org.gradle.api.tasks.testing.Test
/**
* @author Rob Winch
*/
public class SpringSampleWarPlugin extends SpringSamplePlugin {
@Override
public void additionalPlugins(Project project) {
super.additionalPlugins(project);
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply("war");
pluginManager.apply("org.gretty");
project.gretty {
servletContainer = 'tomcat85'
contextPath = '/'
fileLogEnabled = false
}
Task prepareAppServerForIntegrationTests = project.tasks.create('prepareAppServerForIntegrationTests') {
group = 'Verification'
description = 'Prepares the app server for integration tests'
doFirst {
project.gretty {
httpPort = getRandomFreePort()
httpsPort = getRandomPort()
}
}
}
project.tasks.matching { it.name == "appBeforeIntegrationTest" }.all { task ->
task.dependsOn prepareAppServerForIntegrationTests
}
project.tasks.withType(Test).all { task ->
if("integrationTest".equals(task.name)) {
applyForIntegrationTest(project, task)
}
}
}
def applyForIntegrationTest(Project project, Task integrationTest) {
project.gretty.integrationTestTask = integrationTest.name
integrationTest.doFirst {
def gretty = project.gretty
String host = project.gretty.host ?: 'localhost'
boolean isHttps = gretty.httpsEnabled
Integer httpPort = integrationTest.systemProperties['gretty.httpPort']
Integer httpsPort = integrationTest.systemProperties['gretty.httpsPort']
int port = isHttps ? httpsPort : httpPort
String contextPath = project.gretty.contextPath
String httpBaseUrl = "http://${host}:${httpPort}${contextPath}"
String httpsBaseUrl = "https://${host}:${httpsPort}${contextPath}"
String baseUrl = isHttps ? httpsBaseUrl : httpBaseUrl
integrationTest.systemProperty 'app.port', port
integrationTest.systemProperty 'app.httpPort', httpPort
integrationTest.systemProperty 'app.httpsPort', httpsPort
integrationTest.systemProperty 'app.baseURI', baseUrl
integrationTest.systemProperty 'app.httpBaseURI', httpBaseUrl
integrationTest.systemProperty 'app.httpsBaseURI', httpsBaseUrl
integrationTest.systemProperty 'geb.build.baseUrl', baseUrl
integrationTest.systemProperty 'geb.build.reportsDir', 'build/geb-reports'
}
}
def getRandomPort() {
ServerSocket ss = new ServerSocket(0)
int port = ss.localPort
ss.close()
return port
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2016 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.gradle.convention;
import org.gradle.api.Project;
/**
* @author Rob Winch
*/
public class SpringTestPlugin extends AbstractSpringJavaPlugin {
@Override
public void additionalPlugins(Project project) {
project.sonarqube.skipProject = true
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2002-2021 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.gradle.convention;
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.jvm.tasks.Jar
/**
* Adds the ability to depends on the test jar within other projects using:
*
* <code>
* testImplementation project(path: ':foo', configuration: 'tests')
* </code>
*
* @author Rob Winch
*/
public class TestsConfigurationPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.plugins.withType(JavaPlugin) {
applyJavaProject(project)
}
}
private void applyJavaProject(Project project) {
project.configurations {
tests.extendsFrom testRuntime, testRuntimeClasspath
}
project.tasks.create('testJar', Jar) {
classifier = 'test'
from project.sourceSets.test.output
}
project.artifacts {
tests project.testJar
}
}
}

View File

@@ -0,0 +1,34 @@
package io.spring.gradle.convention;
import org.gradle.api.Project;
public class Utils {
static String getProjectName(Project project) {
String projectName = project.getRootProject().getName();
if(projectName.endsWith("-build")) {
projectName = projectName.substring(0, projectName.length() - "-build".length());
}
return projectName;
}
static boolean isSnapshot(Project project) {
String projectVersion = projectVersion(project)
return projectVersion.matches('^.*([.-]BUILD)?-SNAPSHOT$')
}
static boolean isMilestone(Project project) {
String projectVersion = projectVersion(project)
return projectVersion.matches('^.*[.-]M\\d+$') || projectVersion.matches('^.*[.-]RC\\d+$')
}
static boolean isRelease(Project project) {
return !(isSnapshot(project) || isMilestone(project))
}
private static String projectVersion(Project project) {
return String.valueOf(project.getVersion());
}
private Utils() {}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2002-2021 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 org.springframework.gradle;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
public class CopyPropertiesPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
copyPropertyFromRootProjectTo("group", project);
copyPropertyFromRootProjectTo("version", project);
copyPropertyFromRootProjectTo("description", project);
}
private void copyPropertyFromRootProjectTo(String propertyName, Project project) {
Project rootProject = project.getRootProject();
Object property = rootProject.findProperty(propertyName);
if(property != null) {
project.setProperty(propertyName, property);
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright 2019-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 org.springframework.gradle.github.milestones;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.util.List;
public class GitHubMilestoneApi {
private String baseUrl = "https://api.github.com";
private OkHttpClient client;
private Gson gson = new Gson();
public GitHubMilestoneApi() {
this.client = new OkHttpClient.Builder().build();
}
public GitHubMilestoneApi(String gitHubToken) {
this.client = new OkHttpClient.Builder()
.addInterceptor(new AuthorizationInterceptor(gitHubToken))
.build();
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public long findMilestoneNumberByTitle(RepositoryRef repositoryRef, String milestoneTitle) {
String url = this.baseUrl + "/repos/" + repositoryRef.getOwner() + "/" + repositoryRef.getName() + "/milestones?per_page=100";
Request request = new Request.Builder().get().url(url)
.build();
try {
Response response = this.client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new RuntimeException("Could not find milestone with title " + milestoneTitle + " for repository " + repositoryRef + ". Response " + response);
}
List<Milestone> milestones = this.gson.fromJson(response.body().charStream(), new TypeToken<List<Milestone>>(){}.getType());
for (Milestone milestone : milestones) {
if (milestoneTitle.equals(milestone.getTitle())) {
return milestone.getNumber();
}
}
if (milestones.size() <= 100) {
throw new RuntimeException("Could not find open milestone with title " + milestoneTitle + " for repository " + repositoryRef + " Got " + milestones);
}
throw new RuntimeException("It is possible there are too many open milestones open (only 100 are supported). Could not find open milestone with title " + milestoneTitle + " for repository " + repositoryRef + " Got " + milestones);
} catch (IOException e) {
throw new RuntimeException("Could not find open milestone with title " + milestoneTitle + " for repository " + repositoryRef, e);
}
}
public boolean isOpenIssuesForMilestoneNumber(RepositoryRef repositoryRef, long milestoneNumber) {
String url = this.baseUrl + "/repos/" + repositoryRef.getOwner() + "/" + repositoryRef.getName() + "/issues?per_page=1&milestone=" + milestoneNumber;
Request request = new Request.Builder().get().url(url)
.build();
try {
Response response = this.client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new RuntimeException("Could not find issues for milestone number " + milestoneNumber + " for repository " + repositoryRef + ". Response " + response);
}
List<Object> issues = this.gson.fromJson(response.body().charStream(), new TypeToken<List<Object>>(){}.getType());
return !issues.isEmpty();
} catch (IOException e) {
throw new RuntimeException("Could not find issues for milestone number " + milestoneNumber + " for repository " + repositoryRef, e);
}
}
// public boolean isOpenIssuesForMilestoneName(String owner, String repository, String milestoneName) {
//
// }
private static class AuthorizationInterceptor implements Interceptor {
private final String token;
public AuthorizationInterceptor(String token) {
this.token = token;
}
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + this.token).build();
return chain.proceed(request);
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2019-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 org.springframework.gradle.github.milestones;
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.TaskAction;
public class GitHubMilestoneHasNoOpenIssuesTask extends DefaultTask {
@Input
private RepositoryRef repository = new RepositoryRef();
@Input
private String milestoneTitle;
@Input @Optional
private String gitHubAccessToken;
private GitHubMilestoneApi milestones = new GitHubMilestoneApi();
@TaskAction
public void checkHasNoOpenIssues() {
long milestoneNumber = this.milestones.findMilestoneNumberByTitle(this.repository, this.milestoneTitle);
boolean isOpenIssues = this.milestones.isOpenIssuesForMilestoneNumber(this.repository, milestoneNumber);
if (isOpenIssues) {
throw new IllegalStateException("The repository " + this.repository + " has open issues for milestone with the title " + this.milestoneTitle + " and number " + milestoneNumber);
}
System.out.println("The repository " + this.repository + " has no open issues for milestone with the title " + this.milestoneTitle + " and number " + milestoneNumber);
}
public RepositoryRef getRepository() {
return repository;
}
public void repository(Action<RepositoryRef> repository) {
repository.execute(this.repository);
}
public void setRepository(RepositoryRef repository) {
this.repository = repository;
}
public String getMilestoneTitle() {
return milestoneTitle;
}
public void setMilestoneTitle(String milestoneTitle) {
this.milestoneTitle = milestoneTitle;
}
public String getGitHubAccessToken() {
return gitHubAccessToken;
}
public void setGitHubAccessToken(String gitHubAccessToken) {
this.gitHubAccessToken = gitHubAccessToken;
this.milestones = new GitHubMilestoneApi(gitHubAccessToken);
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019-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 org.springframework.gradle.github.milestones;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
public class GitHubMilestonePlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().register("gitHubCheckMilestoneHasNoOpenIssues", GitHubMilestoneHasNoOpenIssuesTask.class, new Action<GitHubMilestoneHasNoOpenIssuesTask>() {
@Override
public void execute(GitHubMilestoneHasNoOpenIssuesTask githubCheckMilestoneHasNoOpenIssues) {
githubCheckMilestoneHasNoOpenIssues.setGroup("Release");
githubCheckMilestoneHasNoOpenIssues.setDescription("Checks if there are any open issues for the specified repository and milestone");
githubCheckMilestoneHasNoOpenIssues.setMilestoneTitle((String) project.findProperty("nextVersion"));
if (project.hasProperty("githubAccessToken")) {
githubCheckMilestoneHasNoOpenIssues.setGitHubAccessToken((String) project.findProperty("gitHubAccessToken"));
}
}
});
}
}

View File

@@ -0,0 +1,31 @@
package org.springframework.gradle.github.milestones;
public class Milestone {
private String title;
private long number;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
@Override
public String toString() {
return "Milestone{" +
"title='" + title + '\'' +
", number=" + number +
'}';
}
}

View File

@@ -0,0 +1,65 @@
package org.springframework.gradle.github.milestones;
public class RepositoryRef {
private String owner;
private String name;
RepositoryRef() {
}
public RepositoryRef(String owner, String name) {
this.owner = owner;
this.name = name;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "RepositoryRef{" +
"owner='" + owner + '\'' +
", name='" + name + '\'' +
'}';
}
public static RepositoryRefBuilder owner(String owner) {
return new RepositoryRefBuilder().owner(owner);
}
public static final class RepositoryRefBuilder {
private String owner;
private String repository;
private RepositoryRefBuilder() {
}
private RepositoryRefBuilder owner(String owner) {
this.owner = owner;
return this;
}
public RepositoryRefBuilder repository(String repository) {
this.repository = repository;
return this;
}
public RepositoryRef build() {
return new RepositoryRef(owner, repository);
}
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2016-2021 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 org.springframework.gradle.maven;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.MavenPom;
import org.gradle.api.publish.maven.MavenPomDeveloperSpec;
import org.gradle.api.publish.maven.MavenPomIssueManagement;
import org.gradle.api.publish.maven.MavenPomLicenseSpec;
import org.gradle.api.publish.maven.MavenPomOrganization;
import org.gradle.api.publish.maven.MavenPomScm;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
public class MavenPublishingConventionsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().withType(MavenPublishPlugin.class).all(new Action<MavenPublishPlugin>() {
@Override
public void execute(MavenPublishPlugin mavenPublish) {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getPublications().withType(MavenPublication.class)
.all((mavenPublication) -> MavenPublishingConventionsPlugin.this.customizePom(mavenPublication.getPom(), project));
MavenPublishingConventionsPlugin.this.customizeJavaPlugin(project);
}
});
}
private void customizePom(MavenPom pom, Project project) {
pom.getUrl().set("https://spring.io/projects/spring-session");
pom.getName().set(project.provider(project::getName));
pom.getDescription().set(project.provider(project::getDescription));
pom.organization(this::customizeOrganization);
pom.licenses(this::customizeLicences);
pom.developers(this::customizeDevelopers);
pom.scm(this::customizeScm);
pom.issueManagement(this::customizeIssueManagement);
}
private void customizeOrganization(MavenPomOrganization organization) {
organization.getName().set("Pivotal Software, Inc.");
organization.getUrl().set("https://spring.io");
}
private void customizeLicences(MavenPomLicenseSpec licences) {
licences.license((licence) -> {
licence.getName().set("Apache License, Version 2.0");
licence.getUrl().set("https://www.apache.org/licenses/LICENSE-2.0");
});
}
private void customizeDevelopers(MavenPomDeveloperSpec developers) {
developers.developer((developer) -> {
developer.getName().set("Pivotal");
developer.getEmail().set("info@pivotal.io");
developer.getOrganization().set("Pivotal Software, Inc.");
developer.getOrganizationUrl().set("https://www.spring.io");
});
}
private void customizeScm(MavenPomScm scm) {
scm.getConnection().set("scm:git:git://github.com/spring-projects/spring-session.git");
scm.getDeveloperConnection().set("scm:git:ssh://git@github.com/spring-projects/spring-session.git");
scm.getUrl().set("https://github.com/spring-projects/spring-session");
}
private void customizeIssueManagement(MavenPomIssueManagement issueManagement) {
issueManagement.getSystem().set("GitHub");
issueManagement.getUrl().set("https://github.com/spring-projects/spring-session/issues");
}
private void customizeJavaPlugin(Project project) {
project.getPlugins().withType(JavaPlugin.class).all((javaPlugin) -> {
JavaPluginExtension extension = project.getExtensions().getByType(JavaPluginExtension.class);
extension.withJavadocJar();
extension.withSourcesJar();
});
}
}

View File

@@ -0,0 +1,33 @@
package org.springframework.gradle.maven;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlatformPlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.VariantVersionMappingStrategy;
import org.gradle.api.publish.VersionMappingStrategy;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
public class PublishAllJavaComponentsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().withType(MavenPublishPlugin.class).all((mavenPublish) -> {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getPublications().create("mavenJava", MavenPublication.class, new Action<MavenPublication>() {
@Override
public void execute(MavenPublication maven) {
project.getPlugins().withType(JavaPlugin.class, (plugin) -> {
maven.from(project.getComponents().getByName("java"));
});
project.getPlugins().withType(JavaPlatformPlugin.class, (plugin) -> {
maven.from(project.getComponents().getByName("javaPlatform"));
});
}
});
});
}
}

View File

@@ -0,0 +1,26 @@
package org.springframework.gradle.maven;
import io.spring.gradle.convention.Utils;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
public class PublishArtifactsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().register("publishArtifacts", new Action<Task>() {
@Override
public void execute(Task publishArtifacts) {
publishArtifacts.setGroup("Publishing");
publishArtifacts.setDescription("Publish the artifacts to either Artifactory or Maven Central based on the version");
if (Utils.isRelease(project)) {
publishArtifacts.dependsOn("publishToOssrh");
}
else {
publishArtifacts.dependsOn("artifactoryPublish");
}
}
});
}
}

View File

@@ -0,0 +1,29 @@
package org.springframework.gradle.maven;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import java.io.File;
public class PublishLocalPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().withType(MavenPublishPlugin.class).all(new Action<MavenPublishPlugin>() {
@Override
public void execute(MavenPublishPlugin mavenPublish) {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getRepositories().maven(new Action<MavenArtifactRepository>() {
@Override
public void execute(MavenArtifactRepository maven) {
maven.setName("local");
maven.setUrl(new File(project.getRootProject().getBuildDir(), "publications/repos"));
}
});
}
});
}
}

View File

@@ -0,0 +1,21 @@
package org.springframework.gradle.maven;
import io.spring.gradle.convention.ArtifactoryPlugin;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.PluginManager;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
public class SpringMavenPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(MavenPublishPlugin.class);
pluginManager.apply(SpringSigningPlugin.class);
pluginManager.apply(MavenPublishingConventionsPlugin.class);
pluginManager.apply(PublishAllJavaComponentsPlugin.class);
pluginManager.apply(PublishLocalPlugin.class);
pluginManager.apply(PublishArtifactsPlugin.class);
pluginManager.apply(ArtifactoryPlugin.class);
}
}

View File

@@ -0,0 +1,28 @@
package org.springframework.gradle.maven;
import io.github.gradlenexus.publishplugin.NexusPublishExtension;
import io.github.gradlenexus.publishplugin.NexusPublishPlugin;
import io.github.gradlenexus.publishplugin.NexusRepository;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import java.net.URI;
import java.time.Duration;
public class SpringNexusPublishPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().apply(NexusPublishPlugin.class);
NexusPublishExtension nexusPublishing = project.getExtensions().findByType(NexusPublishExtension.class);
nexusPublishing.getRepositories().create("ossrh", new Action<NexusRepository>() {
@Override
public void execute(NexusRepository nexusRepository) {
nexusRepository.getNexusUrl().set(URI.create("https://s01.oss.sonatype.org/service/local/"));
nexusRepository.getSnapshotRepositoryUrl().set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/"));
}
});
nexusPublishing.getConnectTimeout().set(Duration.ofMinutes(3));
nexusPublishing.getClientTimeout().set(Duration.ofMinutes(3));
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2016-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 org.springframework.gradle.maven;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.publish.Publication;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.plugins.PublishingPlugin;
import org.gradle.plugins.signing.SigningExtension;
import org.gradle.plugins.signing.SigningPlugin;
import java.util.concurrent.Callable;
public class SpringSigningPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPluginManager().apply(SigningPlugin.class);
project.getPlugins().withType(SigningPlugin.class).all(new Action<SigningPlugin>() {
@Override
public void execute(SigningPlugin signingPlugin) {
boolean hasSigningKey = project.hasProperty("signing.keyId") || project.hasProperty("signingKey");
if (hasSigningKey) {
sign(project);
}
}
});
}
private void sign(Project project) {
SigningExtension signing = project.getExtensions().findByType(SigningExtension.class);
signing.setRequired(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return project.getGradle().getTaskGraph().hasTask("publishArtifacts");
}
});
String signingKeyId = (String) project.findProperty("signingKeyId");
String signingKey = (String) project.findProperty("signingKey");
String signingPassword = (String) project.findProperty("signingPassword");
if (signingKeyId != null) {
signing.useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword);
} else {
signing.useInMemoryPgpKeys(signingKey, signingPassword);
}
project.getPlugins().withType(PublishAllJavaComponentsPlugin.class).all(new Action<PublishAllJavaComponentsPlugin>() {
@Override
public void execute(PublishAllJavaComponentsPlugin publishingPlugin) {
PublishingExtension publishing = project.getExtensions().findByType(PublishingExtension.class);
Publication maven = publishing.getPublications().getByName("mavenJava");
signing.sign(maven);
}
});
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2002-2021 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 org.springframework.gradle.propdeps
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.plugins.ide.eclipse.EclipsePlugin
/**
* Plugin to allow optional and provided dependency configurations to work with the
* standard gradle 'eclipse' plugin
*
* @author Phillip Webb
*/
class PropDepsEclipsePlugin implements Plugin<Project> {
public void apply(Project project) {
project.plugins.apply(PropDepsPlugin)
project.plugins.apply(EclipsePlugin)
project.eclipse {
classpath {
plusConfigurations += [project.configurations.provided, project.configurations.optional]
}
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2021 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 org.springframework.gradle.propdeps
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.plugins.ide.idea.IdeaPlugin
/**
* Plugin to allow optional and provided dependency configurations to work with the
* standard gradle 'idea' plugin
*
* @author Phillip Webb
* @author Brian Clozel
* @link https://youtrack.jetbrains.com/issue/IDEA-107046
* @link https://youtrack.jetbrains.com/issue/IDEA-117668
*/
class PropDepsIdeaPlugin implements Plugin<Project> {
public void apply(Project project) {
project.plugins.apply(PropDepsPlugin)
project.plugins.apply(IdeaPlugin)
project.idea.module {
// IDEA internally deals with 4 scopes : COMPILE, TEST, PROVIDED, RUNTIME
// but only PROVIDED seems to be picked up
scopes.PROVIDED.plus += [project.configurations.provided]
scopes.PROVIDED.plus += [project.configurations.optional]
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2002-2021 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 org.springframework.gradle.propdeps
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.plugins.JavaLibraryPlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.javadoc.Javadoc
/**
* Plugin to allow 'optional' and 'provided' dependency configurations
*
* As stated in the maven documentation, provided scope "is only available on the compilation and test classpath,
* and is not transitive".
*
* This plugin creates two new configurations, and each one:
* <ul>
* <li>is a parent of the compile configuration</li>
* <li>is not visible, not transitive</li>
* <li>all dependencies are excluded from the default configuration</li>
* </ul>
*
* @author Phillip Webb
* @author Brian Clozel
* @author Rob Winch
*
* @see <a href="https://www.gradle.org/docs/current/userguide/java_plugin.html#N121CF">Maven documentation</a>
* @see <a href="https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope">Gradle configurations</a>
* @see PropDepsEclipsePlugin
* @see PropDepsIdeaPlugin
*/
class PropDepsPlugin implements Plugin<Project> {
public void apply(Project project) {
project.plugins.apply(JavaPlugin)
Configuration provided = addConfiguration(project, "provided")
Configuration optional = addConfiguration(project, "optional")
Javadoc javadoc = project.tasks.getByName(JavaPlugin.JAVADOC_TASK_NAME)
javadoc.classpath = javadoc.classpath.plus(provided).plus(optional)
}
private Configuration addConfiguration(Project project, String name) {
Configuration configuration = project.configurations.create(name)
configuration.extendsFrom(project.configurations.implementation)
project.plugins.withType(JavaLibraryPlugin, {
configuration.extendsFrom(project.configurations.api)
})
project.sourceSets.all {
compileClasspath += configuration
runtimeClasspath += configuration
}
return configuration
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2019-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 org.springframework.gradle.sagan;
import java.util.regex.Pattern;
/**
* Domain object for creating a new release version.
*/
public class Release {
private String version;
private ReleaseStatus status;
private boolean current;
private String referenceDocUrl;
private String apiDocUrl;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public ReleaseStatus getStatus() {
return status;
}
public void setStatus(ReleaseStatus status) {
this.status = status;
}
public boolean isCurrent() {
return current;
}
public void setCurrent(boolean current) {
this.current = current;
}
public String getReferenceDocUrl() {
return referenceDocUrl;
}
public void setReferenceDocUrl(String referenceDocUrl) {
this.referenceDocUrl = referenceDocUrl;
}
public String getApiDocUrl() {
return apiDocUrl;
}
public void setApiDocUrl(String apiDocUrl) {
this.apiDocUrl = apiDocUrl;
}
@Override
public String toString() {
return "Release{" +
"version='" + version + '\'' +
", status=" + status +
", current=" + current +
", referenceDocUrl='" + referenceDocUrl + '\'' +
", apiDocUrl='" + apiDocUrl + '\'' +
'}';
}
public enum ReleaseStatus {
/**
* Unstable version with limited support
*/
SNAPSHOT,
/**
* Pre-Release version meant to be tested by the community
*/
PRERELEASE,
/**
* Release Generally Available on public artifact repositories and enjoying full support from maintainers
*/
GENERAL_AVAILABILITY;
private static final Pattern PRERELEASE_PATTERN = Pattern.compile("[A-Za-z0-9\\.\\-]+?(M|RC)\\d+");
private static final String SNAPSHOT_SUFFIX = "SNAPSHOT";
/**
* Parse the ReleaseStatus from a String
* @param version a project version
* @return the release status for this version
*/
public static ReleaseStatus parse(String version) {
if (version == null) {
throw new IllegalArgumentException("version cannot be null");
}
if (version.endsWith(SNAPSHOT_SUFFIX)) {
return SNAPSHOT;
}
if (PRERELEASE_PATTERN.matcher(version).matches()) {
return PRERELEASE;
}
return GENERAL_AVAILABILITY;
}
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2019-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 org.springframework.gradle.sagan;
import com.google.gson.Gson;
import okhttp3.*;
import java.io.IOException;
import java.util.Base64;
/**
* Implements necessary calls to the Sagan API See https://spring.io/restdocs/index.html
*/
public class SaganApi {
private String baseUrl = "https://spring.io/api";
private OkHttpClient client;
private Gson gson = new Gson();
public SaganApi(String gitHubToken) {
this.client = new OkHttpClient.Builder()
.addInterceptor(new BasicInterceptor("not-used", gitHubToken))
.build();
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public void createReleaseForProject(Release release, String projectName) {
String url = this.baseUrl + "/projects/" + projectName + "/releases";
String releaseJsonString = gson.toJson(release);
RequestBody body = RequestBody.create(MediaType.parse("application/json"), releaseJsonString);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try {
Response response = this.client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new RuntimeException("Could not create release " + release + ". Got response " + response);
}
} catch (IOException fail) {
throw new RuntimeException("Could not create release " + release, fail);
}
}
public void deleteReleaseForProject(String release, String projectName) {
String url = this.baseUrl + "/projects/" + projectName + "/releases/" + release;
Request request = new Request.Builder()
.url(url)
.delete()
.build();
try {
Response response = this.client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new RuntimeException("Could not delete release " + release + ". Got response " + response);
}
} catch (IOException fail) {
throw new RuntimeException("Could not delete release " + release, fail);
}
}
private static class BasicInterceptor implements Interceptor {
private final String token;
public BasicInterceptor(String username, String token) {
this.token = Base64.getEncoder().encodeToString((username + ":" + token).getBytes());
}
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("Authorization", "Basic " + this.token).build();
return chain.proceed(request);
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2019-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 org.springframework.gradle.sagan;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction;
public class SaganCreateReleaseTask extends DefaultTask {
@Input
private String gitHubAccessToken;
@Input
private String version;
@Input
private String apiDocUrl;
@Input
private String referenceDocUrl;
@Input
private String projectName;
@TaskAction
public void saganCreateRelease() {
SaganApi sagan = new SaganApi(this.gitHubAccessToken);
Release release = new Release();
release.setVersion(this.version);
release.setApiDocUrl(this.apiDocUrl);
release.setReferenceDocUrl(this.referenceDocUrl);
sagan.createReleaseForProject(release, this.projectName);
}
public String getGitHubAccessToken() {
return gitHubAccessToken;
}
public void setGitHubAccessToken(String gitHubAccessToken) {
this.gitHubAccessToken = gitHubAccessToken;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getApiDocUrl() {
return apiDocUrl;
}
public void setApiDocUrl(String apiDocUrl) {
this.apiDocUrl = apiDocUrl;
}
public String getReferenceDocUrl() {
return referenceDocUrl;
}
public void setReferenceDocUrl(String referenceDocUrl) {
this.referenceDocUrl = referenceDocUrl;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2019-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 org.springframework.gradle.sagan;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction;
public class SaganDeleteReleaseTask extends DefaultTask {
@Input
private String gitHubAccessToken;
@Input
private String version;
@Input
private String projectName;
@TaskAction
public void saganCreateRelease() {
SaganApi sagan = new SaganApi(this.gitHubAccessToken);
sagan.deleteReleaseForProject(this.version, this.projectName);
}
public String getGitHubAccessToken() {
return gitHubAccessToken;
}
public void setGitHubAccessToken(String gitHubAccessToken) {
this.gitHubAccessToken = gitHubAccessToken;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2019-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 org.springframework.gradle.sagan;
import io.spring.gradle.convention.Utils;
import org.gradle.api.*;
public class SaganPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().register("saganCreateRelease", SaganCreateReleaseTask.class, new Action<SaganCreateReleaseTask>() {
@Override
public void execute(SaganCreateReleaseTask saganCreateVersion) {
saganCreateVersion.setGroup("Release");
saganCreateVersion.setDescription("Creates a new version for the specified project on spring.io");
saganCreateVersion.setVersion((String) project.findProperty("nextVersion"));
saganCreateVersion.setProjectName(Utils.getProjectName(project));
saganCreateVersion.setGitHubAccessToken((String) project.findProperty("gitHubAccessToken"));
}
});
project.getTasks().register("saganDeleteRelease", SaganDeleteReleaseTask.class, new Action<SaganDeleteReleaseTask>() {
@Override
public void execute(SaganDeleteReleaseTask saganDeleteVersion) {
saganDeleteVersion.setGroup("Release");
saganDeleteVersion.setDescription("Delete a version for the specified project on spring.io");
saganDeleteVersion.setVersion((String) project.findProperty("previousVersion"));
saganDeleteVersion.setProjectName(Utils.getProjectName(project));
saganDeleteVersion.setGitHubAccessToken((String) project.findProperty("gitHubAccessToken"));
}
});
}
}

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.ArtifactoryPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.MavenBomPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.CheckstylePlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.DocsPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.IncludeCheckRemotePlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.IntegrationTestPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.JacocoPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.JavadocApiPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.JavadocOptionsPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.RepositoryConventionPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.RootProjectPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringModulePlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringSampleBootPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringSampleWarPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringSamplePlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringTestPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringDependencyManagementConventionPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.TestsConfigurationPlugin