blob: 0d604b4ca3d15213779d32bbf4f42f367c926404 [file] [log] [blame]
description = "Apache Tapestry 5 Project"
import org.apache.tools.ant.filters.ReplaceTokens
apply plugin: "base"
apply from: "ssh.gradle"
apply from: "md5.gradle"
apply from: "sha256.gradle"
project.ext.versions = [
jetty: "8.1.19.v20160209",
tomcat: "7.0.70",
testng: "6.8.21",
easymock: "3.3.1",
servletapi: "3.0.1",
spock: "1.1-groovy-2.4",
hibernate: "5.1.1.Final",
slf4j: "1.7.25",
geb: "2.0",
selenium: "3.12.0"
]
ext.continuousIntegrationBuild = Boolean.getBoolean("ci")
// Provided so that the CI server can override the normal version number for nightly builds.
project.version = tapestryVersion()
// Remember that when generating a release, this should be incremented. Also don"t forget to
// tag the release in Git.
// Version number is always "5.x(.y)?-SNAPSHOT" and only gets fixed, e.g. to 5.4-alpha-1
// during a release
def tapestryVersion() {
def major = "5.6.0"
def minor = ""
// When building on the CI server, make sure -SNAPSHOT is appended, as it is a nightly build.
// When building normally, or for a release, no suffix is desired.
continuousIntegrationBuild ? major + "-SNAPSHOT" : major + minor
}
// Let analysis.apache.org get in touch with our builds
project.ext {
stagingUrl = "https://repository.apache.org/service/local/staging/deploy/maven2/"
snapshotUrl = "https://repository.apache.org/content/repositories/snapshots"
doSign = !project.hasProperty("noSign") && project.hasProperty("signing.keyId")
// apacheDeployUserName and apacheDeployPassword should be specified in ~/.gradle/gradle.properties
deployUsernameProperty = isSnapshot() ? "snapshotDeployUserName" : "apacheDeployUserName"
deployPasswordProperty = isSnapshot() ? "snapshotDeployPassword" : "apacheDeployPassword"
canDeploy = [deployUsernameProperty, deployPasswordProperty, "apacheArchivesFolder"].every { project.hasProperty(it) }
// These are all deferred inside closures, to allow people without the necessary values in their
// gradle.properties to build locally, just not deploy. getProperty() throws an exception if the property
// is not present.
deployUsername = { getProperty(deployUsernameProperty) }
deployPassword = { getProperty(deployPasswordProperty) }
archiveDeployFolder = { getProperty("apacheArchivesFolder") }
}
println "JDK: " + System.getProperty("java.version")
//println "Can deploy? $canDeploy"
//println "Is snapshot? isSnapshot"
//println "deployUsernameProperty $deployUsernameProperty"
//println "deployPasswordProperty $deployPasswordProperty"
//println "continuousIntegrationBuild? $continuousIntegrationBuild"
allprojects {
apply plugin: "eclipse"
apply plugin: "idea"
apply plugin: "signing"
repositories {
mavenCentral()
// All things JBoss/Hibernate
maven {
name "JBoss"
url "https://repository.jboss.org/nexus/content/repositories/releases/"
}
}
configurations {
// Non-code artifacts, such as sources JARs and zipped JavaDocs
meta
}
}
idea {
project {
languageLevel = "1.8"
}
}
// Specific to top-level build, not set for subprojects:
configurations {
javadoc
published.extendsFrom archives, meta
if (doSign) {
published.extendsFrom signatures
}
binaries // additional dependencies included in the binary archive
}
dependencies {
javadoc project(":tapestry-javadoc")
// From tapestry-ioc:
binaries "javax.inject:javax.inject:1"
binaries "org.slf4j:slf4j-api:${versions.slf4j}"
binaries "commons-codec:commons-codec:1.5"
binaries "org.antlr:antlr-runtime:3.3", { transitive = false }
}
String jdkVersion = System.properties['java.version']
def jdkMajorVersion = jdkVersion.substring(0, jdkVersion.indexOf(".")) // 1, 9, 10...
subprojects {
def specifyMaxPermSize = jdkVersion ==~ /1\.[67].+/
version = parent.version
group = "org.apache.tapestry"
configurations {
provided
}
apply plugin: "java"
apply plugin: "groovy" // mostly for testing
apply plugin: "maven" // for deployment
// TODO: replace the "maven" plugin above with the newer "maven-publish"
apply plugin: "project-report"
apply plugin: "jacoco"
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
// See http://jira.codehaus.org/browse/GRADLE-784
sourceSets {
main {
compileClasspath += configurations.provided
}
test {
compileClasspath += configurations.provided
runtimeClasspath += configurations.provided
}
}
idea.module {
scopes.PROVIDED.plus += [configurations.provided]
}
eclipse.classpath.plusConfigurations += [configurations.provided]
dependencies {
testCompile "org.spockframework:spock-core:${versions.spock}"
testRuntime "org.slf4j:slf4j-log4j12:${versions.slf4j}"
}
compileTestGroovy {
configure(groovyOptions.forkOptions) {
memoryMaximumSize = '1g'
jvmArgs = ['-Xms512m', '-Xmx1g']
if (specifyMaxPermSize){
jvmArgs << '-XX:MaxPermSize=512m'
}
}
}
tasks.withType(Test) {
useTestNG()
options.suites("src/test/conf/testng.xml")
if (specifyMaxPermSize){
maxHeapSize "400M"
jvmArgs("-XX:MaxPermSize=200m")
}else{
maxHeapSize "600M"
}
// Turn off live service reloading
systemProperties["tapestry.service-reloading-enabled"] = "false"
systemProperties["java.io.tmpdir"] = temporaryDir.absolutePath
jvmArgs("-Dfile.encoding=UTF-8")
if (jdkMajorVersion != "1"){
// TODO: make these regular dependencies instead
jvmArgs += ["--add-modules", "java.xml.ws.annotation,java.xml.bind"]
}
environment.LANG = 'en_US.UTF-8'
if (continuousIntegrationBuild){
// Travis runs our builds with TERM=dumb and kills it if we don't produce any
// output for 10 minutes, so we log some task execution progress
testLogging {
exceptionFormat "full"
}
def numberOfTestsExecuted = 0
afterTest { descriptor, result->
numberOfTestsExecuted++
if (numberOfTestsExecuted % 25 == 0){
logger.lifecycle "$numberOfTestsExecuted tests executed"
}
}
}
}
jar {
from(projectDir) {
include "*.txt"
into "META-INF"
}
}
task sourcesJar(type: Jar) {
dependsOn classes
classifier "sources"
from sourceSets.main.allSource
from(projectDir) {
include "*.txt"
into "META-INF"
}
}
artifacts {
archives sourcesJar
meta sourcesJar
}
configurations {
// published -- what gets uploaded to the Nexus repository
published.extendsFrom archives, meta
if (rootProject.doSign) {
published.extendsFrom signatures
}
}
if (rootProject.doSign) {
// sign (create PGP signature for) archives (standard JARs)
// and meta (sources JARs)
signing { sign configurations.archives, configurations.meta }
}
uploadPublished {
doFirst {
if (!canDeploy) {
throw new InvalidUserDataException("Missing upload credentials. Set '$deployUsernameProperty' and '$deployPasswordProperty' root project properties.")
}
}
if (canDeploy) {
repositories {
project.ext.deployer = repositories.mavenDeployer {
if (doSign) {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
}
repository(url: stagingUrl) {
authentication(userName: deployUsername(), password: deployPassword())
}
snapshotRepository(url: snapshotUrl) {
authentication(userName: deployUsername(), password: deployPassword())
}
}
}
}
}
}
subprojects.each { project.evaluationDependsOn(it.name) }
subprojects {
configurations.all {
resolutionStrategy.force "antlr:antlr:2.7.7",
"cglib:cglib-nodep:2.2",
"commons-codec:commons-codec:1.10",
"commons-io:commons-io:2.4",
"commons-logging:commons-logging:1.1.3",
"hsqldb:hsqldb:2.2.8",
"org.antlr:antlr-runtime:3.5.2",
"org.apache.tomcat:dbcp:6.0.32",
"org.hamcrest:hamcrest-core:1.3",
"org.json:json:20140107",
"org.yaml:snakeyaml:1.8",
"xml-apis:xml-apis:1.4.01"
}
}
// Cribbed from https://github.com/hibernate/hibernate-core/blob/master/release/release.gradle#L19
task aggregateJavadoc(type: Javadoc) {
dependsOn configurations.javadoc
group "Documentation"
description "Build the aggregated JavaDocs for all modules"
maxMemory "512m"
destinationDir file("$buildDir/documentation/javadocs")
def tapestryStylesheet = file("src/javadoc/stylesheet7.css")
int thisYear = java.time.Year.now().getValue()
configure(options) {
splitIndex true
linkSource true
stylesheetFile tapestryStylesheet
windowTitle "Tapestry API - ${project.version}"
header "Tapestry API - ${project.version}"
docTitle "Tapestry API - ($project.version)"
bottom "${project.version} - Copyright &copy; 2003-${thisYear} <a href=\"http://tapestry.apache.org/\">The Apache Software Foundation</a>."
use = true // 'use' seems to be a reserved word for the DSL
links "https://docs.oracle.com/javase/8/docs/api/"
links "https://docs.oracle.com/javaee/7/api/"
addStringOption "tagletpath", configurations.javadoc.asPath
addStringOption "taglet", "org.apache.tapestry5.javadoc.TapestryDocTaglet"
exclude "org/apache/tapestry5/internal/plastic/asm/**"
exclude "org/apache/tapestry5/internal/webresources/**"
exclude "org/apache/tapestry5/webresources/modules/**"
}
def allMainSourceSets = subprojects*.sourceSets*.main.flatten()
def allMainJavaFiles = allMainSourceSets*.java
def allMainJavaSrcDirs = allMainJavaFiles*.srcDirs
source allMainJavaFiles
classpath += files(allMainSourceSets*.compileClasspath)
inputs.files allMainJavaSrcDirs
// As part of generating the documentation, ALSO copy any related files:
// Any extra images (Tapestry logo)
// Any images stored under src/main/java ... everything but .java, .xdoc and package.html
doLast {
copy {
from allMainJavaSrcDirs
into aggregateJavadoc.destinationDir
exclude "**/*.java"
exclude "**/*.xdoc"
exclude "**/package.html"
}
copy {
from file("src/javadoc/images")
into aggregateJavadoc.destinationDir
}
}
}
task coffeeScriptDocs(type: Exec) {
group "Documentation"
description "Build docco documentation for all CoffeeScript sources"
dependsOn project(":tapestry-core").tasks.preprocessCoffeeScript
def outputDir = file("$buildDir/documentation/coffeescript")
def sources = files()
subprojects.each { sub ->
sources += sub.fileTree("src/main/coffeescript", { include "**/*.coffee" })
}
sources += project(":tapestry-core").tasks.preprocessCoffeeScript.outputs.files.asFileTree
// Needs to be installed via "npm install -g docco@0.6.3"
executable isWindows() ? "docco.cmd" : "docco"
args "--output", outputDir
args sources.files.sort({ a, b -> a.name.compareTo b.name })
}
dependencies {
meta aggregateJavadoc.outputs.files
}
task combinedJacocoReport(type:JacocoReport){
def subprojectsToConsider = subprojects.findAll {it.name != 'quickstart'}
dependsOn = subprojectsToConsider.test
additionalSourceDirs = files(subprojectsToConsider.sourceSets.main.allSource.srcDirs)
sourceDirectories = files(subprojectsToConsider.sourceSets.main.allSource.srcDirs)
classDirectories = files(subprojectsToConsider.sourceSets.main.output)
executionData = files(subprojectsToConsider.jacocoTestReport.executionData)
jacocoClasspath = files(subprojectsToConsider.jacocoTestReport.jacocoClasspath)
reports {
html {
enabled = true
destination = file("$buildDir/reports/jacoco")
}
xml {
enabled = false
}
csv {
enabled = false
}
}
onlyIf = {
true
}
doFirst {
executionData = files(executionData.findAll {
it.exists()
})
}
}
task continuousIntegration {
dependsOn subprojects.build, 'tapestry-core:testWithPrototype', aggregateJavadoc, combinedJacocoReport
description "Task executed on Jenkins CI server after Git commits"
}
task wrapper(type: Wrapper) {
gradleVersion = '4.3.1'
description "Regenerates the Gradle Wrapper files"
}
task zippedSources(type: Zip) {
description "Creates a combined Zip file of all sub-project's sources"
group "Release artifact"
destinationDir buildDir
baseName "apache-tapestry"
version project.version
classifier "sources"
from project.projectDir
exclude "out/**"
exclude "**/*.iml"
exclude "**/*.ipr"
exclude "**/*.iws"
exclude "**/.*/**"
exclude "**/bin/**"
exclude "**/target/**"
exclude "**/build/**"
exclude "**/test-output/**" // Left around by TestNG sometimes
}
task zippedApidoc(type: Zip) {
dependsOn aggregateJavadoc
description "Zip archive of the project's aggregate JavaDoc and CoffeeScript documentation"
group "Release artifact"
destinationDir buildDir
baseName "apache-tapestry"
version project.version
classifier "apidocs"
from file("src/docroot-template"), {
filter ReplaceTokens, tokens: [version: project.version]
include "*.html"
}
from file("src/docroot-template"), {
exclude "*.html"
}
into "apidocs", { from aggregateJavadoc.outputs.files }
into "coffeescript", { from coffeeScriptDocs.outputs.files }
}
task zippedBinaries(type: Zip) {
description "Zip archive of binaries of each sub-project"
// TODO: Plus dependencies?
group "Release artifact"
// This may create a few unwanted dependencies, but does
// seem to ensure that the subprojects are created
inputs.files subprojects*.configurations*.archives.artifacts.files
destinationDir buildDir
baseName "apache-tapestry"
version project.version
classifier "bin"
// This is via some experimentation
from subprojects*.configurations*.archives.artifacts*.file*.findAll {
!(it.name.endsWith(".asc") || it.name.startsWith("quickstart"))
}
from configurations.binaries
// Pick up various licenses and notices
from(projectDir) {
include "*.txt"
}
subprojects.each { sub ->
from(sub.projectDir) {
include "*.txt"
into sub.name
}
}
}
if (canDeploy) {
configurations {
archives
uploads.extendsFrom archives, signatures
}
artifacts {
archives zippedApidoc, zippedSources, zippedBinaries
}
configurations {
upload.extendsFrom archives, signatures
}
task generateMD5Checksums(type: GenMD5) {
group "Release artifact"
description "Creates MD5 checksums for archives of source and JavaDoc"
source tasks.withType(Zip)
outputDir "$buildDir/md5"
}
task generateSHA256Checksums(type: GenSHA256) {
group "Release artifact"
description "Creates SHA-256 checksums for archives of source and JavaDoc"
source tasks.withType(Zip)
outputDir "$buildDir/sha256"
}
if (doSign) {
signing {
sign configurations.archives
}
}
// This requires that you have the apacheArchivesFolder property configured in your
// ~/.gradle/gradle.properties. The folder should be a Subversion workspace for
// https://dist.apache.org/repos/dist/dev/tapestry
// after the build, you must manually add the new files to the workspace (using "svn add")
// then commit ("svn commit").
// The files will be visible in https://dist.apache.org/repos/dist/dev/tapestry/, allowing
// committers to download and verify them.
// After a successful release vote, the files can be moved to a second Subversion workspace
// for https://dist.apache.org/repos/dist/release/tapestry. Adding the files and committing
// there will publish them to http://www.apache.org/dist/tapestry ... and from there
// to all Apache mirrors (after about a 24 hour delay).
task copyArchives(type: Copy) {
group "Release artifact"
description "Copies build archives (source, bin, docs) to a configured deployment folder, along with MD5 and SHA-256 checksums and PGP signatures (if signing is enabled)"
destinationDir file(archiveDeployFolder())
from generateMD5Checksums
//from generateSHA256Checksums
from configurations.uploads.allArtifacts.files
}
task generateRelease {
dependsOn subprojects.uploadPublished, copyArchives
group "Release artifact"
description "Generates and uploads a final release to Apache Nexus and copies archives for deployment"
}
}
boolean isSnapshot() {
project.version.contains("SNAPSHOT")
}
boolean isWindows() {
System.properties['os.name'].toLowerCase().contains('windows')
}
task updateBootstrap {
doLast {
def bootstrapVersion = '3.3.7'
def target = new File(temporaryDir, 'bootstrap.zip')
ant.get(src: "https://github.com/twbs/bootstrap/archive/v${bootstrapVersion}.zip", dest: target)
def adjustDirectory = {
def relativePath = it.relativePath
if (relativePath.pathString.contains('/dist/')){
relativePath = new RelativePath(!it.file.isDirectory(), relativePath.segments[2..-1] as String[])
} else {
relativePath = new RelativePath(!it.file.isDirectory(), relativePath.segments[1..-1] as String[])
}
println "copying $it.relativePath to $relativePath"
it.relativePath = relativePath
}
copy {
from(zipTree(target)){
include('*/js/*.js')
include('*/dist/fonts/*')
eachFile adjustDirectory
}
from(zipTree(target)){
include('*/dist/css/bootstrap.css')
include('*/dist/css/bootstrap-theme.css')
eachFile adjustDirectory
// TAP5-2351: remove source map reference from css files
filter({ (it ==~ /\/\*\s*# sourceMappingURL=[\S]+\s*\*\//) ? "" : it })
}
into('tapestry-core/src/main/resources/META-INF/assets/tapestry5/bootstrap/')
}
copy {
from(zipTree(target)){
include('*/js/*.js')
include('*/dist/fonts/*')
include('*/less/**/*.less')
eachFile adjustDirectory
}
into('tapestry-webresources/src/test/webapp/bootstrap/')
}
}
}