blob: e9a416cf497ae871c9146d765f55dc4ab1015301 [file] [log] [blame]
description = "Apache Tapestry 5 Project"
import org.apache.tools.ant.filters.ReplaceTokens
apply plugin: "base"
apply plugin: "maven-publish"
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.14.3",
easymock: "3.3.1",
servletapi: "3.0.1",
spock: "2.1-M2-groovy-3.0",
hibernate: "5.4.32.Final",
slf4j: "1.7.25",
geb: "2.0",
selenium: "3.141.59",
jackson: "2.13.1",
jsonschemaGenerator: "4.20.0",
junitJupiter: "5.8.2",
commonsLang: "3.4"
]
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.8.2"
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"
repositories {
mavenLocal()
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 {
if (JavaVersion.current() != JavaVersion.VERSION_1_8) {
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].+/
apply plugin: "maven-publish" // for deployment
configurations {
provided
}
apply plugin: "java"
apply plugin: "java-library"
apply plugin: "groovy" // mostly for testing
apply plugin: "project-report"
apply plugin: "jacoco"
apply plugin: "base"
jacoco {
toolVersion = "0.8.7"
}
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 {
// https://docs.gradle.org/7.3.3/userguide/upgrading_version_6.html#potential_breaking_changes,
// Table 1. Common configuration upgrades
testImplementation "org.spockframework:spock-core:${versions.spock}"
testRuntimeOnly "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"
}
// Needed to have XMLTokenStreamTests.testStreamEncoding() passing on Java 9+
if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_1_9)) {
jvmArgs("--add-opens=java.base/java.nio.charset=ALL-UNNAMED");
}
// Turn off live service reloading
systemProperties["tapestry.service-reloading-enabled"] = "false"
systemProperties["java.io.tmpdir"] = temporaryDir.absolutePath
jvmArgs("-Dfile.encoding=UTF-8")
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 {
// println "JAR projectDir: " + projectDir.getName().replaceAll("5", "").replaceAll("tapestry-", "").replaceAll("-", "");
from(projectDir) {
include "*.txt"
into "META-INF"
}
manifest {
attributes("Automatic-Module-Name": "org.apache.tapestry." + projectDir.getName()
.replaceAll("tapestry5", "tapestry")
.replaceAll("tapestry-", "")
.replaceAll("-", ""))
if (projectDir.getName().equals("tapestry-version-migrator")) {
attributes("Main-Class": "org.apache.tapestry5.versionmigrator.Main")
}
}
}
assemble.dependsOn(processResources, compileJava, jar)
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
}
}
publishing {
publications {
mavenJava(MavenPublication) {
version = parent.version
groupId = "org.apache.tapestry"
from components.java
artifact sourcesJar
pom {
name = project.name
// TODO: find some way to get the subproject description here.
// description =
url = "https://tapestry.apache.org/"
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
scm {
connection = 'scm:git:https://gitbox.apache.org/repos/asf/tapestry-5.git'
developerConnection = 'scm:git://gitbox.apache.org/repos/asf/tapestry-5.git'
url = 'https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=summary'
}
}
matching {
it.name.endsWith(".jar") || it.name.endsWith(".pom")
}
}
}
if (canDeploy) {
repositories {
mavenLocal()
if (continuousIntegrationBuild) {
maven {
name = "apacheSnapshots"
url = snapshotUrl
credentials {
username = deployUsername()
password = deployPassword()
}
}
}
else {
maven {
name = "apacheStaging"
url = stagingUrl
credentials {
username = deployUsername()
password = deployPassword()
}
}
}
}
}
}
if (doSign) {
apply plugin: "signing"
signing {
sign publishing.publications.mavenJava
}
}
task uploadPublished {
doFirst {
if (!canDeploy) {
throw new InvalidUserDataException("Missing upload credentials. Set '$deployUsernameProperty' and '$deployPasswordProperty' root project properties.")
}
}
}
}
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()
def allMainSourceSets = subprojects*.sourceSets*.main.flatten()
def allMainJavaFiles = allMainSourceSets*.java
def allMainJavaSrcDirs = allMainJavaFiles*.srcDirs
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/"
if (JavaVersion.current() != JavaVersion.VERSION_1_8) {
tagletPath Collections.unmodifiableList(new ArrayList<>((Set) configurations.javadoc.files))
}
// Uncomment jFlags to debug `./gradlew aggregateJavadoc`
// jFlags '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005'
addStringOption '-source-path', files(allMainJavaSrcDirs.flatten()).asPath
addStringOption 'source', '8'
taglets "org.apache.tapestry5.javadoc.TapestryDocTaglet"
}
exclude "org/apache/tapestry5/internal/plastic/asm/**"
exclude "org/apache/tapestry5/internal/webresources/**"
exclude "org/apache/tapestry5/webresources/modules/**"
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 {
if (JavaVersion.current() != JavaVersion.VERSION_1_8) {
meta aggregateJavadoc.outputs.files
}
}
task combinedJacocoReport(type:JacocoReport){
def subprojectsToConsider = subprojects.findAll {it.name != 'quickstart' && it.name != 'beanmodel' && it.name != 'commons' && it.name != 'genericsresolver-guava' && it.name != 'tapestry5-annotations' && it.name != 'tapestry-internal-test' && it.name != 'tapestry-runner' && it.name != 'tapestry-test-constants' && it.name != 'tapestry-test-data' && it.name != 'tapestry-ioc-jcache'}
dependsOn = subprojectsToConsider.test
additionalSourceDirs.from(files(subprojectsToConsider.sourceSets.main.allSource.srcDirs))
sourceDirectories.from(files(subprojectsToConsider.sourceSets.main.allSource.srcDirs))
classDirectories.from(files(subprojectsToConsider.sourceSets.main.output))
executionData.from(files(subprojectsToConsider.jacocoTestReport.executionData).filter { it.exists() })
jacocoClasspath = files(subprojectsToConsider.jacocoTestReport.jacocoClasspath)
reports {
html {
enabled = true
destination = file("$buildDir/reports/jacoco")
}
xml {
enabled = false
}
csv {
enabled = false
}
}
onlyIf = {
true
}
}
task continuousIntegration {
// tapestry-javadoc doesn't work with Java 8 anymore. That's why it's only added if != 8.
def dependants = [subprojects.build, 'tapestry-core:testWithPrototype', combinedJacocoReport]
if (JavaVersion.current() != JavaVersion.VERSION_1_8) {
dependants << aggregateJavadoc
}
dependsOn dependants
description "Task executed on Jenkins CI server after Git commits"
}
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"
}
// 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.assemble, subprojects.uploadPublished, subprojects.publish, 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/')
}
}
}