// 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.internal.tasks.userinput.UserInputHandler plugins { id "org.flywaydb.flyway" version "6.0.1" id 'maven-publish' } ext { Set restrictedDbEnv = [ 'sandbox', 'production' ].asUnmodifiable() Set allDbEnv = [ 'alpha', 'crash' ].plus(restrictedDbEnv).asUnmodifiable() def dbServerProperty = 'dbServer' def dbNameProperty = 'dbName' def dbServer = findProperty(dbServerProperty).toString().toLowerCase() def dbName = findProperty(dbNameProperty) isCloudSql = { return allDbEnv.contains(dbServer) } getAccessInfoByHostPort = { hostAndPort -> return [ url: "jdbc:postgresql://${hostAndPort}/${dbName}", user: findProperty('dbUser'), password: findProperty('dbPassword')] } getSocketFactoryAccessInfo = { env -> def cred = getCloudSqlCredential(env, 'admin').split(' ') def sqlInstance = cred[0] 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 (allDbEnv.contains(dbServer)) { return getSocketFactoryAccessInfo(dbServer) } else { return getAccessInfoByHostPort(dbServer) } } // Retrieves Cloud SQL credential for a given role. Result is in the form of // 'instancename username password'. // // The env parameter may be one of the following: alpha, crash, sandbox, or // production. The role parameter may be superuser. (More roles will be added // later). getCloudSqlCredential = { env, role -> def devProject = project.hasProperty('devProject') ? project.getProperty('devProject') : rootProject.devProject def command = """gsutil cp \ gs://${devProject}-deploy/cloudsql-credentials/${env}/${role}_credential.enc - | \ base64 -d | \ gcloud kms decrypt --location global --keyring nomulus-tool-keyring \ --key nomulus-tool-key --plaintext-file=- \ --ciphertext-file=- \ --project=${devProject}""" return execInBash(command, '/tmp') } } 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 compile, without leaking // unnecessary dependencies to the release artifacts through ':core'. // Jar is put in the 'compileApi' configuration. task compileApiJar(type: Jar) { archiveBaseName = 'compile' from(sourceSets.main.output) { include 'google/registry/persistence/NomulusPostgreSql**' } } configurations { compileApi schema } artifacts { compileApi compileApiJar schema schemaJar } publishing { repositories { maven { url project.publish_repo } } publications { sqlSchemaPublication(MavenPublication) { groupId 'google.registry' artifactId 'schema' version project.schema_version artifact schemaJar } } } flyway { def accessInfo = project.ext.getJdbcAccessInfo() url = accessInfo.url user = accessInfo.user password = accessInfo.password schemas = [ 'public' ] locations = [ "classpath:sql/flyway" ] } dependencies { def deps = rootProject.dependencyMap compile deps['org.flywaydb:flyway-core'] runtimeOnly deps['com.google.cloud.sql:postgres-socket-factory'] runtimeOnly deps['org.postgresql:postgresql'] testCompile deps['com.google.flogger:flogger'] testRuntime deps['com.google.flogger:flogger-system-backend'] testCompile deps['com.google.guava:guava'] testCompile deps['com.google.truth:truth'] testRuntime deps['io.github.java-diff-utils:java-diff-utils'] testCompile deps['junit:junit'] testCompile deps['org.testcontainers:postgresql'] testCompile deps['org.testcontainers:testcontainers'] testCompile project(path: ':common', configuration: 'testing') testCompile project(':third_party') } flywayInfo.dependsOn('buildNeeded') flywayValidate.dependsOn('buildNeeded') if (ext.isCloudSql()) { // Disable dangerous Flyway tasks. 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.") } } } }