From 90d109ca2899474bc7273430ae8e728c66f05220 Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Wed, 25 Sep 2024 18:42:54 -0300 Subject: [PATCH] make deployments reproducible (#27414) --- .github/workflows/angular.yml | 2 + .github/workflows/react.yml | 2 + .github/workflows/vue.yml | 2 + .../base-workspaces/internal/docker-base.ts | 4 +- generators/base/generator.ts | 7 +++ generators/docker-compose/command.ts | 10 +++- generators/docker-compose/generator.ts | 53 ++++++++++--------- generators/java/command.ts | 8 ++- generators/kubernetes-helm/index.ts | 1 + generators/kubernetes-knative/index.ts | 1 + generators/kubernetes/command.ts | 33 ++++++++++++ generators/kubernetes/index.ts | 1 + test-integration/scripts/99-write-matrix.js | 2 + 13 files changed, 91 insertions(+), 35 deletions(-) create mode 100644 generators/kubernetes/command.ts diff --git a/.github/workflows/angular.yml b/.github/workflows/angular.yml index 26aef884c1de..06e843c8db4e 100644 --- a/.github/workflows/angular.yml +++ b/.github/workflows/angular.yml @@ -107,6 +107,7 @@ jobs: env: JHI_FOLDER_APP: ${{ github.workspace }}/app JHIPSTER_DEPENDENCIES_VERSION: ${{ matrix.jhipster-bom-cicd-version }} + JHI_JWT_SECRET_KEY: ${{ matrix.jwt-secret-key }} - run: jhipster.cjs info #---------------------------------------------------------------------- # Detect changes against base commit @@ -123,6 +124,7 @@ jobs: # generate-sample uses JHI_FOLDER_APP to generate the application. JHI_FOLDER_APP: ${{ github.workspace }}/base/app JHIPSTER_DEPENDENCIES_VERSION: ${{ matrix.jhipster-bom-cicd-version }} + JHI_JWT_SECRET_KEY: ${{ matrix.jwt-secret-key }} #---------------------------------------------------------------------- # Launch tests #---------------------------------------------------------------------- diff --git a/.github/workflows/react.yml b/.github/workflows/react.yml index a8ba71b88231..34ea9cdb4f42 100644 --- a/.github/workflows/react.yml +++ b/.github/workflows/react.yml @@ -107,6 +107,7 @@ jobs: env: JHI_FOLDER_APP: ${{ github.workspace }}/app JHIPSTER_DEPENDENCIES_VERSION: ${{ matrix.jhipster-bom-cicd-version }} + JHI_JWT_SECRET_KEY: ${{ matrix.jwt-secret-key }} - run: jhipster.cjs info #---------------------------------------------------------------------- # Detect changes against base commit @@ -123,6 +124,7 @@ jobs: # generate-sample uses JHI_FOLDER_APP to generate the application. JHI_FOLDER_APP: ${{ github.workspace }}/base/app JHIPSTER_DEPENDENCIES_VERSION: ${{ matrix.jhipster-bom-cicd-version }} + JHI_JWT_SECRET_KEY: ${{ matrix.jwt-secret-key }} #---------------------------------------------------------------------- # Launch tests #---------------------------------------------------------------------- diff --git a/.github/workflows/vue.yml b/.github/workflows/vue.yml index 00ddbec10fea..16aa04cfa4e5 100644 --- a/.github/workflows/vue.yml +++ b/.github/workflows/vue.yml @@ -107,6 +107,7 @@ jobs: env: JHI_FOLDER_APP: ${{ github.workspace }}/app JHIPSTER_DEPENDENCIES_VERSION: ${{ matrix.jhipster-bom-cicd-version }} + JHI_JWT_SECRET_KEY: ${{ matrix.jwt-secret-key }} - run: jhipster.cjs info #---------------------------------------------------------------------- # Detect changes against base commit @@ -123,6 +124,7 @@ jobs: # generate-sample uses JHI_FOLDER_APP to generate the application. JHI_FOLDER_APP: ${{ github.workspace }}/base/app JHIPSTER_DEPENDENCIES_VERSION: ${{ matrix.jhipster-bom-cicd-version }} + JHI_JWT_SECRET_KEY: ${{ matrix.jwt-secret-key }} #---------------------------------------------------------------------- # Launch tests #---------------------------------------------------------------------- diff --git a/generators/base-workspaces/internal/docker-base.ts b/generators/base-workspaces/internal/docker-base.ts index 50279c9eab1d..18c3d12be4f6 100644 --- a/generators/base-workspaces/internal/docker-base.ts +++ b/generators/base-workspaces/internal/docker-base.ts @@ -64,9 +64,7 @@ export function checkImages() { * Generate Jwt Secret */ export function generateJwtSecret() { - if (this.jwtSecretKey === undefined) { - this.jwtSecretKey = this.jhipsterConfig.jwtSecretKey = createBase64Secret(this.options.reproducibleTests); - } + this.jwtSecretKey = this.jhipsterConfig.jwtSecretKey = this.jwtSecretKey ?? createBase64Secret(this.options.reproducibleTests); } /** diff --git a/generators/base/generator.ts b/generators/base/generator.ts index b1a7b7f1dc54..b87e9ce8d854 100644 --- a/generators/base/generator.ts +++ b/generators/base/generator.ts @@ -99,6 +99,13 @@ export default class JHipsterBaseBlueprintGenerator(taskGroup: GenericTaskGroup): GenericTaskGroup { + return taskGroup; + } + /** * Priority API stub for blueprints. * diff --git a/generators/docker-compose/command.ts b/generators/docker-compose/command.ts index 6a2b1008e073..ced0fd76c6b6 100644 --- a/generators/docker-compose/command.ts +++ b/generators/docker-compose/command.ts @@ -7,7 +7,15 @@ const command: JHipsterCommandDefinition = { description: 'Application folders', }, }, - options: {}, + configs: { + jwtSecretKey: { + cli: { + type: String, + env: 'JHI_JWT_SECRET_KEY', + }, + scope: 'generator', + }, + }, }; export default command; diff --git a/generators/docker-compose/generator.ts b/generators/docker-compose/generator.ts index 3d73977b185e..b6b1845bf032 100644 --- a/generators/docker-compose/generator.ts +++ b/generators/docker-compose/generator.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /** * Copyright 2013-2024 the original author or authors from the JHipster project. * @@ -45,10 +44,11 @@ const { Options: DeploymentOptions } = deploymentOptions; */ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { existingDeployment; + jwtSecretKey!: string; async beforeQueue() { this.parseJHipsterArguments(command.arguments); - if (this.appsFolders?.length > 0) { + if (this.appsFolders && this.appsFolders.length > 0) { this.jhipsterConfig.appsFolders = this.appsFolders; } @@ -59,7 +59,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { } get initializing() { - return { + return this.asInitializingTaskGroup({ sayHello() { this.log.log(chalk.white(`${chalk.bold('🐳')} Welcome to the JHipster Docker Compose Sub-Generator ${chalk.bold('🐳')}`)); this.log.log(chalk.white(`Files will be generated in folder: ${chalk.yellow(this.destinationRoot())}`)); @@ -75,7 +75,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { `); } }, - }; + }); } get [BaseWorkspacesGenerator.INITIALIZING]() { @@ -83,11 +83,11 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { } get loading() { - return { + return this.asLoadingTaskGroup({ loadWorkspacesConfig() { this.loadWorkspacesConfig(); }, - }; + }); } get [BaseWorkspacesGenerator.LOADING]() { @@ -95,7 +95,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { } get promptingWorkspaces() { - return { + return this.asAnyTaskGroup({ async askForMonitoring({ workspaces }) { if (workspaces.existingWorkspaces && !this.options.askAnswered) return; @@ -111,7 +111,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { await this.askForServiceDiscovery({ applications }); }, - }; + }); } get [BaseWorkspacesGenerator.PROMPTING_WORKSPACES]() { @@ -119,14 +119,15 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { } get configuringWorkspaces() { - return { + return this.asAnyTaskGroup({ configureBaseDeployment({ applications }) { - this.jhipsterConfig.jwtSecretKey = this.jhipsterConfig.jwtSecretKey ?? createBase64Secret(this.options.reproducibleTests); + this.jhipsterConfig.jwtSecretKey = + this.jhipsterConfig.jwtSecretKey ?? this.jwtSecretKey ?? createBase64Secret(this.options.reproducibleTests); if (applications.some(app => app.serviceDiscoveryEureka)) { this.jhipsterConfig.adminPassword = this.jhipsterConfig.adminPassword ?? 'admin'; } }, - }; + }); } get [BaseWorkspacesGenerator.CONFIGURING_WORKSPACES]() { @@ -134,7 +135,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { } get loadingWorkspaces() { - return { + return this.asAnyTaskGroup({ async loadBaseDeployment({ deployment }) { deployment.jwtSecretKey = this.jhipsterConfig.jwtSecretKey; @@ -143,7 +144,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { loadPlatformConfig({ deployment }) { this.loadDeploymentConfig({ deployment }); }, - }; + }); } get [BaseWorkspacesGenerator.LOADING_WORKSPACES]() { @@ -151,11 +152,11 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { } get preparingWorkspaces() { - return { + return this.asAnyTaskGroup({ prepareDeployment({ deployment, applications }) { this.prepareDeploymentDerivedProperties({ deployment, applications }); }, - }; + }); } get [BaseWorkspacesGenerator.PREPARING_WORKSPACES]() { @@ -163,7 +164,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { } get default() { - return { + return this.asAnyTaskGroup({ async setAppsYaml({ workspaces, deployment, applications }) { const faker = await createFaker(); @@ -174,7 +175,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { const parentConfiguration = {}; const path = this.destinationPath(workspaces.directoryPath, appConfig.appFolder); // Add application configuration - const yaml = parseYaml(this.fs.read(`${path}/src/main/docker/app.yml`)); + const yaml = parseYaml(this.fs.read(`${path}/src/main/docker/app.yml`)!); const yamlConfig = yaml.services.app; if (yamlConfig.depends_on) { yamlConfig.depends_on = Object.fromEntries( @@ -253,7 +254,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { if (appConfig.databaseTypeAny && !appConfig.prodDatabaseTypeOracle) { const database = appConfig.databaseTypeSql ? appConfig.prodDatabaseType : appConfig.databaseType; const relativePath = normalize(pathjs.relative(this.destinationRoot(), `${path}/src/main/docker`)); - const databaseYaml = parseYaml(this.fs.read(`${path}/src/main/docker/${database}.yml`)); + const databaseYaml = parseYaml(this.fs.read(`${path}/src/main/docker/${database}.yml`)!); const databaseServiceName = `${lowercaseBaseName}-${database}`; let databaseYamlConfig = databaseYaml.services[database]; // Don't export database ports @@ -261,7 +262,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { if (appConfig.databaseTypeCassandra) { // migration service config - const cassandraMigrationYaml = parseYaml(this.fs.read(`${path}/src/main/docker/cassandra-migration.yml`)); + const cassandraMigrationYaml = parseYaml(this.fs.read(`${path}/src/main/docker/cassandra-migration.yml`)!); const cassandraMigrationConfig = cassandraMigrationYaml.services[`${database}-migration`]; cassandraMigrationConfig.build.context = relativePath; const cqlFilesRelativePath = normalize(pathjs.relative(this.destinationRoot(), `${path}/src/main/resources/config/cql`)); @@ -275,7 +276,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { } if (appConfig.clusteredDb) { - const clusterDbYaml = parseYaml(this.fs.read(`${path}/src/main/docker/${database}-cluster.yml`)); + const clusterDbYaml = parseYaml(this.fs.read(`${path}/src/main/docker/${database}-cluster.yml`)!); const dbNodeConfig = clusterDbYaml.services[`${database}-node`]; dbNodeConfig.build.context = relativePath; databaseYamlConfig = clusterDbYaml.services[database]; @@ -294,14 +295,14 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { if (appConfig.searchEngineElasticsearch) { // Add search engine configuration const searchEngine = appConfig.searchEngine; - const searchEngineYaml = parseYaml(this.fs.read(`${path}/src/main/docker/${searchEngine}.yml`)); + const searchEngineYaml = parseYaml(this.fs.read(`${path}/src/main/docker/${searchEngine}.yml`)!); const searchEngineConfig = searchEngineYaml.services[searchEngine]; delete searchEngineConfig.ports; parentConfiguration[`${lowercaseBaseName}-${searchEngine}`] = searchEngineConfig; } // Add Memcached support if (appConfig.cacheProviderMemcached) { - const memcachedYaml = parseYaml(this.readDestination(`${path}/src/main/docker/memcached.yml`)); + const memcachedYaml = parseYaml(this.readDestination(`${path}/src/main/docker/memcached.yml`)!.toString()); const memcachedConfig = memcachedYaml.services.memcached; delete memcachedConfig.ports; parentConfiguration[`${lowercaseBaseName}-memcached`] = memcachedConfig; @@ -309,7 +310,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { // Add Redis support if (appConfig.cacheProviderRedis) { - const redisYaml = parseYaml(this.readDestination(`${path}/src/main/docker/redis.yml`)); + const redisYaml = parseYaml(this.readDestination(`${path}/src/main/docker/redis.yml`)!.toString()); const redisConfig = redisYaml.services.redis; delete redisConfig.ports; parentConfiguration[`${lowercaseBaseName}-redis`] = redisConfig; @@ -329,7 +330,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { return yamlString; }); }, - }; + }); } get [BaseWorkspacesGenerator.DEFAULT]() { @@ -345,7 +346,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { } get end() { - return { + return this.asAnyTaskGroup({ end({ workspaces, applications }) { this.checkApplicationsDockerImages({ workspaces, applications }); @@ -361,7 +362,7 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator { this.log.log('\n'); } }, - }; + }); } get [BaseWorkspacesGenerator.END]() { diff --git a/generators/java/command.ts b/generators/java/command.ts index 5629df36bc79..e76ee29b9ad8 100644 --- a/generators/java/command.ts +++ b/generators/java/command.ts @@ -16,13 +16,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { asCommand } from '../type-utils.js'; +import type { JHipsterCommandDefinition } from '../../lib/command/types.js'; const command = { options: {}, import: ['jhipster:java:bootstrap', 'jhipster:java:domain', 'jhipster:java:build-tool'], -}; +} as const satisfies JHipsterCommandDefinition; -export type Coomand = typeof command; - -export default asCommand(command); +export default command; diff --git a/generators/kubernetes-helm/index.ts b/generators/kubernetes-helm/index.ts index 58ac334eafae..870818641c5d 100644 --- a/generators/kubernetes-helm/index.ts +++ b/generators/kubernetes-helm/index.ts @@ -16,4 +16,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export { default as command } from '../kubernetes/command.js'; export { default } from './generator.js'; diff --git a/generators/kubernetes-knative/index.ts b/generators/kubernetes-knative/index.ts index 58ac334eafae..870818641c5d 100644 --- a/generators/kubernetes-knative/index.ts +++ b/generators/kubernetes-knative/index.ts @@ -16,4 +16,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export { default as command } from '../kubernetes/command.js'; export { default } from './generator.js'; diff --git a/generators/kubernetes/command.ts b/generators/kubernetes/command.ts new file mode 100644 index 000000000000..c83d0d88f6d2 --- /dev/null +++ b/generators/kubernetes/command.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2013-2024 the original author or authors from the JHipster project. + * + * This file is part of the JHipster project, see https://www.jhipster.tech/ + * for more information. + * + * 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 + * + * https://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 type { JHipsterCommandDefinition } from '../../lib/command/types.js'; + +const command = { + configs: { + jwtSecretKey: { + cli: { + type: String, + env: 'JHI_JWT_SECRET_KEY', + }, + scope: 'generator', + }, + }, +} as const satisfies JHipsterCommandDefinition; + +export default command; diff --git a/generators/kubernetes/index.ts b/generators/kubernetes/index.ts index 58ac334eafae..2d8013d19f51 100644 --- a/generators/kubernetes/index.ts +++ b/generators/kubernetes/index.ts @@ -16,4 +16,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export { default as command } from './command.js'; export { default } from './generator.js'; diff --git a/test-integration/scripts/99-write-matrix.js b/test-integration/scripts/99-write-matrix.js index 253b9aacd4c5..97e5db86fd55 100755 --- a/test-integration/scripts/99-write-matrix.js +++ b/test-integration/scripts/99-write-matrix.js @@ -66,6 +66,8 @@ writeFileSync( ...sample, 'skip-backend-tests': sample['skip-backend-tests'] ? 'true' : 'false', 'skip-frontend-tests': sample['skip-frontend-tests'] ? 'true' : 'false', + 'jwt-secret-key': + 'ZjY4MTM4YjI5YzMwZjhjYjI2OTNkNTRjMWQ5Y2Q0Y2YwOWNmZTE2NzRmYzU3NTMwM2NjOTE3MTllOTM3MWRkMzcyYTljMjVmNmQ0Y2MxOTUzODc0MDhhMTlkMDIxMzI2YzQzZDM2ZDE3MmQ3NjVkODk3OTVmYzljYTQyZDNmMTQ=', }; }); } catch (error) {