mirror of
https://github.com/google/nomulus
synced 2026-08-02 13:26:09 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a57c600b6 |
+1
-1
@@ -1,9 +1,9 @@
|
||||
python/
|
||||
node_modules/
|
||||
**/build/
|
||||
**/out/
|
||||
.*/
|
||||
repos/**
|
||||
**/.idea/
|
||||
*.jar
|
||||
!third_party/**/*.jar
|
||||
!/gradle/wrapper/**/*.jar
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 'master' ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ 'master' ]
|
||||
schedule:
|
||||
- cron: '24 4 * * 2'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'java', 'javascript', 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set Java version
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
# ℹ️ 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
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
+5
-19
@@ -4,7 +4,6 @@
|
||||
######################################################################
|
||||
# Java Ignores
|
||||
|
||||
gjf.out
|
||||
*.class
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
@@ -14,6 +13,7 @@ gjf.out
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
!/third_party/**/*.jar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
@@ -31,7 +31,6 @@ tmp/
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
.DS_Store
|
||||
|
||||
# Eclipse Core
|
||||
.project
|
||||
@@ -76,14 +75,9 @@ local.properties
|
||||
autogenerated/
|
||||
|
||||
# IDEA
|
||||
**/*.iml
|
||||
nomulus.iml
|
||||
nomulus.ipr
|
||||
nomulus.iws
|
||||
**/classpath.index
|
||||
|
||||
# Auto-generated java classes by Intellij
|
||||
*/src/main/generated/
|
||||
*/src/test/generated_tests/
|
||||
|
||||
# VScode
|
||||
.vscode
|
||||
@@ -99,13 +93,12 @@ nomulus.iws
|
||||
######################################################################
|
||||
# Gradle Ignores
|
||||
|
||||
# We don't want to ignore the gradle or google-java-format jar files
|
||||
# We don't want to ignore the gradle jar files
|
||||
!/gradle/wrapper/**/*.jar
|
||||
!/java-format/*.jar
|
||||
.gradle/
|
||||
**/build
|
||||
cloudbuild-caches/
|
||||
**/node_modules/**
|
||||
node_modules/**
|
||||
!node_modules/soyutils_usegoog.js
|
||||
/repos/
|
||||
|
||||
# Compiled JS/CSS code
|
||||
@@ -113,10 +106,3 @@ core/**/registrar_bin*.js
|
||||
core/**/registrar_dbg*.js
|
||||
core/**/registrar_bin*.css
|
||||
core/**/registrar_dbg*.css
|
||||
|
||||
# Appengine generated files
|
||||
core/WEB-INF/appengine-generated/*.bin
|
||||
core/WEB-INF/appengine-generated/*.xml
|
||||
|
||||
# jEnv
|
||||
.java-version
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
17
|
||||
@@ -34,6 +34,3 @@ Guy Bensky <guyben@google.com>
|
||||
Weimin Yu <weiminyu@google.com>
|
||||
Shicong Huang <shicong@google.com>
|
||||
Gustav Brodman <gbrodman@google.com>
|
||||
Sarah Botwinick <sarahbot@google.com>
|
||||
Legina Chen <legina@google.com>
|
||||
Rachel Guan <rachelguan@google.com>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Nomulus
|
||||
|
||||
| Internal Build | FOSS Build | License | Code Search |
|
||||
|:--------------:|:----------:|:-------:|:-----------:|
|
||||
|[](https://storage.googleapis.com/domain-registry-kokoro/internal/index.html)|[](https://storage.googleapis.com/domain-registry-kokoro/foss/index.html)|[](https://github.com/google/nomulus/blob/master/LICENSE)|[](https://cs.opensource.google/nomulus/nomulus)|
|
||||
| Internal Build | FOSS Build | LGTM | License | Code Search |
|
||||
|----------------|------------|------|---------|-------------|
|
||||
|[](https://storage.googleapis.com/domain-registry-kokoro/internal/index.html)|[](https://storage.googleapis.com/domain-registry-kokoro/foss/index.html)|[](https://lgtm.com/projects/g/google/nomulus/alerts/)|[](https://github.com/google/nomulus/blob/master/LICENSE)|[](https://sourcegraph.com/github.com/google/nomulus)|
|
||||
|
||||

|
||||
|
||||
@@ -33,7 +33,7 @@ running system:
|
||||
* View the source code for the [GAE app](https://github.com/google/nomulus/tree/master/core/src/main/java/google/registry)
|
||||
and for the [GKE proxy](https://github.com/google/nomulus/tree/master/proxy/src/main/java/google/registry)
|
||||
* [Other docs](https://github.com/google/nomulus/tree/master/docs)
|
||||
* [Javadoc](https://javadoc.nomulus.foo/)
|
||||
* [Javadoc](https://nomulus.foo/javadoc/latest/)
|
||||
* [Nomulus discussion
|
||||
group](https://groups.google.com/forum/#!forum/nomulus-discuss), for any
|
||||
other questions
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
To report a security issue, please use http://g.co/vulnz. We use
|
||||
http://g.co/vulnz for our intake, and do coordination and disclosure here on
|
||||
GitHub (including using GitHub Security Advisory). The Google Security Team will
|
||||
respond within 5 working days of your report on g.co/vulnz.
|
||||
+5
-15
@@ -26,12 +26,15 @@ project.convention.plugins['war'].webAppDirName =
|
||||
apply plugin: 'com.google.cloud.tools.appengine'
|
||||
|
||||
def coreResourcesDir = "${rootDir}/core/build/resources/main"
|
||||
def coreLibsDir = "${rootDir}/core/build/libs"
|
||||
|
||||
// Get the web.xml file for the service.
|
||||
war {
|
||||
webInf {
|
||||
from "../../core/src/main/java/google/registry/env/common/${project.name}/WEB-INF"
|
||||
|
||||
from("${coreResourcesDir}/META-INF/persistence.xml") {
|
||||
into "classes/META-INF"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,18 +42,10 @@ war {
|
||||
from("${coreResourcesDir}/google/registry/ui/html") {
|
||||
include "*.html"
|
||||
}
|
||||
from("${coreLibsDir}") {
|
||||
include "core.jar"
|
||||
into("WEB-INF/lib")
|
||||
}
|
||||
}
|
||||
|
||||
if (project.path == ":services:default") {
|
||||
war {
|
||||
from("${rootDir}/console-webapp/dist/console-webapp") {
|
||||
include "**/*"
|
||||
into("console")
|
||||
}
|
||||
from("${coreResourcesDir}/google/registry/ui") {
|
||||
include "registrar_bin.js"
|
||||
if (environment != "production") {
|
||||
@@ -86,7 +81,7 @@ appengine {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':core', configuration: 'deploy_jar')
|
||||
compile project(':core')
|
||||
}
|
||||
|
||||
// The tools.jar file gets pulled in from the java environment and for some
|
||||
@@ -103,13 +98,8 @@ explodeWar.doLast {
|
||||
file("${it.explodedAppDirectory}/WEB-INF/lib/tools.jar").setWritable(true)
|
||||
}
|
||||
|
||||
appengineDeployAll.finalizedBy ':deployCloudSchedulerAndQueue'
|
||||
rootProject.deploy.dependsOn appengineDeployAll
|
||||
rootProject.stage.dependsOn appengineStage
|
||||
tasks['war'].dependsOn ':console-webapp:buildConsoleWebappProd'
|
||||
tasks['war'].dependsOn ':core:compileProdJS'
|
||||
tasks['war'].dependsOn ':core:processResources'
|
||||
tasks['war'].dependsOn ':core:jar'
|
||||
|
||||
// Impose verification for all of the deployment tasks. We haven't found a
|
||||
// better way to do this other than to apply to each of them independently.
|
||||
|
||||
+68
-271
@@ -20,16 +20,12 @@ buildscript {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
|
||||
// log4j has high-profile security vulnerabilities. It's a transitive
|
||||
// dependency used by Gradle itself during build, and not strictly needed.
|
||||
exclude group: 'org.apache.logging.log4j'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.1'
|
||||
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:3.1.0'
|
||||
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.0.1'
|
||||
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.6.1"
|
||||
classpath 'org.sonatype.aether:aether-api:1.13.1'
|
||||
classpath 'org.sonatype.aether:aether-impl:1.13.1'
|
||||
}
|
||||
@@ -37,31 +33,22 @@ buildscript {
|
||||
|
||||
plugins {
|
||||
// Java static analysis plugins. Keep versions consistent with
|
||||
// ./buildSrc/build.gradle.kts
|
||||
|
||||
// Re-enable when compatible with Gradle 8
|
||||
// id 'nebula.lint' version '16.0.2'
|
||||
id 'net.ltgt.errorprone' version '3.1.0'
|
||||
// ./buildSrc/build.gradle
|
||||
id 'nebula.lint' version '10.4.2'
|
||||
// TODO(weiminyu): consider remove net.ltgt.apt. Gradle 5.2+
|
||||
// has similar functionalities.
|
||||
id 'net.ltgt.apt' version '0.19' apply false
|
||||
id 'net.ltgt.errorprone' version '0.6.1'
|
||||
id 'checkstyle'
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1'
|
||||
id 'com.github.johnrengelman.shadow' version '5.1.0'
|
||||
|
||||
// NodeJs plugin
|
||||
id "com.github.node-gradle.node" version "3.0.1"
|
||||
id "com.moowork.node" version "1.2.0"
|
||||
|
||||
id 'idea'
|
||||
id 'com.diffplug.spotless' version '6.20.0'
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
|
||||
id 'jacoco'
|
||||
id 'com.dorongold.task-tree' version '2.1.0'
|
||||
}
|
||||
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
}
|
||||
|
||||
node {
|
||||
download = false
|
||||
version = "20.10.0"
|
||||
}
|
||||
|
||||
wrapper {
|
||||
@@ -111,8 +98,7 @@ tasks.build.dependsOn(tasks.checkLicense)
|
||||
// Provide defaults for all of the project properties.
|
||||
|
||||
// Only do linting if the build is successful.
|
||||
// Re-enable when compatible with Gradle 8
|
||||
// gradleLint.autoLintAfterFailure = false
|
||||
gradleLint.autoLintAfterFailure = false
|
||||
|
||||
// Paths to main and test sources.
|
||||
ext.projectRootDir = "${rootDir}"
|
||||
@@ -131,7 +117,7 @@ task stage {
|
||||
// App-engine environment configuration. We set up all of the variables in
|
||||
// the root project.
|
||||
|
||||
def environments = ['production', 'sandbox', 'alpha', 'crash', 'qa']
|
||||
def environments = ['production', 'sandbox', 'alpha', 'crash']
|
||||
|
||||
def gcpProject = null
|
||||
|
||||
@@ -165,7 +151,7 @@ def verifyDeploymentParams() {
|
||||
System.err.println('-----------------------------------------------------------------')
|
||||
throw new GradleException('Aborting. See prominent error above.')
|
||||
} else if (gcpProject == null) {
|
||||
def error = 'You must specify -Penvironment={alpha,crash,qa}'
|
||||
def error = 'You must specify -P environment={alpha,crash}'
|
||||
System.err.println("\033[33;1m${error}\033[0m")
|
||||
throw GradleException("Aborting: ${error}")
|
||||
}
|
||||
@@ -178,145 +164,50 @@ rootProject.ext.verifyDeploymentConfig = {
|
||||
|
||||
// Subproject configuration.
|
||||
|
||||
// Alias this since it collides with the closure variable name
|
||||
def allowInsecure = allowInsecureProtocol
|
||||
|
||||
allprojects {
|
||||
// Skip no-op project
|
||||
if (project.name == 'services') return
|
||||
|
||||
repositories {
|
||||
if (!mavenUrl.isEmpty()) {
|
||||
if (rootProject.mavenUrl) {
|
||||
maven {
|
||||
println "Java dependencies: Using repo ${mavenUrl}..."
|
||||
url mavenUrl
|
||||
allowInsecureProtocol = allowInsecure == "true"
|
||||
println "Java dependencies: Using repo $pluginsUrl..."
|
||||
url rootProject.mavenUrl
|
||||
}
|
||||
} else {
|
||||
println "Java dependencies: Using Maven Central..."
|
||||
mavenCentral()
|
||||
google()
|
||||
maven {
|
||||
url "https://packages.confluent.io/maven/"
|
||||
content {
|
||||
includeGroup "io.confluent"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rootProject.enableCrossReferencing.toBoolean()) {
|
||||
gradle.projectsEvaluated {
|
||||
tasks.withType(JavaCompile) {
|
||||
options.fork = true
|
||||
options.forkOptions.executable =
|
||||
file("${System.env.JAVA_HOME}/bin/javac")
|
||||
options.compilerArgs = ["--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"]
|
||||
options.forkOptions.jvmArgs = ["-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
|
||||
"-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
|
||||
"-J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
|
||||
"-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
|
||||
"-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
|
||||
"-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
|
||||
"-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
|
||||
"-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.ext {
|
||||
pyver = { exe ->
|
||||
try {
|
||||
ext.execInBash(
|
||||
exe + " -c 'import sys; print(sys.hexversion)' 2>/dev/null",
|
||||
"/") as Integer
|
||||
} catch (org.gradle.process.internal.ExecException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the path to a usable python3 executable.
|
||||
getPythonExecutable = {
|
||||
// Find a python version greater than 3.7.3 (this is somewhat arbitrary, we
|
||||
// know we'd like at least 3.6, but 3.7.3 is the latest that ships with
|
||||
// Debian so it seems like that should be available anywhere).
|
||||
def MIN_PY_VER = 0x3070300
|
||||
if (pyver('python') >= MIN_PY_VER) {
|
||||
return 'python'
|
||||
} else if (pyver('/usr/bin/python3') >= MIN_PY_VER) {
|
||||
return '/usr/bin/python3'
|
||||
} else {
|
||||
throw new GradleException("No usable Python version found (build " +
|
||||
"requires at least python 3.7.3)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task runPresubmits(type: Exec) {
|
||||
|
||||
executable '/usr/bin/python'
|
||||
args('config/presubmits.py')
|
||||
|
||||
doFirst {
|
||||
executable getPythonExecutable()
|
||||
}
|
||||
}
|
||||
|
||||
def javadocSource = []
|
||||
def javadocClasspath = []
|
||||
def javadocDependentTasks = []
|
||||
|
||||
subprojects {
|
||||
// Skip no-op project
|
||||
if (project.name == 'services') return
|
||||
|
||||
ext.createUberJar = {
|
||||
taskName,
|
||||
binaryName,
|
||||
mainClass,
|
||||
List<Configuration> configs = [project.configurations.runtimeClasspath],
|
||||
List<SourceSetOutput> srcOutput = [project.sourceSets.main.output],
|
||||
List<String> excludes = [] ->
|
||||
ext.createUberJar = { taskName, binaryName, mainClass ->
|
||||
project.tasks.create(
|
||||
taskName, com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
|
||||
taskName, com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
|
||||
mergeServiceFiles()
|
||||
archiveBaseName = binaryName
|
||||
if (mainClass != '') {
|
||||
manifest {
|
||||
attributes 'Main-Class': mainClass
|
||||
}
|
||||
baseName = binaryName
|
||||
manifest {
|
||||
attributes 'Main-Class': mainClass
|
||||
}
|
||||
zip64 = true
|
||||
archiveClassifier = ''
|
||||
classifier = ''
|
||||
archiveVersion = ''
|
||||
configurations = configs
|
||||
from srcOutput
|
||||
configurations = [project.configurations.runtimeClasspath]
|
||||
from project.sourceSets.main.output
|
||||
// Excludes signature files that accompany some dependency jars, like
|
||||
// bonuncycastle. If they are present, only classes from those signed jars are
|
||||
// made available to the class loader.
|
||||
// see https://discuss.gradle.org/t/signing-a-custom-gradle-plugin-thats-downloaded-by-the-build-system-from-github/1365
|
||||
exclude "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA"
|
||||
exclude excludes
|
||||
|
||||
// We do seem to get duplicates when constructing uber-jars, either
|
||||
// this is a product of something in gradle 7 or a product of gradle 7
|
||||
// now giving an error about them when it didn't previously.
|
||||
duplicatesStrategy DuplicatesStrategy.WARN
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,44 +221,23 @@ subprojects {
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
if (rootProject.enableDependencyLocking.toBoolean()
|
||||
&& project.name != 'integration') {
|
||||
// The ':integration' project runs server/schema integration tests using
|
||||
// dynamically specified jars with no transitive dependency. Therefore
|
||||
// dependency-locking does not make sense. Furthermore, during
|
||||
// evaluation it resolves the 'testRuntimeOnly' configuration, making it
|
||||
// immutable. Locking activation would trigger an invalid operation
|
||||
// exception.
|
||||
//
|
||||
// For all other projects, due to problem with the gradle-license-report
|
||||
// plugin, the dependencyLicenseReport configuration must opt out of
|
||||
// dependency-locking. See dependency_lic.gradle for the reason why.
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
// Lock application dependencies except for the gradle-license-report
|
||||
// plugin. See dependency_lic.gradle for the reason why.
|
||||
//
|
||||
// To selectively activate dependency locking without hardcoding them
|
||||
// in the 'configurations' block, the following code must run after
|
||||
// project evaluation, when all configurations have been created.
|
||||
configurations.each {
|
||||
if (it.name != 'dependencyLicenseReport' && it.name != 'integration') {
|
||||
if (it.name != 'dependencyLicenseReport') {
|
||||
it.resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// '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")
|
||||
}
|
||||
}
|
||||
|
||||
def services = [':services:default',
|
||||
':services:backend',
|
||||
':services:bsa',
|
||||
':services:tools',
|
||||
':services:pubapi']
|
||||
|
||||
@@ -382,15 +252,16 @@ subprojects {
|
||||
|
||||
apply from: "${rootDir.path}/java_common.gradle"
|
||||
|
||||
// When changing Java version here, be sure to update BEAM Java runtime:
|
||||
// search for `flex-template-base-image` and update the parameter value.
|
||||
// There are at least two instances, one in core/build.gradle, one in
|
||||
// release/stage_beam_pipeline.sh
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
if (project.name == 'third_party') return
|
||||
|
||||
project.tasks.test.dependsOn runPresubmits
|
||||
|
||||
// Path to code generated with annotation processors. Note that this path is
|
||||
// chosen by the 'net.ltgt.apt' plugin, and may change if IDE-specific plugins
|
||||
// are applied, e.g., 'idea' or 'eclipse'
|
||||
def aptGeneratedDir = "${project.buildDir}/generated/source/apt/main"
|
||||
def aptGeneratedTestDir = "${project.buildDir}/generated/source/apt/test"
|
||||
|
||||
def commonlyExcludedResources = ['**/*.java', '**/BUILD']
|
||||
|
||||
project.ext.javaDir = "${project.projectDir}/src/main/java"
|
||||
@@ -399,12 +270,18 @@ subprojects {
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDirs += aptGeneratedDir
|
||||
}
|
||||
resources {
|
||||
srcDirs += project.ext.javaDir
|
||||
exclude commonlyExcludedResources
|
||||
}
|
||||
}
|
||||
test {
|
||||
java {
|
||||
srcDirs += aptGeneratedTestDir
|
||||
}
|
||||
resources {
|
||||
srcDirs += project.ext.javaTestDir
|
||||
exclude commonlyExcludedResources
|
||||
@@ -412,13 +289,18 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
// No need to produce javadoc for the docs subproject, which has no APIs to
|
||||
// expose to users.
|
||||
if (project.name != 'docs') {
|
||||
javadocSource << project.sourceSets.main.allJava
|
||||
javadocClasspath << project.sourceSets.main.runtimeClasspath
|
||||
javadocClasspath << "${buildDir}/generated/sources/annotationProcessor/java/main"
|
||||
javadocDependentTasks << project.tasks.compileJava
|
||||
if (['util', 'proxy', 'core', 'prober', 'db'].contains(project.name)) return
|
||||
|
||||
// TODO(weiminyu): investigate if the block below is still needed
|
||||
ext.relativePath = "google/registry/${project.name}"
|
||||
|
||||
sourceSets.each {
|
||||
it.java {
|
||||
include "${project.relativePath}/"
|
||||
}
|
||||
it.resources {
|
||||
include "${project.relativePath}/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,14 +381,6 @@ def createGetBuildSrcDirectDepsTask(outputFileName) {
|
||||
|
||||
rootProject.ext {
|
||||
invokeJavaDiffFormatScript = { action ->
|
||||
def javaHome = project.findProperty('org.gradle.java.home')
|
||||
def javaBin
|
||||
if (javaHome != null) {
|
||||
javaBin = "$javaHome/bin/java"
|
||||
} else {
|
||||
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"
|
||||
@@ -514,10 +388,9 @@ rootProject.ext {
|
||||
? "${rootDir}/.."
|
||||
: rootDir
|
||||
def formatDiffScript = "${scriptDir}/google-java-format-git-diff.sh"
|
||||
def pythonExe = getPythonExecutable()
|
||||
|
||||
return ext.execInBash(
|
||||
"JAVA=${javaBin} PYTHON=${pythonExe} ${formatDiffScript} ${action}", "${workingDir}")
|
||||
"${formatDiffScript} ${action}", "${workingDir}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,23 +398,18 @@ rootProject.ext {
|
||||
// Note that this task checks modified Java files in the entire repository.
|
||||
task javaIncrementalFormatCheck {
|
||||
doLast {
|
||||
// We can only do this in a git tree.
|
||||
if (new File("${rootDir}/.git").exists()) {
|
||||
def checkResult = invokeJavaDiffFormatScript("check")
|
||||
if (checkResult == 'true') {
|
||||
throw new IllegalStateException(
|
||||
"Some Java files need to be reformatted. You may use the "
|
||||
+ "'javaIncrementalFormatDryRun' task to review\n "
|
||||
+ "the changes, or the 'javaIncrementalFormatApply' task "
|
||||
+ "to reformat.")
|
||||
} else if (checkResult != 'false') {
|
||||
throw new RuntimeException(
|
||||
"Failed to invoke format check script:\n" + checkResult)
|
||||
}
|
||||
println("Incremental Java format check ok.")
|
||||
} else {
|
||||
println("Omitting format check: not in a git directory.")
|
||||
def checkResult = invokeJavaDiffFormatScript("check")
|
||||
if (checkResult == 'true') {
|
||||
throw new IllegalStateException(
|
||||
"Some Java files need to be reformatted. You may use the "
|
||||
+ "'javaIncrementalFormatDryRun' task to review\n "
|
||||
+ "the changes, or the 'javaIncrementalFormatApply' task "
|
||||
+ "to reformat.")
|
||||
} else if (checkResult != 'false') {
|
||||
throw new RuntimeException(
|
||||
"Failed to invoke format check script:\n" + checkResult)
|
||||
}
|
||||
println("Incremental Java format check ok.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,7 +420,6 @@ task javaIncrementalFormatDryRun {
|
||||
println("${invokeJavaDiffFormatScript("show")}")
|
||||
}
|
||||
}
|
||||
tasks.build.dependsOn(tasks.javaIncrementalFormatCheck)
|
||||
|
||||
// Checks if modified lines in Java source files need reformatting.
|
||||
// Note that this task processes modified Java files in the entire repository.
|
||||
@@ -562,74 +429,4 @@ task javaIncrementalFormatApply {
|
||||
}
|
||||
}
|
||||
|
||||
task javadoc(type: Javadoc) {
|
||||
source javadocSource
|
||||
// Java 11.0.17 has the following bug that affects annotation handling on
|
||||
// package-info.java:
|
||||
// https://bugs.openjdk.org/browse/JDK-8222091
|
||||
exclude "**/package-info.java"
|
||||
classpath = files(javadocClasspath)
|
||||
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)
|
||||
options.addBooleanOption("-allow-script-in-comments",true)
|
||||
options.tags = ["type:a:Generic Type",
|
||||
"error:a:Expected Error",
|
||||
"invariant:a:Guaranteed Property"]
|
||||
}
|
||||
|
||||
tasks.build.dependsOn(tasks.javadoc)
|
||||
|
||||
// Task for doing development on core Nomulus.
|
||||
// This fixes code formatting automatically as necessary, builds and tests the
|
||||
// core Nomulus codebase, and runs all presubmits.
|
||||
task coreDev {
|
||||
dependsOn 'javaIncrementalFormatApply'
|
||||
dependsOn 'console-webapp:applyFormatting'
|
||||
dependsOn 'javadoc'
|
||||
dependsOn 'checkDependenciesDotGradle'
|
||||
dependsOn 'checkLicense'
|
||||
dependsOn ':console-webapp:runConsoleWebappUnitTests'
|
||||
dependsOn ':core:check'
|
||||
dependsOn 'assemble'
|
||||
}
|
||||
|
||||
javadocDependentTasks.each { tasks.javadoc.dependsOn(it) }
|
||||
|
||||
// Runs the script, which deploys cloud scheduler and tasks based on the config
|
||||
task deployCloudSchedulerAndQueue {
|
||||
doLast {
|
||||
def env = environment
|
||||
if (!prodOrSandboxEnv) {
|
||||
exec {
|
||||
workingDir "${rootDir}/release/builder/"
|
||||
commandLine 'go', 'run',
|
||||
"./deployCloudSchedulerAndQueue.go",
|
||||
"${rootDir}/core/src/main/java/google/registry/config/files/nomulus-config-${env}.yaml",
|
||||
"${rootDir}/core/src/main/java/google/registry/env/${env}/default/WEB-INF/cloud-scheduler-tasks.xml",
|
||||
"domain-registry-${env}"
|
||||
}
|
||||
exec {
|
||||
workingDir "${rootDir}/release/builder/"
|
||||
commandLine 'go', 'run',
|
||||
"./deployCloudSchedulerAndQueue.go",
|
||||
"${rootDir}/core/src/main/java/google/registry/config/files/nomulus-config-${env}.yaml",
|
||||
"${rootDir}/core/src/main/java/google/registry/env/common/default/WEB-INF/cloud-tasks-queue.xml",
|
||||
"domain-registry-${env}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// disable javadoc in subprojects, these will break because they don't have
|
||||
// the correct classpath (see above).
|
||||
gradle.taskGraph.whenReady { graph ->
|
||||
graph.getAllTasks().each { task ->
|
||||
def subprojectJavadoc = (task.path =~ /:.+:javadoc/)
|
||||
if (subprojectJavadoc) {
|
||||
println "Skipping ${task.path} for javadoc (only root javadoc works)"
|
||||
task.enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
tasks.build.dependsOn(tasks.javaIncrementalFormatCheck)
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
buildscript {
|
||||
if (project.enableDependencyLocking.toBoolean()) {
|
||||
// Lock buildscript dependencies.
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
// Java static analysis plugins. Keep versions consistent with ../build.gradle
|
||||
id 'nebula.lint' version '10.4.2'
|
||||
// Config helper for annotation processors such as AutoValue and Dagger.
|
||||
// Ensures that source code is generated at an appropriate location.
|
||||
id 'net.ltgt.apt' version '0.19' apply false
|
||||
id 'net.ltgt.errorprone' version '0.6.1'
|
||||
id 'checkstyle'
|
||||
id 'com.diffplug.gradle.spotless' version '3.18.0'
|
||||
}
|
||||
|
||||
if (rootProject.enableDependencyLocking.toBoolean()) {
|
||||
// Lock application dependencies.
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
if (project.ext.properties.mavenUrl == null) {
|
||||
println "Plugin dependencies: Using Maven central..."
|
||||
mavenCentral()
|
||||
} else {
|
||||
maven {
|
||||
println "Plugin dependencies: Using repo ${mavenUrl}..."
|
||||
url mavenUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply from: '../dependencies.gradle'
|
||||
apply from: '../dependency_lic.gradle'
|
||||
apply from: '../java_common.gradle'
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDirs += "${project.buildDir}/generated/source/apt/main"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
configDir file('../config/checkstyle')
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def deps = dependencyMap
|
||||
compile deps['com.google.auth:google-auth-library-credentials']
|
||||
compile deps['com.google.auth:google-auth-library-oauth2-http']
|
||||
compile deps['com.google.cloud:google-cloud-core']
|
||||
compile deps['com.google.guava:guava']
|
||||
compile deps['com.google.auto.value:auto-value-annotations']
|
||||
compile deps['com.google.cloud:google-cloud-storage']
|
||||
compile deps['org.apache.commons:commons-text']
|
||||
compile deps['com.google.template:soy']
|
||||
annotationProcessor deps['com.google.auto.value:auto-value']
|
||||
testCompile deps['com.google.truth:truth']
|
||||
testCompile deps['com.google.truth.extensions:truth-java8-extension']
|
||||
testCompile deps['junit:junit']
|
||||
testCompile deps['org.mockito:mockito-core']
|
||||
}
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << "-Xlint:unchecked"
|
||||
}
|
||||
}
|
||||
|
||||
task exportDependencies {
|
||||
def outputFileProperty = 'dependencyExportFile'
|
||||
def output = project.hasProperty(outputFileProperty)
|
||||
? new PrintStream(
|
||||
new File(project.getProperty(outputFileProperty)))
|
||||
: System.out
|
||||
|
||||
doLast {
|
||||
project.configurations.all {
|
||||
it.dependencies.findAll {
|
||||
it.group != null
|
||||
}.each {
|
||||
output.println("${it.group}:${it.name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +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["com.google.truth.extensions:truth-java8-extension"]!!)
|
||||
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,106 +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.14.2=buildScriptClasspath,compileClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.14.2=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.2.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.22.6-alpha=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.22.6-alpha=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.22.6-alpha=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.22.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.17.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api:api-common:2.14.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api:gax-grpc:2.31.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api:gax-httpjson:2.31.0=buildScriptClasspath,compileClasspath
|
||||
com.google.api:gax:2.31.0=buildScriptClasspath,compileClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20230301-2.0.0=buildScriptClasspath,compileClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.19.0=buildScriptClasspath,compileClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.19.0=buildScriptClasspath,compileClasspath
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor
|
||||
com.google.auto.value:auto-value-annotations:1.10.1=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.21.0=buildScriptClasspath,compileClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.21.0=buildScriptClasspath,compileClasspath
|
||||
com.google.cloud:google-cloud-core:2.21.0=buildScriptClasspath,compileClasspath
|
||||
com.google.cloud:google-cloud-storage:2.22.6=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,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.43.3=buildScriptClasspath,compileClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.43.3=buildScriptClasspath,compileClasspath
|
||||
com.google.http-client:google-http-client-gson:1.43.3=buildScriptClasspath,compileClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.43.3=buildScriptClasspath,compileClasspath
|
||||
com.google.http-client:google-http-client:1.43.3=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.34.1=buildScriptClasspath,compileClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.23.2=buildScriptClasspath,compileClasspath
|
||||
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor
|
||||
com.google.protobuf:protobuf-java:3.23.2=buildScriptClasspath,compileClasspath
|
||||
com.google.re2j:re2j:1.6=buildScriptClasspath
|
||||
com.google.template:soy:2021-02-01=buildScriptClasspath,compileClasspath
|
||||
com.ibm.icu:icu4j:57.1=buildScriptClasspath,compileClasspath
|
||||
commons-codec:commons-codec:1.15=buildScriptClasspath,compileClasspath
|
||||
commons-logging:commons-logging:1.2=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.55.3=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-api:1.55.3=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-auth:1.55.3=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-context:1.55.3=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-core:1.55.3=buildScriptClasspath
|
||||
io.grpc:grpc-googleapis:1.55.3=buildScriptClasspath
|
||||
io.grpc:grpc-grpclb:1.55.3=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-netty-shaded:1.55.3=buildScriptClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.55.3=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-protobuf:1.55.3=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-rls:1.55.3=buildScriptClasspath
|
||||
io.grpc:grpc-services:1.55.3=buildScriptClasspath
|
||||
io.grpc:grpc-stub:1.55.3=buildScriptClasspath,compileClasspath
|
||||
io.grpc:grpc-xds:1.55.3=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.26.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.41.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 +1 @@
|
||||
pluginsUrl=https://plugins.gradle.org/m2/
|
||||
allowInsecureProtocol=
|
||||
enableDependencyLocking=true
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# 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.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto.value:auto-value:1.6.3
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
@@ -0,0 +1,68 @@
|
||||
# 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.
|
||||
cglib:cglib-nodep:3.2.2
|
||||
com.diffplug.durian:durian-collect:1.2.0
|
||||
com.diffplug.durian:durian-core:1.2.0
|
||||
com.diffplug.durian:durian-io:1.2.0
|
||||
com.diffplug.gradle.spotless:com.diffplug.gradle.spotless.gradle.plugin:3.18.0
|
||||
com.diffplug.spotless:spotless-lib-extra:1.18.0
|
||||
com.diffplug.spotless:spotless-lib:1.18.0
|
||||
com.diffplug.spotless:spotless-plugin-gradle:3.18.0
|
||||
com.google.guava:guava:19.0
|
||||
com.googlecode.concurrent-trees:concurrent-trees:2.6.1
|
||||
com.googlecode.javaewah:JavaEWAH:1.1.6
|
||||
com.jcraft:jsch:0.1.54
|
||||
com.jcraft:jzlib:1.1.1
|
||||
com.netflix.nebula:gradle-lint-plugin:10.4.2
|
||||
com.netflix.nebula:nebula-gradle-interop:1.0.11
|
||||
com.netflix.nebula:nebula-test:7.3.0
|
||||
commons-codec:commons-codec:1.9
|
||||
commons-io:commons-io:2.5
|
||||
commons-lang:commons-lang:2.6
|
||||
commons-logging:commons-logging:1.2
|
||||
javax.inject:javax.inject:1
|
||||
junit:junit:4.12
|
||||
log4j:log4j:1.2.14
|
||||
nebula.lint:nebula.lint.gradle.plugin:10.4.2
|
||||
net.ltgt.apt:net.ltgt.apt.gradle.plugin:0.19
|
||||
net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:0.6.1
|
||||
net.ltgt.gradle:gradle-apt-plugin:0.19
|
||||
net.ltgt.gradle:gradle-errorprone-plugin:0.6.1
|
||||
org.apache.ant:ant-antlr:1.8.4
|
||||
org.apache.ant:ant-junit:1.8.4
|
||||
org.apache.ant:ant-launcher:1.8.4
|
||||
org.apache.ant:ant:1.8.4
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.httpcomponents:httpclient:4.5.2
|
||||
org.apache.httpcomponents:httpcore:4.4.4
|
||||
org.apache.maven:maven-artifact:3.6.2
|
||||
org.apache.maven:maven-builder-support:3.6.2
|
||||
org.apache.maven:maven-model-builder:3.6.2
|
||||
org.apache.maven:maven-model:3.6.2
|
||||
org.codehaus.gpars:gpars:1.2.1
|
||||
org.codehaus.groovy:groovy-all:2.4.9
|
||||
org.codehaus.groovy:groovy-ant:2.1.8
|
||||
org.codehaus.groovy:groovy-groovydoc:2.1.8
|
||||
org.codehaus.groovy:groovy-templates:2.1.8
|
||||
org.codehaus.groovy:groovy-xml:2.4.7
|
||||
org.codehaus.groovy:groovy:2.4.7
|
||||
org.codehaus.jsr166-mirror:jsr166y:1.7.0
|
||||
org.codehaus.plexus:plexus-interpolation:1.25
|
||||
org.codehaus.plexus:plexus-utils:3.2.1
|
||||
org.codenarc:CodeNarc:0.25.2
|
||||
org.eclipse.jdt:core:3.1.1
|
||||
org.eclipse.jgit:org.eclipse.jgit:5.0.1.201806211838-r
|
||||
org.eclipse.sisu:org.eclipse.sisu.inject:0.3.3
|
||||
org.gmetrics:GMetrics:0.7
|
||||
org.hamcrest:hamcrest-core:1.3
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.50
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.3.50
|
||||
org.jetbrains:annotations:13.0
|
||||
org.multiverse:multiverse-core:0.7.0
|
||||
org.objenesis:objenesis:2.4
|
||||
org.ow2.asm:asm:7.0
|
||||
org.slf4j:slf4j-api:1.7.2
|
||||
org.spockframework:spock-core:1.1-groovy-2.4-rc-4
|
||||
@@ -0,0 +1,18 @@
|
||||
# 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.
|
||||
antlr:antlr:2.7.7
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.2.0
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.puppycrawl.tools:checkstyle:8.17
|
||||
commons-beanutils:commons-beanutils:1.9.3
|
||||
commons-collections:commons-collections:3.2.2
|
||||
info.picocli:picocli:3.9.0
|
||||
net.sf.saxon:Saxon-HE:9.9.0-2
|
||||
org.antlr:antlr4-runtime:4.7.2
|
||||
org.checkerframework:checker-qual:2.5.2
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
@@ -0,0 +1,61 @@
|
||||
# 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
|
||||
args4j:args4j:2.0.23
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.27.0
|
||||
com.google.api.grpc:proto-google-common-protos:1.12.0
|
||||
com.google.api.grpc:proto-google-iam-v1:0.12.0
|
||||
com.google.api:api-common:1.7.0
|
||||
com.google.api:gax-httpjson:0.52.1
|
||||
com.google.api:gax:1.35.1
|
||||
com.google.apis:google-api-services-storage:v1-rev20181013-1.27.0
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.cloud:google-cloud-core-http:1.59.0
|
||||
com.google.cloud:google-cloud-core:1.59.0
|
||||
com.google.cloud:google-cloud-storage:1.59.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.http-client:google-http-client-appengine:1.27.0
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.annotation:javax.annotation-api:1.2
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.json:json:20160212
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
org.ow2.asm:asm-tree:6.0
|
||||
org.ow2.asm:asm-util:6.0
|
||||
org.ow2.asm:asm:6.0
|
||||
org.threeten:threetenbp:1.3.3
|
||||
@@ -0,0 +1,61 @@
|
||||
# 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
|
||||
args4j:args4j:2.0.23
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.27.0
|
||||
com.google.api.grpc:proto-google-common-protos:1.12.0
|
||||
com.google.api.grpc:proto-google-iam-v1:0.12.0
|
||||
com.google.api:api-common:1.7.0
|
||||
com.google.api:gax-httpjson:0.52.1
|
||||
com.google.api:gax:1.35.1
|
||||
com.google.apis:google-api-services-storage:v1-rev20181013-1.27.0
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.cloud:google-cloud-core-http:1.59.0
|
||||
com.google.cloud:google-cloud-core:1.59.0
|
||||
com.google.cloud:google-cloud-storage:1.59.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.http-client:google-http-client-appengine:1.27.0
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.annotation:javax.annotation-api:1.2
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.json:json:20160212
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
org.ow2.asm:asm-tree:6.0
|
||||
org.ow2.asm:asm-util:6.0
|
||||
org.ow2.asm:asm:6.0
|
||||
org.threeten:threetenbp:1.3.3
|
||||
@@ -0,0 +1,4 @@
|
||||
# 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.google.errorprone:javac:9+181-r4173-1
|
||||
@@ -0,0 +1,4 @@
|
||||
# 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.
|
||||
org.jacoco:org.jacoco.agent:0.8.4
|
||||
@@ -0,0 +1,11 @@
|
||||
# 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.
|
||||
org.jacoco:org.jacoco.agent:0.8.4
|
||||
org.jacoco:org.jacoco.ant:0.8.4
|
||||
org.jacoco:org.jacoco.core:0.8.4
|
||||
org.jacoco:org.jacoco.report:0.8.4
|
||||
org.ow2.asm:asm-analysis:7.1
|
||||
org.ow2.asm:asm-commons:7.1
|
||||
org.ow2.asm:asm-tree:7.1
|
||||
org.ow2.asm:asm:7.1
|
||||
@@ -0,0 +1,61 @@
|
||||
# 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
|
||||
args4j:args4j:2.0.23
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.27.0
|
||||
com.google.api.grpc:proto-google-common-protos:1.12.0
|
||||
com.google.api.grpc:proto-google-iam-v1:0.12.0
|
||||
com.google.api:api-common:1.7.0
|
||||
com.google.api:gax-httpjson:0.52.1
|
||||
com.google.api:gax:1.35.1
|
||||
com.google.apis:google-api-services-storage:v1-rev20181013-1.27.0
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.cloud:google-cloud-core-http:1.59.0
|
||||
com.google.cloud:google-cloud-core:1.59.0
|
||||
com.google.cloud:google-cloud-storage:1.59.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.http-client:google-http-client-appengine:1.27.0
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.template:soy:2018-03-14
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.annotation:javax.annotation-api:1.2
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.json:json:20160212
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
org.ow2.asm:asm-tree:6.0
|
||||
org.ow2.asm:asm-util:6.0
|
||||
org.ow2.asm:asm:6.0
|
||||
org.threeten:threetenbp:1.3.3
|
||||
@@ -0,0 +1,24 @@
|
||||
# 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.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
@@ -0,0 +1,71 @@
|
||||
# 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
|
||||
args4j:args4j:2.0.23
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.27.0
|
||||
com.google.api.grpc:proto-google-common-protos:1.12.0
|
||||
com.google.api.grpc:proto-google-iam-v1:0.12.0
|
||||
com.google.api:api-common:1.7.0
|
||||
com.google.api:gax-httpjson:0.52.1
|
||||
com.google.api:gax:1.35.1
|
||||
com.google.apis:google-api-services-storage:v1-rev20181013-1.27.0
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.cloud:google-cloud-core-http:1.59.0
|
||||
com.google.cloud:google-cloud-core:1.59.0
|
||||
com.google.cloud:google-cloud-storage:1.59.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.http-client:google-http-client-appengine:1.27.0
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.template:soy:2018-03-14
|
||||
com.google.truth.extensions:truth-java8-extension:1.0
|
||||
com.google.truth:truth:1.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.annotation:javax.annotation-api:1.2
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.9.7
|
||||
net.bytebuddy:byte-buddy:1.9.7
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.hamcrest:hamcrest-core:1.3
|
||||
org.json:json:20160212
|
||||
org.mockito:mockito-core:2.25.0
|
||||
org.objenesis:objenesis:2.6
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
org.ow2.asm:asm-tree:6.0
|
||||
org.ow2.asm:asm-util:6.0
|
||||
org.ow2.asm:asm:6.0
|
||||
org.threeten:threetenbp:1.3.3
|
||||
@@ -0,0 +1,71 @@
|
||||
# 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
|
||||
args4j:args4j:2.0.23
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.27.0
|
||||
com.google.api.grpc:proto-google-common-protos:1.12.0
|
||||
com.google.api.grpc:proto-google-iam-v1:0.12.0
|
||||
com.google.api:api-common:1.7.0
|
||||
com.google.api:gax-httpjson:0.52.1
|
||||
com.google.api:gax:1.35.1
|
||||
com.google.apis:google-api-services-storage:v1-rev20181013-1.27.0
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.cloud:google-cloud-core-http:1.59.0
|
||||
com.google.cloud:google-cloud-core:1.59.0
|
||||
com.google.cloud:google-cloud-storage:1.59.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.http-client:google-http-client-appengine:1.27.0
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.template:soy:2018-03-14
|
||||
com.google.truth.extensions:truth-java8-extension:1.0
|
||||
com.google.truth:truth:1.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.annotation:javax.annotation-api:1.2
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.9.7
|
||||
net.bytebuddy:byte-buddy:1.9.7
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.hamcrest:hamcrest-core:1.3
|
||||
org.json:json:20160212
|
||||
org.mockito:mockito-core:2.25.0
|
||||
org.objenesis:objenesis:2.6
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
org.ow2.asm:asm-tree:6.0
|
||||
org.ow2.asm:asm-util:6.0
|
||||
org.ow2.asm:asm:6.0
|
||||
org.threeten:threetenbp:1.3.3
|
||||
@@ -0,0 +1,71 @@
|
||||
# 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
|
||||
args4j:args4j:2.0.23
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9
|
||||
com.google.api-client:google-api-client:1.27.0
|
||||
com.google.api.grpc:proto-google-common-protos:1.12.0
|
||||
com.google.api.grpc:proto-google-iam-v1:0.12.0
|
||||
com.google.api:api-common:1.7.0
|
||||
com.google.api:gax-httpjson:0.52.1
|
||||
com.google.api:gax:1.35.1
|
||||
com.google.apis:google-api-services-storage:v1-rev20181013-1.27.0
|
||||
com.google.auth:google-auth-library-credentials:0.16.1
|
||||
com.google.auth:google-auth-library-oauth2-http:0.16.1
|
||||
com.google.auto.value:auto-value-annotations:1.6.3
|
||||
com.google.cloud:google-cloud-core-http:1.59.0
|
||||
com.google.cloud:google-cloud-core:1.59.0
|
||||
com.google.cloud:google-cloud-storage:1.59.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.code.gson:gson:2.7
|
||||
com.google.common.html.types:types:1.0.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.gwt:gwt-user:2.8.0-beta1
|
||||
com.google.http-client:google-http-client-appengine:1.27.0
|
||||
com.google.http-client:google-http-client-jackson2:1.30.1
|
||||
com.google.http-client:google-http-client:1.30.1
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0
|
||||
com.google.inject:guice:4.1.0
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.oauth-client:google-oauth-client:1.27.0
|
||||
com.google.protobuf:protobuf-java-util:3.6.1
|
||||
com.google.protobuf:protobuf-java:3.6.1
|
||||
com.google.template:soy:2018-03-14
|
||||
com.google.truth.extensions:truth-java8-extension:1.0
|
||||
com.google.truth:truth:1.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
com.ibm.icu:icu4j:57.1
|
||||
commons-codec:commons-codec:1.11
|
||||
commons-logging:commons-logging:1.2
|
||||
io.grpc:grpc-context:1.19.0
|
||||
io.opencensus:opencensus-api:0.21.0
|
||||
io.opencensus:opencensus-contrib-http-util:0.21.0
|
||||
javax.annotation:javax.annotation-api:1.2
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.validation:validation-api:1.0.0.GA
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.12
|
||||
net.bytebuddy:byte-buddy-agent:1.9.7
|
||||
net.bytebuddy:byte-buddy:1.9.7
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.commons:commons-text:1.6
|
||||
org.apache.httpcomponents:httpclient:4.5.8
|
||||
org.apache.httpcomponents:httpcore:4.4.11
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
org.hamcrest:hamcrest-core:1.3
|
||||
org.json:json:20160212
|
||||
org.mockito:mockito-core:2.25.0
|
||||
org.objenesis:objenesis:2.6
|
||||
org.ow2.asm:asm-analysis:6.0
|
||||
org.ow2.asm:asm-commons:6.0
|
||||
org.ow2.asm:asm-tree:6.0
|
||||
org.ow2.asm:asm-util:6.0
|
||||
org.ow2.asm:asm:6.0
|
||||
org.threeten:threetenbp:1.3.3
|
||||
@@ -23,19 +23,16 @@ 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}.
|
||||
* 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.
|
||||
@@ -119,7 +116,7 @@ final class CoverPageGenerator {
|
||||
|
||||
builder.put("projectState", state.toString());
|
||||
builder.put("title", title);
|
||||
builder.put("cssFiles", ImmutableSet.of(TrustedResourceUrls.fromConstant("css/style.css")));
|
||||
builder.put("cssFiles", ImmutableSet.of("css/style.css"));
|
||||
builder.put("invocation", getInvocation());
|
||||
builder.put("tasksByState", getTasksByStateSoyData());
|
||||
return builder.build();
|
||||
@@ -151,28 +148,20 @@ final class CoverPageGenerator {
|
||||
|
||||
/** 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("log", task.log().isPresent() ? getLogPath(task).toString() : "")
|
||||
.put(
|
||||
"reports",
|
||||
task.reports().entrySet().stream()
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getKey(),
|
||||
entry ->
|
||||
entry.getValue().files().isEmpty()
|
||||
? ""
|
||||
: entry
|
||||
.getValue()
|
||||
.entryPoint()
|
||||
.toString()
|
||||
.replace(File.separator, "/"))))
|
||||
: entry.getValue().entryPoint().toString())))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -199,10 +188,8 @@ final class CoverPageGenerator {
|
||||
}
|
||||
|
||||
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");
|
||||
// TODO(guyben):escape uniqueName to guarantee legal file name.
|
||||
return Paths.get("logs", task.uniqueName() + ".log");
|
||||
}
|
||||
|
||||
private static Supplier<byte[]> resourceLoader(Path path) {
|
||||
|
||||
@@ -57,10 +57,6 @@ final class GcsPluginUtils {
|
||||
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);
|
||||
@@ -68,8 +64,7 @@ final class GcsPluginUtils {
|
||||
|
||||
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, "/");
|
||||
String filename = path.toString();
|
||||
storage.create(
|
||||
BlobInfo.newBuilder(bucket, filename).setContentType(getContentType(filename)).build(),
|
||||
dataSupplier.get());
|
||||
@@ -172,7 +167,7 @@ final class GcsPluginUtils {
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
file -> rootDir.relativize(toNormalizedPath(file)),
|
||||
GcsPluginUtils::toByteArraySupplier));
|
||||
file -> toByteArraySupplier(file)));
|
||||
|
||||
if (files.isEmpty()) {
|
||||
// The directory exists, but is empty. Return empty FilesWithEntryPoint
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.gradle.plugin;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.gradle.plugin.ProjectData.TaskData;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
@@ -90,7 +91,7 @@ abstract class ProjectData {
|
||||
/** 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
|
||||
UP_TO_DATE;
|
||||
}
|
||||
|
||||
abstract String uniqueName();
|
||||
|
||||
@@ -143,7 +143,7 @@ public class ReportUploader extends DefaultTask {
|
||||
.getAsMap()
|
||||
.forEach(
|
||||
(type, report) -> {
|
||||
File destination = report.getOutputLocation().get().getAsFile();
|
||||
File destination = report.getDestination();
|
||||
// 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.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
{template .coverPage}
|
||||
{@param title: string}
|
||||
{@param cssFiles: list<trusted_resource_uri>}
|
||||
{@param cssFiles: list<string>}
|
||||
{@param projectState: string}
|
||||
{@param invocation: string}
|
||||
{@param tasksByState: map<string, list<[uniqueName: string, description: string, log: string, reports: map<string, string>]>>}
|
||||
|
||||
@@ -20,16 +20,17 @@ import static com.google.common.truth.Truth8.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;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Tests for {@link CoverPageGenerator} */
|
||||
final class CoverPageGeneratorTest {
|
||||
@RunWith(JUnit4.class)
|
||||
public final class CoverPageGeneratorTest {
|
||||
|
||||
private static final ProjectData EMPTY_PROJECT =
|
||||
ProjectData.builder()
|
||||
@@ -62,8 +63,6 @@ final class CoverPageGeneratorTest {
|
||||
.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();
|
||||
@@ -85,14 +84,14 @@ final class CoverPageGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetFilesToUpload_entryPoint_isIndexHtml() {
|
||||
public void testGetFilesToUpload_entryPoint_isIndexHtml() {
|
||||
CoverPageGenerator coverPageGenerator = new CoverPageGenerator(EMPTY_PROJECT);
|
||||
assertThat(coverPageGenerator.getFilesToUpload().entryPoint())
|
||||
.isEqualTo(Paths.get("index.html"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetFilesToUpload_containsEntryFile() {
|
||||
public void testGetFilesToUpload_containsEntryFile() {
|
||||
String content = getContentOfGeneratedFile(EMPTY_PROJECT, "index.html");
|
||||
assertThat(content)
|
||||
.contains(
|
||||
@@ -100,7 +99,7 @@ final class CoverPageGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_showsFailedTask() {
|
||||
public 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>");
|
||||
@@ -109,7 +108,7 @@ final class CoverPageGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_showsSuccessfulTask() {
|
||||
public 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>");
|
||||
@@ -118,7 +117,7 @@ final class CoverPageGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_showsUpToDateTask() {
|
||||
public 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>");
|
||||
@@ -127,10 +126,11 @@ final class CoverPageGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_failedAreFirst() {
|
||||
public void testCoverPage_failedAreFirst() {
|
||||
String content =
|
||||
getCoverPage(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
EMPTY_PROJECT
|
||||
.toBuilder()
|
||||
.addTask(EMPTY_TASK_UP_TO_DATE)
|
||||
.addTask(EMPTY_TASK_FAILURE)
|
||||
.addTask(EMPTY_TASK_SUCCESS)
|
||||
@@ -145,10 +145,11 @@ final class CoverPageGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_failingTask_statusIsFailure() {
|
||||
public void testCoverPage_failingTask_statusIsFailure() {
|
||||
String content =
|
||||
getCoverPage(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
EMPTY_PROJECT
|
||||
.toBuilder()
|
||||
.addTask(EMPTY_TASK_UP_TO_DATE)
|
||||
.addTask(EMPTY_TASK_FAILURE)
|
||||
.addTask(EMPTY_TASK_SUCCESS)
|
||||
@@ -157,10 +158,11 @@ final class CoverPageGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoverPage_noFailingTask_statusIsSuccess() {
|
||||
public void testCoverPage_noFailingTask_statusIsSuccess() {
|
||||
String content =
|
||||
getCoverPage(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
EMPTY_PROJECT
|
||||
.toBuilder()
|
||||
.addTask(EMPTY_TASK_UP_TO_DATE)
|
||||
.addTask(EMPTY_TASK_SUCCESS)
|
||||
.build());
|
||||
@@ -168,47 +170,52 @@ final class CoverPageGeneratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetFilesToUpload_containsCssFile() {
|
||||
public 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).containsKey("css/style.css");
|
||||
assertThat(files.get("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() {
|
||||
public void testCreateReportFiles_taskWithLog() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
EMPTY_PROJECT
|
||||
.toBuilder()
|
||||
.addTask(
|
||||
EMPTY_TASK_SUCCESS.toBuilder()
|
||||
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>");
|
||||
assertThat(files).containsEntry("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() {
|
||||
public void testCreateReportFiles_taskWithoutLog() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
EMPTY_PROJECT
|
||||
.toBuilder()
|
||||
.addTask(EMPTY_TASK_SUCCESS.toBuilder().setUniqueName("my:name").build())
|
||||
.build());
|
||||
assertThat(files).doesNotContainKey("logs/my-name.log");
|
||||
assertThat(files).doesNotContainKey("logs/my:name.log");
|
||||
assertThat(files.get("index.html")).contains("<span class=\"report_link_broken\">[log]</span>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_taskWithFilledReport() {
|
||||
public void testCreateReportFiles_taskWithFilledReport() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
EMPTY_PROJECT
|
||||
.toBuilder()
|
||||
.addTask(
|
||||
EMPTY_TASK_SUCCESS.toBuilder()
|
||||
EMPTY_TASK_SUCCESS
|
||||
.toBuilder()
|
||||
.putReport(
|
||||
"someReport",
|
||||
FilesWithEntryPoint.create(
|
||||
@@ -218,35 +225,39 @@ final class CoverPageGeneratorTest {
|
||||
Paths.get("path", "report.txt")))
|
||||
.build())
|
||||
.build());
|
||||
assertThat(files).containsEntry(filenameJoiner.join("path", "report.txt"), "report content");
|
||||
assertThat(files).containsEntry("path/report.txt", "report content");
|
||||
assertThat(files.get("index.html")).contains("<a href=\"path/report.txt\">[someReport]</a>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_taskWithEmptyReport() {
|
||||
public void testCreateReportFiles_taskWithEmptyReport() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
EMPTY_PROJECT
|
||||
.toBuilder()
|
||||
.addTask(
|
||||
EMPTY_TASK_SUCCESS.toBuilder()
|
||||
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).doesNotContainKey("path/report.txt");
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<span class=\"report_link_broken\">[someReport]</span>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateReportFiles_taskWithLogAndMultipleReports() {
|
||||
public void testCreateReportFiles_taskWithLogAndMultipleReports() {
|
||||
ImmutableMap<String, String> files =
|
||||
getGeneratedFiles(
|
||||
EMPTY_PROJECT.toBuilder()
|
||||
EMPTY_PROJECT
|
||||
.toBuilder()
|
||||
.addTask(
|
||||
EMPTY_TASK_SUCCESS.toBuilder()
|
||||
EMPTY_TASK_SUCCESS
|
||||
.toBuilder()
|
||||
.setUniqueName("my:name")
|
||||
.setLog(toByteArraySupplier("log data"))
|
||||
.putReport(
|
||||
@@ -264,15 +275,12 @@ final class CoverPageGeneratorTest {
|
||||
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).containsEntry("path-filled/report.txt", "report content");
|
||||
assertThat(files).containsEntry("path-filled/other/file.txt", "some other content");
|
||||
assertThat(files).containsEntry("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("<a href=\"logs/my:name.log\">[log]</a>");
|
||||
assertThat(files.get("index.html"))
|
||||
.contains("<span class=\"report_link_broken\">[emptyReport]</span>");
|
||||
}
|
||||
|
||||
@@ -23,36 +23,32 @@ 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;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Tests for {@link GcsPluginUtilsTest} */
|
||||
final class GcsPluginUtilsTest {
|
||||
@RunWith(JUnit4.class)
|
||||
public final class GcsPluginUtilsTest {
|
||||
|
||||
private static final Joiner filenameJoiner = Joiner.on(File.separator);
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@TempDir
|
||||
Path tmpDir;
|
||||
@Rule public final TemporaryFolder folder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
void testGetContentType_knownTypes() {
|
||||
public 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");
|
||||
@@ -64,12 +60,12 @@ final class GcsPluginUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetContentType_unknownTypes() {
|
||||
public void testGetContentType_unknownTypes() {
|
||||
assertThat(getContentType("path/to/file.unknown")).isEqualTo("application/octet-stream");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUploadFileToGcs() {
|
||||
public void testUploadFileToGcs() {
|
||||
Storage storage = mock(Storage.class);
|
||||
uploadFileToGcs(
|
||||
storage, "my-bucket", Paths.get("my", "filename.txt"), toByteArraySupplier("my data"));
|
||||
@@ -83,7 +79,7 @@ final class GcsPluginUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUploadFilesToGcsMultithread() {
|
||||
public void testUploadFilesToGcsMultithread() {
|
||||
Storage storage = mock(Storage.class);
|
||||
uploadFilesToGcsMultithread(
|
||||
storage,
|
||||
@@ -122,21 +118,21 @@ final class GcsPluginUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToByteArraySupplier_string() {
|
||||
public void testToByteArraySupplier_string() {
|
||||
assertThat(toByteArraySupplier("my string").get()).isEqualTo("my string".getBytes(UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToByteArraySupplier_stringSupplier() {
|
||||
public 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));
|
||||
public void testToByteArraySupplier_file() throws Exception {
|
||||
folder.newFolder("arbitrary");
|
||||
File file = folder.newFile("arbitrary/file.txt");
|
||||
Files.write(file.toPath(), "some data".getBytes(UTF_8));
|
||||
assertThat(toByteArraySupplier(file).get()).isEqualTo("some data".getBytes(UTF_8));
|
||||
}
|
||||
|
||||
private ImmutableMap<String, String> readAllFiles(FilesWithEntryPoint reportFiles) {
|
||||
@@ -148,72 +144,69 @@ final class GcsPluginUtilsTest {
|
||||
}
|
||||
|
||||
@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));
|
||||
public void testCreateReportFiles_destinationIsFile() throws Exception {
|
||||
Path root = toNormalizedPath(folder.newFolder("my", "root"));
|
||||
folder.newFolder("my", "root", "some", "path");
|
||||
File destination = folder.newFile("my/root/some/path/file.txt");
|
||||
Files.write(destination.toPath(), "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();
|
||||
File ignoredHint = folder.newFile("my/root/ignored.txt");
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo(filenameJoiner.join("non", "existing.txt"));
|
||||
assertThat(files.files()).isEmpty();
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path/file.txt");
|
||||
assertThat(readAllFiles(files)).containsExactly("some/path/file.txt", "some data");
|
||||
}
|
||||
|
||||
@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();
|
||||
public void testCreateReportFiles_destinationDoesntExist() throws Exception {
|
||||
Path root = toNormalizedPath(folder.newFolder("my", "root"));
|
||||
File destination = root.resolve("non/existing.txt").toFile();
|
||||
assertThat(destination.isFile()).isFalse();
|
||||
assertThat(destination.isDirectory()).isFalse();
|
||||
// Since there are not files, any hint given is obvioulsy wrong and will be ignored.
|
||||
File ignoredHint = folder.newFile("my/root/ignored.txt");
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.of(ignoredHint), root);
|
||||
readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo(filenameJoiner.join("some", "path"));
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("non/existing.txt");
|
||||
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));
|
||||
public void testCreateReportFiles_noFiles() throws Exception {
|
||||
Path root = toNormalizedPath(folder.newFolder("my", "root"));
|
||||
File destination = folder.newFolder("my", "root", "some", "path");
|
||||
folder.newFolder("my", "root", "some", "path", "a", "b");
|
||||
folder.newFolder("my", "root", "some", "path", "c");
|
||||
// Since there are not files, any hint given is obvioulsy wrong and will be ignored.
|
||||
File ignoredHint = folder.newFile("my/root/ignored.txt");
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path");
|
||||
assertThat(files.files()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateReportFiles_oneFile() throws Exception {
|
||||
Path root = toNormalizedPath(folder.newFolder("my", "root"));
|
||||
File destination = folder.newFolder("my", "root", "some", "path");
|
||||
folder.newFolder("my", "root", "some", "path", "a", "b");
|
||||
folder.newFolder("my", "root", "some", "path", "c");
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/a/file.txt").toPath(), "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();
|
||||
File ignoredHint = folder.newFile("my/root/ignored.txt");
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.of(ignoredHint), root);
|
||||
readFilesWithEntryPoint(destination, 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");
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path/a/file.txt");
|
||||
assertThat(readAllFiles(files)).containsExactly("some/path/a/file.txt", "some data");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,24 +215,25 @@ final class GcsPluginUtilsTest {
|
||||
* <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"));
|
||||
public void testCreateReportFiles_multipleFiles_noHint() throws Exception {
|
||||
Path root = toNormalizedPath(folder.newFolder("my", "root"));
|
||||
File destination = folder.newFolder("my", "root", "some", "path");
|
||||
folder.newFolder("my", "root", "some", "path", "a", "b");
|
||||
folder.newFolder("my", "root", "some", "path", "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));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/index.html").toPath(), "some data".getBytes(UTF_8));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/a/index.html").toPath(), "wrong index".getBytes(UTF_8));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/c/style.css").toPath(), "css file".getBytes(UTF_8));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/my_image.png").toPath(), "images".getBytes(UTF_8));
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.empty(), root);
|
||||
FilesWithEntryPoint files = readFilesWithEntryPoint(destination, 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"));
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path/path.zip");
|
||||
assertThat(readAllFiles(files).keySet()).containsExactly("some/path/path.zip");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,51 +242,55 @@ final class GcsPluginUtilsTest {
|
||||
* <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"));
|
||||
public void testCreateReportFiles_multipleFiles_withBadHint() throws Exception {
|
||||
Path root = toNormalizedPath(folder.newFolder("my", "root"));
|
||||
File destination = folder.newFolder("my", "root", "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"));
|
||||
File badEntryPoint = folder.newFolder("my", "root", "some", "path", "a", "b");
|
||||
folder.newFolder("my", "root", "some", "path", "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));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/index.html").toPath(), "some data".getBytes(UTF_8));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/a/index.html").toPath(), "wrong index".getBytes(UTF_8));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/c/style.css").toPath(), "css file".getBytes(UTF_8));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/my_image.png").toPath(), "images".getBytes(UTF_8));
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.of(badEntryPoint), root);
|
||||
readFilesWithEntryPoint(destination, 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"));
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("some/path/path.zip");
|
||||
assertThat(readAllFiles(files).keySet()).containsExactly("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"));
|
||||
public void testCreateReportFiles_multipleFiles_withGoodHint() throws Exception {
|
||||
Path root = toNormalizedPath(folder.newFolder("my", "root"));
|
||||
File destination = folder.newFolder("my", "root", "some", "path");
|
||||
folder.newFolder("my", "root", "some", "path", "a", "b");
|
||||
folder.newFolder("my", "root", "some", "path", "c");
|
||||
// The hint is an actual file nested in the destination directory!
|
||||
Path goodEntryPoint = createFile(destination.resolve("index.html"));
|
||||
File goodEntryPoint = folder.newFile("my/root/some/path/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));
|
||||
Files.write(goodEntryPoint.toPath(), "some data".getBytes(UTF_8));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/a/index.html").toPath(), "wrong index".getBytes(UTF_8));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/c/style.css").toPath(), "css file".getBytes(UTF_8));
|
||||
Files.write(
|
||||
folder.newFile("my/root/some/path/my_image.png").toPath(), "images".getBytes(UTF_8));
|
||||
|
||||
FilesWithEntryPoint files =
|
||||
readFilesWithEntryPoint(destination.toFile(), Optional.of(goodEntryPoint.toFile()), root);
|
||||
readFilesWithEntryPoint(destination, Optional.of(goodEntryPoint), root);
|
||||
|
||||
assertThat(files.entryPoint().toString())
|
||||
.isEqualTo(filenameJoiner.join("some", "path", "index.html"));
|
||||
assertThat(files.entryPoint().toString()).isEqualTo("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");
|
||||
"some/path/index.html", "some data",
|
||||
"some/path/a/index.html", "wrong index",
|
||||
"some/path/c/style.css", "css file",
|
||||
"some/path/my_image.png", "images");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
mock-maker-inline
|
||||
@@ -1,62 +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.dorongold.plugins:task-tree:2.1.0=classpath
|
||||
com.dorongold.task-tree:com.dorongold.task-tree.gradle.plugin:2.1.0=classpath
|
||||
com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:8.1.1=classpath
|
||||
com.github.johnrengelman:shadow:8.1.1=classpath
|
||||
com.github.node-gradle.node:com.github.node-gradle.node.gradle.plugin:3.0.1=classpath
|
||||
com.github.node-gradle:gradle-node-plugin:3.0.1=classpath
|
||||
com.google.cloud.tools:appengine-gradle-plugin:2.4.1=classpath
|
||||
com.google.cloud.tools:appengine-plugins-core:0.9.1=classpath
|
||||
com.google.code.findbugs:jsr305:3.0.2=classpath
|
||||
com.google.code.gson:gson:2.8.6=classpath
|
||||
com.google.errorprone:error_prone_annotations:2.3.4=classpath
|
||||
com.google.guava:failureaccess:1.0.1=classpath
|
||||
com.google.guava:guava:28.2-jre=classpath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=classpath
|
||||
com.google.j2objc:j2objc-annotations:1.3=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
|
||||
commons-io:commons-io:2.11.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.apache.ant:ant-launcher:1.10.13=classpath
|
||||
org.apache.ant:ant:1.10.13=classpath
|
||||
org.apache.commons:commons-compress:1.20=classpath
|
||||
org.apache.commons:commons-lang3:3.5=classpath
|
||||
org.checkerframework:checker-qual:2.10.0=classpath
|
||||
org.codehaus.plexus:plexus-utils:3.5.1=classpath
|
||||
org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r=classpath
|
||||
org.eclipse.platform:org.eclipse.osgi:3.18.300=classpath
|
||||
org.glassfish:javax.json:1.0.4=classpath
|
||||
org.jdom:jdom2:2.0.6.1=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.6.20=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.31=classpath
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.6.20=classpath
|
||||
org.jetbrains:annotations:13.0=classpath
|
||||
org.ow2.asm:asm-commons:9.4=classpath
|
||||
org.ow2.asm:asm-tree:9.4=classpath
|
||||
org.ow2.asm:asm:9.4=classpath
|
||||
org.slf4j:slf4j-api:1.7.36=classpath
|
||||
org.sonatype.aether:aether-api:1.13.1=classpath
|
||||
org.sonatype.aether:aether-impl:1.13.1=classpath
|
||||
org.sonatype.aether:aether-spi:1.13.1=classpath
|
||||
org.sonatype.aether:aether-util:1.13.1=classpath
|
||||
org.tukaani:xz:1.9=classpath
|
||||
org.vafer:jdependency:2.8.0=classpath
|
||||
org.yaml:snakeyaml:1.21=classpath
|
||||
empty=
|
||||
@@ -1,7 +0,0 @@
|
||||
## Summary
|
||||
|
||||
This project holds some of the general-purpose utility classes that do not rely
|
||||
on the registry domain model.
|
||||
|
||||
This is an intermediate step in untangling the circular dependencies
|
||||
between :core and :util subprojects.
|
||||
@@ -1,68 +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.
|
||||
|
||||
sourceSets {
|
||||
testing {
|
||||
java {
|
||||
compileClasspath += main.output
|
||||
runtimeClasspath += main.output
|
||||
}
|
||||
}
|
||||
test {
|
||||
java {
|
||||
compileClasspath += testing.output
|
||||
runtimeClasspath += testing.output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
// For reasons I don't understand, testingCompileOnly is the configuration
|
||||
// used for compiling the classes in the "testing" jar.
|
||||
testingCompileOnly.extendsFrom implementation
|
||||
testingRuntimeOnly.extendsFrom runtimeOnly
|
||||
|
||||
testImplementation.extendsFrom testingCompile
|
||||
testRuntimeOnly.extendsFrom testingRuntime
|
||||
|
||||
// All testing util classes. Other projects may declare dependency as:
|
||||
// testImplementation project(path: 'common', configuration: 'testing')
|
||||
create("testing")
|
||||
testing.extendsFrom testingCompileOnly
|
||||
}
|
||||
|
||||
task testingJar(type: Jar) {
|
||||
archiveBaseName = 'testing'
|
||||
from sourceSets.testing.output
|
||||
}
|
||||
|
||||
artifacts {
|
||||
testing testingJar
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def deps = rootProject.dependencyMap
|
||||
|
||||
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['joda-time:joda-time']
|
||||
implementation deps['com.google.flogger:flogger']
|
||||
implementation deps['io.github.java-diff-utils:java-diff-utils']
|
||||
implementation deps['com.google.truth:truth']
|
||||
|
||||
testImplementation deps['org.junit.jupiter:junit-jupiter-api']
|
||||
testImplementation deps['org.junit.jupiter:junit-jupiter-engine']
|
||||
}
|
||||
@@ -1,67 +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,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.github.ben-manes.caffeine:caffeine:2.9.3=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.auto.value:auto-value-annotations:1.10.4=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
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,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,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
|
||||
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.errorprone:javac:9+181-r4173-1=errorproneJavac
|
||||
com.google.flogger:flogger:0.8=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.google.guava:failureaccess:1.0.1=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.guava:failureaccess:1.0.2=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
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: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.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
com.google.truth:truth:1.2.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
com.puppycrawl.tools:checkstyle:9.3=checkstyle
|
||||
commons-beanutils:commons-beanutils:1.9.4=checkstyle
|
||||
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
|
||||
joda-time:joda-time:2.12.6=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
|
||||
org.antlr:antlr4-runtime:4.9.3=checkstyle
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
org.checkerframework:checker-qual:3.12.0=checkstyle
|
||||
org.checkerframework:checker-qual:3.33.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
org.checkerframework:checker-qual:3.42.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
org.hamcrest:hamcrest-core:1.3=testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
org.jacoco:org.jacoco.agent:0.8.9=jacocoAgent,jacocoAnt
|
||||
org.jacoco:org.jacoco.ant:0.8.9=jacocoAnt
|
||||
org.jacoco:org.jacoco.core:0.8.9=jacocoAnt
|
||||
org.jacoco:org.jacoco.report:0.8.9=jacocoAnt
|
||||
org.javassist:javassist:3.28.0-GA=checkstyle
|
||||
org.junit.jupiter:junit-jupiter-api:5.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit:junit-bom:5.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:9.5=jacocoAnt
|
||||
org.ow2.asm:asm-tree:9.5=jacocoAnt
|
||||
org.ow2.asm:asm:9.5=jacocoAnt
|
||||
org.ow2.asm:asm:9.6=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
|
||||
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
|
||||
org.reflections:reflections:0.10.2=checkstyle
|
||||
empty=testingCompile,testingRuntime,testingRuntimeClasspath
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2023 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.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.Iterators.partition;
|
||||
import static com.google.common.collect.Iterators.transform;
|
||||
import static com.google.common.collect.Streams.stream;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/** Utilities for breaking up a {@link Stream} into batches. */
|
||||
public final class BatchedStreams {
|
||||
|
||||
static final int MAX_BATCH = 1024 * 1024;
|
||||
|
||||
private BatchedStreams() {}
|
||||
|
||||
/**
|
||||
* Transform a flat {@link Stream} into a {@code Stream} of batches.
|
||||
*
|
||||
* <p>Closing the returned stream does not close the original stream.
|
||||
*/
|
||||
public static <T> Stream<ImmutableList<T>> toBatches(Stream<T> stream, int batchSize) {
|
||||
checkArgument(batchSize > 0, "batchSize must be a positive integer.");
|
||||
return stream(
|
||||
transform(partition(stream.iterator(), min(MAX_BATCH, batchSize)), ImmutableList::copyOf));
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2023 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.util;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.util.BatchedStreams.toBatches;
|
||||
import static java.util.stream.Collectors.counting;
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link BatchedStreams}. */
|
||||
public class BatchedStreamsTest {
|
||||
|
||||
@Test
|
||||
void invalidBatchSize() {
|
||||
assertThat(assertThrows(IllegalArgumentException.class, () -> toBatches(Stream.of(), 0)))
|
||||
.hasMessageThat()
|
||||
.contains("must be a positive integer");
|
||||
}
|
||||
|
||||
@Test
|
||||
void batch_success() {
|
||||
// 900_002 elements -> 900 1K-batches + 1 2-element-batch
|
||||
Stream<Integer> data = IntStream.rangeClosed(0, 900_001).boxed();
|
||||
assertThat(
|
||||
toBatches(data, 1000).map(ImmutableList::size).collect(groupingBy(x -> x, counting())))
|
||||
.containsExactly(1000, 900L, 2, 1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void batch_partialBatch() {
|
||||
Stream<Integer> data = Stream.of(1, 2, 3);
|
||||
assertThat(
|
||||
toBatches(data, 1000).map(ImmutableList::size).collect(groupingBy(x -> x, counting())))
|
||||
.containsExactly(3, 1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void batch_truncateBatchSize() {
|
||||
// 2M elements -> 2 1M-batches despite the user-specified 2M batch size.
|
||||
Stream<Integer> data = IntStream.range(0, 1024 * 2048).boxed();
|
||||
assertThat(
|
||||
toBatches(data, 2_000_000)
|
||||
.map(ImmutableList::size)
|
||||
.collect(groupingBy(x -> x, counting())))
|
||||
.containsExactly(1024 * 1024, 2L);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
This is a random file,
|
||||
with three lines and terminates without a newline.
|
||||
@@ -1,47 +0,0 @@
|
||||
// Copyright 2020 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.testing.truth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import com.google.common.truth.Truth;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Utils class containing helper functions for {@link Truth}. */
|
||||
public class TruthUtils {
|
||||
|
||||
/** Asserts that both of the given objects are either null or nonnull. */
|
||||
public static void assertNullnessParity(@Nullable Object thisObj, @Nullable Object thatObj) {
|
||||
if (thisObj == null) {
|
||||
assertWithMessage("Expects both objects are null but thatObj is not null")
|
||||
.that(thatObj)
|
||||
.isNull();
|
||||
} else {
|
||||
assertWithMessage("Expects both objects are not null but thatObj is null")
|
||||
.that(thatObj)
|
||||
.isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
/** Asserts that both of the given objects are either null or nonnull. */
|
||||
public static void assertNullnessParity(
|
||||
@Nullable Object thisObj, @Nullable Object thatObj, String errorMessage) {
|
||||
if (thisObj == null) {
|
||||
assertWithMessage(errorMessage).that(thatObj).isNull();
|
||||
} else {
|
||||
assertWithMessage(errorMessage).that(thatObj).isNotNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,29 +43,34 @@ by Joshua Bloch in his book Effective Java -->
|
||||
<property name="message" value='Your Javadocs appear to use invalid <a> tag syntax in @see tags. Please use the correct syntax: @see <a href="http(s)://your_url">url_description</a>'/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that our Ofy wrapper is used instead of the "real" ofy(). -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="com\.googlecode\.objectify\.ObjectifyService\.ofy"/>
|
||||
<property name="message" value="Use google.registry.model.ofy.ObjectifyService.ofy(). Do not use com.googlecode.objectify.v4.ObjectifyService.ofy()."/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that java.util.Optional is used instead of Guava's Optional. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="com\.google\.common\.base\.Optional"/>
|
||||
<property name="message" value="Use java.util.Optional instead of Guava's Optional."/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that our backport JUnit exception assertion methods are used instead of the ones slated for release in JUnit 4.13. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="org\.junit\.Assert\.(assert|expect)Throws"/>
|
||||
<property name="message" value="Use the exception assertion methods in google.registry.testing.JUnitBackports instead of those in JUnit."/>
|
||||
</module>
|
||||
|
||||
<!-- Checks that the deprecated ExpectedException is not used. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="org\.junit\.rules\.ExpectedException"/>
|
||||
<property name="message" value="Use assertThrows and expectThrows instead of the deprecated methods on ExpectedException."/>
|
||||
<property name="message" value="Use assertThrows and expectThrows from JUnitBackports instead of the deprecated methods on ExpectedException."/>
|
||||
</module>
|
||||
|
||||
<module name="LineLength">
|
||||
<!-- Checks if a line is too long. -->
|
||||
<property name="max" value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.max}" default="100"/>
|
||||
<property name="severity" value="error"/>
|
||||
|
||||
<!-- Ignore lines that have any series of 80 or more non-whitespace characters.
|
||||
These lines likely cannot be broken.
|
||||
-->
|
||||
<property name="ignorePattern"
|
||||
value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.ignorePattern}"
|
||||
default=".*[^ ]{80,}.*"/>
|
||||
<!-- Checks that the deprecated MockitoJUnitRunner is not used. -->
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="MockitoJUnitRunner"/>
|
||||
<property name="message" value="MockitoJUnitRunner is deprecated. Use @RunWith(JUnit4.class) and MockitoRule instead."/>
|
||||
</module>
|
||||
|
||||
<!-- All Java AST specific tests live under TreeWalker module. -->
|
||||
@@ -179,6 +184,19 @@ by Joshua Bloch in his book Effective Java -->
|
||||
LENGTH and CODING CHECKS
|
||||
-->
|
||||
|
||||
<module name="LineLength">
|
||||
<!-- Checks if a line is too long. -->
|
||||
<property name="max" value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.max}" default="100"/>
|
||||
<property name="severity" value="error"/>
|
||||
|
||||
<!-- Ignore lines that have any series of 80 or more non-whitespace characters.
|
||||
These lines likely cannot be broken.
|
||||
-->
|
||||
<property name="ignorePattern"
|
||||
value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.ignorePattern}"
|
||||
default=".*[^ ]{80,}.*"/>
|
||||
</module>
|
||||
|
||||
<module name="OperatorWrap">
|
||||
<property name="option" value="nl"/>
|
||||
<property name="tokens" value="QUESTION, EQUAL, NOT_EQUAL, DIV, PLUS, MINUS, STAR, MOD, SR, BSR, GE, GT, SL, LE, LT, BXOR, BOR, LOR, BAND, LAND, TYPE_EXTENSION_AND, LITERAL_INSTANCEOF"/>
|
||||
|
||||
@@ -9,4 +9,6 @@
|
||||
<suppress files="[/\\].*[/\\]generated.*[/\\]" checks="."/>
|
||||
<!-- Ignore Javadoc checks in test files -->
|
||||
<suppress files="[/\\].*[/\\]src/test/java/.*[/\\]" checks="JavadocType"/>
|
||||
<!-- ofy() regex check doesn't apply to these files -->
|
||||
<suppress files="AugmentedDeleter.java|AugmentedSaver.java|Ofy.java" checks="RegexpSingleline"/>
|
||||
</suppressions>
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
## Summary
|
||||
|
||||
This folder contains configuration files for the gradle-license-report plugin:
|
||||
|
||||
* allowed_licenses.json declares the acceptable licenses. A license may have
|
||||
multiple entries in this file, since the 'moduleLicense' property value must
|
||||
match exactly the phrases found in pom or manifest files.
|
||||
* license_normalizer_bundle.json configures normalization rules for license
|
||||
reporting.
|
||||
|
||||
## Notes About Adding New Licenses
|
||||
|
||||
* The WTFPL license is not allowed.
|
||||
|
||||
* Each 'Public Domain' license entry must include a specific 'moduleName'. Do
|
||||
not omit moduleName or use wildcards.
|
||||
@@ -3,9 +3,6 @@
|
||||
{
|
||||
"moduleLicense": "Apache Software License, Version 1.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache Software License, version 1.1"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache 2"
|
||||
},
|
||||
@@ -24,9 +21,6 @@
|
||||
{
|
||||
"moduleLicense": "Apache License v2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache License V2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Apache License, Version 2.0"
|
||||
},
|
||||
@@ -69,27 +63,12 @@
|
||||
{
|
||||
"moduleLicense": "BSD 3-clause New License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD-3-Clause"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD-3-Clause;link=\"https://raw.githubusercontent.com/dnsjava/dnsjava/master/LICENSE\""
|
||||
},
|
||||
{
|
||||
"moduleLicense": "3-Clause BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The 3-Clause BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD Licence 3"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD License 3"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "BSD New License"
|
||||
},
|
||||
@@ -111,15 +90,9 @@
|
||||
{
|
||||
"moduleLicense": "The BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The New BSD License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The PostgreSQL License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CC0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "CC0 1.0 Universal License"
|
||||
},
|
||||
@@ -147,12 +120,6 @@
|
||||
{
|
||||
"moduleLicense": "Eclipse Distribution License v. 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Distribution License - v 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "EDL 1.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License - Version 1.0"
|
||||
},
|
||||
@@ -168,27 +135,18 @@
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License - v 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License v. 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Eclipse Public License v2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "https://www.eclipse.org/legal/epl-2.0/, http://www.gnu.org/copyleft/gpl.html, http://www.gnu.org/licenses/lgpl.html"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Google App Engine Terms of Service"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU General Public License Version 2"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU General Public License, version 2, with the Classpath Exception"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU GENERAL PUBLIC LICENSE, Version 2 + Classpath Exception"
|
||||
},
|
||||
@@ -207,19 +165,9 @@
|
||||
{
|
||||
"moduleLicense": "GNU Library General Public License v2.1 or later"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU Lesser General Public License v3.0"
|
||||
},
|
||||
// This is just 3-clause BSD.
|
||||
{
|
||||
"moduleLicense": "Go License"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The Go license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Google App Engine Terms of Service"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GWT Terms"
|
||||
},
|
||||
@@ -250,9 +198,6 @@
|
||||
{
|
||||
"moduleLicense": "The MIT license"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The MIT License (MIT)"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The PostgreSQL License"
|
||||
},
|
||||
@@ -260,71 +205,13 @@
|
||||
"moduleLicense": "Mozilla Public License Version 2.0"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Unicode/ICU License"
|
||||
"moduleLicense": "Public Domain"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Public Domain",
|
||||
"moduleName": "aopalliance:aopalliance"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Public Domain",
|
||||
"moduleName": "org.tukaani:xz"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "Public Domain",
|
||||
"moduleName": "org.json:json"
|
||||
},
|
||||
{
|
||||
// "Apache License, Version 2.0".
|
||||
"moduleLicense": null,
|
||||
"moduleVersion": "2.10.0",
|
||||
"moduleName": "com.google.gwt:gwt-user"
|
||||
},
|
||||
{
|
||||
// "Apache License, Version 2.0". The plugin is able to parse up to
|
||||
// 2.11.3 correctly but then something changed with 2.12.* and it no
|
||||
// longer parses correctly, even though it's still Apache 2.0.
|
||||
"moduleLicense": null,
|
||||
"moduleName": "com.fasterxml.jackson:jackson-bom"
|
||||
},
|
||||
{
|
||||
// Part of Guava with "Apache License, Version 2.0". The plugin is unable
|
||||
// to parse its license for unknown reason.
|
||||
"moduleLicense": null,
|
||||
"moduleName": "com.google.guava:guava-parent"
|
||||
},
|
||||
{
|
||||
// "Apache License, Version 2.0". The plugin is able to parse up to
|
||||
// 2.0.33.Final but not this verson.
|
||||
"moduleLicense": null,
|
||||
"moduleVersion": "2.0.46.Final",
|
||||
"moduleName": "io.netty:netty-tcnative-classes"
|
||||
},
|
||||
{
|
||||
// Actually Eclipse Public License v2.0
|
||||
"moduleLicense": null,
|
||||
"moduleName": "org.junit:junit-bom"
|
||||
"moduleLicense": "PUBLIC DOMAIN"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "The W3C Software License"
|
||||
},
|
||||
{
|
||||
// "Apache License, Version 2.0".
|
||||
"moduleLicense": null,
|
||||
"moduleName": "com.squareup.okhttp3:okhttp"
|
||||
},
|
||||
{
|
||||
// "Apache License, Version 2.0".
|
||||
"moduleLicense": null,
|
||||
"moduleName": "com.squareup.okio:okio"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "(GPL-2.0-only WITH Classpath-exception-2.0)",
|
||||
"moduleName": "io.github.eisop:dataflow-errorprone"
|
||||
},
|
||||
{
|
||||
"moduleLicense": "GNU General Public License, version 2 (GPL2), with the classpath exception",
|
||||
"moduleName": "io.github.eisop:dataflow-errorprone"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,428 +0,0 @@
|
||||
# Copyright 2020 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.
|
||||
|
||||
"""Script to generate dr-build and the properties file.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import dataclasses
|
||||
import io
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import List, Union
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Property:
|
||||
name : str = ''
|
||||
desc : str = ''
|
||||
default : str = ''
|
||||
constraints : type = str
|
||||
|
||||
def validate(self, value: str):
|
||||
"""Verify that "value" is appropriate for the property."""
|
||||
if type is bool:
|
||||
if value not in ('true', 'false'):
|
||||
raise ValidationError('value of {self.name} must be "true" or '
|
||||
'"false".')
|
||||
|
||||
@dataclasses.dataclass
|
||||
class GradleFlag:
|
||||
flags : Union[str, List[str]]
|
||||
desc : str
|
||||
has_arg : bool = False
|
||||
|
||||
|
||||
PROPERTIES_HEADER = """\
|
||||
# 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
|
||||
#
|
||||
# To view property descriptions (which are command line flags for
|
||||
# nom_build), run ./nom_build --help.
|
||||
#
|
||||
# DO NOT EDIT THIS FILE BY HAND
|
||||
org.gradle.jvmargs=-Xmx1024m
|
||||
org.gradle.caching=true
|
||||
"""
|
||||
|
||||
# Help text to be displayed (in addition to the synopsis and flag help, which
|
||||
# are displayed automatically).
|
||||
HELP_TEXT = """\
|
||||
A wrapper around the gradle build that provides the following features:
|
||||
|
||||
- Converts properties into flags to guard against property name spelling errors
|
||||
and to provide help descriptions for all properties.
|
||||
- Provides pseudo-commands (with the ":nom:" prefix) that encapsulate common
|
||||
actions that are difficult to implement in gradle.
|
||||
|
||||
Pseudo-commands:
|
||||
:nom:generate_golden_file - regenerates the golden file from the current
|
||||
set of flyway files.
|
||||
"""
|
||||
|
||||
# Define all of our special gradle properties here.
|
||||
# TODO(b/169318491): use consistent naming style for properties and variables.
|
||||
PROPERTIES = [
|
||||
Property('mavenUrl',
|
||||
'URL to use for the main maven repository (defaults to maven '
|
||||
'central). This can be http(s) or a "gcs" repo.'),
|
||||
Property('pluginsUrl',
|
||||
'URL to use for the gradle plugins repository (defaults to maven '
|
||||
'central, see also mavenUrl'),
|
||||
Property('allowInsecureProtocol',
|
||||
'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',
|
||||
bool),
|
||||
Property('enableDependencyLocking',
|
||||
'Enables dependency locking.',
|
||||
'true',
|
||||
bool),
|
||||
Property('enableCrossReferencing',
|
||||
'generate metadata during java compile (used for kythe source '
|
||||
'reference generation).',
|
||||
'false'),
|
||||
Property('testFilter',
|
||||
'Comma separated list of test patterns, if specified run only '
|
||||
'these.'),
|
||||
Property('environment', 'GAE Environment for deployment and staging.'),
|
||||
|
||||
# Cloud SQL properties
|
||||
Property('dbServer',
|
||||
'Sets the target database of a Flyway task. This may be a '
|
||||
'registry environment name (e.g., alpha) or the host[:port] '
|
||||
'of a database that accepts direct IP access.'),
|
||||
Property('dbName',
|
||||
'Database name to use in connection.',
|
||||
'postgres'),
|
||||
Property('dbUser', 'Database user name for use in connection'),
|
||||
Property('dbPassword', 'Database password for use in connection'),
|
||||
|
||||
Property('publish_repo',
|
||||
'Maven repository that hosts the Cloud SQL schema jar and the '
|
||||
'registry server test jars. Such jars are needed for '
|
||||
'server/schema integration tests. Please refer to <a '
|
||||
'href="./integration/README.md">integration project</a> for more '
|
||||
'information.'),
|
||||
Property('baseSchemaTag',
|
||||
'The nomulus version tag of the schema for use in the schema'
|
||||
'deployment integration test (:db:schemaIncrementalDeployTest)'),
|
||||
Property('schema_version',
|
||||
'The nomulus version tag of the schema for use in a database'
|
||||
'integration test.'),
|
||||
Property('nomulus_version',
|
||||
'The version of nomulus to test against in a database '
|
||||
'integration test.'),
|
||||
Property('dot_path',
|
||||
'The path to "dot", part of the graphviz package that converts '
|
||||
'a BEAM pipeline to image. Setting this property to empty string '
|
||||
'will disable image generation.',
|
||||
'/usr/bin/dot'),
|
||||
Property('pipeline',
|
||||
'The name of the Beam pipeline being staged.')
|
||||
]
|
||||
|
||||
GRADLE_FLAGS = [
|
||||
GradleFlag(['-a', '--no-rebuild'],
|
||||
'Do not rebuild project dependencies.'),
|
||||
GradleFlag(['-b', '--build-file'], 'Specify the build file.', True),
|
||||
GradleFlag(['--build-cache'],
|
||||
'Enables the Gradle build cache. Gradle will try to reuse '
|
||||
'outputs from previous builds.'),
|
||||
GradleFlag(['-c', '--settings-file'], 'Specify the settings file.', True),
|
||||
GradleFlag(['--configure-on-demand'],
|
||||
'Configure necessary projects only. Gradle will attempt to '
|
||||
'reduce configuration time for large multi-project builds. '
|
||||
'[incubating]'),
|
||||
GradleFlag(['--console'],
|
||||
'Specifies which type of console output to generate. Values '
|
||||
"are 'plain', 'auto' (default), 'rich' or 'verbose'.",
|
||||
True),
|
||||
GradleFlag(['--continue'], 'Continue task execution after a task failure.'),
|
||||
GradleFlag(['-D', '--system-prop'],
|
||||
'Set system property of the JVM (e.g. -Dmyprop=myvalue).',
|
||||
True),
|
||||
GradleFlag(['-d', '--debug'],
|
||||
'Log in debug mode (includes normal stacktrace).'),
|
||||
GradleFlag(['--daemon'],
|
||||
'Uses the Gradle Daemon to run the build. Starts the Daemon '
|
||||
'if not running.'),
|
||||
GradleFlag(['--foreground'], 'Starts the Gradle Daemon in the foreground.'),
|
||||
GradleFlag(['-g', '--gradle-user-home'],
|
||||
'Specifies the gradle user home directory.',
|
||||
True),
|
||||
GradleFlag(['-I', '--init-script'], 'Specify an initialization script.',
|
||||
True),
|
||||
GradleFlag(['-i', '--info'], 'Set log level to info.'),
|
||||
GradleFlag(['--include-build'],
|
||||
'Include the specified build in the composite.',
|
||||
True),
|
||||
GradleFlag(['-m', '--dry-run'],
|
||||
'Run the builds with all task actions disabled.'),
|
||||
GradleFlag(['--max-workers'],
|
||||
'Configure the number of concurrent workers Gradle is '
|
||||
'allowed to use.',
|
||||
True),
|
||||
GradleFlag(['--no-build-cache'], 'Disables the Gradle build cache.'),
|
||||
GradleFlag(['--no-configure-on-demand'],
|
||||
'Disables the use of configuration on demand. [incubating]'),
|
||||
GradleFlag(['--no-daemon'],
|
||||
'Do not use the Gradle daemon to run the build. Useful '
|
||||
'occasionally if you have configured Gradle to always run '
|
||||
'with the daemon by default.'),
|
||||
GradleFlag(['--no-parallel'],
|
||||
'Disables parallel execution to build projects.'),
|
||||
GradleFlag(['--no-scan'],
|
||||
'Disables the creation of a build scan. For more information '
|
||||
'about build scans, please visit '
|
||||
'https://gradle.com/build-scans.'),
|
||||
GradleFlag(['--offline'],
|
||||
'Execute the build without accessing network resources.'),
|
||||
GradleFlag(['-P', '--project-prop'],
|
||||
'Set project property for the build script (e.g. '
|
||||
'-Pmyprop=myvalue).',
|
||||
True),
|
||||
GradleFlag(['-p', '--project-dir'],
|
||||
'Specifies the start directory for Gradle. Defaults to '
|
||||
'current directory.'),
|
||||
GradleFlag(['--parallel'],
|
||||
'Build projects in parallel. Gradle will attempt to '
|
||||
'determine the optimal number of executor threads to use.'),
|
||||
GradleFlag(['--priority'],
|
||||
'Specifies the scheduling priority for the Gradle daemon and '
|
||||
"all processes launched by it. Values are 'normal' (default) "
|
||||
"or 'low' [incubating]",
|
||||
True),
|
||||
GradleFlag(['--profile'],
|
||||
'Profile build execution time and generates a report in the '
|
||||
'<build_dir>/reports/profile directory.'),
|
||||
GradleFlag(['--project-cache-dir'],
|
||||
'Specify the project-specific cache directory. Defaults to '
|
||||
'.gradle in the root project directory.',
|
||||
True),
|
||||
GradleFlag(['-q', '--quiet'], 'Log errors only.'),
|
||||
GradleFlag(['--refresh-dependencies'], 'Refresh the state of dependencies.'),
|
||||
GradleFlag(['--rerun-tasks'], 'Ignore previously cached task results.'),
|
||||
GradleFlag(['-S', '--full-stacktrace'],
|
||||
'Print out the full (very verbose) stacktrace for all '
|
||||
'exceptions.'),
|
||||
GradleFlag(['-s', '--stacktrace'],
|
||||
'Print out the stacktrace for all exceptions.'),
|
||||
GradleFlag(['--scan'],
|
||||
'Creates a build scan. Gradle will emit a warning if the '
|
||||
'build scan plugin has not been applied. '
|
||||
'(https://gradle.com/build-scans)'),
|
||||
GradleFlag(['--status'],
|
||||
'Shows status of running and recently stopped Gradle '
|
||||
'Daemon(s).'),
|
||||
GradleFlag(['--stop'], 'Stops the Gradle Daemon if it is running.'),
|
||||
GradleFlag(['-t', '--continuous'],
|
||||
'Enables continuous build. Gradle does not exit and will '
|
||||
're-execute tasks when task file inputs change.'),
|
||||
GradleFlag(['--update-locks'],
|
||||
'Perform a partial update of the dependency lock, letting '
|
||||
'passed in module notations change version. [incubating]'),
|
||||
GradleFlag(['-v', '--version'], 'Print version info.'),
|
||||
GradleFlag(['-w', '--warn'], 'Set log level to warn.'),
|
||||
GradleFlag(['--warning-mode'],
|
||||
'Specifies which mode of warnings to generate. Values are '
|
||||
"'all', 'fail', 'summary'(default) or 'none'",
|
||||
True),
|
||||
GradleFlag(['--write-locks'],
|
||||
'Persists dependency resolution for locked configurations, '
|
||||
'ignoring existing locking information if it exists '
|
||||
'[incubating]'),
|
||||
GradleFlag(['-x', '--exclude-task'],
|
||||
'Specify a task to be excluded from execution.',
|
||||
True),
|
||||
]
|
||||
|
||||
def generate_gradle_properties() -> str:
|
||||
"""Returns the expected contents of gradle.properties."""
|
||||
out = io.StringIO()
|
||||
out.write(PROPERTIES_HEADER)
|
||||
|
||||
for prop in PROPERTIES:
|
||||
out.write(f'{prop.name}={prop.default}\n')
|
||||
|
||||
return out.getvalue()
|
||||
|
||||
|
||||
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 \
|
||||
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
|
||||
|
||||
|
||||
class Abort(Exception):
|
||||
"""Raised to terminate the process with a non-zero error code.
|
||||
|
||||
Parameters are ignored.
|
||||
"""
|
||||
|
||||
|
||||
def do_pseudo_task(task: str) -> None:
|
||||
root = get_root()
|
||||
if task == ':nom:generate_golden_file':
|
||||
if not subprocess.call([f'{root}/gradlew', ':db:test']):
|
||||
print('\033[33mWARNING:\033[0m Golden schema appears to be '
|
||||
'up-to-date. If you are making schema changes, be sure to '
|
||||
'add a flyway file for them.')
|
||||
return
|
||||
print('\033[33mWARNING:\033[0m Ignore the above failure, it is '
|
||||
'expected.')
|
||||
|
||||
# Copy the new schema into place.
|
||||
shutil.copy(f'{root}/db/build/resources/test/testcontainer/'
|
||||
'mount/dump.txt',
|
||||
f'{root}/db/src/main/resources/sql/schema/'
|
||||
'nomulus.golden.sql')
|
||||
|
||||
# Rerun :db:test and regenerate the ER diagram (at "warning" log
|
||||
# level so it doesn't generate pages of messaging)
|
||||
if subprocess.call([f'{root}/gradlew', ':db:test', 'devTool',
|
||||
'--args=-e localhost --log_level=WARNING '
|
||||
'generate_sql_er_diagram -o '
|
||||
f'{root}/db/src/main/resources/sql/er_diagram']):
|
||||
print('\033[31mERROR:\033[0m Golden file test or ER diagram '
|
||||
'generation failed after copying schema. Please check your '
|
||||
'flyway files.')
|
||||
raise Abort()
|
||||
else:
|
||||
print(f'\033[31mERROR:\033[0m Unknown task {task}')
|
||||
raise Abort()
|
||||
|
||||
|
||||
def main(args) -> int:
|
||||
parser = argparse.ArgumentParser('nom_build', description=HELP_TEXT,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
for prop in PROPERTIES:
|
||||
parser.add_argument('--' + prop.name, default=prop.default,
|
||||
help=prop.desc)
|
||||
|
||||
# Add Gradle flags. We set 'dest' to the first flag to get a name that is
|
||||
# predictable for getattr (even though it will have a leading '-' and thus
|
||||
# we can't use normal python attribute syntax to get it).
|
||||
for flag in GRADLE_FLAGS:
|
||||
if flag.has_arg:
|
||||
parser.add_argument(*flag.flags, dest=flag.flags[0],
|
||||
help=flag.desc)
|
||||
else:
|
||||
parser.add_argument(*flag.flags, dest=flag.flags[0],
|
||||
help=flag.desc,
|
||||
action='store_true')
|
||||
|
||||
# Add a flag to regenerate the gradle properties file.
|
||||
parser.add_argument('--generate-gradle-properties',
|
||||
help='Regenerate the gradle.properties file. This '
|
||||
'file must be regenerated when changes are made to '
|
||||
'config/nom_build.py, and should not be updated by '
|
||||
'hand.',
|
||||
action='store_true')
|
||||
|
||||
# Consume the remaining non-flag arguments.
|
||||
parser.add_argument('non_flag_args', nargs='*')
|
||||
|
||||
# Parse command line arguments. Note that this exits the program and
|
||||
# prints usage if either of the help options (-h, --help) are specified.
|
||||
args = parser.parse_args(args)
|
||||
|
||||
gradle_properties = generate_gradle_properties()
|
||||
root = get_root()
|
||||
|
||||
# If we're regenerating properties, do so and exit.
|
||||
if args.generate_gradle_properties:
|
||||
with open(f'{root}/gradle.properties', 'w') as dst:
|
||||
dst.write(gradle_properties)
|
||||
return 0
|
||||
|
||||
# Verify that the gradle properties file is what we expect it to be.
|
||||
with open(f'{root}/gradle.properties') as src:
|
||||
if src.read() != gradle_properties:
|
||||
print('\033[33mWARNING:\033[0m Gradle properties out of sync '
|
||||
'with nom_build. Run with --generate-gradle-properties '
|
||||
'to regenerate.')
|
||||
|
||||
# Add properties to the gradle argument list.
|
||||
gradle_command = [f'{root}/gradlew']
|
||||
for prop in PROPERTIES:
|
||||
arg_val = getattr(args, prop.name)
|
||||
if arg_val != prop.default:
|
||||
prop.validate(arg_val)
|
||||
gradle_command.extend(['-P', f'{prop.name}={arg_val}'])
|
||||
|
||||
# Add Gradle flags to the gradle argument list.
|
||||
for flag in GRADLE_FLAGS:
|
||||
arg_val = getattr(args, flag.flags[0])
|
||||
if arg_val:
|
||||
gradle_command.append(flag.flags[-1])
|
||||
if flag.has_arg:
|
||||
gradle_command.append(arg_val)
|
||||
|
||||
# See if there are any special ":nom:" pseudo-tasks specified.
|
||||
got_non_pseudo_tasks = False
|
||||
got_pseudo_tasks = False
|
||||
for arg in args.non_flag_args[1:]:
|
||||
if arg.startswith(':nom:'):
|
||||
if got_non_pseudo_tasks:
|
||||
# We can't currently deal with the situation of gradle tasks
|
||||
# before pseudo-tasks. This could be implemented by invoking
|
||||
# gradle for only the set of gradle tasks before the pseudo
|
||||
# task, but that's overkill for now.
|
||||
print(f'\033[31mERROR:\033[0m Pseudo task ({arg}) must be '
|
||||
'specified prior to all actual gradle tasks. Aborting.')
|
||||
return 1
|
||||
do_pseudo_task(arg)
|
||||
got_pseudo_tasks = True
|
||||
else:
|
||||
got_non_pseudo_tasks = True
|
||||
non_flag_args = [
|
||||
arg for arg in args.non_flag_args[1:] if not arg.startswith(':nom:')]
|
||||
|
||||
if not non_flag_args:
|
||||
if not got_pseudo_tasks:
|
||||
print('\033[33mWARNING:\033[0m No tasks specified. Not '
|
||||
'doing anything')
|
||||
return 0
|
||||
|
||||
# Add the non-flag args (we exclude the first, which is the command name
|
||||
# itself) and run.
|
||||
gradle_command.extend(non_flag_args)
|
||||
return subprocess.call(gradle_command)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
sys.exit(main(sys.argv))
|
||||
except Abort as ex:
|
||||
sys.exit(1)
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
# Copyright 2020 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 io
|
||||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
from unittest import mock
|
||||
import nom_build
|
||||
import subprocess
|
||||
|
||||
FAKE_PROPERTIES = [
|
||||
nom_build.Property('foo', 'help text'),
|
||||
nom_build.Property('bar', 'more text', 'true', bool),
|
||||
]
|
||||
|
||||
FAKE_PROP_CONTENTS = nom_build.PROPERTIES_HEADER + 'foo=\nbar=true\n'
|
||||
PROPERTIES_FILENAME = '/tmp/rootdir/gradle.properties'
|
||||
GRADLEW = '/tmp/rootdir/gradlew'
|
||||
|
||||
|
||||
class FileFake(io.StringIO):
|
||||
"""File fake that writes file contents to the dictionary on close."""
|
||||
def __init__(self, contents_dict, filename):
|
||||
self.dict = contents_dict
|
||||
self.filename = filename
|
||||
super(FileFake, self).__init__()
|
||||
|
||||
def close(self):
|
||||
self.dict[self.filename] = self.getvalue()
|
||||
super(FileFake, self).close()
|
||||
|
||||
|
||||
class MyTest(unittest.TestCase):
|
||||
|
||||
def open_fake(self, filename, action='r'):
|
||||
if action == 'r':
|
||||
return io.StringIO(self.file_contents.get(filename, ''))
|
||||
elif action == 'w':
|
||||
result = self.file_contents[filename] = (
|
||||
FileFake(self.file_contents, filename))
|
||||
return result
|
||||
else:
|
||||
raise Exception(f'Unexpected action {action}')
|
||||
|
||||
def print_fake(self, data):
|
||||
self.printed.append(data)
|
||||
|
||||
def setUp(self):
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
self.exists_mock = mock.patch.object(os.path, 'exists').start()
|
||||
self.getcwd_mock = mock.patch.object(os, 'getcwd').start()
|
||||
self.getcwd_mock.return_value = '/tmp/rootdir'
|
||||
self.open_mock = (
|
||||
mock.patch.object(nom_build, 'open', self.open_fake).start())
|
||||
self.print_mock = (
|
||||
mock.patch.object(nom_build, 'print', self.print_fake).start())
|
||||
|
||||
self.call_mock = mock.patch.object(subprocess, 'call').start()
|
||||
self.copy_mock = mock.patch.object(shutil, 'copy').start()
|
||||
|
||||
self.file_contents = {
|
||||
# Prefil with the actual file contents.
|
||||
PROPERTIES_FILENAME: nom_build.generate_gradle_properties()
|
||||
}
|
||||
self.printed = []
|
||||
|
||||
@mock.patch.object(nom_build, 'PROPERTIES', FAKE_PROPERTIES)
|
||||
def test_property_generation(self):
|
||||
self.assertEqual(nom_build.generate_gradle_properties(),
|
||||
FAKE_PROP_CONTENTS)
|
||||
|
||||
@mock.patch.object(nom_build, 'PROPERTIES', FAKE_PROPERTIES)
|
||||
def test_property_file_write(self):
|
||||
nom_build.main(['nom_build', '--generate-gradle-properties'])
|
||||
self.assertEqual(self.file_contents[PROPERTIES_FILENAME],
|
||||
FAKE_PROP_CONTENTS)
|
||||
|
||||
def test_property_file_incorrect(self):
|
||||
self.file_contents[PROPERTIES_FILENAME] = 'bad contents'
|
||||
nom_build.main(['nom_build'])
|
||||
self.assertIn('', self.printed[0])
|
||||
|
||||
def test_no_args(self):
|
||||
nom_build.main(['nom_build'])
|
||||
self.assertEqual(self.printed,
|
||||
['\x1b[33mWARNING:\x1b[0m No tasks specified. Not '
|
||||
'doing anything'])
|
||||
|
||||
def test_property_calls(self):
|
||||
nom_build.main(['nom_build', 'task-name', '--testFilter=foo'])
|
||||
self.call_mock.assert_called_with([GRADLEW, '-P', 'testFilter=foo',
|
||||
'task-name'])
|
||||
|
||||
def test_gradle_flags(self):
|
||||
nom_build.main(['nom_build', 'task-name', '-d', '-b', 'foo'])
|
||||
self.call_mock.assert_called_with([GRADLEW, '--build-file', 'foo',
|
||||
'--debug', 'task-name'])
|
||||
|
||||
def test_generate_golden_file(self):
|
||||
self.call_mock.side_effect = [1, 0]
|
||||
nom_build.main(['nom_build', ':nom:generate_golden_file'])
|
||||
self.call_mock.assert_has_calls([
|
||||
mock.call([GRADLEW, ':db:test']),
|
||||
mock.call([GRADLEW, ':db:test', 'devTool',
|
||||
'--args=-e localhost --log_level=WARNING '
|
||||
'generate_sql_er_diagram -o '
|
||||
'/tmp/rootdir/db/src/main/resources/sql/er_diagram'])
|
||||
])
|
||||
|
||||
def test_generate_golden_file_nofail(self):
|
||||
self.call_mock.return_value = 0
|
||||
nom_build.main(['nom_build', ':nom:generate_golden_file'])
|
||||
self.call_mock.assert_has_calls([mock.call([GRADLEW, ':db:test'])])
|
||||
|
||||
unittest.main()
|
||||
+10
-133
@@ -17,26 +17,16 @@ These aren't built in to the static code analysis tools we use (e.g. Checkstyle,
|
||||
Error Prone) so we must write them manually.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import List, Tuple
|
||||
import sys
|
||||
import textwrap
|
||||
import re
|
||||
|
||||
# We should never analyze any generated files
|
||||
UNIVERSALLY_SKIPPED_PATTERNS = {"/build/", "cloudbuild-caches", "/out/", ".git/", ".gradle/", "/dist/", "karma.conf.js", "polyfills.ts", "test.ts", "/docs/console-endpoints/"}
|
||||
UNIVERSALLY_SKIPPED_PATTERNS = {"/build/", "/out/"}
|
||||
# We can't rely on CI to have the Enum package installed so we do this instead.
|
||||
FORBIDDEN = 1
|
||||
REQUIRED = 2
|
||||
|
||||
# The list of expected json packages and their licenses.
|
||||
# These should be one of the allowed licenses in:
|
||||
# config/dependency-license/allowed_licenses.json
|
||||
EXPECTED_JS_PACKAGES = [
|
||||
'google-closure-library', # Owned by Google, Apache 2.0
|
||||
]
|
||||
|
||||
|
||||
class PresubmitCheck:
|
||||
|
||||
@@ -74,7 +64,7 @@ class PresubmitCheck:
|
||||
for pattern in self.skipped_patterns:
|
||||
if pattern in file:
|
||||
return False
|
||||
with open(file, "r", encoding='utf8') as f:
|
||||
with open(file, "r") as f:
|
||||
file_content = f.read()
|
||||
matches = re.match(self.regex, file_content, re.DOTALL)
|
||||
if self.regex_type == FORBIDDEN:
|
||||
@@ -86,16 +76,16 @@ PRESUBMITS = {
|
||||
# License check
|
||||
PresubmitCheck(
|
||||
r".*Copyright 20\d{2} The Nomulus Authors\. All Rights Reserved\.",
|
||||
("java", "js", "soy", "sql", "py", "sh", "gradle", "ts"), {
|
||||
".git", "/build/", "/bin/generated-sources/", "/bin/generated-test-sources/",
|
||||
"node_modules/", "LoggerConfig.java", "registrar_bin.",
|
||||
"registrar_dbg.", "google-java-format-diff.py",
|
||||
"nomulus.golden.sql", "soyutils_usegoog.js", "javascript/checks.js"
|
||||
("java", "js", "soy", "sql", "py", "sh", "gradle"), {
|
||||
".git", "/build/", "/generated/", "node_modules/",
|
||||
"JUnitBackports.java", "registrar_bin.", "registrar_dbg.",
|
||||
"google-java-format-diff.py",
|
||||
"nomulus.golden.sql"
|
||||
}, REQUIRED):
|
||||
"File did not include the license header.",
|
||||
|
||||
# Files must end in a newline
|
||||
PresubmitCheck(r".*\n$", ("java", "js", "soy", "sql", "py", "sh", "gradle", "ts"),
|
||||
PresubmitCheck(r".*\n$", ("java", "js", "soy", "sql", "py", "sh", "gradle"),
|
||||
{"node_modules/"}, REQUIRED):
|
||||
"Source files must end in a newline.",
|
||||
|
||||
@@ -103,7 +93,7 @@ PRESUBMITS = {
|
||||
PresubmitCheck(
|
||||
r".*\bSystem\.(out|err)\.print", "java", {
|
||||
"StackdriverDashboardBuilder.java", "/tools/", "/example/",
|
||||
"RegistryTestServerMain.java", "TestServerExtension.java",
|
||||
"RegistryTestServerMain.java", "TestServerRule.java",
|
||||
"FlowDocumentationTool.java"
|
||||
}):
|
||||
"System.(out|err).println is only allowed in tools/ packages. Please "
|
||||
@@ -170,113 +160,9 @@ PRESUBMITS = {
|
||||
"js",
|
||||
{"/node_modules/", "google/registry/ui/js/util.js", "registrar_bin."},
|
||||
):
|
||||
"JavaScript files should not include console logging.",
|
||||
"JavaScript files should not include console logging."
|
||||
}
|
||||
|
||||
# Note that this regex only works for one kind of Flyway file. If we want to
|
||||
# start using "R" and "U" files we'll need to update this script.
|
||||
FLYWAY_FILE_RX = re.compile(r'V(\d+)__.*')
|
||||
|
||||
|
||||
def get_seqnum(filename: str, location: str) -> int:
|
||||
"""Extracts the sequence number from a filename."""
|
||||
m = FLYWAY_FILE_RX.match(filename)
|
||||
if m is None:
|
||||
raise ValueError('Illegal Flyway filename: %s in %s' % (filename, location))
|
||||
return int(m.group(1))
|
||||
|
||||
|
||||
def files_by_seqnum(files: List[str], location: str) -> List[Tuple[int, str]]:
|
||||
"""Returns the list of seqnum, filename sorted by sequence number."""
|
||||
return [(get_seqnum(filename, location), filename) for filename in files]
|
||||
|
||||
|
||||
def has_valid_order(indexed_files: List[Tuple[int, str]], location: str) -> bool:
|
||||
"""Verify that sequence numbers are in order without gaps or duplicates.
|
||||
|
||||
Args:
|
||||
files: List of seqnum, filename for a list of Flyway files.
|
||||
location: Where the list of files came from (for error reporting).
|
||||
|
||||
Returns:
|
||||
True if the file list is valid.
|
||||
"""
|
||||
last_index = 0
|
||||
valid = True
|
||||
for seqnum, filename in indexed_files:
|
||||
if seqnum == last_index:
|
||||
print('duplicate Flyway file sequence number found in %s: %s' %
|
||||
(location, filename))
|
||||
valid = False
|
||||
elif seqnum < last_index:
|
||||
print('File %s in %s is out of order.' % (filename, location))
|
||||
valid = False
|
||||
elif seqnum != last_index + 1:
|
||||
print('Missing Flyway sequence number %d in %s. Next file is %s' %
|
||||
(last_index + 1, location, filename))
|
||||
valid = False
|
||||
last_index = seqnum
|
||||
return valid
|
||||
|
||||
|
||||
def verify_flyway_index():
|
||||
"""Verifies that the Flyway index file is in sync with the directory."""
|
||||
success = True
|
||||
|
||||
# Sort the files in the Flyway directory by their sequence number.
|
||||
files = sorted(
|
||||
files_by_seqnum(os.listdir('db/src/main/resources/sql/flyway'),
|
||||
'Flyway directory'))
|
||||
|
||||
# Make sure that there are no gaps and no duplicate sequence numbers in the
|
||||
# files themselves.
|
||||
if not has_valid_order(files, 'Flyway directory'):
|
||||
success = False
|
||||
|
||||
# Remove the sequence numbers and compare against the index file contents.
|
||||
files = [filename[1] for filename in sorted(files)]
|
||||
with open('db/src/main/resources/sql/flyway.txt', encoding='utf8') as index:
|
||||
indexed_files = index.read().splitlines()
|
||||
if files != indexed_files:
|
||||
unindexed = set(files) - set(indexed_files)
|
||||
if unindexed:
|
||||
print('The following Flyway files are not in flyway.txt: %s' % unindexed)
|
||||
|
||||
nonexistent = set(indexed_files) - set(files)
|
||||
if nonexistent:
|
||||
print('The following files are in flyway.txt but not in the Flyway '
|
||||
'directory: %s' % nonexistent)
|
||||
|
||||
# Do an ordering check on the index file (ignore the result, we're failing
|
||||
# anyway).
|
||||
has_valid_order(files_by_seqnum(indexed_files, 'flyway.txt'), 'flyway.txt')
|
||||
success = False
|
||||
|
||||
if not success:
|
||||
print('Please fix any conflicts and run "./nom_build :db:generateFlywayIndex"')
|
||||
|
||||
return not success
|
||||
|
||||
|
||||
def verify_javascript_deps():
|
||||
"""Verifies that we haven't introduced any new javascript dependencies."""
|
||||
with open('package.json') as f:
|
||||
package = json.load(f)
|
||||
|
||||
deps = list(package['dependencies'].keys())
|
||||
if deps != EXPECTED_JS_PACKAGES:
|
||||
print('Unexpected javascript dependencies. Was expecting '
|
||||
'%s, got %s.' % (EXPECTED_JS_PACKAGES, deps))
|
||||
print(textwrap.dedent("""
|
||||
* If the new dependencies are intentional, please verify that the
|
||||
* license is one of the allowed licenses (see
|
||||
* config/dependency-license/allowed_licenses.json) and add an entry
|
||||
* for the package (with the license in a comment) to the
|
||||
* EXPECTED_JS_PACKAGES variable in config/presubmits.py.
|
||||
"""))
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_files():
|
||||
for root, dirnames, filenames in os.walk("."):
|
||||
@@ -285,7 +171,6 @@ def get_files():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print('python version is %s' % sys.version)
|
||||
failed = False
|
||||
for file in get_files():
|
||||
error_messages = []
|
||||
@@ -297,13 +182,5 @@ if __name__ == "__main__":
|
||||
failed = True
|
||||
print("%s had errors: \n %s" % (file, "\n ".join(error_messages)))
|
||||
|
||||
# And now for something completely different: check to see if the Flyway
|
||||
# index is up-to-date. It's quicker to do it here than in the unit tests:
|
||||
# when we put it here it fails fast before all of the tests are run.
|
||||
failed |= verify_flyway_index()
|
||||
|
||||
# Make sure we haven't introduced any javascript dependencies.
|
||||
failed |= verify_javascript_deps()
|
||||
|
||||
if failed:
|
||||
sys.exit(1)
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
# Copyright 2021 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.
|
||||
|
||||
"""Show the set of dependency diffs introduced by a branch.
|
||||
|
||||
Usage:
|
||||
show-upgrade-diffs.py [-d <directory>] <user> <branch>
|
||||
|
||||
Assumes that there is a <user>/nomulus repository on github with the specified
|
||||
branch name.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import six
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from typing import cast, Dict, Set, Tuple, Union
|
||||
|
||||
|
||||
def run(*args):
|
||||
if subprocess.call(args):
|
||||
raise Abort(f'"{" ".join(args)}" failed')
|
||||
|
||||
|
||||
PackageName = Tuple[bytes, bytes]
|
||||
VersionSet = Set[bytes]
|
||||
PackageMap = Dict[PackageName, VersionSet]
|
||||
|
||||
RED = b'\033[40;31;1m'
|
||||
GREEN = b'\033[40;32;1m'
|
||||
|
||||
|
||||
class Abort(Exception):
|
||||
"""Raised to abort processing and record an error."""
|
||||
|
||||
|
||||
def merge(dest: PackageMap, new: PackageMap) -> None:
|
||||
for key, val in new.items():
|
||||
dest[key] = dest.setdefault(key, set()) | val
|
||||
|
||||
|
||||
def parse_lockfile(filename: str) -> PackageMap:
|
||||
result: PackageMap = {}
|
||||
for line in open(filename, 'rb'):
|
||||
if line.startswith(b'#'):
|
||||
continue
|
||||
line = line.rstrip()
|
||||
package = line.split(b'=')[0]
|
||||
if package == 'empty':
|
||||
continue
|
||||
package = cast(Tuple[bytes, bytes, bytes], tuple(package.split(b':')))
|
||||
result.setdefault(package[:-1], set()).add(package[-1])
|
||||
return result
|
||||
|
||||
|
||||
def get_all_package_versions(dir: str) -> PackageMap:
|
||||
"""Return list of all package versions in the directory."""
|
||||
packages = {}
|
||||
for file in os.listdir(dir):
|
||||
file = os.path.join(dir, file)
|
||||
if file.endswith('.lockfile'):
|
||||
merge(packages, parse_lockfile(file))
|
||||
elif os.path.isdir(file):
|
||||
merge(packages, get_all_package_versions(file))
|
||||
return packages
|
||||
|
||||
|
||||
def pr(*args: Union[str, bytes]) -> None:
|
||||
"""Print replacement that prints bytes without weird conversions."""
|
||||
for text in args:
|
||||
sys.stdout.buffer.write(six.ensure_binary(text))
|
||||
sys.stdout.buffer.flush()
|
||||
|
||||
|
||||
def format_versions(a: VersionSet, b: VersionSet, missing_esc: bytes) -> bytes:
|
||||
"""Returns a formatted string of the elements of "a".
|
||||
|
||||
Returns the elements of "a" as a comma-separated string, colorizes the
|
||||
elements of "a" that are not also in "b" with "missing_esc".
|
||||
|
||||
Args:
|
||||
a: Elements to print.
|
||||
b: Other set, if a printed element is not a member of "b" it is
|
||||
colorized.
|
||||
missing_esc: ANSI terminal sequence to use to colorize elements that
|
||||
are missing from "b".
|
||||
"""
|
||||
elems = []
|
||||
for item in a:
|
||||
if item in b:
|
||||
elems.append(item)
|
||||
else:
|
||||
elems.append(missing_esc + item + b'\033[0m')
|
||||
return b', '.join(elems)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--directory', '-d', type=str, default='',
|
||||
dest='directory',
|
||||
help=('Directory to use for a local git '
|
||||
'repository. By default, this script clones '
|
||||
'the nomulus repo into a temporary directory '
|
||||
'which is deleted after the script is run. '
|
||||
'This option allows you to specify the '
|
||||
'directory and causes it to be retained (not '
|
||||
'deleted) after the script is run, allowing '
|
||||
'it to be reused for subsequent runs, speeding '
|
||||
'them up considerably.'))
|
||||
parser.add_argument('user', type=str,
|
||||
help=('The name of the user on github. The full '
|
||||
'github repository name is presumed to be '
|
||||
'"$user/nomulus".'))
|
||||
parser.add_argument('branch', type=str,
|
||||
help='The git branch containing the changes.')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
user = args.user
|
||||
branch = args.branch
|
||||
if not args.directory:
|
||||
tempdir = tempfile.TemporaryDirectory()
|
||||
dir = tempdir.name
|
||||
else:
|
||||
dir = args.directory
|
||||
|
||||
# Either clone or fetch the master branch if it exists.
|
||||
if args.directory and os.path.exists(dir):
|
||||
pr(f'Reusing directory {dir}\n')
|
||||
os.chdir(dir)
|
||||
run('git', 'fetch', 'git@github.com:google/nomulus', 'master')
|
||||
run('git', 'checkout', 'origin/master')
|
||||
else:
|
||||
run('git', 'clone', 'git@github.com:google/nomulus', dir)
|
||||
os.chdir(dir)
|
||||
|
||||
old_packages = get_all_package_versions('.')
|
||||
run('git', 'fetch', f'https://github.com/{user}/nomulus.git',
|
||||
f'{branch}:{branch}')
|
||||
run('git', 'checkout', branch)
|
||||
new_packages = get_all_package_versions('.')
|
||||
|
||||
if new_packages != old_packages:
|
||||
pr('\n\nPackage version change report:\n')
|
||||
pr('change package-name: {old versions} -> {new versions}\n')
|
||||
pr('=====================================================\n\n')
|
||||
for package, new_versions in new_packages.items():
|
||||
old_versions = old_packages.get(package)
|
||||
if not old_versions:
|
||||
pr('added ', b':'.join(package), ': {',
|
||||
format_versions(new_versions, set(), GREEN),
|
||||
'}\n')
|
||||
elif new_versions != old_versions:
|
||||
|
||||
# Print out "package-name: {old versions} -> {new versions} with
|
||||
# pretty colors.
|
||||
formatted_old_versions = (
|
||||
format_versions(old_versions, new_versions, RED))
|
||||
formatted_new_versions = (
|
||||
format_versions(new_versions, old_versions, GREEN))
|
||||
pr('updated ', b':'.join(package), ': {',
|
||||
formatted_old_versions, '} -> {',
|
||||
formatted_new_versions, '}\n')
|
||||
|
||||
# Print the list of packages that were removed.
|
||||
for package in old_packages:
|
||||
if package not in new_packages:
|
||||
pr('removed ', b':'.join(package), '\n')
|
||||
else:
|
||||
pr('Package versions not updated!\n')
|
||||
|
||||
if args.directory:
|
||||
pr(f'\nRetaining git directory {dir}, to delete: rm -rf {dir}\n')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,16 +0,0 @@
|
||||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.ts]
|
||||
quote_type = single
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"ignorePatterns": [
|
||||
"projects/**/*"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.ts"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@angular-eslint/recommended",
|
||||
"plugin:@angular-eslint/template/process-inline-templates"
|
||||
],
|
||||
"rules": {
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "attribute",
|
||||
"prefix": "app",
|
||||
"style": "camelCase"
|
||||
}
|
||||
],
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "element",
|
||||
"prefix": "app",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
],
|
||||
"eol-last": [
|
||||
"error",
|
||||
"always"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.html"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:@angular-eslint/template/recommended"
|
||||
],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# Compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
/bazel-out
|
||||
|
||||
# Node
|
||||
/node_modules
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# IDEs and editors
|
||||
.idea/
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# Miscellaneous
|
||||
/.angular/cache
|
||||
.sass-cache/
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -1 +0,0 @@
|
||||
{}
|
||||
@@ -1,52 +0,0 @@
|
||||
# ConsoleWebapp
|
||||
|
||||
A web application for managing [Nomulus](https://github.com/google/nomulus).
|
||||
|
||||
## Status
|
||||
|
||||
Console webapp is currently under active development and some parts of it are
|
||||
expected to change.
|
||||
|
||||
## Deployment
|
||||
|
||||
Webapp is deployed with the nomulus default service war to Google App Engine.
|
||||
During nomulus default service war build task, gradle script triggers the
|
||||
following:
|
||||
|
||||
1) Console webapp build script `buildConsoleWebappProd`, which installs
|
||||
dependencies, assembles a compiled ts -> js, minified, optimized static
|
||||
artifact (html, css, js)
|
||||
2) Artifact assembled in step 1 then gets copied to core project web artifact
|
||||
location, so that it can be deployed with the rest of the core webapp
|
||||
|
||||
## Development server
|
||||
|
||||
Run `npm run start:dev` to start both webapp dev server and API server instance.
|
||||
Navigate to `http://localhost:4200/`. The application will automatically reload
|
||||
if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can
|
||||
also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in
|
||||
the `dist/` directory.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests
|
||||
via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To
|
||||
use this command, you need to first add a package that implements end-to-end
|
||||
testing capabilities.
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out
|
||||
the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
||||
@@ -1,130 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"console-webapp": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
}
|
||||
},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/console-webapp",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/theme.scss",
|
||||
"src/styles.scss"
|
||||
],
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": ["node_modules/"]
|
||||
},
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "2kb",
|
||||
"maximumError": "4kb"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"buildOptimizer": false,
|
||||
"optimization": false,
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "console-webapp:build:production"
|
||||
},
|
||||
"development": {
|
||||
"browserTarget": "console-webapp:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "console-webapp:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/theme.scss",
|
||||
"src/styles.scss"
|
||||
],
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": ["node_modules/"]
|
||||
},
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.html"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"analytics": false,
|
||||
"schematicCollections": [
|
||||
"@angular-eslint/schematics"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
def consoleDir = "${rootDir}/console-webapp"
|
||||
|
||||
clean {
|
||||
delete "${consoleDir}/node_modules"
|
||||
delete "${consoleDir}/dist"
|
||||
}
|
||||
|
||||
task npmInstallDeps(type: Exec) {
|
||||
workingDir "${consoleDir}/"
|
||||
executable 'npm'
|
||||
args 'i', '--no-audit', '--no-fund', '--loglevel=error'
|
||||
}
|
||||
|
||||
task runConsoleWebappLocally(type: Exec) {
|
||||
workingDir "${consoleDir}/"
|
||||
executable 'npm'
|
||||
args 'run', 'start:dev'
|
||||
}
|
||||
|
||||
task runConsoleWebappUnitTests(type: Exec) {
|
||||
workingDir "${consoleDir}/"
|
||||
executable 'npm'
|
||||
args 'run', 'test'
|
||||
}
|
||||
|
||||
task buildConsoleWebappNonProd(type: Exec) {
|
||||
workingDir "${consoleDir}/"
|
||||
executable 'npm'
|
||||
args 'run', 'build'
|
||||
}
|
||||
|
||||
// Keeping the same as non prod for now before we figure out optimization we want to include
|
||||
task buildConsoleWebappProd(type: Exec) {
|
||||
workingDir "${consoleDir}/"
|
||||
executable 'npm'
|
||||
args 'run', 'build'
|
||||
}
|
||||
|
||||
task applyFormatting(type: Exec) {
|
||||
workingDir "${consoleDir}/"
|
||||
executable 'npm'
|
||||
args 'run', 'prettify'
|
||||
}
|
||||
|
||||
task checkFormatting(type: Exec) {
|
||||
workingDir "${consoleDir}/"
|
||||
executable 'npm'
|
||||
args 'run', 'prettify:check'
|
||||
}
|
||||
|
||||
tasks.runConsoleWebappUnitTests.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.buildConsoleWebappProd.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.applyFormatting.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.checkFormatting.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.build.dependsOn(tasks.checkFormatting)
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"/console-api":
|
||||
{
|
||||
"target": "http://localhost:8080",
|
||||
"secure": false,
|
||||
"logLevel": "debug",
|
||||
"changeOrigin": true
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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,errorprone,testAnnotationProcessor
|
||||
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle
|
||||
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.errorprone:javac:9+181-r4173-1=errorproneJavac
|
||||
com.google.guava:failureaccess:1.0.1=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor
|
||||
com.google.guava:guava-parent:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.guava:guava:31.0.1-jre=checkstyle
|
||||
com.google.guava:guava:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle
|
||||
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.j2objc:j2objc-annotations:1.3=checkstyle
|
||||
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.puppycrawl.tools:checkstyle:9.3=checkstyle
|
||||
commons-beanutils:commons-beanutils:1.9.4=checkstyle
|
||||
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
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
net.sf.saxon:Saxon-HE:10.6=checkstyle
|
||||
org.antlr:antlr4-runtime:4.9.3=checkstyle
|
||||
org.checkerframework:checker-qual:3.12.0=checkstyle
|
||||
org.checkerframework:checker-qual:3.33.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
org.jacoco:org.jacoco.agent:0.8.9=jacocoAgent,jacocoAnt
|
||||
org.jacoco:org.jacoco.ant:0.8.9=jacocoAnt
|
||||
org.jacoco:org.jacoco.core:0.8.9=jacocoAnt
|
||||
org.jacoco:org.jacoco.report:0.8.9=jacocoAnt
|
||||
org.javassist:javassist:3.28.0-GA=checkstyle
|
||||
org.ow2.asm:asm-commons:9.5=jacocoAnt
|
||||
org.ow2.asm:asm-tree:9.5=jacocoAnt
|
||||
org.ow2.asm:asm:9.5=jacocoAnt
|
||||
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
org.reflections:reflections:0.10.2=checkstyle
|
||||
empty=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
@@ -1,44 +0,0 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
},
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true // removes the duplicated traces
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/console-webapp'),
|
||||
subdir: '.',
|
||||
reporters: [
|
||||
{ type: 'html' },
|
||||
{ type: 'text-summary' }
|
||||
]
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
};
|
||||
Generated
-15499
File diff suppressed because it is too large
Load Diff
@@ -1,57 +0,0 @@
|
||||
{
|
||||
"name": "console-webapp",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --proxy-config dev-proxy.config.json",
|
||||
"build": "ng build --base-href=/console/",
|
||||
"build:local": "ng build --base-href=/default/console/",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test --browsers=ChromeHeadless --watch=false",
|
||||
"run:dev": "",
|
||||
"prettify": "npx prettier --write ./src/",
|
||||
"prettify:check": "npx prettier --check ./src/",
|
||||
"start:dev": "concurrently \"./../gradlew :core:runTestServer\" \"ng serve --proxy-config dev-proxy.config.json\"",
|
||||
"lint": "ng lint"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^17.0.7",
|
||||
"@angular/cdk": "^17.0.4",
|
||||
"@angular/common": "^17.0.7",
|
||||
"@angular/compiler": "^17.0.7",
|
||||
"@angular/core": "^17.0.7",
|
||||
"@angular/forms": "^17.0.7",
|
||||
"@angular/material": "^17.0.4",
|
||||
"@angular/platform-browser": "^17.0.7",
|
||||
"@angular/platform-browser-dynamic": "^17.0.7",
|
||||
"@angular/router": "^17.0.7",
|
||||
"rxjs": "~7.5.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^17.0.7",
|
||||
"@angular-eslint/builder": "17.1.1",
|
||||
"@angular-eslint/eslint-plugin": "17.1.1",
|
||||
"@angular-eslint/eslint-plugin-template": "17.1.1",
|
||||
"@angular-eslint/schematics": "17.1.1",
|
||||
"@angular-eslint/template-parser": "17.1.1",
|
||||
"@angular/cli": "~17.0.7",
|
||||
"@angular/compiler-cli": "^17.0.7",
|
||||
"@types/jasmine": "~4.0.0",
|
||||
"@types/node": "^18.11.18",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.2",
|
||||
"@typescript-eslint/parser": "^5.59.2",
|
||||
"concurrently": "^7.6.0",
|
||||
"eslint": "^8.39.0",
|
||||
"jasmine-core": "~4.3.0",
|
||||
"karma": "~6.4.0",
|
||||
"karma-chrome-launcher": "~3.1.0",
|
||||
"karma-coverage": "~2.2.0",
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "~2.0.0",
|
||||
"prettier": "2.8.7",
|
||||
"typescript": "~5.2.2"
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
// Copyright 2023 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 { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { TldsComponent } from './tlds/tlds.component';
|
||||
import { HomeComponent } from './home/home.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import SettingsContactComponent from './settings/contact/contact.component';
|
||||
import SettingsWhoisComponent from './settings/whois/whois.component';
|
||||
import SettingsUsersComponent from './settings/users/users.component';
|
||||
import SettingsSecurityComponent from './settings/security/security.component';
|
||||
import { RegistrarGuard } from './registrar/registrar.guard';
|
||||
import { RegistrarComponent } from './registrar/registrarsTable.component';
|
||||
import { EmptyRegistrar } from './registrar/emptyRegistrar.component';
|
||||
import ContactComponent from './settings/contact/contact.component';
|
||||
import WhoisComponent from './settings/whois/whois.component';
|
||||
import SecurityComponent from './settings/security/security.component';
|
||||
import UsersComponent from './settings/users/users.component';
|
||||
import { DomainListComponent } from './domains/domainList.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||
{ path: 'registrars', component: RegistrarComponent },
|
||||
{ path: 'empty-registrar', component: EmptyRegistrar },
|
||||
{ path: 'home', component: HomeComponent, canActivate: [RegistrarGuard] },
|
||||
{ path: 'tlds', component: TldsComponent, canActivate: [RegistrarGuard] },
|
||||
{
|
||||
path: DomainListComponent.PATH,
|
||||
component: DomainListComponent,
|
||||
canActivate: [RegistrarGuard],
|
||||
},
|
||||
{
|
||||
path: SettingsComponent.PATH,
|
||||
component: SettingsComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'registrars',
|
||||
pathMatch: 'full',
|
||||
},
|
||||
{
|
||||
path: ContactComponent.PATH,
|
||||
component: SettingsContactComponent,
|
||||
canActivate: [RegistrarGuard],
|
||||
},
|
||||
{
|
||||
path: WhoisComponent.PATH,
|
||||
component: SettingsWhoisComponent,
|
||||
canActivate: [RegistrarGuard],
|
||||
},
|
||||
{
|
||||
path: SecurityComponent.PATH,
|
||||
component: SettingsSecurityComponent,
|
||||
canActivate: [RegistrarGuard],
|
||||
},
|
||||
{
|
||||
path: UsersComponent.PATH,
|
||||
component: SettingsUsersComponent,
|
||||
canActivate: [RegistrarGuard],
|
||||
},
|
||||
{
|
||||
path: RegistrarComponent.PATH,
|
||||
component: RegistrarComponent,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes, { useHash: true })],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
@@ -1,26 +0,0 @@
|
||||
<div class="console-app">
|
||||
<app-header (toggleNavOpen)="sidenav.toggle()"></app-header>
|
||||
<mat-sidenav-container class="console-app__container">
|
||||
<mat-sidenav #sidenav class="console-app__sidebar">
|
||||
<mat-nav-list>
|
||||
<a mat-list-item [routerLink]="'/home'" routerLinkActive="active">
|
||||
Home page
|
||||
</a>
|
||||
<a mat-list-item [routerLink]="'/tlds'" routerLinkActive="active">
|
||||
TLDS
|
||||
</a>
|
||||
<a mat-list-item [routerLink]="'/settings'" routerLinkActive="active">
|
||||
Settings
|
||||
</a>
|
||||
</mat-nav-list>
|
||||
</mat-sidenav>
|
||||
<mat-sidenav-content class="console-app__content-wrapper">
|
||||
<div *ngIf="globalLoader.isLoading" class="console-app__global-spinner">
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
</div>
|
||||
<div class="console-app__content" *ngIf="renderRouter">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</mat-sidenav-content>
|
||||
</mat-sidenav-container>
|
||||
</div>
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright 2023 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.
|
||||
|
||||
:host {
|
||||
font-family: Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji",
|
||||
"Segoe UI Emoji", "Segoe UI Symbol" !important;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
box-sizing: border-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.console-app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
&__container {
|
||||
flex: 1;
|
||||
margin-top: -12px;
|
||||
padding-bottom: 36px;
|
||||
}
|
||||
&__sidebar {
|
||||
min-width: 300px;
|
||||
a::before {
|
||||
background-color: transparent;
|
||||
}
|
||||
.active {
|
||||
background-color: var(--secondary);
|
||||
}
|
||||
}
|
||||
&__content-wrapper {
|
||||
margin: 12px 24px;
|
||||
}
|
||||
&__content {
|
||||
max-width: 1340px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
&__global-spinner {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright 2022 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 { TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MaterialModule } from './material.module';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { BackendService } from './shared/services/backend.service';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
HttpClientTestingModule,
|
||||
RouterTestingModule,
|
||||
MaterialModule,
|
||||
BrowserAnimationsModule,
|
||||
],
|
||||
providers: [BackendService],
|
||||
declarations: [AppComponent],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2022 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 { AfterViewInit, Component, ViewChild, effect } from '@angular/core';
|
||||
import { RegistrarService } from './registrar/registrar.service';
|
||||
import { UserDataService } from './shared/services/userData.service';
|
||||
import { GlobalLoaderService } from './shared/services/globalLoader.service';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { MatSidenav } from '@angular/material/sidenav';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
})
|
||||
export class AppComponent implements AfterViewInit {
|
||||
renderRouter: boolean = true;
|
||||
|
||||
@ViewChild('sidenav')
|
||||
sidenav!: MatSidenav;
|
||||
|
||||
constructor(
|
||||
protected registrarService: RegistrarService,
|
||||
protected userDataService: UserDataService,
|
||||
protected globalLoader: GlobalLoaderService,
|
||||
protected router: Router
|
||||
) {
|
||||
effect(() => {
|
||||
if (registrarService.registrarId()) {
|
||||
this.renderRouter = false;
|
||||
setTimeout(() => {
|
||||
this.renderRouter = true;
|
||||
}, 400);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.router.events.subscribe((event) => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
this.sidenav.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
// Copyright 2023 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 { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MaterialModule } from './material.module';
|
||||
|
||||
import { BackendService } from './shared/services/backend.service';
|
||||
|
||||
import { HomeComponent } from './home/home.component';
|
||||
import { TldsComponent } from './tlds/tlds.component';
|
||||
import { HeaderComponent } from './header/header.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import SettingsContactComponent, {
|
||||
ContactDetailsDialogComponent,
|
||||
} from './settings/contact/contact.component';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { RegistrarComponent } from './registrar/registrarsTable.component';
|
||||
import { RegistrarGuard } from './registrar/registrar.guard';
|
||||
import SecurityComponent from './settings/security/security.component';
|
||||
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
||||
import { EmptyRegistrar } from './registrar/emptyRegistrar.component';
|
||||
import { RegistrarSelectorComponent } from './registrar/registrarSelector.component';
|
||||
import { GlobalLoaderService } from './shared/services/globalLoader.service';
|
||||
import { ContactWidgetComponent } from './home/widgets/contactWidget.component';
|
||||
import { PromotionsWidgetComponent } from './home/widgets/promotionsWidget.component';
|
||||
import { TldsWidgetComponent } from './home/widgets/tldsWidget.component';
|
||||
import { ResourcesWidgetComponent } from './home/widgets/resourcesWidget.component';
|
||||
import { EppWidgetComponent } from './home/widgets/eppWidget.component';
|
||||
import { BillingWidgetComponent } from './home/widgets/billingWidget.component';
|
||||
import { DomainsWidgetComponent } from './home/widgets/domainsWidget.component';
|
||||
import { SettingsWidgetComponent } from './home/widgets/settingsWidget.component';
|
||||
import { UserDataService } from './shared/services/userData.service';
|
||||
import WhoisComponent from './settings/whois/whois.component';
|
||||
import { SnackBarModule } from './snackbar.module';
|
||||
import { RegistrarDetailsComponent } from './registrar/registrarDetails.component';
|
||||
import { DomainListComponent } from './domains/domainList.component';
|
||||
import { DialogBottomSheetWrapper } from './shared/components/dialogBottomSheet.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
DialogBottomSheetWrapper,
|
||||
BillingWidgetComponent,
|
||||
ContactDetailsDialogComponent,
|
||||
ContactWidgetComponent,
|
||||
DomainListComponent,
|
||||
DomainsWidgetComponent,
|
||||
EmptyRegistrar,
|
||||
EppWidgetComponent,
|
||||
HeaderComponent,
|
||||
HomeComponent,
|
||||
PromotionsWidgetComponent,
|
||||
RegistrarComponent,
|
||||
RegistrarDetailsComponent,
|
||||
RegistrarSelectorComponent,
|
||||
ResourcesWidgetComponent,
|
||||
SecurityComponent,
|
||||
SettingsComponent,
|
||||
SettingsContactComponent,
|
||||
SettingsWidgetComponent,
|
||||
TldsComponent,
|
||||
TldsWidgetComponent,
|
||||
WhoisComponent,
|
||||
],
|
||||
imports: [
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpClientModule,
|
||||
MaterialModule,
|
||||
SnackBarModule,
|
||||
],
|
||||
providers: [
|
||||
BackendService,
|
||||
GlobalLoaderService,
|
||||
RegistrarGuard,
|
||||
UserDataService,
|
||||
{
|
||||
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
|
||||
useValue: {
|
||||
subscriptSizing: 'dynamic',
|
||||
},
|
||||
},
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {}
|
||||
@@ -1,60 +0,0 @@
|
||||
<div class="console-domains">
|
||||
<mat-form-field>
|
||||
<mat-label>Filter</mat-label>
|
||||
<input
|
||||
type="search"
|
||||
matInput
|
||||
[(ngModel)]="searchTerm"
|
||||
(ngModelChange)="sendInput()"
|
||||
#input
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="isLoading; else domains_content" class="console-domains__loading">
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
</div>
|
||||
<ng-template #domains_content>
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="domainName">
|
||||
<th mat-header-cell *matHeaderCellDef>Domain Name</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.domainName }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="creationTime">
|
||||
<th mat-header-cell *matHeaderCellDef>Creation Time</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
{{ element.creationTime.creationTime }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="registrationExpirationTime">
|
||||
<th mat-header-cell *matHeaderCellDef>Expiration Time</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
{{ element.registrationExpirationTime }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="statuses">
|
||||
<th mat-header-cell *matHeaderCellDef>Statuses</th>
|
||||
<td mat-cell *matCellDef="let element">{{ element.statuses }}</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
|
||||
<!-- Row shown when there is no matching data. -->
|
||||
<tr class="mat-row" *matNoDataRow>
|
||||
<td class="mat-cell" colspan="4">No domains found</td>
|
||||
</tr>
|
||||
</table>
|
||||
<mat-paginator
|
||||
[length]="totalResults"
|
||||
[pageIndex]="pageNumber"
|
||||
[pageSize]="resultsPerPage"
|
||||
[pageSizeOptions]="[10, 25, 50, 100, 500]"
|
||||
(page)="onPageChange($event)"
|
||||
aria-label="Select page of domain results"
|
||||
showFirstLastButtons
|
||||
></mat-paginator>
|
||||
</ng-template>
|
||||
</div>
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright 2023 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 { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DomainListComponent } from './domainList.component';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('DomainListComponent', () => {
|
||||
let component: DomainListComponent;
|
||||
let fixture: ComponentFixture<DomainListComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [DomainListComponent],
|
||||
imports: [
|
||||
HttpClientTestingModule,
|
||||
MaterialModule,
|
||||
BrowserAnimationsModule,
|
||||
],
|
||||
providers: [BackendService],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(DomainListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,98 +0,0 @@
|
||||
// Copyright 2023 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 { Component, ViewChild } from '@angular/core';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { Domain, DomainListService } from './domainList.service';
|
||||
import { Subject, debounceTime } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-domain-list',
|
||||
templateUrl: './domainList.component.html',
|
||||
styleUrls: ['./domainList.component.scss'],
|
||||
providers: [DomainListService],
|
||||
})
|
||||
export class DomainListComponent {
|
||||
public static PATH = 'domain-list';
|
||||
private readonly DEBOUNCE_MS = 500;
|
||||
|
||||
displayedColumns: string[] = [
|
||||
'domainName',
|
||||
'creationTime',
|
||||
'registrationExpirationTime',
|
||||
'statuses',
|
||||
];
|
||||
|
||||
dataSource: MatTableDataSource<Domain> = new MatTableDataSource();
|
||||
isLoading = true;
|
||||
|
||||
searchTermSubject = new Subject<string>();
|
||||
searchTerm?: string;
|
||||
|
||||
pageNumber?: number;
|
||||
resultsPerPage = 50;
|
||||
totalResults?: number;
|
||||
|
||||
@ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
|
||||
|
||||
constructor(
|
||||
private backendService: BackendService,
|
||||
private domainListService: DomainListService,
|
||||
private registrarService: RegistrarService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
// Don't spam the server unnecessarily while the user is typing
|
||||
this.searchTermSubject
|
||||
.pipe(debounceTime(this.DEBOUNCE_MS))
|
||||
.subscribe((searchTermValue) => {
|
||||
this.reloadData();
|
||||
});
|
||||
this.reloadData();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.searchTermSubject.complete();
|
||||
}
|
||||
|
||||
reloadData() {
|
||||
this.isLoading = true;
|
||||
this.domainListService
|
||||
.retrieveDomains(
|
||||
this.pageNumber,
|
||||
this.resultsPerPage,
|
||||
this.totalResults,
|
||||
this.searchTerm
|
||||
)
|
||||
.subscribe((domainListResult) => {
|
||||
this.dataSource.data = domainListResult.domains;
|
||||
this.totalResults = domainListResult.totalResults;
|
||||
this.isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
sendInput() {
|
||||
this.searchTermSubject.next(this.searchTerm!);
|
||||
}
|
||||
|
||||
onPageChange(event: PageEvent) {
|
||||
this.pageNumber = event.pageIndex;
|
||||
this.resultsPerPage = event.pageSize;
|
||||
this.reloadData();
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
// Copyright 2023 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 { Injectable } from '@angular/core';
|
||||
import { BackendService } from '../shared/services/backend.service';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { tap } from 'rxjs';
|
||||
|
||||
export interface CreateAutoTimestamp {
|
||||
creationTime: string;
|
||||
}
|
||||
|
||||
export interface Domain {
|
||||
creationTime: CreateAutoTimestamp;
|
||||
currentSponsorRegistrarId: string;
|
||||
domainName: string;
|
||||
registrationExpirationTime: string;
|
||||
statuses: string[];
|
||||
}
|
||||
|
||||
export interface DomainListResult {
|
||||
checkpointTime: string;
|
||||
domains: Domain[];
|
||||
totalResults: number;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DomainListService {
|
||||
checkpointTime?: string;
|
||||
|
||||
constructor(
|
||||
private backendService: BackendService,
|
||||
private registrarService: RegistrarService
|
||||
) {}
|
||||
|
||||
retrieveDomains(
|
||||
pageNumber?: number,
|
||||
resultsPerPage?: number,
|
||||
totalResults?: number,
|
||||
searchTerm?: string
|
||||
) {
|
||||
return this.backendService
|
||||
.getDomains(
|
||||
this.registrarService.registrarId(),
|
||||
this.checkpointTime,
|
||||
pageNumber,
|
||||
resultsPerPage,
|
||||
totalResults,
|
||||
searchTerm
|
||||
)
|
||||
.pipe(
|
||||
tap((domainListResult: DomainListResult) => {
|
||||
this.checkpointTime = domainListResult.checkpointTime;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<p class="console-app__header">
|
||||
<mat-toolbar color="primary">
|
||||
<button mat-icon-button aria-label="Open menu" (click)="toggleNavPane()">
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
<a
|
||||
[routerLink]="'/home'"
|
||||
routerLinkActive="active"
|
||||
class="console-app__logo"
|
||||
>
|
||||
Google Registry
|
||||
</a>
|
||||
<span class="spacer"></span>
|
||||
<app-registrar-selector />
|
||||
<button mat-icon-button aria-label="Open FAQ">
|
||||
<mat-icon>question_mark</mat-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
#menuTrigger
|
||||
aria-label="Open user info"
|
||||
>
|
||||
<mat-icon>person</mat-icon>
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item (click)="logOut()">Log out</button>
|
||||
</mat-menu>
|
||||
</mat-toolbar>
|
||||
</p>
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright 2023 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.
|
||||
|
||||
.console-app {
|
||||
&__logo {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
&__header {
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
@media (max-width: 599px) {
|
||||
.mat-toolbar {
|
||||
padding: 0;
|
||||
}
|
||||
.console-app__logo {
|
||||
font-size: 16px;
|
||||
}
|
||||
button {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.spacer {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright 2023 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 { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HeaderComponent } from './header.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MaterialModule } from '../material.module';
|
||||
|
||||
describe('HeaderComponent', () => {
|
||||
let component: HeaderComponent;
|
||||
let fixture: ComponentFixture<HeaderComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MaterialModule, BrowserAnimationsModule],
|
||||
declarations: [HeaderComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright 2023 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 { Component, EventEmitter, Output } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
templateUrl: './header.component.html',
|
||||
styleUrls: ['./header.component.scss'],
|
||||
})
|
||||
export class HeaderComponent {
|
||||
private isNavOpen = false;
|
||||
|
||||
@Output() toggleNavOpen = new EventEmitter<boolean>();
|
||||
|
||||
toggleNavPane() {
|
||||
this.isNavOpen = !this.isNavOpen;
|
||||
this.toggleNavOpen.emit(this.isNavOpen);
|
||||
}
|
||||
|
||||
logOut() {
|
||||
window.open('/console?gcp-iap-mode=CLEAR_LOGIN_COOKIE', '_self');
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<div class="console-app__home">
|
||||
<h1>Welcome to the Google Registry Console</h1>
|
||||
<div class="console-app__home-widgets">
|
||||
<div app-domains-widget class="console-app__widget-wrapper__wide"></div>
|
||||
<div app-contact-widget class="console-app__widget-wrapper__wide"></div>
|
||||
<div app-tlds-widget></div>
|
||||
<div app-promotions-widget class="console-app__widget-wrapper__wide"></div>
|
||||
<div app-settings-widget class="console-app__widget-wrapper__wide"></div>
|
||||
<div app-resources-widget></div>
|
||||
<div app-billing-widget></div>
|
||||
<div app-epp-widget></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
.console-app {
|
||||
&__home {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
&__home-widgets {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||||
grid-gap: 20px;
|
||||
grid-auto-flow: dense;
|
||||
|
||||
mat-card {
|
||||
height: 100%;
|
||||
h1 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (max-width: 510px) {
|
||||
.console-app__widget-wrapper__wide {
|
||||
grid-column: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright 2022 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 { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HomeComponent } from './home.component';
|
||||
import { MaterialModule } from '../material.module';
|
||||
|
||||
describe('HomeComponent', () => {
|
||||
let component: HomeComponent;
|
||||
let fixture: ComponentFixture<HomeComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MaterialModule],
|
||||
declarations: [HomeComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HomeComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2022 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 { Component, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
templateUrl: './home.component.html',
|
||||
styleUrls: ['./home.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class HomeComponent {}
|
||||
@@ -1,22 +0,0 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="console-app__widget">
|
||||
<a
|
||||
class="console-app__widget_left"
|
||||
href="{{ driveFolderUrl }}"
|
||||
(click)="openBillingDetails($event)"
|
||||
>
|
||||
<mat-icon class="console-app__widget-icon">account_balance</mat-icon>
|
||||
<h1 class="console-app__widget-title">Billing Info</h1>
|
||||
<h4 class="secondary-text text-center">
|
||||
<span *ngIf="driveFolderUrl; else noDriveFolderUrl">
|
||||
View important billing and payments information.
|
||||
</span>
|
||||
<ng-template #noDriveFolderUrl>
|
||||
<span> Your billing folder is pending allocation. </span>
|
||||
</ng-template>
|
||||
</h4>
|
||||
</a>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright 2023 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 { Component } from '@angular/core';
|
||||
import { RegistrarService } from 'src/app/registrar/registrar.service';
|
||||
|
||||
@Component({
|
||||
selector: '[app-billing-widget]',
|
||||
templateUrl: './billingWidget.component.html',
|
||||
})
|
||||
export class BillingWidgetComponent {
|
||||
constructor(public registrarService: RegistrarService) {}
|
||||
|
||||
public get driveFolderUrl(): string {
|
||||
if (this.registrarService.registrar()?.driveFolderId) {
|
||||
return `https://drive.google.com/drive/folders/${
|
||||
this.registrarService.registrar()?.driveFolderId
|
||||
}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
openBillingDetails(e: MouseEvent) {
|
||||
if (!this.driveFolderUrl) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="console-app__widget">
|
||||
<div class="console-app__widget_left">
|
||||
<mat-icon class="console-app__widget-icon">call</mat-icon>
|
||||
<h1 class="console-app__widget-title">Contact Support</h1>
|
||||
<h4 class="secondary-text text-center">
|
||||
Let us know if you have any questions
|
||||
</h4>
|
||||
</div>
|
||||
<div class="console-app__widget_right">
|
||||
<div class="console-app__widget-section-header">Give us a Call</div>
|
||||
<p class="secondary-text">
|
||||
Call {{ userDataService.userData?.productName }} support at
|
||||
<a href="tel:{{ userDataService.userData?.supportPhoneNumber }}">{{
|
||||
userDataService.userData?.supportPhoneNumber
|
||||
}}</a>
|
||||
</p>
|
||||
<div class="console-app__widget-section-header">Send us an Email</div>
|
||||
<p class="secondary-text">
|
||||
Email {{ userDataService.userData?.productName }} at
|
||||
<a href="mailto:{{ userDataService.userData?.supportEmail }}">{{
|
||||
userDataService.userData?.supportEmail
|
||||
}}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright 2023 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 { Component } from '@angular/core';
|
||||
import { UserDataService } from 'src/app/shared/services/userData.service';
|
||||
|
||||
@Component({
|
||||
selector: '[app-contact-widget]',
|
||||
templateUrl: './contactWidget.component.html',
|
||||
})
|
||||
export class ContactWidgetComponent {
|
||||
constructor(public userDataService: UserDataService) {}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="console-app__widget">
|
||||
<div class="console-app__widget_left">
|
||||
<mat-icon class="console-app__widget-icon">view_list</mat-icon>
|
||||
<h1 class="console-app__widget-title">Domains</h1>
|
||||
<h4 class="secondary-text text-center">
|
||||
Manage domain names and registry lock settings.
|
||||
</h4>
|
||||
</div>
|
||||
<div class="console-app__widget_right">
|
||||
<button mat-button color="primary" class="console-app__widget-link">
|
||||
Create a Domain
|
||||
</button>
|
||||
<p class="secondary-text">Register a new domain name</p>
|
||||
<button
|
||||
mat-button
|
||||
color="primary"
|
||||
class="console-app__widget-link"
|
||||
(click)="openDomainsPage()"
|
||||
>
|
||||
View DUMs
|
||||
</button>
|
||||
<p class="secondary-text">
|
||||
Download a csv of all domains under management
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright 2023 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 { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { DomainListComponent } from 'src/app/domains/domainList.component';
|
||||
|
||||
@Component({
|
||||
selector: '[app-domains-widget]',
|
||||
templateUrl: './domainsWidget.component.html',
|
||||
})
|
||||
export class DomainsWidgetComponent {
|
||||
constructor(private router: Router) {}
|
||||
|
||||
openDomainsPage() {
|
||||
this.router.navigate([DomainListComponent.PATH]);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="console-app__widget">
|
||||
<div class="console-app__widget_left">
|
||||
<mat-icon class="console-app__widget-icon">computer</mat-icon>
|
||||
<h1 class="console-app__widget-title">EPP Console</h1>
|
||||
<h4 class="secondary-text text-center">
|
||||
Test run and execute EPP commands using XML files.
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2023 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 { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: '[app-epp-widget]',
|
||||
templateUrl: './eppWidget.component.html',
|
||||
})
|
||||
export class EppWidgetComponent {
|
||||
constructor() {}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<mat-card class="console-app__widget-wrapper__wide">
|
||||
<mat-card-content>
|
||||
<div class="console-app__widget">
|
||||
<div class="console-app__widget_left">
|
||||
<mat-icon class="console-app__widget-icon">subject</mat-icon>
|
||||
<h1 class="console-app__widget-title">Promotions</h1>
|
||||
<h4 class="secondary-text text-center">
|
||||
Manage Google Registry promotions and view onboarding process.
|
||||
</h4>
|
||||
</div>
|
||||
<div class="console-app__widget_right">
|
||||
<button mat-button color="primary" class="console-app__widget-link">
|
||||
Manage Preferred Partner Program
|
||||
</button>
|
||||
<p class="secondary-text">
|
||||
Onboard or view current preferred partner status
|
||||
</p>
|
||||
<button mat-button color="primary" class="console-app__widget-link">
|
||||
Manage Registry Lock Program
|
||||
</button>
|
||||
<p class="secondary-text">
|
||||
Onboard or view current registry lock status
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2023 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 { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: '[app-promotions-widget]',
|
||||
templateUrl: './promotionsWidget.component.html',
|
||||
})
|
||||
export class PromotionsWidgetComponent {
|
||||
constructor() {}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="console-app__widget">
|
||||
<a
|
||||
class="console-app__widget_left"
|
||||
href="{{ userDataService.userData?.technicalDocsUrl }}"
|
||||
target="_blank"
|
||||
>
|
||||
<mat-icon class="console-app__widget-icon">menu_book</mat-icon>
|
||||
<h1 class="console-app__widget-title">Resources</h1>
|
||||
<h4 class="secondary-text text-center">
|
||||
Use Google Drive to view onboarding FAQs, and technical documentation.
|
||||
</h4>
|
||||
</a>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright 2023 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 { Component } from '@angular/core';
|
||||
import { UserDataService } from 'src/app/shared/services/userData.service';
|
||||
|
||||
@Component({
|
||||
selector: '[app-resources-widget]',
|
||||
templateUrl: './resourcesWidget.component.html',
|
||||
})
|
||||
export class ResourcesWidgetComponent {
|
||||
constructor(public userDataService: UserDataService) {}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<mat-card class="console-app__widget-wrapper__wide">
|
||||
<mat-card-content>
|
||||
<div class="console-app__widget">
|
||||
<div class="console-app__widget_left">
|
||||
<mat-icon class="console-app__widget-icon">settings</mat-icon>
|
||||
<h1 class="console-app__widget-title">Settings</h1>
|
||||
<h4 class="secondary-text text-center">
|
||||
Configure registrar settings, manage console users, and view activity
|
||||
log.
|
||||
</h4>
|
||||
</div>
|
||||
<div class="console-app__widget_right">
|
||||
<button
|
||||
mat-button
|
||||
color="primary"
|
||||
class="console-app__widget-link"
|
||||
(click)="openContactsPage()"
|
||||
>
|
||||
Contact Information
|
||||
</button>
|
||||
<p class="secondary-text">Manage Primary, Technical, etc contacts.</p>
|
||||
<button
|
||||
mat-button
|
||||
color="primary"
|
||||
class="console-app__widget-link"
|
||||
(click)="openSecurityPage()"
|
||||
>
|
||||
Security
|
||||
</button>
|
||||
<p class="secondary-text">
|
||||
Manage IP allow lists and SSL certificates.
|
||||
</p>
|
||||
<button mat-button color="primary" class="console-app__widget-link">
|
||||
Nomulus Password
|
||||
</button>
|
||||
<p class="secondary-text">Reset your Nomulus password.</p>
|
||||
<button mat-button color="primary" class="console-app__widget-link">
|
||||
User Management
|
||||
</button>
|
||||
<p class="secondary-text">Create and manage console user accounts</p>
|
||||
<button
|
||||
mat-button
|
||||
color="primary"
|
||||
class="console-app__widget-link"
|
||||
(click)="openRegistrarsPage()"
|
||||
>
|
||||
Registrar Management
|
||||
</button>
|
||||
<p class="secondary-text">Create and manage registrar accounts</p>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright 2023 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 { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { RegistrarComponent } from 'src/app/registrar/registrarsTable.component';
|
||||
import ContactComponent from 'src/app/settings/contact/contact.component';
|
||||
import SecurityComponent from 'src/app/settings/security/security.component';
|
||||
import { SettingsComponent } from 'src/app/settings/settings.component';
|
||||
|
||||
@Component({
|
||||
selector: '[app-settings-widget]',
|
||||
templateUrl: './settingsWidget.component.html',
|
||||
})
|
||||
export class SettingsWidgetComponent {
|
||||
constructor(private router: Router) {}
|
||||
|
||||
openRegistrarsPage() {
|
||||
this.navigate(RegistrarComponent.PATH);
|
||||
}
|
||||
|
||||
openSecurityPage() {
|
||||
this.navigate(SecurityComponent.PATH);
|
||||
}
|
||||
|
||||
openContactsPage() {
|
||||
this.navigate(ContactComponent.PATH);
|
||||
}
|
||||
|
||||
private navigate(route: string) {
|
||||
this.router.navigate([SettingsComponent.PATH, route]);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="console-app__widget">
|
||||
<div class="console-app__widget_left">
|
||||
<mat-icon class="console-app__widget-icon">list_alt</mat-icon>
|
||||
<h1 class="console-app__widget-title">TLDs</h1>
|
||||
<h4 class="secondary-text text-center">
|
||||
View launch phase information for all onboarded and available TLDs.
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2023 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 { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: '[app-tlds-widget]',
|
||||
templateUrl: './tldsWidget.component.html',
|
||||
})
|
||||
export class TldsWidgetComponent {
|
||||
constructor() {}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user