mirror of
https://github.com/google/nomulus.git
synced 2025-04-29 19:47:51 +02:00
* Run cross-release SQL integration tests Run SQL integration tests across arbitrary schema and server releases. Refer to integration/README.md in this change for more information. TESTED=Cloud build changes tested with cloud-build-local Used the published jars to test sqlIntegration task locally.
427 lines
14 KiB
Groovy
427 lines
14 KiB
Groovy
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
|
//
|
|
// 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
|
|
//
|
|
// http://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.
|
|
|
|
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
|
import org.gradle.api.tasks.testing.logging.TestLogEvent
|
|
|
|
buildscript {
|
|
if (rootProject.enableDependencyLocking.toBoolean()) {
|
|
// Lock buildscript dependencies.
|
|
configurations.classpath {
|
|
resolutionStrategy.activateDependencyLocking()
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.0.1'
|
|
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.6.1"
|
|
classpath 'org.sonatype.aether:aether-api:1.13.1'
|
|
classpath 'org.sonatype.aether:aether-impl:1.13.1'
|
|
}
|
|
}
|
|
|
|
plugins {
|
|
// Java static analysis plugins. Keep versions consistent with
|
|
// ./buildSrc/build.gradle
|
|
id 'nebula.lint' version '16.0.2'
|
|
// TODO(weiminyu): consider remove net.ltgt.apt. Gradle 5.2+
|
|
// has similar functionalities.
|
|
id 'net.ltgt.apt' version '0.19' apply false
|
|
id 'net.ltgt.errorprone' version '0.6.1'
|
|
id 'checkstyle'
|
|
id 'com.github.johnrengelman.shadow' version '5.1.0'
|
|
|
|
// NodeJs plugin
|
|
id "com.moowork.node" version "1.2.0"
|
|
|
|
id 'idea'
|
|
id 'com.diffplug.gradle.spotless' version '3.25.0'
|
|
|
|
id 'jacoco'
|
|
}
|
|
|
|
wrapper {
|
|
distributionType = Wrapper.DistributionType.ALL
|
|
}
|
|
|
|
apply plugin: google.registry.gradle.plugin.ReportUploaderPlugin
|
|
|
|
reportUploader {
|
|
// Set the location where we want to upload the build results.
|
|
// e.g. -P uploaderDestination=gcs://domain-registry-alpha-build-result-test
|
|
//
|
|
// If not set - the upload will be skipped
|
|
destination = uploaderDestination
|
|
|
|
// The location of the file containing the OAuth2 Google Cloud credentials.
|
|
//
|
|
// The file can contain a Service Account key file in JSON format from the
|
|
// Google Developers Console or a stored user credential using the format
|
|
// supported by the Cloud SDK.
|
|
//
|
|
// If no file is given - the default credentials are used.
|
|
credentialsFile = uploaderCredentialsFile
|
|
|
|
// If set to 'yes', each file will be uploaded to GCS in a separate thread.
|
|
// This is MUCH faster.
|
|
multithreadedUpload = uploaderMultithreadedUpload
|
|
}
|
|
|
|
apply from: 'dependencies.gradle'
|
|
|
|
apply from: 'dependency_lic.gradle'
|
|
|
|
apply from: 'utils.gradle'
|
|
|
|
// Custom task to run checkLicense in buildSrc, which is not triggered
|
|
// by root project tasks. A shell task is used because buildSrc tasks
|
|
// cannot be referenced in the same way as tasks from a regular included
|
|
// build.
|
|
task checkBuildSrcLicense(type:Exec) {
|
|
workingDir "${rootDir}/buildSrc"
|
|
commandLine '../gradlew', 'checkLicense'
|
|
}
|
|
tasks.checkLicense.dependsOn(tasks.checkBuildSrcLicense)
|
|
tasks.build.dependsOn(tasks.checkLicense)
|
|
|
|
// Provide defaults for all of the project properties.
|
|
|
|
// Only do linting if the build is successful.
|
|
gradleLint.autoLintAfterFailure = false
|
|
|
|
// Paths to main and test sources.
|
|
ext.projectRootDir = "${rootDir}"
|
|
|
|
// Tasks to deploy/stage all App Engine services
|
|
task deploy {
|
|
group = 'deployment'
|
|
description = 'Deploys all services to App Engine.'
|
|
}
|
|
|
|
task stage {
|
|
group = 'deployment'
|
|
description = 'Generates application directories for all services.'
|
|
}
|
|
|
|
// App-engine environment configuration. We set up all of the variables in
|
|
// the root project.
|
|
|
|
def environments = ['production', 'sandbox', 'alpha', 'crash']
|
|
|
|
def gcpProject = null
|
|
|
|
apply from: "${rootDir.path}/projects.gradle"
|
|
|
|
if (environment == '') {
|
|
// Keep the project null, this will prevent deployment. Set the
|
|
// environment to "alpha" because other code needs this property to
|
|
// explode the war file.
|
|
environment = 'alpha'
|
|
} else if (environment != 'production' && environment != 'sandbox') {
|
|
gcpProject = projects[environment]
|
|
if (gcpProject == null) {
|
|
throw new GradleException("-Penvironment must be one of " +
|
|
"${projects.keySet()}.")
|
|
}
|
|
}
|
|
|
|
rootProject.ext.environment = environment
|
|
rootProject.ext.gcpProject = gcpProject
|
|
rootProject.ext.prodOrSandboxEnv = environment in ['production', 'sandbox']
|
|
|
|
// Function to verify that the deployment parameters have been set.
|
|
def verifyDeploymentParams() {
|
|
if (prodOrSandboxEnv) {
|
|
// Do not deploy to prod or sandbox. Print a prominent error in bright red.
|
|
System.err.println('\033[31;1m-----------------------------------------------------------------')
|
|
System.err.println('*** DANGER WILL ROBINSON!')
|
|
System.err.println('*** You may not deploy to production or sandbox from gradle. Do a')
|
|
System.err.println('*** release from Spinnaker, see deployment playbook.')
|
|
System.err.println('-----------------------------------------------------------------')
|
|
throw new GradleException('Aborting. See prominent error above.')
|
|
} else if (gcpProject == null) {
|
|
def error = 'You must specify -P environment={alpha,crash}'
|
|
System.err.println("\033[33;1m${error}\033[0m")
|
|
throw GradleException("Aborting: ${error}")
|
|
}
|
|
}
|
|
|
|
// Closure that we can just drop into all of our deployment tasks.
|
|
rootProject.ext.verifyDeploymentConfig = {
|
|
doFirst { verifyDeploymentParams() }
|
|
}
|
|
|
|
// Subproject configuration.
|
|
|
|
allprojects {
|
|
// Skip no-op project
|
|
if (project.name == 'services') return
|
|
|
|
repositories {
|
|
if (rootProject.mavenUrl) {
|
|
maven {
|
|
println "Java dependencies: Using repo $pluginsUrl..."
|
|
url rootProject.mavenUrl
|
|
}
|
|
} else {
|
|
println "Java dependencies: Using Maven Central..."
|
|
mavenCentral()
|
|
}
|
|
}
|
|
}
|
|
|
|
task runPresubmits(type: Exec) {
|
|
executable '/usr/bin/python'
|
|
args('config/presubmits.py')
|
|
}
|
|
|
|
subprojects {
|
|
// Skip no-op project
|
|
if (project.name == 'services') return
|
|
|
|
ext.createUberJar = { taskName, binaryName, mainClass ->
|
|
project.tasks.create(
|
|
taskName, com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
|
|
mergeServiceFiles()
|
|
baseName = binaryName
|
|
manifest {
|
|
attributes 'Main-Class': mainClass
|
|
}
|
|
zip64 = true
|
|
classifier = ''
|
|
archiveVersion = ''
|
|
configurations = [project.configurations.runtimeClasspath]
|
|
from project.sourceSets.main.output
|
|
// Excludes signature files that accompany some dependency jars, like
|
|
// bonuncycastle. If they are present, only classes from those signed jars are
|
|
// made available to the class loader.
|
|
// see https://discuss.gradle.org/t/signing-a-custom-gradle-plugin-thats-downloaded-by-the-build-system-from-github/1365
|
|
exclude "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA"
|
|
}
|
|
}
|
|
|
|
if (rootProject.enableDependencyLocking.toBoolean()) {
|
|
buildscript {
|
|
// Lock buildscript dependencies.
|
|
configurations.classpath {
|
|
resolutionStrategy.activateDependencyLocking()
|
|
}
|
|
}
|
|
}
|
|
|
|
afterEvaluate {
|
|
if (rootProject.enableDependencyLocking.toBoolean()
|
|
&& project.name != 'integration') {
|
|
// The ':integration' project runs server/schema integration tests using
|
|
// dynamically specified jars with no transitive dependency. Therefore
|
|
// dependency-locking does not make sense. Furthermore, during
|
|
// evaluation it resolves the 'testRuntime' configuration, making it
|
|
// immutable. Locking activation would trigger an invalid operation
|
|
// exception.
|
|
//
|
|
// For all other projects, due to problem with the gradle-license-report
|
|
// plugin, the dependencyLicenseReport configuration must opt out of
|
|
// dependency-locking. See dependency_lic.gradle for the reason why.
|
|
//
|
|
// To selectively activate dependency locking without hardcoding them
|
|
// in the 'configurations' block, the following code must run after
|
|
// project evaluation, when all configurations have been created.
|
|
configurations.each {
|
|
if (it.name != 'dependencyLicenseReport') {
|
|
it.resolutionStrategy.activateDependencyLocking()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
def services = [':services:default',
|
|
':services:backend',
|
|
':services:tools',
|
|
':services:pubapi']
|
|
|
|
// Set up all of the deployment projects.
|
|
if (services.contains(project.path)) {
|
|
|
|
apply from: "${rootDir.path}/appengine_war.gradle"
|
|
|
|
// Return early, do not apply the settings below.
|
|
return
|
|
}
|
|
|
|
apply from: "${rootDir.path}/java_common.gradle"
|
|
|
|
if (project.name == 'third_party') return
|
|
|
|
project.tasks.test.dependsOn runPresubmits
|
|
|
|
// Path to code generated with annotation processors. Note that this path is
|
|
// chosen by the 'net.ltgt.apt' plugin, and may change if IDE-specific plugins
|
|
// are applied, e.g., 'idea' or 'eclipse'
|
|
def aptGeneratedDir = "${project.buildDir}/generated/source/apt/main"
|
|
def aptGeneratedTestDir = "${project.buildDir}/generated/source/apt/test"
|
|
|
|
def commonlyExcludedResources = ['**/*.java', '**/BUILD']
|
|
|
|
project.ext.javaDir = "${project.projectDir}/src/main/java"
|
|
project.ext.javaTestDir = "${project.projectDir}/src/test/java"
|
|
project.ext.resourcesSourceDir = "${project.projectDir}/src/main/resources"
|
|
|
|
sourceSets {
|
|
main {
|
|
java {
|
|
srcDirs += aptGeneratedDir
|
|
}
|
|
resources {
|
|
srcDirs += project.ext.javaDir
|
|
exclude commonlyExcludedResources
|
|
}
|
|
}
|
|
test {
|
|
java {
|
|
srcDirs += aptGeneratedTestDir
|
|
}
|
|
resources {
|
|
srcDirs += project.ext.javaTestDir
|
|
exclude commonlyExcludedResources
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If "-P verboseTestOutput=true" is passed in, configure all subprojects to dump all of their
|
|
// output and final test status (pass/fail, errors) for each test class.
|
|
//
|
|
// Note that we can't do this in the main subprojects section above because that's evaluated before
|
|
// the subproject build files and the test tasks haven't been defined yet. We have to do it from
|
|
// the projectsEvaluted hook, which gets called after the subprojects are configured.
|
|
if (verboseTestOutput.toBoolean()) {
|
|
gradle.projectsEvaluated({
|
|
subprojects {
|
|
tasks.withType(Test) {
|
|
testLogging {
|
|
events TestLogEvent.FAILED, TestLogEvent.PASSED, TestLogEvent.SKIPPED,
|
|
TestLogEvent.STANDARD_OUT, TestLogEvent.STANDARD_ERROR
|
|
exceptionFormat TestExceptionFormat.FULL
|
|
showExceptions true
|
|
showCauses true
|
|
showStackTraces true
|
|
|
|
afterSuite { desc, result ->
|
|
println "Results: ${result.resultType}, " +
|
|
"${result.successfulTestCount}/${result.testCount} tests " +
|
|
"passed, ${result.failedTestCount} failures.";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
task checkDependenciesDotGradle {
|
|
def buildSrcDepsFile = File.createTempFile('buildSrc', 'deps')
|
|
buildSrcDepsFile.deleteOnExit()
|
|
dependsOn createGetBuildSrcDirectDepsTask(buildSrcDepsFile)
|
|
|
|
doLast {
|
|
Set<String> depsInUse = []
|
|
allprojects {
|
|
configurations.all {
|
|
it.dependencies.findAll { it.group != null }.each {
|
|
// Note: .toString() is required since GString should
|
|
// not be mixed with Java Strings.
|
|
depsInUse.add("${it.group}:${it.name}".toString())
|
|
}
|
|
}
|
|
}
|
|
if (buildSrcDepsFile.exists()) {
|
|
depsInUse.addAll(buildSrcDepsFile.readLines())
|
|
}
|
|
def unusedDeps =
|
|
rootProject.dependencyMap.keySet()
|
|
.findAll { !depsInUse.contains(it) }
|
|
.toSorted()
|
|
|
|
if (unusedDeps.isEmpty()) {
|
|
return
|
|
}
|
|
logger.error(
|
|
"Unused dependencies in dependencies.gradle:\n${unusedDeps.toListString()}")
|
|
throw new IllegalStateException(
|
|
"The dependencies.gradle file should only contain direct dependencies.")
|
|
}
|
|
}
|
|
tasks.build.dependsOn(tasks.checkDependenciesDotGradle)
|
|
|
|
def createGetBuildSrcDirectDepsTask(outputFileName) {
|
|
return tasks
|
|
.create(
|
|
"getBuildSrcDeps_${java.util.UUID.randomUUID()}".toString(),
|
|
Exec) {
|
|
workingDir "${rootDir}/buildSrc"
|
|
commandLine '../gradlew', 'exportDependencies',
|
|
"-PdependencyExportFile=${outputFileName}"
|
|
}
|
|
}
|
|
|
|
rootProject.ext {
|
|
invokeJavaDiffFormatScript = { action ->
|
|
def scriptDir = rootDir.path.endsWith('buildSrc')
|
|
? "${rootDir}/../java-format"
|
|
: "${rootDir}/java-format"
|
|
def workingDir = rootDir.path.endsWith('buildSrc')
|
|
? "${rootDir}/.."
|
|
: rootDir
|
|
def formatDiffScript = "${scriptDir}/google-java-format-git-diff.sh"
|
|
|
|
return ext.execInBash(
|
|
"${formatDiffScript} ${action}", "${workingDir}")
|
|
}
|
|
}
|
|
|
|
// Checks if modified lines in Java source files need reformatting.
|
|
// Note that this task checks modified Java files in the entire repository.
|
|
task javaIncrementalFormatCheck {
|
|
doLast {
|
|
def checkResult = invokeJavaDiffFormatScript("check")
|
|
if (checkResult == 'true') {
|
|
throw new IllegalStateException(
|
|
"Some Java files need to be reformatted. You may use the "
|
|
+ "'javaIncrementalFormatDryRun' task to review\n "
|
|
+ "the changes, or the 'javaIncrementalFormatApply' task "
|
|
+ "to reformat.")
|
|
} else if (checkResult != 'false') {
|
|
throw new RuntimeException(
|
|
"Failed to invoke format check script:\n" + checkResult)
|
|
}
|
|
println("Incremental Java format check ok.")
|
|
}
|
|
}
|
|
|
|
// Shows how modified lines in Java source files will change after formatting.
|
|
// Note that this task checks modified Java files in the entire repository.
|
|
task javaIncrementalFormatDryRun {
|
|
doLast {
|
|
println("${invokeJavaDiffFormatScript("show")}")
|
|
}
|
|
}
|
|
|
|
// Checks if modified lines in Java source files need reformatting.
|
|
// Note that this task processes modified Java files in the entire repository.
|
|
task javaIncrementalFormatApply {
|
|
doLast {
|
|
invokeJavaDiffFormatScript("format")
|
|
}
|
|
}
|
|
|
|
tasks.build.dependsOn(tasks.javaIncrementalFormatCheck)
|