mirror of
https://github.com/google/nomulus
synced 2025-12-23 06:15:42 +00:00
We used to publish test artifacts to a Maven repo on GCS, for use by schema tests. For this to work with Kokoro, the GCS bucket must be accessible to all users. To comply with the no-public-user requirement, we store the necessary jars at at well-known bucket and map them into Kokoro. This strategy cannot be used on the Maven repo because only a small number of files with fixed names may be mapped. With the Maven repo, there are too many files to map.
260 lines
8.5 KiB
Groovy
260 lines
8.5 KiB
Groovy
import org.gradle.process.internal.ExecException
|
|
|
|
// 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.
|
|
|
|
buildscript {
|
|
dependencies {
|
|
def deps = rootProject.dependencyMap
|
|
|
|
classpath deps['org.flywaydb:flyway-database-postgresql']
|
|
}
|
|
}
|
|
|
|
plugins {
|
|
id "org.flywaydb.flyway" version "11.0.1"
|
|
id 'maven-publish'
|
|
}
|
|
|
|
ext {
|
|
Set restrictedDbEnv =
|
|
[ 'sandbox', 'production' ].asUnmodifiable()
|
|
|
|
def dbServerProperty = 'dbServer'
|
|
def dbNameProperty = 'dbName'
|
|
|
|
def dbServer = findProperty(dbServerProperty).toString().toLowerCase()
|
|
def dbName = findProperty(dbNameProperty)
|
|
|
|
isRestricted = {
|
|
return restrictedDbEnv.contains(dbServer)
|
|
}
|
|
|
|
getAccessInfoByHostPort = { hostAndPort ->
|
|
println "Database set to ${hostAndPort}."
|
|
return [
|
|
url: "jdbc:postgresql://${hostAndPort}/${dbName}",
|
|
user: findProperty('dbUser'),
|
|
password: findProperty('dbPassword')]
|
|
}
|
|
|
|
getSocketFactoryAccessInfo = { env ->
|
|
def cred = getCloudSqlCredential(env).split(' ')
|
|
def sqlInstance = cred[0]
|
|
println "Database set to Cloud SQL instance ${sqlInstance}."
|
|
return [
|
|
url: """\
|
|
jdbc:postgresql://google/${dbName}?cloudSqlInstance=
|
|
${sqlInstance}&socketFactory=
|
|
com.google.cloud.sql.postgres.SocketFactory"""
|
|
.stripIndent()
|
|
.replaceAll(System.lineSeparator(), '') ,
|
|
user: cred[1],
|
|
password: cred[2]]
|
|
}
|
|
|
|
getJdbcAccessInfo = {
|
|
if (rootProject.projects.keySet().contains(dbServer)) {
|
|
return getSocketFactoryAccessInfo(dbServer)
|
|
} else if (!dbServer.isEmpty()) {
|
|
return getAccessInfoByHostPort(dbServer)
|
|
} else {
|
|
// Not running flyway tasks. Return a dummy object for Flyway config.
|
|
return [ url: '', user: '', password: '' ]
|
|
}
|
|
}
|
|
|
|
// Retrieves the Cloud SQL credential for the schema deployer. Result is in
|
|
// the form of 'instancename username password'.
|
|
//
|
|
// The env parameter may be one of the following: alpha, crash, sandbox, or
|
|
// production.
|
|
//
|
|
// User must make sure that the nomulus tool can be found on PATH. An alias
|
|
// will not work.
|
|
getCloudSqlCredential = { env ->
|
|
try {
|
|
execInBash('which nomulus', '/tmp')
|
|
} catch (ExecException e) {
|
|
throw new IllegalStateException(
|
|
'nomulus not found. Make sure it is on PATH, not just an alias.')
|
|
}
|
|
def command =
|
|
"nomulus -e ${env} get_sql_credential --user schema_deployer"
|
|
|
|
return execInBash(command, project.rootDir)
|
|
}
|
|
}
|
|
|
|
task schemaJar(type: Jar) {
|
|
archiveBaseName = 'schema'
|
|
from(sourceSets.main.resources) {
|
|
include 'sql/flyway/**'
|
|
include 'sql/schema/nomulus.golden.sql'
|
|
}
|
|
}
|
|
|
|
// Expose NomulusPostgreSql class to ':core' for implementation, without
|
|
// leaking unnecessary dependencies to the release artifacts through ':core'.
|
|
// Jar is put in the 'implementationApi' configuration.
|
|
task implementationApiJar(type: Jar) {
|
|
archiveBaseName = 'implementation'
|
|
from(sourceSets.main.output) {
|
|
include 'google/registry/persistence/NomulusPostgreSql**'
|
|
}
|
|
}
|
|
|
|
configurations {
|
|
implementationApi
|
|
schema
|
|
integration
|
|
}
|
|
|
|
artifacts {
|
|
implementationApi implementationApiJar
|
|
schema schemaJar
|
|
}
|
|
|
|
// Adds flyway tasks such as: flywayInfo, flywayValidate, flywayMigrate (
|
|
// deploying the schema in local repository), and flywayClean (dropping all data
|
|
// in the database). The latter two commands are disallowed in environments
|
|
// listed in ext.restrictedDbEnv.
|
|
//
|
|
// Examples:
|
|
// Get info in alpha: nom_build :db:flywayInfo --dbServer=alpha
|
|
// Deploy schema to a local test instance and override the database name:
|
|
// nom_build :db:flywayMigrate --dbServer=localhost:5432 --dbName=not-default \
|
|
// --dbUser=... --dbPassword=...
|
|
|
|
flyway {
|
|
def accessInfo = project.ext.getJdbcAccessInfo()
|
|
// Below config is required when adding an index concurrently using the
|
|
// `flywayMigrate` Gradle task. However it is currently broken and an
|
|
// `unknonw property` exception is thrown. Disabling it for now since we
|
|
// do not expect adding indexes concurrently very often.
|
|
// See also: https://github.com/flyway/flyway/issues/3858
|
|
//
|
|
// pluginConfiguration = [
|
|
// postgresqlTransactionalLock: 'false'
|
|
// ]
|
|
|
|
url = accessInfo.url
|
|
user = accessInfo.user
|
|
password = accessInfo.password
|
|
schemas = [ 'public' ]
|
|
|
|
locations = [ "classpath:sql/flyway" ]
|
|
}
|
|
|
|
dependencies {
|
|
def deps = rootProject.dependencyMap
|
|
|
|
implementation deps['org.flywaydb:flyway-core']
|
|
implementation deps['org.flywaydb:flyway-database-postgresql']
|
|
implementation deps['org.testcontainers:testcontainers']
|
|
|
|
runtimeOnly deps['com.google.cloud.sql:postgres-socket-factory']
|
|
runtimeOnly deps['org.postgresql:postgresql']
|
|
|
|
testImplementation deps['com.google.flogger:flogger']
|
|
testRuntimeOnly deps['com.google.flogger:flogger-system-backend']
|
|
testImplementation deps['com.google.guava:guava']
|
|
testImplementation deps['com.google.truth:truth']
|
|
testRuntimeOnly deps['io.github.java-diff-utils:java-diff-utils']
|
|
testImplementation deps['org.junit.jupiter:junit-jupiter-api']
|
|
testImplementation deps['org.junit.jupiter:junit-jupiter-engine']
|
|
testImplementation deps['org.junit.platform:junit-platform-launcher']
|
|
testImplementation deps['org.testcontainers:junit-jupiter']
|
|
testImplementation deps['org.testcontainers:postgresql']
|
|
testImplementation project(path: ':common', configuration: 'testing')
|
|
}
|
|
|
|
test {
|
|
// When set, run FlywayDeadlockTest#validNewScript.
|
|
def deadlock_check = 'do_flyway_deadlock_check'
|
|
if (findProperty(deadlock_check)) {
|
|
systemProperty deadlock_check, findProperty(deadlock_check)
|
|
}
|
|
}
|
|
|
|
task generateFlywayIndex {
|
|
def flywayBase = "$projectDir/src/main/resources/sql/flyway"
|
|
def filenamePattern = /V(\d+)__.*\.sql/
|
|
|
|
def getSeqNum = { file ->
|
|
def match = file.getName() =~ filenamePattern
|
|
if (match.size() != 1) {
|
|
throw new IllegalArgumentException("Bad Flyway filename: $file")
|
|
}
|
|
return match[0][1] as int
|
|
}
|
|
|
|
doLast {
|
|
def files = new File(flywayBase).listFiles()
|
|
def indexFile = new File("${flywayBase}.txt")
|
|
indexFile.write ''
|
|
for (def file : files.sort{a, b -> getSeqNum(a) <=> getSeqNum(b)}) {
|
|
indexFile << "${file.name}\n"
|
|
}
|
|
}
|
|
}
|
|
|
|
flywayInfo.dependsOn('buildNeeded')
|
|
flywayValidate.dependsOn('buildNeeded')
|
|
|
|
if (ext.isRestricted()) {
|
|
// Disable dangerous Flyway tasks in sandbox and production. Only allow info and validate.
|
|
tasks.findAll { task -> task.group.equals('Flyway')}.each {
|
|
if (it.name == 'flywayMigrate') {
|
|
it.doFirst {
|
|
throw new UnsupportedOperationException(
|
|
""" \
|
|
FlywayMigrate is disabled. See README.md for schema deployment
|
|
instructions.""".stripIndent())
|
|
}
|
|
} else if (it.name != 'flywayInfo' && it.name != 'flywayValidate') {
|
|
it.doFirst {
|
|
throw new UnsupportedOperationException(
|
|
"${it.name} from commandline is not allowed.")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (project.schemaTestArtifactsDir != '') {
|
|
dependencies {
|
|
// For schemaIncrementalDeployTest, which only uses sandbox schema
|
|
integration files("${project.schemaTestArtifactsDir}/schema.sandbox.jar")
|
|
}
|
|
|
|
// Checks if Flyway scripts can be deployed to an existing database with
|
|
// an older release. Please refer to SchemaTest.java for more information.
|
|
task schemaIncrementalDeployTest(dependsOn: processTestResources, type: Test) {
|
|
useJUnitPlatform()
|
|
include 'google/registry/sql/flyway/SchemaTest.*'
|
|
classpath = configurations.testRuntimeClasspath
|
|
.plus(configurations.integration)
|
|
.plus(files(sourceSets.test.output.classesDirs))
|
|
.plus(files(sourceSets.test.output.resourcesDir))
|
|
.plus(files(sourceSets.main.output.classesDirs))
|
|
|
|
// Declare test-runtime dependency on Flyway scripts in the resources dir.
|
|
// They are not on classpath since they conflict with the base schema.
|
|
inputs.dir sourceSets.main.output.resourcesDir
|
|
|
|
// Specifies which test to run using the following property
|
|
systemProperty 'deploy_to_existing_db', 'true'
|
|
}
|
|
}
|