mirror of
https://github.com/google/nomulus
synced 2025-12-23 06:15:42 +00:00
Add environment support to the console build (#2539)
This commit is contained in:
@@ -13,7 +13,7 @@ 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
|
||||
1) Console webapp build script `buildConsoleWebapp`, 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
|
||||
|
||||
@@ -63,6 +63,39 @@
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"sandbox": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "2kb",
|
||||
"maximumError": "4kb"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.sandbox.ts"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"crash": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
},
|
||||
"alpha": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
},
|
||||
"development": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
@@ -78,6 +111,15 @@
|
||||
"production": {
|
||||
"buildTarget": "console-webapp:build:production"
|
||||
},
|
||||
"alpha": {
|
||||
"buildTarget": "console-webapp:build:alpha"
|
||||
},
|
||||
"crash": {
|
||||
"buildTarget": "console-webapp:build:crash"
|
||||
},
|
||||
"sandbox": {
|
||||
"buildTarget": "console-webapp:build:sandbox"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "console-webapp:build:development"
|
||||
}
|
||||
|
||||
@@ -37,17 +37,16 @@ task runConsoleWebappUnitTests(type: Exec) {
|
||||
args 'run', 'test'
|
||||
}
|
||||
|
||||
task buildConsoleWebappNonProd(type: Exec) {
|
||||
task buildConsoleWebapp(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'
|
||||
def configuration = project.hasProperty('configuration') ?
|
||||
project.getProperty('configuration') :
|
||||
'production'
|
||||
args 'run', "build", "--configuration=${configuration}"
|
||||
doFirst {
|
||||
println "Building console for environment: ${configuration}"
|
||||
}
|
||||
}
|
||||
|
||||
task applyFormatting(type: Exec) {
|
||||
@@ -68,10 +67,10 @@ task deploy(type: Exec) {
|
||||
args 'app', 'deploy', "${projectParam}", '--quiet'
|
||||
}
|
||||
|
||||
tasks.buildConsoleWebappProd.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.buildConsoleWebapp.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.runConsoleWebappUnitTests.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.applyFormatting.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.checkFormatting.dependsOn(tasks.npmInstallDeps)
|
||||
tasks.build.dependsOn(tasks.checkFormatting)
|
||||
tasks.build.dependsOn(tasks.runConsoleWebappUnitTests)
|
||||
tasks.deploy.dependsOn(tasks.buildConsoleWebappProd)
|
||||
tasks.deploy.dependsOn(tasks.buildConsoleWebapp)
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --proxy-config dev-proxy.config.json",
|
||||
"build": "ng build --base-href=/console/",
|
||||
"build": "ng build --base-href=/console/ --configuration=$npm_config_configuration",
|
||||
"build:local": "ng build --base-href=/default/console/",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"watch": "ng build --watch --configuration=development",
|
||||
"test": "ng test --browsers=ChromeHeadless --watch=false",
|
||||
"run:dev": "",
|
||||
"prettify": "npx prettier --write ./src/",
|
||||
|
||||
@@ -34,6 +34,10 @@ export interface RouteWithIcon extends Route {
|
||||
iconName?: string;
|
||||
}
|
||||
|
||||
export const PATHS = {
|
||||
NewOteComponent: 'new-ote',
|
||||
OteStatusComponent: 'ote-status/:registrarId',
|
||||
};
|
||||
export const routes: RouteWithIcon[] = [
|
||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||
{
|
||||
@@ -41,12 +45,14 @@ export const routes: RouteWithIcon[] = [
|
||||
component: RegistryLockVerifyComponent,
|
||||
},
|
||||
{
|
||||
path: NewOteComponent.PATH,
|
||||
component: NewOteComponent,
|
||||
path: PATHS.NewOteComponent,
|
||||
loadComponent: () =>
|
||||
import('./ote/newOte.component').then((mod) => mod.NewOteComponent),
|
||||
},
|
||||
{
|
||||
path: OteStatusComponent.PATH,
|
||||
component: OteStatusComponent,
|
||||
path: PATHS.OteStatusComponent,
|
||||
loadComponent: () =>
|
||||
import('./ote/oteStatus.component').then((mod) => mod.OteStatusComponent),
|
||||
},
|
||||
{ path: 'registrars', component: RegistrarComponent },
|
||||
{
|
||||
|
||||
@@ -16,16 +16,16 @@ import { provideHttpClient } from '@angular/common/http';
|
||||
import { provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { MaterialModule } from './material.module';
|
||||
import { BackendService } from './shared/services/backend.service';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [AppComponent],
|
||||
imports: [RouterTestingModule, MaterialModule, BrowserAnimationsModule],
|
||||
imports: [MaterialModule, BrowserAnimationsModule, AppRoutingModule],
|
||||
providers: [
|
||||
BackendService,
|
||||
provideHttpClient(),
|
||||
|
||||
@@ -68,8 +68,6 @@ import { TldsComponent } from './tlds/tlds.component';
|
||||
HeaderComponent,
|
||||
HomeComponent,
|
||||
LocationBackDirective,
|
||||
NewOteComponent,
|
||||
OteStatusComponent,
|
||||
UserLevelVisibility,
|
||||
NavigationComponent,
|
||||
NewRegistrarComponent,
|
||||
@@ -99,6 +97,7 @@ import { TldsComponent } from './tlds/tlds.component';
|
||||
MaterialModule,
|
||||
SnackBarModule,
|
||||
],
|
||||
exports: [SelectedRegistrarWrapper],
|
||||
providers: [
|
||||
BackendService,
|
||||
BreakPointObserverService,
|
||||
|
||||
@@ -4,4 +4,8 @@
|
||||
white-space: break-spaces;
|
||||
padding: 20px;
|
||||
}
|
||||
mat-form-field {
|
||||
width: 100%;
|
||||
max-width: 350px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ import { Component, computed, signal } from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { SnackBarModule } from '../snackbar.module';
|
||||
|
||||
export interface OteCreateResponse extends Map<string, string> {
|
||||
password: string;
|
||||
@@ -24,12 +26,12 @@ export interface OteCreateResponse extends Map<string, string> {
|
||||
|
||||
@Component({
|
||||
selector: 'app-ote',
|
||||
standalone: true,
|
||||
imports: [MaterialModule, SnackBarModule],
|
||||
templateUrl: './newOte.component.html',
|
||||
styleUrls: ['./newOte.component.scss'],
|
||||
})
|
||||
export class NewOteComponent {
|
||||
public static PATH = 'new-ote';
|
||||
|
||||
oteCreateResponse = signal<OteCreateResponse | undefined>(undefined);
|
||||
|
||||
readonly oteCreateResponseFormatted = computed(() => {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<app-selected-registrar-wrapper>
|
||||
<h1 class="mat-headline-4">OT&E Status Check</h1>
|
||||
@if(isOte()) {
|
||||
<h1 *ngIf="oteStatusResponse().length">
|
||||
<h1 class="mat-headline-4">OT&E Status Check</h1>
|
||||
@if(registrarId() === null) {
|
||||
<h1>Missing registrarId param</h1>
|
||||
} @else if(isOte()) {
|
||||
<h1 *ngIf="oteStatusResponse().length">
|
||||
Status:
|
||||
<span>{{ oteStatusUnfinished().length ? "Unfinished" : "Completed" }}</span>
|
||||
</h1>
|
||||
<div class="console-app__ote-status">
|
||||
</h1>
|
||||
<div class="console-app__ote-status">
|
||||
@if(oteStatusCompleted().length) {
|
||||
<div class="console-app__ote-status_completed">
|
||||
<h1>Completed</h1>
|
||||
@@ -21,11 +22,7 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
} @else {
|
||||
<h1>
|
||||
Registrar {{ registrarService.registrar()?.registrarId }} is not an OT&E
|
||||
registrar
|
||||
</h1>
|
||||
}
|
||||
</app-selected-registrar-wrapper>
|
||||
</div>
|
||||
} @else {
|
||||
<h1>Registrar {{ registrarId() }} is not an OT&E registrar</h1>
|
||||
}
|
||||
|
||||
@@ -13,9 +13,14 @@
|
||||
// limitations under the License.
|
||||
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component, computed, signal } from '@angular/core';
|
||||
import { Component, computed, OnInit, signal } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { SnackBarModule } from '../snackbar.module';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { take } from 'rxjs';
|
||||
|
||||
export interface OteStatusResponse {
|
||||
description: string;
|
||||
@@ -26,12 +31,13 @@ export interface OteStatusResponse {
|
||||
|
||||
@Component({
|
||||
selector: 'app-ote-status',
|
||||
standalone: true,
|
||||
imports: [MaterialModule, SnackBarModule, CommonModule],
|
||||
templateUrl: './oteStatus.component.html',
|
||||
styleUrls: ['./oteStatus.component.scss'],
|
||||
})
|
||||
export class OteStatusComponent {
|
||||
public static PATH = 'ote-status';
|
||||
|
||||
export class OteStatusComponent implements OnInit {
|
||||
registrarId = signal<string | null>(null);
|
||||
oteStatusResponse = signal<OteStatusResponse[]>([]);
|
||||
|
||||
oteStatusCompleted = computed(() =>
|
||||
@@ -41,16 +47,26 @@ export class OteStatusComponent {
|
||||
this.oteStatusResponse().filter((v) => !v.completed)
|
||||
);
|
||||
isOte = computed(
|
||||
() => this.registrarService.registrar()?.type?.toLowerCase() === 'ote'
|
||||
() =>
|
||||
this.registrarService
|
||||
.registrars()
|
||||
.find((r) => r.registrarId === this.registrarId())
|
||||
?.type?.toLowerCase() === 'ote'
|
||||
);
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
protected registrarService: RegistrarService,
|
||||
private _snackBar: MatSnackBar
|
||||
) {
|
||||
this.registrarService
|
||||
.oteStatus(this.registrarService.registrarId())
|
||||
.subscribe({
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.route.paramMap.pipe(take(1)).subscribe((params: ParamMap) => {
|
||||
this.registrarId.set(params.get('registrarId'));
|
||||
const registrarId = this.registrarId();
|
||||
if (!registrarId) throw 'Missing registrarId param';
|
||||
|
||||
this.registrarService.oteStatus(registrarId).subscribe({
|
||||
next: (oteStatusResponse: OteStatusResponse[]) => {
|
||||
this.oteStatusResponse.set(oteStatusResponse);
|
||||
},
|
||||
@@ -58,5 +74,6 @@ export class OteStatusComponent {
|
||||
this._snackBar.open(err.error || err.message);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<div class="spacer"></div>
|
||||
@if(!inEdit && !registrarNotFound) {
|
||||
<button
|
||||
*ngIf="oteButtonVisible"
|
||||
mat-stroked-button
|
||||
(click)="checkOteStatus()"
|
||||
aria-label="Check OT&E account"
|
||||
|
||||
@@ -18,10 +18,10 @@ import { MatChipInputEvent } from '@angular/material/chips';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { OteStatusComponent } from '../ote/oteStatus.component';
|
||||
import { RESTRICTED_ELEMENTS } from '../shared/directives/userLevelVisiblity.directive';
|
||||
import { Registrar, RegistrarService } from './registrar.service';
|
||||
import { RegistrarComponent, columns } from './registrarsTable.component';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-registrar-details',
|
||||
@@ -31,8 +31,9 @@ import { RegistrarComponent, columns } from './registrarsTable.component';
|
||||
export class RegistrarDetailsComponent implements OnInit {
|
||||
public static PATH = 'registrars/:id';
|
||||
inEdit: boolean = false;
|
||||
oteButtonVisible = environment.sandbox;
|
||||
registrarInEdit!: Registrar;
|
||||
registrarNotFound: boolean = false;
|
||||
registrarNotFound: boolean = true;
|
||||
columns = columns.filter((c) => !c.hiddenOnDetailsCard);
|
||||
private subscription!: Subscription;
|
||||
|
||||
@@ -73,7 +74,9 @@ export class RegistrarDetailsComponent implements OnInit {
|
||||
}
|
||||
|
||||
checkOteStatus() {
|
||||
this.router.navigate([OteStatusComponent.PATH]);
|
||||
this.router.navigate(['ote-status/', this.registrarInEdit.registrarId], {
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
}
|
||||
|
||||
getElementIdForOteBlock() {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<div class="spacer"></div>
|
||||
<button
|
||||
mat-stroked-button
|
||||
*ngIf="oteButtonVisible"
|
||||
(click)="createOteAccount()"
|
||||
aria-label="Generate OT&E accounts"
|
||||
[elementId]="getElementIdForOteBlock()"
|
||||
|
||||
@@ -17,9 +17,10 @@ import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { Router } from '@angular/router';
|
||||
import { NewOteComponent } from '../ote/newOte.component';
|
||||
import { RESTRICTED_ELEMENTS } from '../shared/directives/userLevelVisiblity.directive';
|
||||
import { Registrar, RegistrarService } from './registrar.service';
|
||||
import { PATHS } from '../app-routing.module';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
export const columns = [
|
||||
{
|
||||
@@ -82,7 +83,7 @@ export class RegistrarComponent {
|
||||
public static PATH = 'registrars';
|
||||
dataSource: MatTableDataSource<Registrar>;
|
||||
columns = columns;
|
||||
|
||||
oteButtonVisible = environment.sandbox;
|
||||
displayedColumns = this.columns.map((c) => c.columnDef);
|
||||
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@@ -106,7 +107,7 @@ export class RegistrarComponent {
|
||||
}
|
||||
|
||||
createOteAccount() {
|
||||
this.router.navigate([NewOteComponent.PATH]);
|
||||
this.router.navigate([PATHS.NewOteComponent]);
|
||||
}
|
||||
|
||||
getElementIdForOteBlock() {
|
||||
|
||||
@@ -14,4 +14,5 @@
|
||||
|
||||
export const environment = {
|
||||
production: true,
|
||||
sandbox: false,
|
||||
};
|
||||
|
||||
18
console-webapp/src/environments/environment.sandbox.ts
Normal file
18
console-webapp/src/environments/environment.sandbox.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
export const environment = {
|
||||
production: false,
|
||||
sandbox: true,
|
||||
};
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
export const environment = {
|
||||
production: false,
|
||||
sandbox: false,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,7 +18,7 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
if (environment.production || environment.sandbox) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ tasks.register('copyConsole', Copy) {
|
||||
include "**/*"
|
||||
}
|
||||
into layout.buildDirectory.dir('jetty-base/webapps/console')
|
||||
dependsOn(':console-webapp:buildConsoleWebappProd')
|
||||
dependsOn(':console-webapp:buildConsoleWebapp')
|
||||
}
|
||||
|
||||
tasks.register('stage') {
|
||||
|
||||
@@ -51,6 +51,7 @@ else
|
||||
mv services/"${service}"/build/staged-app "${dest}/${service}"
|
||||
done
|
||||
|
||||
./gradlew :console-webapp:buildConsoleWebapp -Pconfiguration="${environment}"
|
||||
mkdir -p "${dest}/console" && cp -r console-webapp/staged/* "${dest}/console"
|
||||
|
||||
mv core/build/resources/main/google/registry/env/common/META-INF \
|
||||
|
||||
@@ -18,18 +18,6 @@ steps:
|
||||
'-PmavenUrl=gcs://domain-registry-maven-repository/maven',
|
||||
'-PpluginsUrl=gcs://domain-registry-maven-repository/plugins'
|
||||
]
|
||||
# Build Registry Console
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
# Set home for Gradle caches. Must be consistent with last step below
|
||||
# and ./build_nomulus_for_env.sh
|
||||
env: [ 'GRADLE_USER_HOME=/workspace/cloudbuild-caches' ]
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
./gradlew \
|
||||
:console-webapp:buildConsoleWebappProd
|
||||
# Build and package the deployment files for each environment, and the tool
|
||||
# binary and image.
|
||||
- name: 'gcr.io/${PROJECT_ID}/builder:latest'
|
||||
|
||||
Reference in New Issue
Block a user