Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time
// 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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
apply plugin: 'java'
apply plugin: 'nebula.lint'
apply plugin: 'net.ltgt.errorprone'
apply plugin: 'checkstyle'
apply plugin: 'jacoco'
// Checkstyle should run as part of the testing task
tasks.test.dependsOn tasks.checkstyleMain
tasks.test.dependsOn tasks.checkstyleTest
// Generate per-subproject reports in build/reports/jacoco directory.
// TODO(weiminyu): publish periodical reports to well known location.
// TODO(weiminyu): investigate incremental coverage change calculation and alert.
tasks.test.finalizedBy jacocoTestReport
// Exclude test-only dependencies from release artifacts.
// TLDR: Project dependency should be on runtimeClasspath. A custom
// configuration 'deploy_jar' is used as a proxy to expose runtimeClasspath
// to other projects. It is also convenient to exclude test-only jars from
// runtimeClasspath.
// Here is the context:
// - Some dependencies have test-only jars on their 'compile' classpaths.
// - As a result, they appear in our 'compile', 'runtimeClasspath' and
// 'default' configurations, among others, and end up in our release war
// files.
// - Since these jars are needed for our own tests, we can only exclude them
// from runtimeClasspath. Excluding them from 'compile' or 'runtime' would
// also exclude them from testCompileClasspath and testRuntimeClasspath,
// resulting in test failures.
// - If configuration is not specified, project dependency uses the 'default'
// configuration, which always has the same content as 'runtime'.
// - When release is involved, 'runtimeClasspath' is actually the right
// configuration to use. The 'runtime' configuration does not include
// 'runtimeOnly' dependencies, while 'runtimeClasspath' does.
// - 'runtimeClasspath' cannot be referenced directly by another project.
// We use a custom configuration 'deploy_jar' as a proxy.
// TODO(weiminyu): Fix all project dependencies to use deploy_jar
configurations {
deploy_jar.extendsFrom runtimeClasspath
all.findAll { in ['runtimeClasspath', 'compileClasspath']
}.each {
// JUnit is from org.apache.beam:beam-runners-google-cloud-dataflow-java,
// and json-simple.
it.exclude group: 'junit'
// Mockito is from org.apache.beam:beam-runners-google-cloud-dataflow-java
// See
it.exclude group: 'org.mockito', module: 'mockito-core'
dependencies {
// compatibility with Java 8
test {
// Sets up integration test with a registry environment. The target environment
// is passed by the 'test.gcp_integration.env' property. Test runner must have
// been authorized to access the corresponding GCP project, e.g., by running
// 'gcloud auth application-default login' or by downloading a credential file
// and assign the path to it to the GOOGLE_APPLICATION_CREDENTIALS environment
// variable.
// A typical use case is to run tests from desktop that accesses Cloud resources. See
// core/src/test/java/google/registry/beam/initsql/ for an example.
tasks.withType(Test).configureEach {
def gcp_integration_env_property = 'test.gcp_integration.env'
if (project.hasProperty(gcp_integration_env_property)) {
String targetEnv =
if (targetEnv in ['sandbox', 'production']) {
throw new RuntimeException("Integration test with production or sandbox not allowed.")
systemProperty gcp_integration_env_property, targetEnv
// This environment variable along with testcontainers 1.15.2 works around
// a race condition introduced in 1.15.0. This can be removed once httpclient5
// becomes the default transport type in testcontainers, which may happen
// in 1.16.x.
// See
// for more information.
environment('TESTCONTAINERS_TRANSPORT_TYPE', 'httpclient5')
tasks.withType(JavaCompile).configureEach {
// The -Werror flag causes Intellij to fail on deprecated api use.
// Allow IDE user to turn off this flag by specifying a Gradle VM
// option from inside the IDE.
if (System.getProperty('no_werror') != 'true' &&
// The core project throws an warning about Gradle annotation processor
// not compatible with Java source version > 8. Re-assess once the
// warning is fixed.
getProject().name != 'core') {
options.compilerArgs << "-Werror"
options.errorprone.disableWarningsInGeneratedCode = true
asArguments: {
return ['-XepExcludedPaths:.*/build/generated/.*']
}] as CommandLineArgumentProvider)
// Disable features currently incompatible with Java 12
if ((JavaVersion.current().majorVersion as Integer) > 11) {
// This check is broken in Java 12.
// See
// TODO: Change source version to 11 after target version is changed to 11 and
// once we figure out what's wrong with Dagger compilation with source version
// >8.
sourceCompatibility = '8'
// TODO: Change target version to 11. Source version can stay at 8.
targetCompatibility = '8'
compileJava { options.encoding = "UTF-8" }
compileTestJava { options.encoding = "UTF-8" }
gradleLint.rules = [
// Checks if Gradle wrapper is up-to-date
// Checks for indirect dependencies with dynamic version spec. Best
// practice calls for declaring them with specific versions.
// TODO(weiminyu): enable more dependency checks
// To check or fix file formats, run the following commands from this directory:
// - Check: ./gradlew spotlessCheck
// - Format in place: ./gradlew spotlessApply
spotless {
format 'misc', {
target '**/*.gradle'
targetExclude '**/cloudbuild-caches/**'
jacocoTestReport {
// Use coverage data from all tests tasks, not just the one named 'test'.
// Initialize for coverage minimum determination for each sub project.
task initCoverageMinimums {
// Use current coverage ratio of each subproject as placeholder value.
// Long-term plan is to calculate incremental coverage on the fly.
rootProject.ext.coverageMinimums = [
'core' : 0.6,
'proxy' : 0.52,
'util' : 0.57
rootProject.ext.getMinCoverage = { key ->
if (rootProject.coverageMinimums.containsKey(key)) {
return rootProject.coverageMinimums.get(key)
return 0.0
// Alerts for coverage violation. Note that,
// - This task is FYI only and needs to be invoked explicitly.
// - This task does not address incremental coverage.
jacocoTestCoverageVerification {
dependsOn initCoverageMinimums
violationRules {
rule {
// Each limit consists of the following properties:
// - An 'element' type: BUNDLE (default), PACKAGE, CLASS, SOURCEFILE, or METHOD.
// - A 'counter' type: INSTRUCTION (default), LINE, BRANCH, COMPLEXITY, METHOD, or CLASS
// - The 'minimum' threshold, given as a fraction or a percentage (including '%')
limit {
minimum = rootProject.getMinCoverage(project.getName())