mirror of
https://github.com/google/nomulus
synced 2026-05-18 13:51:45 +00:00
Compare commits
22 Commits
proxy-2024
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de3af34b66 | ||
|
|
5c62dc78ba | ||
|
|
3fdecde6e9 | ||
|
|
e7bf74d91d | ||
|
|
ff211fb4f9 | ||
|
|
3a7c53d895 | ||
|
|
f5b279a288 | ||
|
|
c68583f666 | ||
|
|
6d2eb2e140 | ||
|
|
00a2022292 | ||
|
|
de372c4d47 | ||
|
|
5f9c7de516 | ||
|
|
6e57d93507 | ||
|
|
b9cfa65546 | ||
|
|
9af006836c | ||
|
|
cd95be4776 | ||
|
|
bdc9a1fd1d | ||
|
|
d0b036227a | ||
|
|
0f02858965 | ||
|
|
6acb14c60d | ||
|
|
e881f254f8 | ||
|
|
1fb27fcf8e |
23
.github/workflows/codeql.yml
vendored
23
.github/workflows/codeql.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ 'master' ]
|
||||
schedule:
|
||||
- cron: '24 4 * * 2'
|
||||
- cron: '24 4 * * *'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
@@ -27,17 +27,17 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Java version
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -47,11 +47,20 @@ jobs:
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
queries: security-and-quality
|
||||
|
||||
# Build with Gradle
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
build-scan-publish: true
|
||||
build-scan-terms-of-service-url: "https://gradle.com/terms-of-service"
|
||||
build-scan-terms-of-service-agree: "yes"
|
||||
- name: Execute Gradle build
|
||||
run: ./gradlew build -x test -x jIFC
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
#- name: Autobuild
|
||||
# uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
@@ -64,6 +73,6 @@ jobs:
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
25
.github/workflows/dependency-submission.yml
vendored
Normal file
25
.github/workflows/dependency-submission.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Dependency Submission
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 'master' ]
|
||||
schedule:
|
||||
- cron: '24 3 * * *'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
|
||||
dependency-submission:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Set Java version
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
- name: Generate and submit dependency graph
|
||||
uses: gradle/actions/dependency-submission@v3
|
||||
23
.github/workflows/do-not-merge.yml
vendored
Normal file
23
.github/workflows/do-not-merge.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: "Check labels"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ["master"]
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- labeled
|
||||
- unlabeled
|
||||
merge_group:
|
||||
branches: ["master"]
|
||||
types: [checks_requested]
|
||||
|
||||
jobs:
|
||||
fail-by-label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fail if PR is labeled as "do not merge"
|
||||
if: contains(github.event.pull_request.labels.*.name, 'do not merge')
|
||||
run: |
|
||||
echo "This PR is labeled as do not merge!"
|
||||
exit 1
|
||||
68
build.gradle
68
build.gradle
@@ -36,8 +36,7 @@ buildscript {
|
||||
}
|
||||
|
||||
plugins {
|
||||
// Java static analysis plugins. Keep versions consistent with
|
||||
// ./buildSrc/build.gradle.kts
|
||||
// Java static analysis plugins.
|
||||
|
||||
// Re-enable when compatible with Gradle 8
|
||||
// id 'nebula.lint' version '16.0.2'
|
||||
@@ -68,44 +67,12 @@ 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.
|
||||
@@ -452,9 +419,6 @@ if (verboseTestOutput.toBoolean()) {
|
||||
}
|
||||
|
||||
task checkDependenciesDotGradle {
|
||||
def buildSrcDepsFile = File.createTempFile('buildSrc', 'deps')
|
||||
buildSrcDepsFile.deleteOnExit()
|
||||
dependsOn createGetBuildSrcDirectDepsTask(buildSrcDepsFile)
|
||||
|
||||
doLast {
|
||||
Set<String> depsInUse = []
|
||||
@@ -467,9 +431,7 @@ task checkDependenciesDotGradle {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (buildSrcDepsFile.exists()) {
|
||||
depsInUse.addAll(buildSrcDepsFile.readLines())
|
||||
}
|
||||
|
||||
def unusedDeps =
|
||||
rootProject.dependencyMap.keySet()
|
||||
.findAll { !depsInUse.contains(it) }
|
||||
@@ -486,17 +448,6 @@ task checkDependenciesDotGradle {
|
||||
}
|
||||
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 javaHome = project.findProperty('org.gradle.java.home')
|
||||
@@ -507,12 +458,8 @@ rootProject.ext {
|
||||
javaBin = ext.execInBash("which java", rootDir)
|
||||
}
|
||||
println("Running the formatting tool with $javaBin")
|
||||
def scriptDir = rootDir.path.endsWith('buildSrc')
|
||||
? "${rootDir}/../java-format"
|
||||
: "${rootDir}/java-format"
|
||||
def workingDir = rootDir.path.endsWith('buildSrc')
|
||||
? "${rootDir}/.."
|
||||
: rootDir
|
||||
def scriptDir = "${rootDir}/java-format"
|
||||
def workingDir = rootDir
|
||||
def formatDiffScript = "${scriptDir}/google-java-format-git-diff.sh"
|
||||
def pythonExe = getPythonExecutable()
|
||||
|
||||
@@ -572,7 +519,9 @@ task javadoc(type: Javadoc) {
|
||||
destinationDir = file("${buildDir}/docs/javadoc")
|
||||
options.encoding = "UTF-8"
|
||||
// In a lot of places we don't write @return so suppress warnings about that.
|
||||
options.addBooleanOption('Xdoclint:all,-missing', true)
|
||||
// We don't report HTML lint errors because XJB-generated POJO files have
|
||||
// incorrect tags (like dangling </p> without the corresponding open tag.
|
||||
options.addBooleanOption('Xdoclint:all,-missing,-html', true)
|
||||
options.addBooleanOption("-allow-script-in-comments",true)
|
||||
options.tags = ["type:a:Generic Type",
|
||||
"error:a:Expected Error",
|
||||
@@ -590,7 +539,8 @@ task coreDev {
|
||||
dependsOn 'javadoc'
|
||||
dependsOn 'checkDependenciesDotGradle'
|
||||
dependsOn 'checkLicense'
|
||||
dependsOn ':console-webapp:runConsoleWebappUnitTests'
|
||||
// TODO: @ptkach reenable after console design merged
|
||||
// dependsOn ':console-webapp:runConsoleWebappUnitTests'
|
||||
dependsOn ':core:check'
|
||||
dependsOn 'assemble'
|
||||
}
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
// 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 java.io.PrintStream;
|
||||
|
||||
val enableDependencyLocking: String by project
|
||||
val allowInsecureProtocol: String by project
|
||||
val allowInsecure = allowInsecureProtocol
|
||||
|
||||
buildscript {
|
||||
// We need to do this again within "buildscript" because setting it in the
|
||||
// main script doesn't affect build dependencies.
|
||||
val enableDependencyLocking: String by project
|
||||
if (enableDependencyLocking.toBoolean()) {
|
||||
// Lock application dependencies.
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
// Java static analysis plugins. Keep versions consistent with ../build.gradle
|
||||
|
||||
// We don't anticipate enabling the Gradle lint plugin because they will not support Kotlin
|
||||
// See https://github.com/nebula-plugins/gradle-lint-plugin/issues/166
|
||||
// id 'nebula.lint' version '16.0.2'
|
||||
id("net.ltgt.errorprone") version "3.1.0"
|
||||
checkstyle
|
||||
id("com.diffplug.spotless") version "6.20.0"
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
configDirectory.set(file("../config/checkstyle"))
|
||||
}
|
||||
|
||||
println("enableDependencyLocking is $enableDependencyLocking")
|
||||
if (enableDependencyLocking.toBoolean()) {
|
||||
// Lock application dependencies.
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
val mavenUrl = (project.ext.properties.get("mavenUrl") ?: "") as String
|
||||
if (mavenUrl.isEmpty()) {
|
||||
println("Java dependencies: Using Maven central...")
|
||||
mavenCentral()
|
||||
google()
|
||||
} else {
|
||||
maven {
|
||||
println("Java dependencies: Using repo ${mavenUrl}...")
|
||||
url = uri(mavenUrl)
|
||||
isAllowInsecureProtocol = allowInsecureProtocol == "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply(from = "../dependencies.gradle")
|
||||
apply(from = "../dependency_lic.gradle")
|
||||
apply(from = "../java_common.gradle")
|
||||
|
||||
// 'listenablefuture' is folded into guava since v32. This block is required
|
||||
// until all transitive dependencies have upgraded past guava v32.
|
||||
// TODO(periodically): remove this block and see if build succeeds.
|
||||
configurations.all {
|
||||
resolutionStrategy
|
||||
.capabilitiesResolution
|
||||
.withCapability("com.google.guava:listenablefuture") {
|
||||
select("com.google.guava:guava:0")
|
||||
}
|
||||
}
|
||||
|
||||
project.the<SourceSetContainer>()["main"].java {
|
||||
srcDir("${project.buildDir}/generated/source/apt/main")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
val deps = project.ext["dependencyMap"] as Map<*, *>
|
||||
val implementation by configurations
|
||||
val testImplementation by configurations
|
||||
val annotationProcessor by configurations
|
||||
implementation(deps["com.google.auth:google-auth-library-credentials"]!!)
|
||||
implementation(deps["com.google.auth:google-auth-library-oauth2-http"]!!)
|
||||
implementation(deps["com.google.auto.value:auto-value-annotations"]!!)
|
||||
// implementation(deps["com.google.common.html.types:types"]!!)
|
||||
implementation(deps["com.google.cloud:google-cloud-core"]!!)
|
||||
implementation(deps["com.google.cloud:google-cloud-storage"]!!)
|
||||
implementation(deps["com.google.guava:guava"]!!)
|
||||
implementation(deps["com.google.protobuf:protobuf-java"]!!)
|
||||
implementation(deps["com.google.template:soy"]!!)
|
||||
implementation(deps["org.apache.commons:commons-text"]!!)
|
||||
annotationProcessor(deps["com.google.auto.value:auto-value"]!!)
|
||||
testImplementation(deps["com.google.truth:truth"]!!)
|
||||
testImplementation(deps["org.junit.jupiter:junit-jupiter-api"]!!)
|
||||
testImplementation(deps["org.junit.jupiter:junit-jupiter-engine"]!!)
|
||||
testImplementation(deps["org.mockito:mockito-core"]!!)
|
||||
}
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
tasks.withType<JavaCompile> {
|
||||
options.compilerArgs.add("-Xlint:unchecked")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("exportDependencies") {
|
||||
doLast {
|
||||
project.configurations.forEach {
|
||||
println("dependency is $it")
|
||||
// it.dependencies.findAll {
|
||||
// it.group != null
|
||||
// }.each {
|
||||
// output.println("${it.group}:${it.name}")
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.diffplug.durian:durian-collect:1.2.0=classpath
|
||||
com.diffplug.durian:durian-core:1.2.0=classpath
|
||||
com.diffplug.durian:durian-io:1.2.0=classpath
|
||||
com.diffplug.durian:durian-swt.os:4.2.0=classpath
|
||||
com.diffplug.spotless:com.diffplug.spotless.gradle.plugin:6.20.0=classpath
|
||||
com.diffplug.spotless:spotless-lib-extra:2.40.0=classpath
|
||||
com.diffplug.spotless:spotless-lib:2.40.0=classpath
|
||||
com.diffplug.spotless:spotless-plugin-gradle:6.20.0=classpath
|
||||
com.googlecode.concurrent-trees:concurrent-trees:2.6.1=classpath
|
||||
com.googlecode.javaewah:JavaEWAH:1.2.3=classpath
|
||||
com.squareup.okhttp3:okhttp:4.10.0=classpath
|
||||
com.squareup.okio:okio-jvm:3.0.0=classpath
|
||||
com.squareup.okio:okio:3.0.0=classpath
|
||||
dev.equo.ide:solstice:1.3.1=classpath
|
||||
net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:3.1.0=classpath
|
||||
net.ltgt.gradle:gradle-errorprone-plugin:3.1.0=classpath
|
||||
org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r=classpath
|
||||
org.eclipse.platform:org.eclipse.osgi:3.18.300=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.20=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.9.20=classpath
|
||||
org.jetbrains:annotations:13.0=classpath
|
||||
org.slf4j:slf4j-api:1.7.36=classpath
|
||||
org.tukaani:xz:1.9=classpath
|
||||
empty=
|
||||
@@ -1,108 +0,0 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
aopalliance:aopalliance:1.0=annotationProcessor,buildScriptClasspath,compileClasspath
|
||||
args4j:args4j:2.0.23=buildScriptClasspath,compileClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.16.1=buildScriptClasspath,compileClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.16.1=buildScriptClasspath,compileClasspath
|
||||
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor
|
||||
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor
|
||||
com.google.android:annotations:4.1.1.4=buildScriptClasspath
|
||||
com.google.api-client:google-api-client:2.3.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.35.0-alpha=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.35.0-alpha=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.35.0-alpha=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.36.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.31.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api:api-common:2.28.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api:gax-grpc:2.45.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api:gax-httpjson:2.45.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api:gax:2.45.0=buildScriptClasspath,compileClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240209-2.0.0=buildScriptClasspath,compileClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.23.0=buildScriptClasspath,compileClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.23.0=buildScriptClasspath,compileClasspath
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor
|
||||
com.google.auto.value:auto-value-annotations:1.10.4=buildScriptClasspath,compileClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor
|
||||
com.google.auto.value:auto-value:1.10.4=annotationProcessor
|
||||
com.google.auto:auto-common:1.2.1=annotationProcessor
|
||||
com.google.cloud:google-cloud-core-grpc:2.35.0=buildScriptClasspath,compileClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.35.0=buildScriptClasspath,compileClasspath
|
||||
com.google.cloud:google-cloud-core:2.35.0=buildScriptClasspath,compileClasspath
|
||||
com.google.cloud:google-cloud-storage:2.35.0=buildScriptClasspath,compileClasspath
|
||||
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,buildScriptClasspath,compileClasspath
|
||||
com.google.code.gson:gson:2.10.1=buildScriptClasspath,compileClasspath
|
||||
com.google.common.html.types:types:1.0.6=buildScriptClasspath,compileClasspath
|
||||
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.24.1=buildScriptClasspath,compileClasspath
|
||||
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor
|
||||
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor
|
||||
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor
|
||||
com.google.escapevelocity:escapevelocity:0.9.1=buildScriptClasspath,compileClasspath
|
||||
com.google.guava:failureaccess:1.0.1=annotationProcessor
|
||||
com.google.guava:failureaccess:1.0.2=buildScriptClasspath,compileClasspath
|
||||
com.google.guava:guava-parent:32.1.1-jre=annotationProcessor
|
||||
com.google.guava:guava:32.1.1-jre=annotationProcessor
|
||||
com.google.guava:guava:33.0.0-jre=buildScriptClasspath,compileClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=buildScriptClasspath,compileClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.44.1=buildScriptClasspath,compileClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.44.1=buildScriptClasspath,compileClasspath
|
||||
com.google.http-client:google-http-client-gson:1.44.1=buildScriptClasspath,compileClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.44.1=buildScriptClasspath,compileClasspath
|
||||
com.google.http-client:google-http-client:1.44.1=buildScriptClasspath,compileClasspath
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0=buildScriptClasspath,compileClasspath
|
||||
com.google.inject:guice:4.1.0=buildScriptClasspath,compileClasspath
|
||||
com.google.inject:guice:5.1.0=annotationProcessor
|
||||
com.google.j2objc:j2objc-annotations:2.8=buildScriptClasspath,compileClasspath
|
||||
com.google.jsinterop:jsinterop-annotations:1.0.1=buildScriptClasspath,compileClasspath
|
||||
com.google.oauth-client:google-oauth-client:1.35.0=buildScriptClasspath,compileClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.25.2=buildScriptClasspath,compileClasspath
|
||||
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor
|
||||
com.google.protobuf:protobuf-java:3.25.2=buildScriptClasspath,compileClasspath
|
||||
com.google.re2j:re2j:1.7=buildScriptClasspath
|
||||
com.google.template:soy:2021-02-01=buildScriptClasspath,compileClasspath
|
||||
com.ibm.icu:icu4j:57.1=buildScriptClasspath,compileClasspath
|
||||
commons-codec:commons-codec:1.16.1=buildScriptClasspath,compileClasspath
|
||||
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor
|
||||
io.grpc:grpc-alts:1.62.2=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-api:1.62.2=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-auth:1.62.2=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-context:1.62.2=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-core:1.62.2=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-googleapis:1.62.2=buildScriptClasspath
|
||||
io.grpc:grpc-grpclb:1.62.2=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-inprocess:1.62.2=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-netty-shaded:1.62.2=buildScriptClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.62.2=buildScriptClasspath
|
||||
io.grpc:grpc-protobuf:1.62.2=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-rls:1.62.2=buildScriptClasspath
|
||||
io.grpc:grpc-services:1.62.2=buildScriptClasspath
|
||||
io.grpc:grpc-stub:1.62.2=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-util:1.62.2=buildScriptClasspath
|
||||
io.grpc:grpc-xds:1.62.2=buildScriptClasspath
|
||||
io.opencensus:opencensus-api:0.31.1=buildScriptClasspath,compileClasspath
|
||||
io.opencensus:opencensus-contrib-http-util:0.31.1=buildScriptClasspath,compileClasspath
|
||||
io.opencensus:opencensus-proto:0.2.0=buildScriptClasspath
|
||||
io.perfmark:perfmark-api:0.27.0=buildScriptClasspath
|
||||
javax.annotation:javax.annotation-api:1.3.2=buildScriptClasspath,compileClasspath
|
||||
javax.annotation:jsr250-api:1.0=buildScriptClasspath,compileClasspath
|
||||
javax.inject:javax.inject:1=annotationProcessor,buildScriptClasspath,compileClasspath
|
||||
org.apache.commons:commons-lang3:3.13.0=buildScriptClasspath,compileClasspath
|
||||
org.apache.commons:commons-text:1.11.0=buildScriptClasspath,compileClasspath
|
||||
org.apache.httpcomponents:httpclient:4.5.14=buildScriptClasspath,compileClasspath
|
||||
org.apache.httpcomponents:httpcore:4.4.16=buildScriptClasspath,compileClasspath
|
||||
org.checkerframework:checker-qual:3.33.0=annotationProcessor
|
||||
org.checkerframework:checker-qual:3.42.0=buildScriptClasspath,compileClasspath
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.23=buildScriptClasspath
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.2=buildScriptClasspath,compileClasspath
|
||||
org.json:json:20160212=buildScriptClasspath,compileClasspath
|
||||
org.ow2.asm:asm-analysis:7.0=buildScriptClasspath,compileClasspath
|
||||
org.ow2.asm:asm-commons:7.0=buildScriptClasspath,compileClasspath
|
||||
org.ow2.asm:asm-tree:7.0=buildScriptClasspath,compileClasspath
|
||||
org.ow2.asm:asm-util:7.0=buildScriptClasspath,compileClasspath
|
||||
org.ow2.asm:asm:7.0=buildScriptClasspath,compileClasspath
|
||||
org.pcollections:pcollections:3.1.4=annotationProcessor
|
||||
org.threeten:threetenbp:1.6.8=buildScriptClasspath,compileClasspath
|
||||
empty=
|
||||
@@ -1,3 +0,0 @@
|
||||
pluginsUrl=https://plugins.gradle.org/m2/
|
||||
allowInsecureProtocol=
|
||||
enableDependencyLocking=true
|
||||
@@ -1,29 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Alias this since it collides with the closure variable name
|
||||
def allowInsecure = allowInsecureProtocol
|
||||
|
||||
if (!pluginsUrl.isEmpty()) {
|
||||
pluginManagement {
|
||||
repositories {
|
||||
maven {
|
||||
url pluginsUrl
|
||||
allowInsecureProtocol = allowInsecure == "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println "Plugins: Using default repo..."
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.gradle.plugin;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMultimap;
|
||||
import static com.google.common.io.Resources.getResource;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.toByteArraySupplier;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.html.types.TrustedResourceUrls;
|
||||
import com.google.template.soy.SoyFileSet;
|
||||
import com.google.template.soy.tofu.SoyTofu;
|
||||
import google.registry.gradle.plugin.ProjectData.TaskData;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Creates the files for a web-page summary of a given {@link ProjectData}.
|
||||
*
|
||||
* <p>The main job of this class is rendering a tailored cover page that includes information about
|
||||
* the project and any task that ran.
|
||||
*
|
||||
* <p>It returns all the files that need uploading for the cover page to work. This includes any
|
||||
* report and log files linked to in the ProjectData, as well as a cover page (and associated
|
||||
* resources such as CSS files).
|
||||
*/
|
||||
final class CoverPageGenerator {
|
||||
|
||||
/** List of all resource files that will be uploaded as-is. */
|
||||
private static final ImmutableSet<Path> STATIC_RESOURCE_FILES =
|
||||
ImmutableSet.of(Paths.get("css", "style.css"));
|
||||
/** Name of the entry-point file that will be created. */
|
||||
private static final Path ENTRY_POINT = Paths.get("index.html");
|
||||
|
||||
private final ProjectData projectData;
|
||||
private final ImmutableSetMultimap<TaskData.State, TaskData> tasksByState;
|
||||
/**
|
||||
* The compiled SOY files.
|
||||
*
|
||||
* <p>Will be generated only when actually needed, because it takes a while to compile and we
|
||||
* don't want that to happen unless we actually use it.
|
||||
*/
|
||||
private SoyTofu tofu = null;
|
||||
|
||||
CoverPageGenerator(ProjectData projectData) {
|
||||
this.projectData = projectData;
|
||||
this.tasksByState =
|
||||
projectData.tasks().stream().collect(toImmutableSetMultimap(TaskData::state, task -> task));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the files that need uploading for the cover page to work.
|
||||
*
|
||||
* <p>This includes all the report files as well, to make sure that the link works.
|
||||
*/
|
||||
FilesWithEntryPoint getFilesToUpload() {
|
||||
ImmutableMap.Builder<Path, Supplier<byte[]>> builder = new ImmutableMap.Builder<>();
|
||||
// Add all the static resource pages
|
||||
STATIC_RESOURCE_FILES.stream().forEach(file -> builder.put(file, resourceLoader(file)));
|
||||
// Create the cover page
|
||||
// Note that the ByteArraySupplier here is lazy - the createCoverPage function is only called
|
||||
// when the resulting Supplier's get function is called.
|
||||
builder.put(ENTRY_POINT, toByteArraySupplier(this::createCoverPage));
|
||||
// Add all the files from the tasks
|
||||
tasksByState.values().stream()
|
||||
.flatMap(task -> task.reports().values().stream())
|
||||
.forEach(reportFiles -> builder.putAll(reportFiles.files()));
|
||||
// Add the logs of every test
|
||||
tasksByState.values().stream()
|
||||
.filter(task -> task.log().isPresent())
|
||||
.forEach(task -> builder.put(getLogPath(task), task.log().get()));
|
||||
|
||||
return FilesWithEntryPoint.create(builder.build(), ENTRY_POINT);
|
||||
}
|
||||
|
||||
/** Renders the cover page. */
|
||||
private String createCoverPage() {
|
||||
return getTofu()
|
||||
.newRenderer("google.registry.gradle.plugin.coverPage")
|
||||
.setData(getSoyData())
|
||||
.render();
|
||||
}
|
||||
|
||||
/** Converts the projectData and all taskData into all the data the soy template needs. */
|
||||
private ImmutableMap<String, Object> getSoyData() {
|
||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
||||
|
||||
TaskData.State state =
|
||||
tasksByState.containsKey(TaskData.State.FAILURE)
|
||||
? TaskData.State.FAILURE
|
||||
: TaskData.State.SUCCESS;
|
||||
String title =
|
||||
state != TaskData.State.FAILURE
|
||||
? "Success!"
|
||||
: "Failed: "
|
||||
+ tasksByState.get(state).stream()
|
||||
.map(TaskData::uniqueName)
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
builder.put("projectState", state.toString());
|
||||
builder.put("title", title);
|
||||
builder.put("cssFiles", ImmutableSet.of(TrustedResourceUrls.fromConstant("css/style.css")));
|
||||
builder.put("invocation", getInvocation());
|
||||
builder.put("tasksByState", getTasksByStateSoyData());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a soy-friendly map from the TaskData.State to the task itslef.
|
||||
*
|
||||
* <p>The key order in the resulting map is always the same (the order from the enum definition)
|
||||
* no matter the key order in the original tasksByState map.
|
||||
*/
|
||||
private ImmutableMap<String, Object> getTasksByStateSoyData() {
|
||||
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
||||
|
||||
// We go over the States in the order they are defined rather than the order in which they
|
||||
// happen to be in the tasksByState Map.
|
||||
//
|
||||
// That way we guarantee a consistent order.
|
||||
for (TaskData.State state : TaskData.State.values()) {
|
||||
builder.put(
|
||||
state.toString(),
|
||||
tasksByState.get(state).stream()
|
||||
.map(task -> taskDataToSoy(task))
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/** returns a soy-friendly version of the given task data. */
|
||||
static ImmutableMap<String, Object> taskDataToSoy(TaskData task) {
|
||||
// Note that all instances of File.separator are replaced with forward slashes so that we can
|
||||
// generate a valid href on Windows.
|
||||
return new ImmutableMap.Builder<String, Object>()
|
||||
.put("uniqueName", task.uniqueName())
|
||||
.put("description", task.description())
|
||||
.put(
|
||||
"log",
|
||||
task.log().isPresent() ? getLogPath(task).toString().replace(File.separator, "/") : "")
|
||||
.put(
|
||||
"reports",
|
||||
task.reports().entrySet().stream()
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
Map.Entry::getKey,
|
||||
entry ->
|
||||
entry.getValue().files().isEmpty()
|
||||
? ""
|
||||
: entry
|
||||
.getValue()
|
||||
.entryPoint()
|
||||
.toString()
|
||||
.replace(File.separator, "/"))))
|
||||
.build();
|
||||
}
|
||||
|
||||
private String getInvocation() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("./gradlew");
|
||||
projectData.tasksRequested().forEach(task -> builder.append(" ").append(task));
|
||||
projectData
|
||||
.projectProperties()
|
||||
.forEach((key, value) -> builder.append(String.format(" -P %s=%s", key, value)));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/** Returns a lazily created soy renderer */
|
||||
private SoyTofu getTofu() {
|
||||
if (tofu == null) {
|
||||
tofu =
|
||||
SoyFileSet.builder()
|
||||
.add(getResource(CoverPageGenerator.class, "soy/coverpage.soy"))
|
||||
.build()
|
||||
.compileToTofu();
|
||||
}
|
||||
return tofu;
|
||||
}
|
||||
|
||||
private static Path getLogPath(TaskData task) {
|
||||
// We replace colons with dashes so that the resulting filename is always valid, even in
|
||||
// Windows. As a dash is not a valid character in Java identifies, a task name cannot include
|
||||
// it, so the uniqueness of the name is perserved.
|
||||
return Paths.get("logs", task.uniqueName().replace(":", "-") + ".log");
|
||||
}
|
||||
|
||||
private static Supplier<byte[]> resourceLoader(Path path) {
|
||||
return toByteArraySupplier(getResource(CoverPageGenerator.class, path.toString()));
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.gradle.plugin;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Holds a set of files with a browser-friendly entry point to those files.
|
||||
*
|
||||
* <p>The file data is lazily generated.
|
||||
*
|
||||
* <p>If there is at least one file, it's guaranteed that the entry point is one of these files.
|
||||
*/
|
||||
@AutoValue
|
||||
abstract class FilesWithEntryPoint {
|
||||
|
||||
/**
|
||||
* All files that are part of this report, keyed from their path to a supplier of their content.
|
||||
*
|
||||
* <p>The reason we use a supplier instead of loading the content is in case the content is very
|
||||
* large...
|
||||
*
|
||||
* <p>Also, no point in doing IO before we need it!
|
||||
*/
|
||||
abstract ImmutableMap<Path, Supplier<byte[]>> files();
|
||||
|
||||
/**
|
||||
* The file that gives access (links...) to all the data in the report.
|
||||
*
|
||||
* <p>Guaranteed to be a key in {@link #files} if and only if files isn't empty.
|
||||
*/
|
||||
abstract Path entryPoint();
|
||||
|
||||
static FilesWithEntryPoint create(ImmutableMap<Path, Supplier<byte[]>> files, Path entryPoint) {
|
||||
checkArgument(files.isEmpty() || files.containsKey(entryPoint));
|
||||
return new AutoValue_FilesWithEntryPoint(files, entryPoint);
|
||||
}
|
||||
|
||||
static FilesWithEntryPoint createSingleFile(Path path, Supplier<byte[]> data) {
|
||||
return create(ImmutableMap.of(path, data), path);
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.gradle.plugin;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.cloud.storage.BlobInfo;
|
||||
import com.google.cloud.storage.Storage;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.io.Resources;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/** Utility functions used in the GCS plugin. */
|
||||
final class GcsPluginUtils {
|
||||
|
||||
private static final ImmutableMap<String, String> EXTENSION_TO_CONTENT_TYPE =
|
||||
new ImmutableMap.Builder<String, String>()
|
||||
.put("html", "text/html")
|
||||
.put("htm", "text/html")
|
||||
.put("log", "text/plain")
|
||||
.put("txt", "text/plain")
|
||||
.put("css", "text/css")
|
||||
.put("xml", "text/xml")
|
||||
.put("zip", "application/zip")
|
||||
.put("js", "text/javascript")
|
||||
.build();
|
||||
|
||||
private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
|
||||
|
||||
static Path toNormalizedPath(File file) {
|
||||
return file.toPath().toAbsolutePath().normalize();
|
||||
}
|
||||
|
||||
static Path toNormalizedPath(Path file) {
|
||||
return file.toAbsolutePath().normalize();
|
||||
}
|
||||
|
||||
static String getContentType(String fileName) {
|
||||
return EXTENSION_TO_CONTENT_TYPE.getOrDefault(
|
||||
Files.getFileExtension(fileName), DEFAULT_CONTENT_TYPE);
|
||||
}
|
||||
|
||||
static void uploadFileToGcs(
|
||||
Storage storage, String bucket, Path path, Supplier<byte[]> dataSupplier) {
|
||||
// Replace Windows file separators with forward slashes.
|
||||
String filename = path.toString().replace(File.separator, "/");
|
||||
storage.create(
|
||||
BlobInfo.newBuilder(bucket, filename).setContentType(getContentType(filename)).build(),
|
||||
dataSupplier.get());
|
||||
}
|
||||
|
||||
static void uploadFilesToGcsMultithread(
|
||||
Storage storage, String bucket, Path folder, Map<Path, Supplier<byte[]>> files) {
|
||||
ImmutableMap.Builder<Path, Thread> threads = new ImmutableMap.Builder<>();
|
||||
files.forEach(
|
||||
(path, dataSupplier) -> {
|
||||
Thread thread =
|
||||
new Thread(
|
||||
() -> uploadFileToGcs(storage, bucket, folder.resolve(path), dataSupplier));
|
||||
thread.start();
|
||||
threads.put(path, thread);
|
||||
});
|
||||
threads
|
||||
.build()
|
||||
.forEach(
|
||||
(path, thread) -> {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.format("Upload of %s interrupted", path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static Supplier<byte[]> toByteArraySupplier(String data) {
|
||||
return () -> data.getBytes(UTF_8);
|
||||
}
|
||||
|
||||
static Supplier<byte[]> toByteArraySupplier(Supplier<String> dataSupplier) {
|
||||
return () -> dataSupplier.get().getBytes(UTF_8);
|
||||
}
|
||||
|
||||
static Supplier<byte[]> toByteArraySupplier(File file) {
|
||||
return () -> {
|
||||
try {
|
||||
return Files.toByteArray(file);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Supplier<byte[]> toByteArraySupplier(URL url) {
|
||||
return () -> {
|
||||
try {
|
||||
return Resources.toByteArray(url);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all the files generated by a Report into a FilesWithEntryPoint object.
|
||||
*
|
||||
* <p>Every FilesWithEntryPoint must have a single link "entry point" that gives users access to
|
||||
* all the files. If the report generated just one file - we will just link to that file.
|
||||
*
|
||||
* <p>However, if the report generated more than one file - the only thing we can safely do is to
|
||||
* zip all the files and link to the zip file.
|
||||
*
|
||||
* <p>As an alternative to using a zip file, we allow the caller to supply an optional "entry
|
||||
* point" file that will link to all the other files. If that file is given and is "appropriate"
|
||||
* (exists and is in the correct location) - we will upload all the report files "as is" and link
|
||||
* to the entry file.
|
||||
*
|
||||
* @param destination the location of the output. Either a file or a directory. If a directory -
|
||||
* then all the files inside that directory are the outputs we're looking for.
|
||||
* @param entryPointHint If present - a hint to what the entry point to this directory tree is.
|
||||
* Will only be used if all of the following apply: (a) {@code
|
||||
* destination.isDirectory()==true}, (b) there are 2 or more files in the {@code destination}
|
||||
* directory, and (c) {@code entryPointHint.get()} is one of the files nested inside of the
|
||||
* {@code destination} directory.
|
||||
*/
|
||||
static FilesWithEntryPoint readFilesWithEntryPoint(
|
||||
File destination, Optional<File> entryPointHint, Path rootDir) {
|
||||
|
||||
Path destinationPath = rootDir.relativize(toNormalizedPath(destination));
|
||||
|
||||
if (destination.isFile()) {
|
||||
// The destination is a single file - find its root, and add this single file to the
|
||||
// FilesWithEntryPoint.
|
||||
return FilesWithEntryPoint.createSingleFile(
|
||||
destinationPath, toByteArraySupplier(destination));
|
||||
}
|
||||
|
||||
if (!destination.isDirectory()) {
|
||||
// This isn't a file nor a directory - so it doesn't exist! Return empty FilesWithEntryPoint
|
||||
return FilesWithEntryPoint.create(ImmutableMap.of(), destinationPath);
|
||||
}
|
||||
|
||||
// The destination is a directory - find all the actual files first
|
||||
ImmutableMap<Path, Supplier<byte[]>> files =
|
||||
Streams.stream(Files.fileTraverser().depthFirstPreOrder(destination))
|
||||
.filter(File::isFile)
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
file -> rootDir.relativize(toNormalizedPath(file)),
|
||||
GcsPluginUtils::toByteArraySupplier));
|
||||
|
||||
if (files.isEmpty()) {
|
||||
// The directory exists, but is empty. Return empty FilesWithEntryPoint
|
||||
return FilesWithEntryPoint.create(ImmutableMap.of(), destinationPath);
|
||||
}
|
||||
|
||||
if (files.size() == 1) {
|
||||
// We got a directory, but it only has a single file. We can link to that.
|
||||
return FilesWithEntryPoint.create(files, getOnlyElement(files.keySet()));
|
||||
}
|
||||
|
||||
// There are multiple files in the report! We need to check the entryPointHint
|
||||
Optional<Path> entryPointPath =
|
||||
entryPointHint.map(file -> rootDir.relativize(toNormalizedPath(file)));
|
||||
|
||||
if (entryPointPath.isPresent() && files.containsKey(entryPointPath.get())) {
|
||||
// We were given the entry point! Use it!
|
||||
return FilesWithEntryPoint.create(files, entryPointPath.get());
|
||||
}
|
||||
|
||||
// We weren't given an appropriate entry point. But we still need a single link to all this data
|
||||
// - so we'll zip it and just host a single file.
|
||||
Path zipFilePath = destinationPath.resolve(destinationPath.getFileName().toString() + ".zip");
|
||||
return FilesWithEntryPoint.createSingleFile(zipFilePath, createZippedByteArraySupplier(files));
|
||||
}
|
||||
|
||||
static Supplier<byte[]> createZippedByteArraySupplier(Map<Path, Supplier<byte[]>> files) {
|
||||
return () -> zipFiles(files);
|
||||
}
|
||||
|
||||
private static byte[] zipFiles(Map<Path, Supplier<byte[]>> files) {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zip = new ZipOutputStream(output)) {
|
||||
for (Path path : files.keySet()) {
|
||||
zip.putNextEntry(new ZipEntry(path.toString()));
|
||||
zip.write(files.get(path).get());
|
||||
zip.closeEntry();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
return output.toByteArray();
|
||||
}
|
||||
|
||||
private GcsPluginUtils() {}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.gradle.plugin;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* All the data of a root Gradle project.
|
||||
*
|
||||
* <p>This is basically all the "relevant" data from a Gradle Project, arranged in an immutable and
|
||||
* more convenient way.
|
||||
*/
|
||||
@AutoValue
|
||||
abstract class ProjectData {
|
||||
|
||||
abstract String name();
|
||||
|
||||
abstract String description();
|
||||
|
||||
abstract String gradleVersion();
|
||||
|
||||
abstract ImmutableMap<String, String> projectProperties();
|
||||
|
||||
abstract ImmutableMap<String, String> systemProperties();
|
||||
|
||||
abstract ImmutableSet<String> tasksRequested();
|
||||
|
||||
abstract ImmutableSet<TaskData> tasks();
|
||||
|
||||
abstract Builder toBuilder();
|
||||
|
||||
static Builder builder() {
|
||||
return new AutoValue_ProjectData.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
abstract static class Builder {
|
||||
abstract Builder setName(String name);
|
||||
|
||||
abstract Builder setDescription(String description);
|
||||
|
||||
abstract Builder setGradleVersion(String gradleVersion);
|
||||
|
||||
abstract Builder setProjectProperties(Map<String, String> projectProperties);
|
||||
|
||||
abstract Builder setSystemProperties(Map<String, String> systemProperties);
|
||||
|
||||
abstract Builder setTasksRequested(Iterable<String> tasksRequested);
|
||||
|
||||
abstract ImmutableSet.Builder<TaskData> tasksBuilder();
|
||||
|
||||
Builder addTask(TaskData task) {
|
||||
tasksBuilder().add(task);
|
||||
return this;
|
||||
}
|
||||
|
||||
abstract ProjectData build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Relevant data to a single Task's.
|
||||
*
|
||||
* <p>Some Tasks are also "Reporting", meaning they create file outputs we want to upload in
|
||||
* various formats. The format that interests us the most is "html", as that's nicely browsable,
|
||||
* but they might also have other formats.
|
||||
*/
|
||||
@AutoValue
|
||||
abstract static class TaskData {
|
||||
|
||||
enum State {
|
||||
/** The task has failed for some reason. */
|
||||
FAILURE,
|
||||
/** The task was actually run and has finished successfully. */
|
||||
SUCCESS,
|
||||
/** The task was up-to-date and successful, and hence didn't need to run again. */
|
||||
UP_TO_DATE
|
||||
}
|
||||
|
||||
abstract String uniqueName();
|
||||
|
||||
abstract String description();
|
||||
|
||||
abstract State state();
|
||||
|
||||
abstract Optional<Supplier<byte[]>> log();
|
||||
|
||||
/**
|
||||
* Returns the FilesWithEntryPoint for every report, keyed on the report type.
|
||||
*
|
||||
* <p>The "html" report type is the most interesting, but there are other report formats.
|
||||
*/
|
||||
abstract ImmutableMap<String, FilesWithEntryPoint> reports();
|
||||
|
||||
abstract Builder toBuilder();
|
||||
|
||||
static Builder builder() {
|
||||
return new AutoValue_ProjectData_TaskData.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
abstract static class Builder {
|
||||
abstract Builder setUniqueName(String name);
|
||||
|
||||
abstract Builder setDescription(String description);
|
||||
|
||||
abstract Builder setState(State state);
|
||||
|
||||
abstract Builder setLog(Supplier<byte[]> log);
|
||||
|
||||
abstract ImmutableMap.Builder<String, FilesWithEntryPoint> reportsBuilder();
|
||||
|
||||
Builder putReport(String type, FilesWithEntryPoint reportFiles) {
|
||||
reportsBuilder().put(type, reportFiles);
|
||||
return this;
|
||||
}
|
||||
|
||||
abstract TaskData build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,311 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.gradle.plugin;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.readFilesWithEntryPoint;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.toByteArraySupplier;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.toNormalizedPath;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.uploadFileToGcs;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.uploadFilesToGcsMultithread;
|
||||
|
||||
import com.google.auth.oauth2.GoogleCredentials;
|
||||
import com.google.cloud.storage.Storage;
|
||||
import com.google.cloud.storage.StorageOptions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.Files;
|
||||
import google.registry.gradle.plugin.ProjectData.TaskData;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.reporting.DirectoryReport;
|
||||
import org.gradle.api.reporting.Report;
|
||||
import org.gradle.api.reporting.ReportContainer;
|
||||
import org.gradle.api.reporting.Reporting;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
/** A task that uploads the Reports generated by other tasks to GCS. */
|
||||
public class ReportUploader extends DefaultTask {
|
||||
|
||||
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
|
||||
private static final ImmutableMap<String, BiConsumer<ReportUploader, String>> UPLOAD_FUNCTIONS =
|
||||
ImmutableMap.of(
|
||||
"file://", ReportUploader::saveResultsToLocalFolder,
|
||||
"gcs://", ReportUploader::uploadResultsToGcs);
|
||||
|
||||
private final ArrayList<Task> tasks = new ArrayList<>();
|
||||
private final HashMap<String, StringBuilder> logs = new HashMap<>();
|
||||
private Project project;
|
||||
|
||||
private String destination = null;
|
||||
private String credentialsFile = null;
|
||||
private String multithreadedUpload = null;
|
||||
|
||||
/**
|
||||
* Sets the destination of the reports.
|
||||
*
|
||||
* <p>Currently supports two types of destinations:
|
||||
*
|
||||
* <ul>
|
||||
* <li>file://[absulute local path], e.g. file:///tmp/buildOutputs/
|
||||
* <li>gcs://[bucket name]/[optional path], e.g. gcs://my-bucket/buildOutputs/
|
||||
* </ul>
|
||||
*/
|
||||
public void setDestination(String destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public void setCredentialsFile(String credentialsFile) {
|
||||
this.credentialsFile = credentialsFile;
|
||||
}
|
||||
|
||||
public void setMultithreadedUpload(String multithreadedUpload) {
|
||||
this.multithreadedUpload = multithreadedUpload;
|
||||
}
|
||||
|
||||
/** Converts the given Gradle Project into a ProjectData. */
|
||||
private ProjectData createProjectData() {
|
||||
ProjectData.Builder builder =
|
||||
ProjectData.builder()
|
||||
.setName(project.getPath() + project.getName())
|
||||
.setDescription(
|
||||
Optional.ofNullable(project.getDescription()).orElse("[No description available]"))
|
||||
.setGradleVersion(project.getGradle().getGradleVersion())
|
||||
.setProjectProperties(project.getGradle().getStartParameter().getProjectProperties())
|
||||
.setSystemProperties(project.getGradle().getStartParameter().getSystemPropertiesArgs())
|
||||
.setTasksRequested(project.getGradle().getStartParameter().getTaskNames());
|
||||
|
||||
Path rootDir = toNormalizedPath(project.getRootDir());
|
||||
tasks.stream()
|
||||
.filter(task -> task.getState().getExecuted() || task.getState().getUpToDate())
|
||||
.map(task -> createTaskData(task, rootDir))
|
||||
.forEach(builder.tasksBuilder()::add);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Gradle Task into a TaskData.
|
||||
*
|
||||
* @param rootDir the root directory of the main Project - used to get the relative path of any
|
||||
* Task files.
|
||||
*/
|
||||
private TaskData createTaskData(Task task, Path rootDir) {
|
||||
TaskData.State state =
|
||||
task.getState().getFailure() != null
|
||||
? TaskData.State.FAILURE
|
||||
: task.getState().getUpToDate() ? TaskData.State.UP_TO_DATE : TaskData.State.SUCCESS;
|
||||
String log = logs.get(task.getPath()).toString();
|
||||
|
||||
TaskData.Builder builder =
|
||||
TaskData.builder()
|
||||
.setState(state)
|
||||
.setUniqueName(task.getPath())
|
||||
.setDescription(
|
||||
Optional.ofNullable(task.getDescription()).orElse("[No description available]"));
|
||||
if (!log.isEmpty()) {
|
||||
builder.setLog(toByteArraySupplier(log));
|
||||
}
|
||||
|
||||
Reporting<? extends ReportContainer<? extends Report>> reporting = asReporting(task);
|
||||
|
||||
if (reporting != null) {
|
||||
// This Task is also a Reporting task! It has a destination file/directory for every supported
|
||||
// format.
|
||||
// Add the files for each of the formats into the ReportData.
|
||||
reporting
|
||||
.getReports()
|
||||
.getAsMap()
|
||||
.forEach(
|
||||
(type, report) -> {
|
||||
File destination = report.getOutputLocation().get().getAsFile();
|
||||
// The destination could be a file, or a directory. If it's a directory - the Report
|
||||
// could have created multiple files - and we need to know to which one of those to
|
||||
// link.
|
||||
//
|
||||
// If we're lucky, whoever implemented the Report made sure to extend
|
||||
// DirectoryReport, which gives us the entry point to all the files.
|
||||
//
|
||||
// This isn't guaranteed though, as it depends on the implementer.
|
||||
Optional<File> entryPointHint =
|
||||
destination.isDirectory() && (report instanceof DirectoryReport)
|
||||
? Optional.ofNullable(((DirectoryReport) report).getEntryPoint())
|
||||
: Optional.empty();
|
||||
builder
|
||||
.reportsBuilder()
|
||||
.put(type, readFilesWithEntryPoint(destination, entryPointHint, rootDir));
|
||||
});
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private FilesWithEntryPoint generateFilesToUpload() {
|
||||
ProjectData projectData = createProjectData();
|
||||
CoverPageGenerator coverPageGenerator = new CoverPageGenerator(projectData);
|
||||
return coverPageGenerator.getFilesToUpload();
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
void uploadResults() {
|
||||
System.out.format("ReportUploader: destination= '%s'\n", destination);
|
||||
|
||||
try {
|
||||
|
||||
if (isNullOrEmpty(destination)) {
|
||||
System.out.format("ReportUploader: no destination given, skipping...\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (String key : UPLOAD_FUNCTIONS.keySet()) {
|
||||
if (destination.startsWith(key)) {
|
||||
UPLOAD_FUNCTIONS.get(key).accept(this, destination.substring(key.length()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
System.out.format(
|
||||
"ReportUploader: given destination '%s' doesn't start with one of %s."
|
||||
+ " Defaulting to saving in /tmp\n",
|
||||
destination, UPLOAD_FUNCTIONS.keySet());
|
||||
saveResultsToLocalFolder("/tmp/");
|
||||
} catch (Throwable e) {
|
||||
System.out.format("ReportUploader: Encountered error %s\n", e);
|
||||
e.printStackTrace(System.out);
|
||||
System.out.format("ReportUploader: skipping upload\n");
|
||||
}
|
||||
}
|
||||
|
||||
private void saveResultsToLocalFolder(String absoluteFolderName) {
|
||||
Path folder = Paths.get(absoluteFolderName, createUniqueFolderName());
|
||||
checkArgument(
|
||||
folder.isAbsolute(),
|
||||
"Local files destination must be an absolute path, but is %s",
|
||||
absoluteFolderName);
|
||||
FilesWithEntryPoint filesToUpload = generateFilesToUpload();
|
||||
System.out.format(
|
||||
"ReportUploader: going to save %s files to %s\n", filesToUpload.files().size(), folder);
|
||||
filesToUpload
|
||||
.files()
|
||||
.forEach((path, dataSupplier) -> saveFile(folder.resolve(path), dataSupplier));
|
||||
System.out.format(
|
||||
"ReportUploader: report saved to file://%s\n", folder.resolve(filesToUpload.entryPoint()));
|
||||
}
|
||||
|
||||
private void saveFile(Path path, Supplier<byte[]> dataSupplier) {
|
||||
File dir = path.getParent().toFile();
|
||||
if (!dir.isDirectory()) {
|
||||
checkState(dir.mkdirs(), "Couldn't create directory %s", dir);
|
||||
}
|
||||
try {
|
||||
Files.write(dataSupplier.get(), path.toFile());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadResultsToGcs(String destination) {
|
||||
checkArgument(
|
||||
!destination.isEmpty(), "destination must include at least the bucket name, but is empty");
|
||||
Path bucketWithFolder = Paths.get(destination, createUniqueFolderName());
|
||||
String bucket = bucketWithFolder.getName(0).toString();
|
||||
Path folder = bucketWithFolder.subpath(1, bucketWithFolder.getNameCount());
|
||||
|
||||
StorageOptions.Builder storageOptions = StorageOptions.newBuilder();
|
||||
if (!isNullOrEmpty(credentialsFile)) {
|
||||
try {
|
||||
storageOptions.setCredentials(
|
||||
GoogleCredentials.fromStream(new FileInputStream(credentialsFile)));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
Storage storage = storageOptions.build().getService();
|
||||
|
||||
FilesWithEntryPoint filesToUpload = generateFilesToUpload();
|
||||
|
||||
System.out.format(
|
||||
"ReportUploader: going to upload %s files to %s/%s\n",
|
||||
filesToUpload.files().size(), bucket, folder);
|
||||
if ("yes".equals(multithreadedUpload)) {
|
||||
System.out.format("ReportUploader: multi-threaded upload\n");
|
||||
uploadFilesToGcsMultithread(storage, bucket, folder, filesToUpload.files());
|
||||
} else {
|
||||
System.out.format("ReportUploader: single threaded upload\n");
|
||||
filesToUpload
|
||||
.files()
|
||||
.forEach(
|
||||
(path, dataSupplier) -> {
|
||||
System.out.format("ReportUploader: Uploading %s\n", path);
|
||||
uploadFileToGcs(storage, bucket, folder.resolve(path), dataSupplier);
|
||||
});
|
||||
}
|
||||
System.out.format(
|
||||
"ReportUploader: report uploaded to https://storage.googleapis.com/%s/%s\n",
|
||||
bucket, folder.resolve(filesToUpload.entryPoint()));
|
||||
}
|
||||
|
||||
void setProject(Project project) {
|
||||
this.project = project;
|
||||
|
||||
for (Project subProject : project.getAllprojects()) {
|
||||
subProject.getTasks().all(this::addTask);
|
||||
}
|
||||
}
|
||||
|
||||
private void addTask(Task task) {
|
||||
if (task instanceof ReportUploader) {
|
||||
return;
|
||||
}
|
||||
tasks.add(task);
|
||||
StringBuilder log = new StringBuilder();
|
||||
checkArgument(
|
||||
!logs.containsKey(task.getPath()),
|
||||
"Multiple tasks with the same .getPath()=%s",
|
||||
task.getPath());
|
||||
logs.put(task.getPath(), log);
|
||||
task.getLogging().addStandardOutputListener(output -> log.append(output));
|
||||
task.getLogging().addStandardErrorListener(output -> log.append(output));
|
||||
task.finalizedBy(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Reporting<? extends ReportContainer<? extends Report>> asReporting(Task task) {
|
||||
if (task instanceof Reporting) {
|
||||
return (Reporting<? extends ReportContainer<? extends Report>>) task;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String createUniqueFolderName() {
|
||||
return String.format(
|
||||
"%h-%h-%h-%h",
|
||||
SECURE_RANDOM.nextInt(),
|
||||
SECURE_RANDOM.nextInt(),
|
||||
SECURE_RANDOM.nextInt(),
|
||||
SECURE_RANDOM.nextInt());
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.gradle.plugin;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
/**
|
||||
* Plugin setting up the ReportUploader task.
|
||||
*
|
||||
* <p>It goes over all the tasks in a project and pass them on to the ReportUploader task for set
|
||||
* up.
|
||||
*
|
||||
* <p>Note that since we're passing in all the projects' tasks - this includes the ReportUploader
|
||||
* itself! It's up to the ReportUploader to take care of not having "infinite loops" caused by
|
||||
* waiting for itself to end before finishing.
|
||||
*/
|
||||
public class ReportUploaderPlugin implements Plugin<Project> {
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
ReportUploader reportUploader =
|
||||
project
|
||||
.getTasks()
|
||||
.create(
|
||||
"reportUploader",
|
||||
ReportUploader.class,
|
||||
task -> {
|
||||
task.setDescription("Uploads the reports to GCS bucket");
|
||||
task.setGroup("uploads");
|
||||
});
|
||||
|
||||
reportUploader.setProject(project);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
.task_state_SUCCESS {
|
||||
color: green;
|
||||
}
|
||||
.task_state_FAILURE {
|
||||
color: red;
|
||||
}
|
||||
.task_name {
|
||||
display: block;
|
||||
font-size: larger;
|
||||
font-weight: bold;
|
||||
}
|
||||
.task_description {
|
||||
display: block;
|
||||
margin-left: 1em;
|
||||
color: gray;
|
||||
}
|
||||
.report_links {
|
||||
margin-left: 1em;
|
||||
}
|
||||
.report_link_broken {
|
||||
text-decoration: line-through;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
// 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.
|
||||
|
||||
{namespace google.registry.gradle.plugin}
|
||||
|
||||
{template .coverPage}
|
||||
{@param title: string}
|
||||
{@param cssFiles: list<trusted_resource_uri>}
|
||||
{@param projectState: string}
|
||||
{@param invocation: string}
|
||||
{@param tasksByState: map<string, list<[uniqueName: string, description: string, log: string, reports: map<string, string>]>>}
|
||||
|
||||
<title>{$title}</title>
|
||||
{for $cssFile in $cssFiles}
|
||||
<link rel="stylesheet" type="text/css" href="{$cssFile}">
|
||||
{/for}
|
||||
<body>
|
||||
<div class="project">
|
||||
<h1 class="project_title {'task_state_' + $projectState}">{$title}</h1>
|
||||
<span class="project_subtitle">
|
||||
Build results for <span class="project_invocation">{$invocation}</span>
|
||||
</span>
|
||||
|
||||
{for $taskState in mapKeys($tasksByState)}
|
||||
{if length($tasksByState[$taskState]) > 0}
|
||||
{call .tasksOfState}
|
||||
{param state: $taskState /}
|
||||
{param tasks: $tasksByState[$taskState] /}
|
||||
{/call}
|
||||
{/if}
|
||||
{/for}
|
||||
|
||||
</div>
|
||||
</body>
|
||||
{/template}
|
||||
|
||||
{template .tasksOfState}
|
||||
{@param state: string}
|
||||
{@param tasks: list<[uniqueName: string, description: string, log: string, reports: map<string, string>]>}
|
||||
|
||||
<div class="{'task_state_' + $state}">
|
||||
<p>{$state}</p>
|
||||
// Place the tasks with actual reports first, since those are more likely to be useful
|
||||
{for $task in $tasks}
|
||||
{if length(mapKeys($task.reports)) > 0}
|
||||
{call .task}
|
||||
{param task: $task /}
|
||||
{/call}
|
||||
{/if}
|
||||
{/for}
|
||||
// Followup with reports without links
|
||||
{for $task in $tasks}
|
||||
{if length(mapKeys($task.reports)) == 0}
|
||||
{call .task}
|
||||
{param task: $task /}
|
||||
{/call}
|
||||
{/if}
|
||||
{/for}
|
||||
</div>
|
||||
{/template}
|
||||
|
||||
{template .task}
|
||||
{@param task: [uniqueName: string, description: string, log: string, reports: map<string, string>]}
|
||||
{call .taskInternal}
|
||||
{param uniqueName: $task.uniqueName /}
|
||||
{param description: $task.description /}
|
||||
{param log: $task.log /}
|
||||
{param reports: $task.reports /}
|
||||
{/call}
|
||||
{/template}
|
||||
|
||||
{template .taskInternal}
|
||||
{@param uniqueName: string}
|
||||
{@param description: string}
|
||||
{@param log: string}
|
||||
{@param reports: map<string, string>}
|
||||
|
||||
<div class="task">
|
||||
<span class="task_name">{$uniqueName}</span>
|
||||
<span class="task_description">{$description}</span>
|
||||
<span class="report_links">
|
||||
{if $log}
|
||||
<a href="{$log}">[log]</a>
|
||||
{else}
|
||||
<span class="report_link_broken">[log]</span>
|
||||
{/if}
|
||||
{for $type in mapKeys($reports)}
|
||||
{if $reports[$type]}
|
||||
<a href="{$reports[$type]}">[{$type}]</a>
|
||||
{else}
|
||||
<span class="report_link_broken">[{$type}]</span>
|
||||
{/if}
|
||||
{/for}
|
||||
</span>
|
||||
</div>
|
||||
{/template}
|
||||
@@ -1,278 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.gradle.plugin;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.toByteArraySupplier;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.gradle.plugin.ProjectData.TaskData;
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Tests for {@link CoverPageGenerator} */
|
||||
final class CoverPageGeneratorTest {
|
||||
|
||||
private static final ProjectData EMPTY_PROJECT =
|
||||
ProjectData.builder()
|
||||
.setName("project-name")
|
||||
.setDescription("project-description")
|
||||
.setGradleVersion("gradle-version")
|
||||
.setProjectProperties(ImmutableMap.of("key", "value"))
|
||||
.setSystemProperties(ImmutableMap.of())
|
||||
.setTasksRequested(ImmutableSet.of(":a:task1", ":a:task2"))
|
||||
.build();
|
||||
|
||||
private static final TaskData EMPTY_TASK_SUCCESS =
|
||||
TaskData.builder()
|
||||
.setUniqueName("task-success")
|
||||
.setDescription("a successful task")
|
||||
.setState(TaskData.State.SUCCESS)
|
||||
.build();
|
||||
|
||||
private static final TaskData EMPTY_TASK_FAILURE =
|
||||
TaskData.builder()
|
||||
.setUniqueName("task-failure")
|
||||
.setDescription("a failed task")
|
||||
.setState(TaskData.State.FAILURE)
|
||||
.build();
|
||||
|
||||
private static final TaskData EMPTY_TASK_UP_TO_DATE =
|
||||
TaskData.builder()
|
||||
.setUniqueName("task-up-to-date")
|
||||
.setDescription("an up-to-date task")
|
||||
.setState(TaskData.State.UP_TO_DATE)
|
||||
.build();
|
||||
|
||||
private static final Joiner filenameJoiner = Joiner.on(File.separator);
|
||||
|
||||
private ImmutableMap<String, String> getGeneratedFiles(ProjectData project) {
|
||||
CoverPageGenerator coverPageGenerator = new CoverPageGenerator(project);
|
||||
FilesWithEntryPoint files = coverPageGenerator.getFilesToUpload();
|
||||
return files.files().entrySet().stream()
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
entry -> entry.getKey().toString(),
|
||||
entry -> new String(entry.getValue().get(), UTF_8)));
|
||||
}
|
||||
|
||||
private String getContentOfGeneratedFile(ProjectData project, String expectedPath) {
|
||||
ImmutableMap<String, String> files = getGeneratedFiles(project);
|
||||
assertThat(files).containsKey(expectedPath);
|
||||
return files.get(expectedPath);
|
||||
}
|
||||
|
||||
private String getCoverPage(ProjectData project) {
|
||||
return getContentOfGeneratedFile(project, "index.html");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetFilesToUpload_entryPoint_isIndexHtml() {
|
||||
CoverPageGenerator coverPageGenerator = new CoverPageGenerator(EMPTY_PROJECT);
|
||||
assertThat(coverPageGenerator.getFilesToUpload().entryPoint())
|
||||
.isEqualTo(Paths.get("index.html"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetFilesToUpload_containsEntryFile() {
|
||||
String content = getContentOfGeneratedFile(EMPTY_PROJECT, "index.html");
|
||||
assertThat(content)
|
||||
.contains(
|
||||
"<span class=\"project_invocation\">./gradlew :a:task1 :a:task2 -P key=value</span>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_showsFailedTask() {
|
||||
String content = getCoverPage(EMPTY_PROJECT.toBuilder().addTask(EMPTY_TASK_FAILURE).build());
|
||||
assertThat(content).contains("task-failure");
|
||||
assertThat(content).contains("<p>FAILURE</p>");
|
||||
assertThat(content).doesNotContain("<p>SUCCESS</p>");
|
||||
assertThat(content).doesNotContain("<p>UP_TO_DATE</p>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_showsSuccessfulTask() {
|
||||
String content = getCoverPage(EMPTY_PROJECT.toBuilder().addTask(EMPTY_TASK_SUCCESS).build());
|
||||
assertThat(content).contains("task-success");
|
||||
assertThat(content).doesNotContain("<p>FAILURE</p>");
|
||||
assertThat(content).contains("<p>SUCCESS</p>");
|
||||
assertThat(content).doesNotContain("<p>UP_TO_DATE</p>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_showsUpToDateTask() {
|
||||
String content = getCoverPage(EMPTY_PROJECT.toBuilder().addTask(EMPTY_TASK_UP_TO_DATE).build());
|
||||
assertThat(content).contains("task-up-to-date");
|
||||
assertThat(content).doesNotContain("<p>FAILURE</p>");
|
||||
assertThat(content).doesNotContain("<p>SUCCESS</p>");
|
||||
assertThat(content).contains("<p>UP_TO_DATE</p>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_failedAreFirst() {
|
||||
String content =
|
||||
getCoverPage(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
.addTask(EMPTY_TASK_UP_TO_DATE)
|
||||
.addTask(EMPTY_TASK_FAILURE)
|
||||
.addTask(EMPTY_TASK_SUCCESS)
|
||||
.build());
|
||||
assertThat(content).contains("<p>FAILURE</p>");
|
||||
assertThat(content).contains("<p>SUCCESS</p>");
|
||||
assertThat(content).contains("<p>UP_TO_DATE</p>");
|
||||
assertThat(content).containsMatch("(?s)<p>FAILURE</p>.*<p>SUCCESS</p>");
|
||||
assertThat(content).containsMatch("(?s)<p>FAILURE</p>.*<p>UP_TO_DATE</p>");
|
||||
assertThat(content).doesNotContainMatch("(?s)<p>SUCCESS</p>.*<p>FAILURE</p>");
|
||||
assertThat(content).doesNotContainMatch("(?s)<p>UP_TO_DATE</p>.*<p>FAILURE</p>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_failingTask_statusIsFailure() {
|
||||
String content =
|
||||
getCoverPage(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
.addTask(EMPTY_TASK_UP_TO_DATE)
|
||||
.addTask(EMPTY_TASK_FAILURE)
|
||||
.addTask(EMPTY_TASK_SUCCESS)
|
||||
.build());
|
||||
assertThat(content).contains("<title>Failed: task-failure</title>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_noFailingTask_statusIsSuccess() {
|
||||
String content =
|
||||
getCoverPage(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
.addTask(EMPTY_TASK_UP_TO_DATE)
|
||||
.addTask(EMPTY_TASK_SUCCESS)
|
||||
.build());
|
||||
assertThat(content).contains("<title>Success!</title>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetFilesToUpload_containsCssFile() {
|
||||
ImmutableMap<String, String> files = getGeneratedFiles(EMPTY_PROJECT);
|
||||
assertThat(files).containsKey(filenameJoiner.join("css", "style.css"));
|
||||
assertThat(files.get(filenameJoiner.join("css", "style.css"))).contains("body {");
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\">");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_taskWithLog() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
.addTask(
|
||||
EMPTY_TASK_SUCCESS.toBuilder()
|
||||
.setUniqueName("my:name")
|
||||
.setLog(toByteArraySupplier("my log data"))
|
||||
.build())
|
||||
.build());
|
||||
assertThat(files).containsEntry(filenameJoiner.join("logs", "my-name.log"), "my log data");
|
||||
assertThat(files.get("index.html")).contains("<a href=\"logs/my-name.log\">[log]</a>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_taskWithoutLog() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
.addTask(EMPTY_TASK_SUCCESS.toBuilder().setUniqueName("my:name").build())
|
||||
.build());
|
||||
assertThat(files).doesNotContainKey("logs/my-name.log");
|
||||
assertThat(files.get("index.html")).contains("<span class=\"report_link_broken\">[log]</span>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_taskWithFilledReport() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
.addTask(
|
||||
EMPTY_TASK_SUCCESS.toBuilder()
|
||||
.putReport(
|
||||
"someReport",
|
||||
FilesWithEntryPoint.create(
|
||||
ImmutableMap.of(
|
||||
Paths.get("path", "report.txt"),
|
||||
toByteArraySupplier("report content")),
|
||||
Paths.get("path", "report.txt")))
|
||||
.build())
|
||||
.build());
|
||||
assertThat(files).containsEntry(filenameJoiner.join("path", "report.txt"), "report content");
|
||||
assertThat(files.get("index.html")).contains("<a href=\"path/report.txt\">[someReport]</a>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_taskWithEmptyReport() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
.addTask(
|
||||
EMPTY_TASK_SUCCESS.toBuilder()
|
||||
.putReport(
|
||||
"someReport",
|
||||
FilesWithEntryPoint.create(
|
||||
ImmutableMap.of(), Paths.get("path", "report.txt")))
|
||||
.build())
|
||||
.build());
|
||||
assertThat(files).doesNotContainKey(filenameJoiner.join("path", "report.txt"));
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<span class=\"report_link_broken\">[someReport]</span>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_taskWithLogAndMultipleReports() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
.addTask(
|
||||
EMPTY_TASK_SUCCESS.toBuilder()
|
||||
.setUniqueName("my:name")
|
||||
.setLog(toByteArraySupplier("log data"))
|
||||
.putReport(
|
||||
"filledReport",
|
||||
FilesWithEntryPoint.create(
|
||||
ImmutableMap.of(
|
||||
Paths.get("path-filled", "report.txt"),
|
||||
toByteArraySupplier("report content"),
|
||||
Paths.get("path-filled", "other", "file.txt"),
|
||||
toByteArraySupplier("some other content")),
|
||||
Paths.get("path-filled", "report.txt")))
|
||||
.putReport(
|
||||
"emptyReport",
|
||||
FilesWithEntryPoint.create(
|
||||
ImmutableMap.of(), Paths.get("path-empty", "report.txt")))
|
||||
.build())
|
||||
.build());
|
||||
assertThat(files)
|
||||
.containsEntry(filenameJoiner.join("path-filled", "report.txt"), "report content");
|
||||
assertThat(files)
|
||||
.containsEntry(
|
||||
filenameJoiner.join("path-filled", "other", "file.txt"), "some other content");
|
||||
assertThat(files).containsEntry(filenameJoiner.join("logs", "my-name.log"), "log data");
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<a href=\"path-filled/report.txt\">[filledReport]</a>");
|
||||
assertThat(files.get("index.html")).contains("<a href=\"logs/my-name.log\">[log]</a>");
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<span class=\"report_link_broken\">[emptyReport]</span>");
|
||||
}
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.gradle.plugin;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.getContentType;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.readFilesWithEntryPoint;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.toByteArraySupplier;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.toNormalizedPath;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.uploadFileToGcs;
|
||||
import static google.registry.gradle.plugin.GcsPluginUtils.uploadFilesToGcsMultithread;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.nio.file.Files.createDirectories;
|
||||
import static java.nio.file.Files.createDirectory;
|
||||
import static java.nio.file.Files.createFile;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import com.google.cloud.storage.BlobInfo;
|
||||
import com.google.cloud.storage.Storage;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
/** Tests for {@link GcsPluginUtilsTest} */
|
||||
final class GcsPluginUtilsTest {
|
||||
|
||||
private static final Joiner filenameJoiner = Joiner.on(File.separator);
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@TempDir
|
||||
Path tmpDir;
|
||||
|
||||
@Test
|
||||
void testGetContentType_knownTypes() {
|
||||
assertThat(getContentType("path/to/file.html")).isEqualTo("text/html");
|
||||
assertThat(getContentType("path/to/file.htm")).isEqualTo("text/html");
|
||||
assertThat(getContentType("path/to/file.log")).isEqualTo("text/plain");
|
||||
assertThat(getContentType("path/to/file.txt")).isEqualTo("text/plain");
|
||||
assertThat(getContentType("path/to/file.css")).isEqualTo("text/css");
|
||||
assertThat(getContentType("path/to/file.xml")).isEqualTo("text/xml");
|
||||
assertThat(getContentType("path/to/file.zip")).isEqualTo("application/zip");
|
||||
assertThat(getContentType("path/to/file.js")).isEqualTo("text/javascript");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetContentType_unknownTypes() {
|
||||
assertThat(getContentType("path/to/file.unknown")).isEqualTo("application/octet-stream");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUploadFileToGcs() {
|
||||
Storage storage = mock(Storage.class);
|
||||
uploadFileToGcs(
|
||||
storage, "my-bucket", Paths.get("my", "filename.txt"), toByteArraySupplier("my data"));
|
||||
verify(storage)
|
||||
.create(
|
||||
BlobInfo.newBuilder("my-bucket", "my/filename.txt")
|
||||
.setContentType("text/plain")
|
||||
.build(),
|
||||
"my data".getBytes(UTF_8));
|
||||
verifyNoMoreInteractions(storage);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUploadFilesToGcsMultithread() {
|
||||
Storage storage = mock(Storage.class);
|
||||
uploadFilesToGcsMultithread(
|
||||
storage,
|
||||
"my-bucket",
|
||||
Paths.get("my", "folder"),
|
||||
ImmutableMap.of(
|
||||
Paths.get("some", "index.html"), toByteArraySupplier("some web page"),
|
||||
Paths.get("some", "style.css"), toByteArraySupplier("some style"),
|
||||
Paths.get("other", "index.html"), toByteArraySupplier("other web page"),
|
||||
Paths.get("other", "style.css"), toByteArraySupplier("other style")));
|
||||
verify(storage)
|
||||
.create(
|
||||
BlobInfo.newBuilder("my-bucket", "my/folder/some/index.html")
|
||||
.setContentType("text/html")
|
||||
.build(),
|
||||
"some web page".getBytes(UTF_8));
|
||||
verify(storage)
|
||||
.create(
|
||||
BlobInfo.newBuilder("my-bucket", "my/folder/some/style.css")
|
||||
.setContentType("text/css")
|
||||
.build(),
|
||||
"some style".getBytes(UTF_8));
|
||||
verify(storage)
|
||||
.create(
|
||||
BlobInfo.newBuilder("my-bucket", "my/folder/other/index.html")
|
||||
.setContentType("text/html")
|
||||
.build(),
|
||||
"other web page".getBytes(UTF_8));
|
||||
verify(storage)
|
||||
.create(
|
||||
BlobInfo.newBuilder("my-bucket", "my/folder/other/style.css")
|
||||
.setContentType("text/css")
|
||||
.build(),
|
||||
"other style".getBytes(UTF_8));
|
||||
verifyNoMoreInteractions(storage);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToByteArraySupplier_string() {
|
||||
assertThat(toByteArraySupplier("my string").get()).isEqualTo("my string".getBytes(UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToByteArraySupplier_stringSupplier() {
|
||||
assertThat(toByteArraySupplier(() -> "my string").get()).isEqualTo("my string".getBytes(UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToByteArraySupplier_file() throws Exception {
|
||||
Path dir = createDirectory(tmpDir.resolve("arbitrary"));
|
||||
Path file = createFile(dir.resolve("file.txt"));
|
||||
Files.write(file, "some data".getBytes(UTF_8));
|
||||
assertThat(toByteArraySupplier(file.toFile()).get()).isEqualTo("some data".getBytes(UTF_8));
|
||||
}
|
||||
|
||||
private ImmutableMap<String, String> readAllFiles(FilesWithEntryPoint reportFiles) {
|
||||
return reportFiles.files().entrySet().stream()
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
entry -> entry.getKey().toString(),
|
||||
entry -> new String(entry.getValue().get(), UTF_8)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_destinationIsFile() throws Exception {
|
||||
Path root = toNormalizedPath(createDirectories(tmpDir.resolve("my/root")).toAbsolutePath());
|
||||
Path somePath = createDirectories(root.resolve("some/path"));
|
||||
Path destination = createFile(somePath.resolve("file.txt"));
|
||||
Files.write(destination, "some data".getBytes(UTF_8));
|
||||
// Since the entry point is obvious here - any hint given is just ignored.
|
||||
File ignoredHint = createFile(root.resolve("ignored.txt")).toFile();
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "file.txt"));
|
||||
assertThat(readAllFiles(files))
|
||||
.containsExactly(filenameJoiner.join("some", "path", "file.txt"), "some data");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_destinationDoesntExist() throws Exception {
|
||||
Path root = toNormalizedPath(createDirectories(tmpDir.resolve("my/root")).toAbsolutePath());
|
||||
File destination = root.resolve("non/existing.txt").toFile();
|
||||
assertThat(destination.isFile()).isFalse();
|
||||
assertThat(destination.isDirectory()).isFalse();
|
||||
// Since there are no files, any hint given is obviously wrong and will be ignored.
|
||||
File ignoredHint = createFile(root.resolve("ignored.txt")).toFile();
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo(filenameJoiner.join("non", "existing.txt"));
|
||||
assertThat(files.files()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_noFiles() throws Exception {
|
||||
Path root = toNormalizedPath(createDirectories(tmpDir.resolve("my/root")).toAbsolutePath());
|
||||
Path destination = createDirectories(root.resolve("some/path"));
|
||||
createDirectories(destination.resolve("a/b"));
|
||||
createDirectory(destination.resolve("c"));
|
||||
// Since there are not files, any hint given is obviously wrong and will be ignored.
|
||||
File ignoredHint = createFile(root.resolve("ignored.txt")).toFile();
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo(filenameJoiner.join("some", "path"));
|
||||
assertThat(files.files()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_oneFile() throws Exception {
|
||||
Path root = toNormalizedPath(createDirectories(tmpDir.resolve("my/root")).toAbsolutePath());
|
||||
Path destination = createDirectories(root.resolve("some/path"));
|
||||
createDirectories(destination.resolve("a/b"));
|
||||
createDirectory(destination.resolve("c"));
|
||||
Files.write(createFile(destination.resolve("a/file.txt")), "some data".getBytes(UTF_8));
|
||||
// Since the entry point is obvious here - any hint given is just ignored.
|
||||
File ignoredHint = createFile(root.resolve("ignored.txt")).toFile();
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "a", "file.txt"));
|
||||
assertThat(readAllFiles(files))
|
||||
.containsExactly(filenameJoiner.join("some", "path", "a", "file.txt"), "some data");
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently tests the "unimplemented" behavior.
|
||||
*
|
||||
* <p>TODO(guyben): switch to checking zip file instead.
|
||||
*/
|
||||
@Test
|
||||
void testCreateReportFiles_multipleFiles_noHint() throws Exception {
|
||||
Path root = toNormalizedPath(createDirectories(tmpDir.resolve("my/root")).toAbsolutePath());
|
||||
Path destination = createDirectories(root.resolve("some/path"));
|
||||
createDirectories(destination.resolve("a/b"));
|
||||
createDirectory(destination.resolve("c"));
|
||||
|
||||
Files.write(createFile(destination.resolve("index.html")), "some data".getBytes(UTF_8));
|
||||
Files.write(createFile(destination.resolve("a/index.html")), "wrong index".getBytes(UTF_8));
|
||||
Files.write(createFile(destination.resolve("c/style.css")), "css file".getBytes(UTF_8));
|
||||
Files.write(createFile(destination.resolve("my_image.png")), "images".getBytes(UTF_8));
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.empty(), root);
|
||||
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "path.zip"));
|
||||
assertThat(readAllFiles(files).keySet())
|
||||
.containsExactly(filenameJoiner.join("some", "path", "path.zip"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently tests the "unimplemented" behavior.
|
||||
*
|
||||
* <p>TODO(guyben): switch to checking zip file instead.
|
||||
*/
|
||||
@Test
|
||||
void testCreateReportFiles_multipleFiles_withBadHint() throws Exception {
|
||||
Path root = toNormalizedPath(createDirectories(tmpDir.resolve("my/root")).toAbsolutePath());
|
||||
Path destination = createDirectories(root.resolve("some/path"));
|
||||
// This entry point points to a directory, which isn't an appropriate entry point
|
||||
File badEntryPoint = createDirectories(destination.resolve("a/b")).toFile();
|
||||
createDirectory(destination.resolve("c"));
|
||||
|
||||
Files.write(createFile(destination.resolve("index.html")), "some data".getBytes(UTF_8));
|
||||
Files.write(createFile(destination.resolve("a/index.html")), "wrong index".getBytes(UTF_8));
|
||||
Files.write(createFile(destination.resolve("c/style.css")), "css file".getBytes(UTF_8));
|
||||
Files.write(createFile(destination.resolve("my_image.png")), "images".getBytes(UTF_8));
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.of(badEntryPoint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "path.zip"));
|
||||
assertThat(readAllFiles(files).keySet())
|
||||
.containsExactly(filenameJoiner.join("some", "path", "path.zip"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_multipleFiles_withGoodHint() throws Exception {
|
||||
Path root = toNormalizedPath(createDirectories(tmpDir.resolve("my/root")).toAbsolutePath());
|
||||
Path destination = createDirectories(root.resolve("some/path"));
|
||||
createDirectories(destination.resolve("a/b"));
|
||||
createDirectory(destination.resolve("c"));
|
||||
// The hint is an actual file nested in the destination directory!
|
||||
Path goodEntryPoint = createFile(destination.resolve("index.html"));
|
||||
|
||||
Files.write(goodEntryPoint, "some data".getBytes(UTF_8));
|
||||
Files.write(createFile(destination.resolve("a/index.html")), "wrong index".getBytes(UTF_8));
|
||||
Files.write(createFile(destination.resolve("c/style.css")), "css file".getBytes(UTF_8));
|
||||
Files.write(createFile(destination.resolve("my_image.png")), "images".getBytes(UTF_8));
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.of(goodEntryPoint.toFile()), root);
|
||||
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "index.html"));
|
||||
assertThat(readAllFiles(files))
|
||||
.containsExactly(
|
||||
filenameJoiner.join("some", "path", "index.html"), "some data",
|
||||
filenameJoiner.join("some", "path", "a", "index.html"), "wrong index",
|
||||
filenameJoiner.join("some", "path", "c", "style.css"), "css file",
|
||||
filenameJoiner.join("some", "path", "my_image.png"), "images");
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
mock-maker-inline
|
||||
@@ -57,7 +57,7 @@ dependencies {
|
||||
implementation deps['com.github.ben-manes.caffeine:caffeine']
|
||||
implementation deps['com.google.code.findbugs:jsr305']
|
||||
implementation deps['com.google.guava:guava']
|
||||
implementation deps['javax.inject:javax.inject']
|
||||
implementation deps['jakarta.inject:jakarta.inject-api']
|
||||
implementation deps['joda-time:joda-time']
|
||||
implementation deps['com.google.flogger:flogger']
|
||||
implementation deps['io.github.java-diff-utils:java-diff-utils']
|
||||
|
||||
@@ -12,7 +12,7 @@ com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,testAnnotationP
|
||||
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
|
||||
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.25.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.26.1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle
|
||||
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
@@ -24,11 +24,11 @@ com.google.guava:failureaccess:1.0.2=compileClasspath,deploy_jar,runtimeClasspat
|
||||
com.google.guava:guava-parent:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.guava:guava:31.0.1-jre=checkstyle
|
||||
com.google.guava:guava:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.guava:guava:33.0.0-jre=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.guava:guava:33.1.0-jre=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.j2objc:j2objc-annotations:1.3=checkstyle
|
||||
com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath,testingCompileClasspath
|
||||
com.google.j2objc:j2objc-annotations:3.0.0=compileClasspath,testCompileClasspath,testingCompileClasspath
|
||||
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.truth:truth:1.4.2=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.puppycrawl.tools:checkstyle:9.3=checkstyle
|
||||
@@ -37,7 +37,8 @@ commons-collections:commons-collections:3.2.2=checkstyle
|
||||
info.picocli:picocli:4.6.2=checkstyle
|
||||
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
|
||||
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
|
||||
jakarta.inject:jakarta.inject-api:1.0.5=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
joda-time:joda-time:2.12.7=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
net.sf.saxon:Saxon-HE:10.6=checkstyle
|
||||
|
||||
@@ -47,7 +47,7 @@ class GradleFlag:
|
||||
|
||||
|
||||
PROPERTIES_HEADER = """\
|
||||
# This file defines properties used by the gradle build. It must be kept in
|
||||
# This file defines properties used by the gradle build. It must be kept in
|
||||
# sync with config/nom_build.py.
|
||||
#
|
||||
# To regenerate, run ./nom_build --generate-gradle-properties
|
||||
@@ -89,13 +89,6 @@ PROPERTIES = [
|
||||
'Allow connecting to plain HTTP repositories. This is provided '
|
||||
'to allow us to communicate to a local proxy when doing '
|
||||
'dependency updates.'),
|
||||
Property('uploaderDestination',
|
||||
'Location to upload test reports to. Normally this should be a '
|
||||
'GCS url (see also uploaderCredentialsFile)'),
|
||||
Property('uploaderCredentialsFile',
|
||||
'json credentials file to use to upload test reports.'),
|
||||
Property('uploaderMultithreadedUpload',
|
||||
'Whether to enable multithread upload.'),
|
||||
Property('verboseTestOutput',
|
||||
'If true, show all test output in near-realtime.',
|
||||
'false',
|
||||
@@ -277,8 +270,7 @@ def generate_gradle_properties() -> str:
|
||||
def get_root() -> str:
|
||||
"""Returns the root of the nomulus build tree."""
|
||||
cur_dir = os.getcwd()
|
||||
if not os.path.exists(os.path.join(cur_dir, 'buildSrc')) or \
|
||||
not os.path.exists(os.path.join(cur_dir, 'core')) or \
|
||||
if not os.path.exists(os.path.join(cur_dir, 'core')) or \
|
||||
not os.path.exists(os.path.join(cur_dir, 'gradle.properties')):
|
||||
raise Exception('You must run this script from the root directory')
|
||||
return cur_dir
|
||||
|
||||
@@ -173,17 +173,24 @@ PRESUBMITS = {
|
||||
):
|
||||
"JavaScript files should not include console logging.",
|
||||
PresubmitCheck(
|
||||
r"org\.testcontainers\.shaded\.",
|
||||
r".*org\.testcontainers\.shaded.*",
|
||||
"java",
|
||||
{"/node_modules/"},
|
||||
):
|
||||
"Do not use shaded dependencies from testcontainers.",
|
||||
PresubmitCheck(
|
||||
r"com\.google\.common\.truth\.Truth8",
|
||||
r".*com\.google\.common\.truth\.Truth8.*",
|
||||
"java",
|
||||
{"/node_modules/"},
|
||||
):
|
||||
"Truth8 is deprecated. Use Truth instead.",
|
||||
PresubmitCheck(
|
||||
r".*java\.util\.Date.*",
|
||||
"java",
|
||||
{"/node_modules/", "JpaTransactionManagerImpl.java"},
|
||||
):
|
||||
"Do not use java.util.Date. Use classes in java.time package instead.",
|
||||
|
||||
}
|
||||
|
||||
# Note that this regex only works for one kind of Flyway file. If we want to
|
||||
|
||||
6
console-webapp/package-lock.json
generated
6
console-webapp/package-lock.json
generated
@@ -8944,9 +8944,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.5",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
|
||||
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
||||
@@ -188,19 +188,16 @@ dependencies {
|
||||
implementation deps['com.google.template:soy']
|
||||
implementation deps['com.googlecode.json-simple:json-simple']
|
||||
implementation deps['com.jcraft:jsch']
|
||||
testImplementation deps['com.thoughtworks.qdox:qdox']
|
||||
implementation deps['com.zaxxer:HikariCP']
|
||||
implementation deps['com.squareup.okhttp3:okhttp']
|
||||
implementation deps['dnsjava:dnsjava']
|
||||
testRuntimeOnly deps['guru.nidi:graphviz-java-all-j2v8']
|
||||
testImplementation deps['io.github.classgraph:classgraph']
|
||||
testRuntimeOnly deps['io.github.java-diff-utils:java-diff-utils']
|
||||
testImplementation deps['javax.annotation:javax.annotation-api']
|
||||
testImplementation deps['javax.annotation:jsr250-api']
|
||||
implementation deps['javax.mail:mail']
|
||||
implementation deps['javax.inject:javax.inject']
|
||||
implementation deps['jakarta.inject:jakarta.inject-api']
|
||||
implementation deps['javax.persistence:javax.persistence-api']
|
||||
implementation deps['javax.servlet:servlet-api']
|
||||
implementation deps['jakarta.servlet:jakarta.servlet-api']
|
||||
implementation deps['javax.xml.bind:jaxb-api']
|
||||
implementation deps['jline:jline']
|
||||
implementation deps['joda-time:joda-time']
|
||||
@@ -222,19 +219,19 @@ dependencies {
|
||||
testImplementation deps['org.apache.sshd:sshd-scp']
|
||||
testImplementation deps['org.apache.sshd:sshd-sftp']
|
||||
testImplementation deps['org.apache.tomcat:tomcat-annotations-api']
|
||||
implementation deps['org.bouncycastle:bcpg-jdk15on']
|
||||
implementation deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
implementation deps['org.bouncycastle:bcprov-jdk15on']
|
||||
implementation deps['org.bouncycastle:bcpg-jdk18on']
|
||||
implementation deps['org.bouncycastle:bcpkix-jdk18on']
|
||||
implementation deps['org.bouncycastle:bcprov-jdk18on']
|
||||
testImplementation deps['com.fasterxml.jackson.core:jackson-databind']
|
||||
implementation deps['org.hibernate:hibernate-core']
|
||||
implementation deps['org.hibernate:hibernate-hikaricp']
|
||||
implementation deps['org.joda:joda-money']
|
||||
implementation deps['org.json:json']
|
||||
implementation deps['org.jsoup:jsoup']
|
||||
testImplementation deps['org.mortbay.jetty:jetty']
|
||||
testImplementation deps['org.eclipse.jetty:jetty-server']
|
||||
testImplementation deps['org.eclipse.jetty.ee10:jetty-ee10-servlet']
|
||||
testImplementation deps['org.eclipse.jetty.ee10:jetty-ee10-webapp']
|
||||
implementation deps['org.postgresql:postgresql']
|
||||
implementation "org.eclipse.jetty:jetty-server:9.4.49.v20220914"
|
||||
implementation "org.eclipse.jetty:jetty-servlet:9.4.49.v20220914"
|
||||
testImplementation deps['org.seleniumhq.selenium:selenium-api']
|
||||
testImplementation deps['org.seleniumhq.selenium:selenium-chrome-driver']
|
||||
testImplementation deps['org.seleniumhq.selenium:selenium-java']
|
||||
|
||||
@@ -24,22 +24,22 @@ com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,deploy_jar,nonprod
|
||||
com.github.docker-java:docker-java-api:3.3.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.docker-java:docker-java-transport-zerodep:3.3.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.docker-java:docker-java-transport:3.3.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jffi:1.3.12=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jffi:1.3.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-a64asm:1.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-constants:0.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-enxio:0.32.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-ffi:2.2.15=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-posix:3.1.18=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-unixsocket:0.38.21=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-enxio:0.32.17=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-ffi:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-posix:3.1.19=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-unixsocket:0.38.22=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-x86asm:1.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.android:annotations:4.1.1.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-appengine:1.35.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-appengine:2.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-jackson2:2.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-java6:1.35.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:1.35.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-java6:2.1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:2.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client:1.35.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.35.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.36.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.172.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.172.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -49,7 +49,7 @@ com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.12.20=compileClasspath,dep
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.35.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.36.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.30.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.172.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -68,7 +68,7 @@ com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.56.0=compileC
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.35.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.36.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.127.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.127.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -78,26 +78,27 @@ com.google.api:api-common:2.28.0=compileClasspath,deploy_jar,nonprodCompileClass
|
||||
com.google.api:gax-grpc:2.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240304-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-appengine:v1-rev20240226-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20230812-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20230806-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20240113-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-drive:v2-rev393-1.25.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-gmail:v1-rev20220404-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-gmail:v1-rev20231218-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev20210624-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-healthcare:v1-rev20240110-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20240128-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20240303-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20230815-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20240205-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240209-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.appengine:appengine-api-1.0-sdk:2.0.25=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-stubs:2.0.25=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-testing:1.9.86=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20240304-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20240307-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-1.0-sdk:2.0.25=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-stubs:2.0.25=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-remote-api:2.0.25=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-testing:2.0.25=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-tools-sdk:2.0.25=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
@@ -112,8 +113,8 @@ com.google.cloud.bigdataoss:gcsio:2.2.16=compileClasspath,deploy_jar,nonprodComp
|
||||
com.google.cloud.bigdataoss:util:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.17.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.16.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.16.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.17.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.17.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:3.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable-stats:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -128,7 +129,7 @@ com.google.cloud:google-cloud-pubsub:1.126.0=compileClasspath,deploy_jar,nonprod
|
||||
com.google.cloud:google-cloud-pubsublite:1.12.20=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:grpc-gcp:1.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.16.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -143,8 +144,7 @@ com.google.dagger:dagger:2.51=annotationProcessor,compileClasspath,deploy_jar,no
|
||||
com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14=annotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.24.1=compileClasspath,nonprodCompileClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.25.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.26.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle,soy
|
||||
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
@@ -160,11 +160,12 @@ com.google.googlejavaformat:google-java-format:1.5=annotationProcessor,testAnnot
|
||||
com.google.guava:failureaccess:1.0.1=checkstyle,errorprone,nonprodAnnotationProcessor,soy
|
||||
com.google.guava:failureaccess:1.0.2=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava-parent:32.1.1-jre=errorprone,nonprodAnnotationProcessor
|
||||
com.google.guava:guava-testlib:33.0.0-jre=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava-testlib:33.1.0-jre=testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava:20.0=css
|
||||
com.google.guava:guava:31.0.1-jre=checkstyle,soy
|
||||
com.google.guava:guava:32.1.1-jre=errorprone,nonprodAnnotationProcessor
|
||||
com.google.guava:guava:33.0.0-jre=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava:33.0.0-jre=annotationProcessor,testAnnotationProcessor
|
||||
com.google.guava:guava:33.1.0-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.gwt:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -178,7 +179,8 @@ com.google.inject:guice:4.1.0=compileClasspath,deploy_jar,nonprodCompileClasspat
|
||||
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
com.google.inject:guice:7.0.0=soy
|
||||
com.google.j2objc:j2objc-annotations:1.3=checkstyle,soy
|
||||
com.google.j2objc:j2objc-annotations:2.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.j2objc:j2objc-annotations:2.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
|
||||
com.google.j2objc:j2objc-annotations:3.0.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.javascript:closure-compiler-externs:v20160713=css
|
||||
com.google.javascript:closure-compiler-unshaded:v20160713=css
|
||||
com.google.javascript:closure-compiler:v20210505=closureCompiler
|
||||
@@ -229,12 +231,11 @@ com.squareup:kotlinpoet:1.15.1=compileClasspath,deploy_jar,nonprodCompileClasspa
|
||||
com.sun.activation:jakarta.activation:1.2.2=jaxb
|
||||
com.sun.activation:javax.activation:1.2.0=jaxb
|
||||
com.sun.istack:istack-commons-runtime:3.0.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.sun.xml.bind:jaxb-impl:2.3.3=jaxb
|
||||
com.sun.xml.bind:jaxb-impl:2.3.9=jaxb
|
||||
com.sun.xml.bind:jaxb-osgi:4.0.5=jaxb
|
||||
com.sun.xml.bind:jaxb-xjc:2.3.3=jaxb
|
||||
com.sun.xml.bind:jaxb-xjc:2.3.9=jaxb
|
||||
com.sun.xml.fastinfoset:FastInfoset:1.2.15=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.thoughtworks.paranamer:paranamer:2.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.thoughtworks.qdox:qdox:1.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.zaxxer:HikariCP:5.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-beanutils:commons-beanutils:1.9.4=checkstyle
|
||||
commons-codec:commons-codec:1.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -308,7 +309,10 @@ io.outfoxx:swiftpoet:1.3.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,t
|
||||
io.perfmark:perfmark-api:0.27.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
jakarta-regexp:jakarta-regexp:1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
jakarta.activation:jakarta.activation-api:2.1.3=jaxb
|
||||
jakarta.inject:jakarta.inject-api:1.0.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
jakarta.inject:jakarta.inject-api:2.0.1=soy
|
||||
jakarta.servlet:jakarta.servlet-api:6.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
jakarta.servlet:jakarta.servlet-api:6.1.0-M2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
|
||||
jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=jaxb
|
||||
javacc:javacc:4.1=css
|
||||
javax.activation:activation:1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -371,14 +375,16 @@ org.apache.ftpserver:ftpserver-core:1.2.0=testCompileClasspath,testRuntimeClassp
|
||||
org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.mina:mina-core:2.1.6=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-core:2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-scp:2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-sftp:2.0.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.tomcat:tomcat-annotations-api:11.0.0-M17=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-common:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-core:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-scp:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.sshd:sshd-sftp:2.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.tomcat:tomcat-annotations-api:11.0.0-M18=testCompileClasspath,testRuntimeClasspath
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
|
||||
org.bouncycastle:bcpg-jdk15on:1.67=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk15on:1.67=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcprov-jdk15on:1.67=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpg-jdk18on:1.77=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk18on:1.77=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcprov-jdk18on:1.77=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcutil-jdk18on:1.77=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,nonprodCompileClasspath,testCompileClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.5=annotationProcessor,testAnnotationProcessor
|
||||
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
@@ -391,15 +397,17 @@ org.codehaus.jackson:jackson-mapper-asl:1.9.13=compileClasspath,deploy_jar,nonpr
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.23=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.easymock:easymock:3.0=css
|
||||
org.eclipse.jetty:jetty-http:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-io:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-security:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-server:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-servlet:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util-ajax:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:10.9.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-database-postgresql:10.9.1=testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-http:12.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-io:12.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-security:12.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-server:12.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-session:12.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:12.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-xml:12.0.7=testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:10.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-database-postgresql:10.10.0=testRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-runtime:2.3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:txw2:2.3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.gwtproject:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -457,8 +465,6 @@ org.jvnet.staxex:stax-ex:1.8=compileClasspath,deploy_jar,nonprodCompileClasspath
|
||||
org.mockito:mockito-core:1.10.19=css
|
||||
org.mockito:mockito-core:5.11.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.mockito:mockito-junit-jupiter:5.11.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.mortbay.jetty:jetty-util:6.1.26=testCompileClasspath,testRuntimeClasspath
|
||||
org.mortbay.jetty:jetty:6.1.26=testCompileClasspath,testRuntimeClasspath
|
||||
org.objenesis:objenesis:2.1=css
|
||||
org.objenesis:objenesis:3.3=testRuntimeClasspath
|
||||
org.ogce:xpp3:1.1.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -476,7 +482,7 @@ org.ow2.asm:asm:7.0=soy
|
||||
org.ow2.asm:asm:9.2=compileClasspath,nonprodCompileClasspath
|
||||
org.ow2.asm:asm:9.6=deploy_jar,jacocoAnt,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
|
||||
org.postgresql:postgresql:42.7.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.postgresql:postgresql:42.7.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.reflections:reflections:0.10.2=checkstyle
|
||||
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-api:3.141.59=testCompileClasspath,testRuntimeClasspath
|
||||
@@ -489,7 +495,7 @@ org.seleniumhq.selenium:selenium-opera-driver:3.141.59=testCompileClasspath,test
|
||||
org.seleniumhq.selenium:selenium-remote-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-safari-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
|
||||
org.seleniumhq.selenium:selenium-support:3.141.59=testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:jcl-over-slf4j:1.7.30=testRuntimeClasspath
|
||||
org.slf4j:jcl-over-slf4j:1.7.32=testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:jul-to-slf4j:1.7.30=testRuntimeClasspath
|
||||
org.slf4j:slf4j-api:2.0.12=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath
|
||||
org.slf4j:slf4j-api:2.1.0-alpha1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
|
||||
@@ -32,8 +32,8 @@ import com.google.common.collect.ImmutableSet;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.request.Parameter;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Dagger module for injecting common settings for batch actions. */
|
||||
|
||||
@@ -20,10 +20,10 @@ import static google.registry.flows.FlowUtils.marshalWithLenientRetry;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.ResourceUtils.readResourceUtf8;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
|
||||
@@ -20,8 +20,8 @@ import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.RequestParameters.PARAM_DRY_RUN;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.services.dataflow.Dataflow;
|
||||
import com.google.api.services.dataflow.model.LaunchFlexTemplateParameter;
|
||||
|
||||
@@ -19,8 +19,8 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
|
||||
@@ -16,8 +16,8 @@ package google.registry.batch;
|
||||
|
||||
import static google.registry.batch.BatchModule.PARAM_FAST;
|
||||
import static google.registry.beam.BeamUtils.createJobName;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.services.dataflow.Dataflow;
|
||||
import com.google.api.services.dataflow.model.LaunchFlexTemplateParameter;
|
||||
|
||||
@@ -16,8 +16,8 @@ package google.registry.batch;
|
||||
|
||||
import static google.registry.beam.BeamUtils.createJobName;
|
||||
import static google.registry.request.RequestParameters.PARAM_DRY_RUN;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.services.dataflow.Dataflow;
|
||||
import com.google.api.services.dataflow.model.LaunchFlexTemplateParameter;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
package google.registry.bsa;
|
||||
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.client.http.HttpMethods;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@@ -23,7 +23,7 @@ import static google.registry.bsa.persistence.LabelDiffUpdates.applyLabelDiff;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.util.BatchedStreams.toBatches;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
41
core/src/main/java/google/registry/bsa/BsaEmailSender.java
Normal file
41
core/src/main/java/google/registry/bsa/BsaEmailSender.java
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2024 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.
|
||||
|
||||
package google.registry.bsa;
|
||||
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.groups.GmailClient;
|
||||
import google.registry.util.EmailMessage;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
/** Sends BSA-related email notifications. */
|
||||
class BsaEmailSender {
|
||||
|
||||
private final InternetAddress alertRecipientAddress;
|
||||
private final GmailClient gmailClient;
|
||||
|
||||
@Inject
|
||||
BsaEmailSender(
|
||||
GmailClient gmailClient,
|
||||
@Config("newAlertRecipientEmailAddress") InternetAddress alertRecipientAddress) {
|
||||
this.alertRecipientAddress = alertRecipientAddress;
|
||||
this.gmailClient = gmailClient;
|
||||
}
|
||||
|
||||
/** Sends an email to the configured alert recipient. */
|
||||
void sendNotification(String subject, String body) {
|
||||
this.gmailClient.sendEmail(EmailMessage.create(subject, body, alertRecipientAddress));
|
||||
}
|
||||
}
|
||||
@@ -14,10 +14,11 @@
|
||||
|
||||
package google.registry.bsa;
|
||||
|
||||
import static com.google.common.base.Throwables.getStackTraceAsString;
|
||||
import static google.registry.bsa.BsaStringUtils.LINE_SPLITTER;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
@@ -55,6 +56,7 @@ public class BsaRefreshAction implements Runnable {
|
||||
private final BsaReportSender bsaReportSender;
|
||||
private final int transactionBatchSize;
|
||||
private final Duration domainCreateTxnCommitTimeLag;
|
||||
private final BsaEmailSender emailSender;
|
||||
private final BsaLock bsaLock;
|
||||
private final Clock clock;
|
||||
private final Response response;
|
||||
@@ -66,6 +68,7 @@ public class BsaRefreshAction implements Runnable {
|
||||
BsaReportSender bsaReportSender,
|
||||
@Config("bsaTxnBatchSize") int transactionBatchSize,
|
||||
@Config("domainCreateTxnCommitTimeLag") Duration domainCreateTxnCommitTimeLag,
|
||||
BsaEmailSender emailSender,
|
||||
BsaLock bsaLock,
|
||||
Clock clock,
|
||||
Response response) {
|
||||
@@ -74,6 +77,7 @@ public class BsaRefreshAction implements Runnable {
|
||||
this.bsaReportSender = bsaReportSender;
|
||||
this.transactionBatchSize = transactionBatchSize;
|
||||
this.domainCreateTxnCommitTimeLag = domainCreateTxnCommitTimeLag;
|
||||
this.emailSender = emailSender;
|
||||
this.bsaLock = bsaLock;
|
||||
this.clock = clock;
|
||||
this.response = response;
|
||||
@@ -83,11 +87,15 @@ public class BsaRefreshAction implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
if (!bsaLock.executeWithLock(this::runWithinLock)) {
|
||||
logger.atInfo().log("Job is being executed by another worker.");
|
||||
String message = "BSA refresh did not run: another BSA related task is running";
|
||||
logger.atInfo().log("%s.", message);
|
||||
emailSender.sendNotification(message, /* body= */ "");
|
||||
} else {
|
||||
emailSender.sendNotification("BSA refreshed successfully", "");
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
// TODO(12/31/2023): consider sending an alert email.
|
||||
logger.atWarning().withCause(throwable).log("Failed to update block lists.");
|
||||
logger.atWarning().withCause(throwable).log("Failed to refresh BSA data.");
|
||||
emailSender.sendNotification("BSA refresh aborted", getStackTraceAsString(throwable));
|
||||
}
|
||||
// Always return OK. No need to use a retrier on `runWithinLock`. Its individual steps are
|
||||
// implicitly retried. If action fails, the next cron will continue at checkpoint.
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.bsa;
|
||||
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
|
||||
import static google.registry.persistence.transaction.JpaTransactionManagerImpl.isInTransaction;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
@@ -36,18 +35,18 @@ public final class BsaTransactions {
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public static <T> T bsaTransact(Callable<T> work) {
|
||||
verify(!isInTransaction(), "May only be used for top-level transactions.");
|
||||
verify(!tm().inTransaction(), "May only be used for top-level transactions.");
|
||||
return tm().transact(TRANSACTION_REPEATABLE_READ, work);
|
||||
}
|
||||
|
||||
public static void bsaTransact(ThrowingRunnable work) {
|
||||
verify(!isInTransaction(), "May only be used for top-level transactions.");
|
||||
verify(!tm().inTransaction(), "May only be used for top-level transactions.");
|
||||
tm().transact(TRANSACTION_REPEATABLE_READ, work);
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public static <T> T bsaQuery(Callable<T> work) {
|
||||
verify(!isInTransaction(), "May only be used for top-level transactions.");
|
||||
verify(!tm().inTransaction(), "May only be used for top-level transactions.");
|
||||
// TRANSACTION_REPEATABLE_READ is default on replica.
|
||||
return replicaTm().transact(work);
|
||||
}
|
||||
|
||||
@@ -15,26 +15,43 @@
|
||||
package google.registry.bsa;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.bsa.persistence.DownloadScheduler.fetchMostRecentDownloadJobIdIfCompleted;
|
||||
import static com.google.common.base.Throwables.getStackTraceAsString;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.bsa.BsaTransactions.bsaQuery;
|
||||
import static google.registry.bsa.ReservedDomainsUtils.isReservedDomain;
|
||||
import static google.registry.bsa.persistence.Queries.batchReadBsaLabelText;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Sets.SetView;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import google.registry.bsa.api.UnblockableDomain;
|
||||
import google.registry.bsa.api.UnblockableDomain.Reason;
|
||||
import google.registry.bsa.persistence.DownloadScheduler;
|
||||
import google.registry.bsa.persistence.Queries;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.ForeignKeyUtils;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Validates the BSA data in the database against the most recent block lists. */
|
||||
@Action(
|
||||
@@ -48,18 +65,30 @@ public class BsaValidateAction implements Runnable {
|
||||
|
||||
static final String PATH = "/_dr/task/bsaValidate";
|
||||
private final GcsClient gcsClient;
|
||||
private final IdnChecker idnChecker;
|
||||
private final BsaEmailSender emailSender;
|
||||
private final int transactionBatchSize;
|
||||
private final Duration maxStaleness;
|
||||
private final Clock clock;
|
||||
private final BsaLock bsaLock;
|
||||
private final Response response;
|
||||
|
||||
@Inject
|
||||
BsaValidateAction(
|
||||
GcsClient gcsClient,
|
||||
IdnChecker idnChecker,
|
||||
BsaEmailSender emailSender,
|
||||
@Config("bsaTxnBatchSize") int transactionBatchSize,
|
||||
@Config("bsaValidationMaxStaleness") Duration maxStaleness,
|
||||
Clock clock,
|
||||
BsaLock bsaLock,
|
||||
Response response) {
|
||||
this.gcsClient = gcsClient;
|
||||
this.idnChecker = idnChecker;
|
||||
this.emailSender = emailSender;
|
||||
this.transactionBatchSize = transactionBatchSize;
|
||||
this.maxStaleness = maxStaleness;
|
||||
this.clock = clock;
|
||||
this.bsaLock = bsaLock;
|
||||
this.response = response;
|
||||
}
|
||||
@@ -68,12 +97,13 @@ public class BsaValidateAction implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
if (!bsaLock.executeWithLock(this::runWithinLock)) {
|
||||
logger.atInfo().log("Cannot execute action. Other BSA related task is executing.");
|
||||
// TODO(blocked by go/r3pr/2354): send email
|
||||
String message = "BSA validation did not run: another BSA related task is running";
|
||||
logger.atInfo().log("%s.", message);
|
||||
emailSender.sendNotification(message, /* body= */ "");
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
logger.atWarning().withCause(throwable).log("Failed to update block lists.");
|
||||
// TODO(blocked by go/r3pr/2354): send email
|
||||
logger.atWarning().withCause(throwable).log("Failed to validate block lists.");
|
||||
emailSender.sendNotification("BSA validation aborted", getStackTraceAsString(throwable));
|
||||
}
|
||||
// Always return OK. No need to retry since all queries and GCS accesses are already
|
||||
// implicitly retried.
|
||||
@@ -82,23 +112,36 @@ public class BsaValidateAction implements Runnable {
|
||||
|
||||
/** Executes the validation action while holding the BSA lock. */
|
||||
Void runWithinLock() {
|
||||
Optional<String> downloadJobName = fetchMostRecentDownloadJobIdIfCompleted();
|
||||
Optional<String> downloadJobName =
|
||||
bsaQuery(DownloadScheduler::fetchMostRecentDownloadJobIdIfCompleted);
|
||||
if (downloadJobName.isEmpty()) {
|
||||
logger.atInfo().log("Cannot validate: latest download not found or unfinished.");
|
||||
logger.atInfo().log("Cannot validate: block list downloads not found.");
|
||||
emailSender.sendNotification(
|
||||
"BSA validation does not run: block list downloads not found", "");
|
||||
return null;
|
||||
}
|
||||
logger.atInfo().log("Validating BSA with latest download: %s", downloadJobName.get());
|
||||
|
||||
ImmutableList.Builder<String> errors = new ImmutableList.Builder();
|
||||
errors.addAll(checkBsaLabels(downloadJobName.get()));
|
||||
ImmutableList.Builder<String> errorsBuilder = new ImmutableList.Builder<>();
|
||||
errorsBuilder.addAll(checkBsaLabels(downloadJobName.get()));
|
||||
errorsBuilder.addAll(checkUnblockableDomains());
|
||||
|
||||
emailValidationResults(downloadJobName.get(), errors.build());
|
||||
ImmutableList<String> errors = errorsBuilder.build();
|
||||
|
||||
String resultSummary =
|
||||
errors.isEmpty()
|
||||
? "BSA validation completed: no errors found"
|
||||
: "BSA validation completed with errors";
|
||||
|
||||
emailValidationResults(resultSummary, downloadJobName.get(), errors);
|
||||
logger.atInfo().log("Finished validating BSA with latest download: %s", downloadJobName.get());
|
||||
return null;
|
||||
}
|
||||
|
||||
void emailValidationResults(String job, ImmutableList<String> errors) {
|
||||
// TODO(blocked by go/r3pr/2354): send email
|
||||
void emailValidationResults(String subject, String jobName, ImmutableList<String> results) {
|
||||
String body =
|
||||
String.format("Most recent download is %s.\n\n", jobName) + Joiner.on('\n').join(results);
|
||||
emailSender.sendNotification(subject, body);
|
||||
}
|
||||
|
||||
ImmutableList<String> checkBsaLabels(String jobName) {
|
||||
@@ -129,12 +172,76 @@ public class BsaValidateAction implements Runnable {
|
||||
return errors.build();
|
||||
}
|
||||
|
||||
ImmutableList<String> checkUnblockableDomains() {
|
||||
ImmutableList.Builder<String> errors = new ImmutableList.Builder<>();
|
||||
Optional<UnblockableDomain> lastRead = Optional.empty();
|
||||
ImmutableList<UnblockableDomain> batch;
|
||||
do {
|
||||
batch = Queries.batchReadUnblockableDomains(lastRead, transactionBatchSize);
|
||||
ImmutableMap<String, VKey<Domain>> activeDomains =
|
||||
ForeignKeyUtils.load(
|
||||
Domain.class,
|
||||
batch.stream().map(UnblockableDomain::domainName).collect(toImmutableList()),
|
||||
clock.nowUtc());
|
||||
for (var unblockable : batch) {
|
||||
verifyDomainStillUnblockableWithReason(unblockable, activeDomains).ifPresent(errors::add);
|
||||
}
|
||||
if (!batch.isEmpty()) {
|
||||
lastRead = Optional.of(Iterables.getLast(batch));
|
||||
}
|
||||
} while (batch.size() == transactionBatchSize);
|
||||
return errors.build();
|
||||
}
|
||||
|
||||
Optional<String> verifyDomainStillUnblockableWithReason(
|
||||
UnblockableDomain domain, ImmutableMap<String, VKey<Domain>> activeDomains) {
|
||||
DateTime now = clock.nowUtc();
|
||||
boolean isRegistered = activeDomains.containsKey(domain.domainName());
|
||||
boolean isReserved = isReservedDomain(domain.domainName(), now);
|
||||
InternetDomainName domainName = InternetDomainName.from(domain.domainName());
|
||||
boolean isInvalid = idnChecker.getAllValidIdns(domainName.parts().get(0)).isEmpty();
|
||||
|
||||
Reason expectedReason =
|
||||
isRegistered
|
||||
? Reason.REGISTERED
|
||||
: (isReserved ? Reason.RESERVED : (isInvalid ? Reason.INVALID : null));
|
||||
if (Objects.equals(expectedReason, domain.reason())) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (isRegistered || domain.reason().equals(Reason.REGISTERED)) {
|
||||
if (isStalenessAllowed(isRegistered, activeDomains.get(domain.domainName()))) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
return Optional.of(
|
||||
String.format(
|
||||
"%s: should be %s, found %s",
|
||||
domain.domainName(),
|
||||
expectedReason != null ? expectedReason.name() : "BLOCKABLE",
|
||||
domain.reason()));
|
||||
}
|
||||
|
||||
boolean isStalenessAllowed(boolean isNewDomain, VKey<Domain> domainVKey) {
|
||||
Domain domain = bsaQuery(() -> replicaTm().loadByKey(domainVKey));
|
||||
var now = clock.nowUtc();
|
||||
if (isNewDomain) {
|
||||
return domain.getCreationTime().plus(maxStaleness).isAfter(now);
|
||||
} else {
|
||||
return domain.getDeletionTime().isBefore(now)
|
||||
&& domain.getDeletionTime().plus(maxStaleness).isAfter(now);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns unique labels across all block lists in the download specified by {@code jobName}. */
|
||||
ImmutableSet<String> fetchDownloadedLabels(String jobName) {
|
||||
ImmutableSet.Builder<String> labelsBuilder = new ImmutableSet.Builder<>();
|
||||
for (BlockListType blockListType : BlockListType.values()) {
|
||||
try (Stream<String> lines = gcsClient.readBlockList(jobName, blockListType)) {
|
||||
lines.skip(1).map(BsaValidateAction::parseBlockListLine).forEach(labelsBuilder::add);
|
||||
lines
|
||||
.skip(1)
|
||||
.map(BsaValidateAction::parseBlockListLine)
|
||||
.filter(label -> !idnChecker.getAllValidIdns(label).isEmpty())
|
||||
.forEach(labelsBuilder::add);
|
||||
}
|
||||
}
|
||||
return labelsBuilder.build();
|
||||
@@ -146,10 +253,11 @@ public class BsaValidateAction implements Runnable {
|
||||
Optional<String> lastRead = Optional.empty();
|
||||
do {
|
||||
batch = batchReadBsaLabelText(lastRead, batchSize);
|
||||
batch.forEach(labelsBuilder::add);
|
||||
labelsBuilder.addAll(batch);
|
||||
if (!batch.isEmpty()) {
|
||||
lastRead = Optional.of(Iterables.getLast(batch));
|
||||
}
|
||||
|
||||
} while (batch.size() == batchSize);
|
||||
return labelsBuilder.build();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class IdnChecker {
|
||||
}
|
||||
|
||||
/** Returns all IDNs in which the {@code label} is valid. */
|
||||
ImmutableSet<IdnTableEnum> getAllValidIdns(String label) {
|
||||
public ImmutableSet<IdnTableEnum> getAllValidIdns(String label) {
|
||||
return idnToTlds.keySet().stream()
|
||||
.filter(idnTable -> idnTable.getTable().isValidLabel(label))
|
||||
.collect(toImmutableSet());
|
||||
|
||||
@@ -91,6 +91,7 @@ public class UploadBsaUnavailableDomainsAction implements Runnable {
|
||||
String gcsBucket;
|
||||
|
||||
String apiUrl;
|
||||
BsaEmailSender emailSender;
|
||||
|
||||
google.registry.request.Response response;
|
||||
|
||||
@@ -99,6 +100,7 @@ public class UploadBsaUnavailableDomainsAction implements Runnable {
|
||||
Clock clock,
|
||||
BsaCredential bsaCredential,
|
||||
GcsUtils gcsUtils,
|
||||
BsaEmailSender emailSender,
|
||||
@Config("bsaUnavailableDomainsGcsBucket") String gcsBucket,
|
||||
@Config("bsaUploadUnavailableDomainsUrl") String apiUrl,
|
||||
google.registry.request.Response response) {
|
||||
@@ -107,6 +109,7 @@ public class UploadBsaUnavailableDomainsAction implements Runnable {
|
||||
this.gcsUtils = gcsUtils;
|
||||
this.gcsBucket = gcsBucket;
|
||||
this.apiUrl = apiUrl;
|
||||
this.emailSender = emailSender;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@@ -118,26 +121,36 @@ public class UploadBsaUnavailableDomainsAction implements Runnable {
|
||||
String unavailableDomains = Joiner.on("\n").join(getUnavailableDomains(runTime));
|
||||
if (unavailableDomains.isEmpty()) {
|
||||
logger.atWarning().log("No unavailable domains found; terminating.");
|
||||
emailSender.sendNotification(
|
||||
"BSA daily upload found no domains to upload", "This is unexpected. Please investigate.");
|
||||
} else {
|
||||
uploadToGcs(unavailableDomains, runTime);
|
||||
uploadToBsa(unavailableDomains, runTime);
|
||||
boolean isGcsSuccess = uploadToGcs(unavailableDomains, runTime);
|
||||
boolean isBsaSuccess = uploadToBsa(unavailableDomains, runTime);
|
||||
if (isBsaSuccess && isGcsSuccess) {
|
||||
emailSender.sendNotification("BSA daily upload completed successfully", "");
|
||||
} else {
|
||||
emailSender.sendNotification(
|
||||
"BSA daily upload completed with errors", "Please see logs for details.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Uploads the unavailable domains list to GCS in the unavailable domains bucket. */
|
||||
void uploadToGcs(String unavailableDomains, DateTime runTime) {
|
||||
boolean uploadToGcs(String unavailableDomains, DateTime runTime) {
|
||||
logger.atInfo().log("Uploading unavailable names file to GCS in bucket %s", gcsBucket);
|
||||
BlobId blobId = BlobId.of(gcsBucket, createFilename(runTime));
|
||||
try (OutputStream gcsOutput = gcsUtils.openOutputStream(blobId);
|
||||
Writer osWriter = new OutputStreamWriter(gcsOutput, US_ASCII)) {
|
||||
osWriter.write(unavailableDomains);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
logger.atSevere().withCause(e).log(
|
||||
"Error writing BSA unavailable domains to GCS; skipping to BSA upload ...");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void uploadToBsa(String unavailableDomains, DateTime runTime) {
|
||||
boolean uploadToBsa(String unavailableDomains, DateTime runTime) {
|
||||
try {
|
||||
byte[] gzippedContents = gzipUnavailableDomains(unavailableDomains);
|
||||
String sha512Hash = ByteSource.wrap(gzippedContents).hash(Hashing.sha512()).toString();
|
||||
@@ -174,10 +187,12 @@ public class UploadBsaUnavailableDomainsAction implements Runnable {
|
||||
uploadResponse.code(),
|
||||
uploadResponse.body() == null ? "(none)" : uploadResponse.body().string());
|
||||
}
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
logger.atSevere().withCause(e).log("Error while attempting to upload to BSA, aborting.");
|
||||
response.setStatus(HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
|
||||
response.setPayload("Error while attempting to upload to BSA: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
package google.registry.bsa.api;
|
||||
|
||||
import static google.registry.request.UrlConnectionUtils.getResponseBytes;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.client.http.HttpMethods;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
package google.registry.bsa.api;
|
||||
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_ACCEPTED;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_ACCEPTED;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.api.client.http.HttpMethods;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.bsa.BsaStringUtils.DOMAIN_SPLITTER;
|
||||
import static google.registry.bsa.BsaTransactions.bsaQuery;
|
||||
import static google.registry.persistence.transaction.JpaTransactionManagerImpl.em;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.bsa.api.UnblockableDomain;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -39,17 +41,17 @@ public final class Queries {
|
||||
* JpaTransactionManagerImpl}.
|
||||
*/
|
||||
private static Object detach(Object obj) {
|
||||
em().detach(obj);
|
||||
tm().getEntityManager().detach(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static ImmutableList<String> batchReadBsaLabelText(
|
||||
Optional<String> lastRead, int batchSize) {
|
||||
|
||||
return ImmutableList.copyOf(
|
||||
bsaQuery(
|
||||
() ->
|
||||
em().createQuery(
|
||||
tm().getEntityManager()
|
||||
.createQuery(
|
||||
"SELECT b.label FROM BsaLabel b WHERE b.label > :lastRead ORDER BY b.label",
|
||||
String.class)
|
||||
.setParameter("lastRead", lastRead.orElse(""))
|
||||
@@ -57,10 +59,18 @@ public final class Queries {
|
||||
.getResultList()));
|
||||
}
|
||||
|
||||
public static ImmutableList<UnblockableDomain> batchReadUnblockableDomains(
|
||||
Optional<UnblockableDomain> lastRead, int batchSize) {
|
||||
return batchReadUnblockables(lastRead.map(BsaUnblockableDomain::of), batchSize).stream()
|
||||
.map(BsaUnblockableDomain::toUnblockableDomain)
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
static Stream<BsaUnblockableDomain> queryBsaUnblockableDomainByLabels(
|
||||
ImmutableCollection<String> labels) {
|
||||
return ((Stream<?>)
|
||||
em().createQuery("FROM BsaUnblockableDomain WHERE label in (:labels)")
|
||||
tm().getEntityManager()
|
||||
.createQuery("FROM BsaUnblockableDomain WHERE label in (:labels)")
|
||||
.setParameter("labels", labels)
|
||||
.getResultStream())
|
||||
.map(Queries::detach)
|
||||
@@ -69,7 +79,8 @@ public final class Queries {
|
||||
|
||||
static Stream<BsaLabel> queryBsaLabelByLabels(ImmutableCollection<String> labels) {
|
||||
return ((Stream<?>)
|
||||
em().createQuery("FROM BsaLabel where label in (:labels)")
|
||||
tm().getEntityManager()
|
||||
.createQuery("FROM BsaLabel where label in (:labels)")
|
||||
.setParameter("labels", labels)
|
||||
.getResultStream())
|
||||
.map(Queries::detach)
|
||||
@@ -77,7 +88,8 @@ public final class Queries {
|
||||
}
|
||||
|
||||
static int deleteBsaLabelByLabels(ImmutableCollection<String> labels) {
|
||||
return em().createQuery("DELETE FROM BsaLabel where label IN (:deleted_labels)")
|
||||
return tm().getEntityManager()
|
||||
.createQuery("DELETE FROM BsaLabel where label IN (:deleted_labels)")
|
||||
.setParameter("deleted_labels", labels)
|
||||
.executeUpdate();
|
||||
}
|
||||
@@ -87,7 +99,8 @@ public final class Queries {
|
||||
return ImmutableList.copyOf(
|
||||
bsaQuery(
|
||||
() ->
|
||||
em().createQuery(
|
||||
tm().getEntityManager()
|
||||
.createQuery(
|
||||
"FROM BsaUnblockableDomain d WHERE d.label > :label OR (d.label = :label"
|
||||
+ " AND d.tld > :tld) ORDER BY d.tld, d.label ")
|
||||
.setParameter("label", lastRead.map(d -> d.label).orElse(""))
|
||||
@@ -111,13 +124,14 @@ public final class Queries {
|
||||
"SELECT CONCAT(d.label, '.', d.tld) FROM \"BsaUnblockableDomain\" d "
|
||||
+ "WHERE (d.label, d.tld) IN (%s)",
|
||||
labelTldParis);
|
||||
return ImmutableSet.copyOf(em().createNativeQuery(sql).getResultList());
|
||||
return ImmutableSet.copyOf(tm().getEntityManager().createNativeQuery(sql).getResultList());
|
||||
}
|
||||
|
||||
static ImmutableSet<String> queryNewlyCreatedDomains(
|
||||
ImmutableCollection<String> tlds, DateTime minCreationTime, DateTime now) {
|
||||
return ImmutableSet.copyOf(
|
||||
em().createQuery(
|
||||
tm().getEntityManager()
|
||||
.createQuery(
|
||||
"SELECT domainName FROM Domain WHERE creationTime >= :minCreationTime "
|
||||
+ "AND deletionTime > :now "
|
||||
+ "AND tld in (:tlds)",
|
||||
|
||||
@@ -45,7 +45,6 @@ import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
@@ -195,10 +194,7 @@ public class DelegatedCredentials extends GoogleCredentials {
|
||||
GenericData responseData = response.parseAs(GenericData.class);
|
||||
String accessToken = validateString(responseData, "access_token", PARSE_ERROR_PREFIX);
|
||||
int expiresInSeconds = validateInt32(responseData, "expires_in", PARSE_ERROR_PREFIX);
|
||||
long expiresAtMilliseconds = clock.nowUtc().getMillis() + expiresInSeconds * 1000L;
|
||||
@SuppressWarnings("JavaUtilDate")
|
||||
AccessToken token = new AccessToken(accessToken, new Date(expiresAtMilliseconds));
|
||||
return token;
|
||||
return new AccessToken(accessToken, clock.nowUtc().plusSeconds(expiresInSeconds).toDate());
|
||||
}
|
||||
|
||||
String createAssertion(JsonFactory jsonFactory, long currentTime) throws IOException {
|
||||
@@ -257,8 +253,7 @@ public class DelegatedCredentials extends GoogleCredentials {
|
||||
if (value == null) {
|
||||
throw new IOException(String.format(VALUE_NOT_FOUND_MESSAGE, errorPrefix, key));
|
||||
}
|
||||
if (value instanceof BigDecimal) {
|
||||
BigDecimal bigDecimalValue = (BigDecimal) value;
|
||||
if (value instanceof BigDecimal bigDecimalValue) {
|
||||
return bigDecimalValue.intValueExact();
|
||||
}
|
||||
if (!(value instanceof Integer)) {
|
||||
|
||||
@@ -1488,6 +1488,12 @@ public final class RegistryConfig {
|
||||
return Duration.standardSeconds(config.bsa.domainCreateTxnCommitTimeLagSeconds);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("bsaValidationMaxStaleness")
|
||||
public static Duration provideBsaValidationMaxStaleness(RegistryConfigSettings config) {
|
||||
return Duration.standardSeconds(config.bsa.bsaValidationMaxStalenessSeconds);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("bsaAuthUrl")
|
||||
public static String provideBsaAuthUrl(RegistryConfigSettings config) {
|
||||
|
||||
@@ -275,6 +275,7 @@ public class RegistryConfigSettings {
|
||||
public int bsaMaxNopIntervalHours;
|
||||
public int bsaTxnBatchSize;
|
||||
public int domainCreateTxnCommitTimeLagSeconds;
|
||||
public int bsaValidationMaxStalenessSeconds;
|
||||
public String authUrl;
|
||||
public int authTokenExpirySeconds;
|
||||
public Map<String, String> dataUrls;
|
||||
|
||||
@@ -640,6 +640,9 @@ bsa:
|
||||
# Number of entities (labels and unblockable domains) to process in a single
|
||||
# DB transaction.
|
||||
bsaTxnBatchSize: 1000
|
||||
# Used by `BsaValidateAction`: ignore inconsistencies caused by recent events
|
||||
# in the past. This is roughly equal to two `BsaRefreshAction` runs.
|
||||
bsaValidationMaxStalenessSeconds: 3600
|
||||
|
||||
# Http endpoint for acquiring Auth tokens.
|
||||
authUrl: "https://"
|
||||
|
||||
@@ -23,8 +23,8 @@ import com.google.common.collect.ImmutableSet;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.request.Parameter;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/** Dagger module for the cron package. */
|
||||
@Module
|
||||
|
||||
@@ -31,9 +31,9 @@ import google.registry.dns.DnsUtils.TargetType;
|
||||
import google.registry.dns.writer.DnsWriterZone;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.RequestParameters;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Dagger module for the dns package. */
|
||||
|
||||
@@ -30,7 +30,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.request.RequestParameters.PARAM_TLD;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_ACCEPTED;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_ACCEPTED;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@@ -18,7 +18,7 @@ import static google.registry.dns.DnsUtils.requestDomainDnsRefresh;
|
||||
import static google.registry.dns.RefreshDnsOnHostRenameAction.PATH;
|
||||
import static google.registry.model.EppResourceUtils.getLinkedDomainKeys;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.model.EppResourceUtils;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
|
||||
version="6.0">
|
||||
<!-- Servlets -->
|
||||
|
||||
<!-- Servlet for injected backends actions -->
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
|
||||
version="6.0">
|
||||
<!-- Servlets -->
|
||||
|
||||
<!-- Servlet for injected backends actions -->
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
|
||||
version="6.0">
|
||||
<!-- Servlets -->
|
||||
|
||||
<!-- Servlet for injected frontend actions -->
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
|
||||
version="6.0">
|
||||
<!-- Servlets -->
|
||||
|
||||
<!-- Servlet for injected frontend actions -->
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
|
||||
version="6.0">
|
||||
<!-- Servlets -->
|
||||
|
||||
<!-- Servlet for injected tools actions -->
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
</manual-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
</manual-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
</automatic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
</manual-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
</manual-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</basic-scaling>
|
||||
|
||||
<system-properties>
|
||||
<property name="appengine.use.EE8" value="true"/>
|
||||
<property name="java.util.logging.config.file"
|
||||
value="WEB-INF/logging.properties"/>
|
||||
<property name="google.registry.environment"
|
||||
|
||||
@@ -18,9 +18,9 @@ import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@@ -17,9 +17,9 @@ package google.registry.export;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
|
||||
@@ -20,8 +20,8 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static google.registry.util.RegistrarUtils.normalizeRegistrarId;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@@ -19,8 +19,8 @@ import static com.google.common.base.Strings.emptyToNull;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.request.Parameter;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/** Dagger module for the sheet package. */
|
||||
@Module
|
||||
|
||||
@@ -16,10 +16,10 @@ package google.registry.export.sheet;
|
||||
|
||||
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
|
||||
@@ -58,10 +58,10 @@ import google.registry.request.Parameter;
|
||||
import google.registry.request.RequestParameters;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,9 +17,9 @@ package google.registry.flows;
|
||||
import static google.registry.flows.FlowUtils.marshalWithLenientRetry;
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_AND_CLOSE;
|
||||
import static google.registry.xml.XmlTransformer.prettyPrint;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
|
||||
@@ -18,8 +18,8 @@ import google.registry.request.Action;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.Payload;
|
||||
import google.registry.request.auth.Auth;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* Establishes a transport for EPP+TLS over HTTP. All commands and responses are EPP XML according
|
||||
|
||||
@@ -25,8 +25,8 @@ import google.registry.request.Action;
|
||||
import google.registry.request.Action.Method;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/** Runs EPP commands directly without logging in, verifying an XSRF token from the tool. */
|
||||
@Action(
|
||||
|
||||
@@ -18,9 +18,9 @@ import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/** A metadata class that is a wrapper around {@link HttpSession}. */
|
||||
public class HttpSessionMetadata implements SessionMetadata {
|
||||
|
||||
@@ -34,11 +34,11 @@ import google.registry.request.Header;
|
||||
import google.registry.util.CidrAddressBlock;
|
||||
import google.registry.util.ProxyHttpHeaders;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.InetAddress;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Container and validation for TLS certificate and IP-allow-listing.
|
||||
|
||||
@@ -31,7 +31,6 @@ import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.Date;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
|
||||
@@ -106,12 +105,9 @@ public class CertificateChecker {
|
||||
// These 2 different instances of PublicKey need to be handled separately since their OIDs are
|
||||
// encoded differently. More details on this can be found at
|
||||
// https://stackoverflow.com/questions/49895713/how-to-find-the-matching-curve-name-from-an-ecpublickey.
|
||||
if (key instanceof ECPublicKey) {
|
||||
ECPublicKey ecKey = (ECPublicKey) key;
|
||||
if (key instanceof ECPublicKey ecKey) {
|
||||
params = EC5Util.convertSpec(ecKey.getParams());
|
||||
} else if (key instanceof org.bouncycastle.jce.interfaces.ECPublicKey) {
|
||||
org.bouncycastle.jce.interfaces.ECPublicKey ecKey =
|
||||
(org.bouncycastle.jce.interfaces.ECPublicKey) key;
|
||||
} else if (key instanceof org.bouncycastle.jce.interfaces.ECPublicKey ecKey) {
|
||||
params = ecKey.getParameters();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unrecognized instance of PublicKey.");
|
||||
@@ -148,7 +144,7 @@ public class CertificateChecker {
|
||||
if (!violations.isEmpty()) {
|
||||
String displayMessages =
|
||||
violations.stream()
|
||||
.map(violation -> getViolationDisplayMessage(violation))
|
||||
.map(this::getViolationDisplayMessage)
|
||||
.collect(Collectors.joining("\n"));
|
||||
throw new InsecureCertificateException(violations, displayMessages);
|
||||
}
|
||||
@@ -162,7 +158,7 @@ public class CertificateChecker {
|
||||
ImmutableSet.Builder<CertificateViolation> violations = new ImmutableSet.Builder<>();
|
||||
|
||||
// Check if currently in validity period
|
||||
Date now = clock.nowUtc().toDate();
|
||||
DateTime now = clock.nowUtc();
|
||||
if (DateTimeComparator.getInstance().compare(certificate.getNotAfter(), now) < 0) {
|
||||
violations.add(CertificateViolation.EXPIRED);
|
||||
} else if (DateTimeComparator.getInstance().compare(certificate.getNotBefore(), now) > 0) {
|
||||
@@ -231,13 +227,13 @@ public class CertificateChecker {
|
||||
DateTime lastExpiringNotificationSentDate, String certificateStr) {
|
||||
X509Certificate certificate = getCertificate(certificateStr);
|
||||
DateTime now = clock.nowUtc();
|
||||
// expiration date is one day after lastValidDate
|
||||
// the expiration date is one day after lastValidDate
|
||||
DateTime lastValidDate = new DateTime(certificate.getNotAfter());
|
||||
if (lastValidDate.isBefore(now)) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Client should receive a notification if :
|
||||
* Client should receive a notification if:
|
||||
* 1) client has never received notification (lastExpiringNotificationSentDate is initially
|
||||
* set to START_OF_TIME) and the certificate has entered the expiring period, OR
|
||||
* 2) client has received notification but the interval between now and
|
||||
@@ -254,29 +250,21 @@ public class CertificateChecker {
|
||||
// Yes, we'd rather do this as an instance method on the CertificateViolation enum itself, but
|
||||
// we can't because we need access to configuration (injected as instance variables) which you
|
||||
// can't get in a static enum context.
|
||||
switch (certificateViolation) {
|
||||
case EXPIRED:
|
||||
return "Certificate is expired.";
|
||||
case NOT_YET_VALID:
|
||||
return "Certificate start date is in the future.";
|
||||
case ALGORITHM_CONSTRAINED:
|
||||
return "Certificate key algorithm must be RSA or ECDSA.";
|
||||
case RSA_KEY_LENGTH_TOO_SHORT:
|
||||
return String.format(
|
||||
"RSA key length is too short; the minimum allowed length is %d bits.",
|
||||
this.minimumRsaKeyLength);
|
||||
case VALIDITY_LENGTH_TOO_LONG:
|
||||
return String.format(
|
||||
"Certificate validity period is too long; it must be less than or equal to %d days.",
|
||||
this.maxValidityLengthSchedule.lastEntry().getValue());
|
||||
case INVALID_ECDSA_CURVE:
|
||||
return String.format(
|
||||
"The ECDSA key must use one of these algorithms: %s", allowedEcdsaCurves);
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Unknown CertificateViolation enum value: %s", certificateViolation.name()));
|
||||
}
|
||||
return switch (certificateViolation) {
|
||||
case EXPIRED -> "Certificate is expired.";
|
||||
case NOT_YET_VALID -> "Certificate start date is in the future.";
|
||||
case ALGORITHM_CONSTRAINED -> "Certificate key algorithm must be RSA or ECDSA.";
|
||||
case RSA_KEY_LENGTH_TOO_SHORT ->
|
||||
String.format(
|
||||
"RSA key length is too short; the minimum allowed length is %d bits.",
|
||||
this.minimumRsaKeyLength);
|
||||
case VALIDITY_LENGTH_TOO_LONG ->
|
||||
String.format(
|
||||
"Certificate validity period is too long; it must be less than or equal to %d days.",
|
||||
this.maxValidityLengthSchedule.lastEntry().getValue());
|
||||
case INVALID_ECDSA_CURVE ->
|
||||
String.format("The ECDSA key must use one of these algorithms: %s", allowedEcdsaCurves);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,7 +283,7 @@ public class CertificateChecker {
|
||||
* Gets a suitable end-user-facing display message for this particular certificate violation.
|
||||
*
|
||||
* <p>Note that the {@link CertificateChecker} instance must be passed in because it contains
|
||||
* configuration values (e.g. minimum RSA key length) that go into the error message text.
|
||||
* configuration values (e.g., minimum RSA key length) that go into the error message text.
|
||||
*/
|
||||
public String getDisplayMessage(CertificateChecker certificateChecker) {
|
||||
return certificateChecker.getViolationDisplayMessage(this);
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
package google.registry.groups;
|
||||
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_CONFLICT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND;
|
||||
|
||||
import com.google.api.client.googleapis.json.GoogleJsonError;
|
||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
||||
import com.google.api.services.admin.directory.Directory;
|
||||
import com.google.api.services.admin.directory.model.Group;
|
||||
import com.google.api.services.admin.directory.model.Member;
|
||||
import com.google.api.services.admin.directory.model.Members;
|
||||
import com.google.api.services.directory.Directory;
|
||||
import com.google.api.services.directory.model.Group;
|
||||
import com.google.api.services.directory.model.Member;
|
||||
import com.google.api.services.directory.model.Members;
|
||||
import com.google.api.services.groupssettings.Groupssettings;
|
||||
import com.google.api.services.groupssettings.model.Groups;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user