diff --git a/.blueprint/generate-sample/command.mjs b/.blueprint/generate-sample/command.mjs index 283e8b3..e301c2b 100644 --- a/.blueprint/generate-sample/command.mjs +++ b/.blueprint/generate-sample/command.mjs @@ -51,7 +51,7 @@ const command = { default: DEFAULT_SAMPLES_GROUP, }), configure: gen => { - gen.samplesGroup = DEFAULT_SAMPLES_GROUP; + gen.samplesGroup ??= DEFAULT_SAMPLES_GROUP; }, scope: 'generator', }, diff --git a/.blueprint/generate-sample/generator.mjs b/.blueprint/generate-sample/generator.mjs index 9087fb1..c870ce4 100644 --- a/.blueprint/generate-sample/generator.mjs +++ b/.blueprint/generate-sample/generator.mjs @@ -42,14 +42,18 @@ export default class extends BaseGenerator { 'sample-file': sampleFile = sampleName, 'sample-folder': sampleFolder = samplesPath, generatorOptions, + jdlOptions, } = samples[sampleName]; this.generatorOptions = generatorOptions; - this.sampleType = sampleType; + this.sampleType = sampleType === 'jdl-ejs' ? 'jdl' : sampleType; if (sampleType === 'jdl') { const jdlFile = `${sampleFile}.jdl`; this.copyTemplate(join(sampleFolder, jdlFile), jdlFile, { noGlob: true }); + } else if (sampleType === 'jdl-ejs') { + const jdlFile = `${sampleFile}.jdl`; + this.renderTemplate(join(sampleFolder, `${jdlFile}.ejs`), jdlFile, jdlOptions, undefined, { noGlob: true }); } else if (sampleType === 'yo-rc') { this.copyTemplate('**', '', { fromBasePath: this.templatePath(sampleFolder, sampleFile), diff --git a/.blueprint/generate-sample/templates/samples.js b/.blueprint/generate-sample/templates/samples.js new file mode 100644 index 0000000..dc11d2c --- /dev/null +++ b/.blueprint/generate-sample/templates/samples.js @@ -0,0 +1,21 @@ +import { fromMatrix } from 'generator-jhipster/testing'; + +export default Object.fromEntries( + Object.entries( + fromMatrix({ + buildTool: ['maven', 'gradle'], + auditFramework: ['custom', 'javers'], + }), + ).map(([key, { buildTool, auditFramework, ...value }]) => [ + key, + { + ...value, + 'job-name': `${auditFramework}, ${buildTool}, postgresql-mvc-jwt`, + 'sample-type': 'jdl-ejs', + 'sample-file': 'postgresql-mvc-jwt', + jdlOptions: { auditFramework, buildTool }, + 'audit-framework': auditFramework, + 'build-tool': buildTool, + }, + ]), +); diff --git a/.blueprint/generate-sample/templates/samples/postgresql-mvc-jwt.jdl b/.blueprint/generate-sample/templates/samples/postgresql-mvc-jwt.jdl index 539d4a4..38185db 100644 --- a/.blueprint/generate-sample/templates/samples/postgresql-mvc-jwt.jdl +++ b/.blueprint/generate-sample/templates/samples/postgresql-mvc-jwt.jdl @@ -1,10 +1,9 @@ application { config { - applicationType monolith + baseName jhipster cacheProvider no creationTimestamp 1632872179205 devDatabaseType h2Disk - enableHibernateCache false enableTranslation false jwtSecretKey "ZjY4MTM4YjI5YzMwZjhjYjI2OTNkNTRjMWQ5Y2Q0Y2YwOWNmZTE2NzRmYzU3NTMwM2NjOTE3MTllOTM3MWRkMzcyYTljMjVmNmQ0Y2MxOTUzODc0MDhhMTlkMDIxMzI2YzQzZDM2ZDE3MmQ3NjVkODk3OTVmYzljYTQyZDNmMTQ=" testFrameworks [cypress] diff --git a/.blueprint/generate-sample/templates/samples/postgresql-mvc-jwt.jdl.ejs b/.blueprint/generate-sample/templates/samples/postgresql-mvc-jwt.jdl.ejs new file mode 100644 index 0000000..9b61428 --- /dev/null +++ b/.blueprint/generate-sample/templates/samples/postgresql-mvc-jwt.jdl.ejs @@ -0,0 +1,48 @@ +application { + config { + baseName jhipster + blueprints [generator-jhipster-entity-audit] + buildTool <%- buildTool %> + cacheProvider no + creationTimestamp 1632872179205 + devDatabaseType h2Disk + enableTranslation false + jwtSecretKey "ZjY4MTM4YjI5YzMwZjhjYjI2OTNkNTRjMWQ5Y2Q0Y2YwOWNmZTE2NzRmYzU3NTMwM2NjOTE3MTllOTM3MWRkMzcyYTljMjVmNmQ0Y2MxOTUzODc0MDhhMTlkMDIxMzI2YzQzZDM2ZDE3MmQ3NjVkODk3OTVmYzljYTQyZDNmMTQ=" + testFrameworks [cypress] + } + + config(generator-jhipster-entity-audit) { + auditFramework <%- auditFramework %> + } + + entities Blog, Post, Tag +} + +@EnableAudit +@ChangelogDate(20240101000000) +entity Blog { + name String required minlength(3) + handle String required minlength(2) +} + +@EnableAudit +@ChangelogDate(20240101000100) +entity Post { + title String required + content TextBlob required + date Instant required +} + +@EnableAudit +@ChangelogDate(20240101000300) +entity Tag { + name String required minlength(2) +} + +relationship ManyToOne { + Post{blog(name)} to Blog +} + +relationship ManyToMany { + Post{tag(name)} to Tag{entry} +} diff --git a/.blueprint/github-build-matrix/__snapshots__/generator.spec.mjs.snap b/.blueprint/github-build-matrix/__snapshots__/generator.spec.mjs.snap index a498de7..0cd5567 100644 --- a/.blueprint/github-build-matrix/__snapshots__/generator.spec.mjs.snap +++ b/.blueprint/github-build-matrix/__snapshots__/generator.spec.mjs.snap @@ -4,15 +4,79 @@ exports[`generator - github-build-matrix > with samples > should match matrix va { "include": [ { + "audit-framework": "custom", + "build-tool": "maven", "default-environment": "prod", "java-version": "17", - "job-name": "postgresql-mvc-jwt", + "jdlOptions": { + "auditFramework": "custom", + "buildTool": "maven", + }, + "job-name": "custom, maven, postgresql-mvc-jwt", "jwt-secret-key": "ZjY4MTM4YjI5YzMwZjhjYjI2OTNkNTRjMWQ5Y2Q0Y2YwOWNmZTE2NzRmYzU3NTMwM2NjOTE3MTllOTM3MWRkMzcyYTljMjVmNmQ0Y2MxOTUzODc0MDhhMTlkMDIxMzI2YzQzZDM2ZDE3MmQ3NjVkODk3OTVmYzljYTQyZDNmMTQ=", "node-version": "22.12.0", "npm-version": "11.0.0", "os": "ubuntu-latest", - "sample": "postgresql-mvc-jwt", - "sample-type": "jdl", + "sample": "maven-custom", + "sample-file": "postgresql-mvc-jwt", + "sample-type": "jdl-ejs", + "samples-group": "samples", + }, + { + "audit-framework": "javers", + "build-tool": "maven", + "default-environment": "prod", + "java-version": "17", + "jdlOptions": { + "auditFramework": "javers", + "buildTool": "maven", + }, + "job-name": "javers, maven, postgresql-mvc-jwt", + "jwt-secret-key": "ZjY4MTM4YjI5YzMwZjhjYjI2OTNkNTRjMWQ5Y2Q0Y2YwOWNmZTE2NzRmYzU3NTMwM2NjOTE3MTllOTM3MWRkMzcyYTljMjVmNmQ0Y2MxOTUzODc0MDhhMTlkMDIxMzI2YzQzZDM2ZDE3MmQ3NjVkODk3OTVmYzljYTQyZDNmMTQ=", + "node-version": "22.12.0", + "npm-version": "11.0.0", + "os": "ubuntu-latest", + "sample": "maven-javers", + "sample-file": "postgresql-mvc-jwt", + "sample-type": "jdl-ejs", + "samples-group": "samples", + }, + { + "audit-framework": "custom", + "build-tool": "gradle", + "default-environment": "prod", + "java-version": "17", + "jdlOptions": { + "auditFramework": "custom", + "buildTool": "gradle", + }, + "job-name": "custom, gradle, postgresql-mvc-jwt", + "jwt-secret-key": "ZjY4MTM4YjI5YzMwZjhjYjI2OTNkNTRjMWQ5Y2Q0Y2YwOWNmZTE2NzRmYzU3NTMwM2NjOTE3MTllOTM3MWRkMzcyYTljMjVmNmQ0Y2MxOTUzODc0MDhhMTlkMDIxMzI2YzQzZDM2ZDE3MmQ3NjVkODk3OTVmYzljYTQyZDNmMTQ=", + "node-version": "22.12.0", + "npm-version": "11.0.0", + "os": "ubuntu-latest", + "sample": "gradle-custom", + "sample-file": "postgresql-mvc-jwt", + "sample-type": "jdl-ejs", + "samples-group": "samples", + }, + { + "audit-framework": "javers", + "build-tool": "gradle", + "default-environment": "prod", + "java-version": "17", + "jdlOptions": { + "auditFramework": "javers", + "buildTool": "gradle", + }, + "job-name": "javers, gradle, postgresql-mvc-jwt", + "jwt-secret-key": "ZjY4MTM4YjI5YzMwZjhjYjI2OTNkNTRjMWQ5Y2Q0Y2YwOWNmZTE2NzRmYzU3NTMwM2NjOTE3MTllOTM3MWRkMzcyYTljMjVmNmQ0Y2MxOTUzODc0MDhhMTlkMDIxMzI2YzQzZDM2ZDE3MmQ3NjVkODk3OTVmYzljYTQyZDNmMTQ=", + "node-version": "22.12.0", + "npm-version": "11.0.0", + "os": "ubuntu-latest", + "sample": "gradle-javers", + "sample-file": "postgresql-mvc-jwt", + "sample-type": "jdl-ejs", "samples-group": "samples", }, ], diff --git a/.blueprint/github-build-matrix/generator.spec.mjs b/.blueprint/github-build-matrix/generator.spec.mjs index b3e4c15..15e22a2 100644 --- a/.blueprint/github-build-matrix/generator.spec.mjs +++ b/.blueprint/github-build-matrix/generator.spec.mjs @@ -10,7 +10,7 @@ const generator = basename(__dirname); describe(`generator - ${generator}`, async () => { const groups = await getGithubSamplesGroups(join(__dirname, '../generate-sample/templates/')); - for (const workflow of groups.map(sample => sample.split('.')[0])) { + for (const workflow of [...new Set(groups.map(sample => sample.split('.')[0]))]) { describe(`with ${workflow}`, () => { beforeAll(async () => { await helpers.runJHipster(join(__dirname, 'index.mjs'), { useEnvironmentBuilder: true }).withArguments(workflow); diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml index b43989d..7280615 100644 --- a/.github/workflows/samples.yml +++ b/.github/workflows/samples.yml @@ -1,23 +1,4 @@ -# -# Copyright 2013-2022 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. -# - -name: JDL tests +name: Verify Sample Projects concurrency: # Group PRs by head_ref, push to main branch by commit id, and others branch by ref. group: ${{ github.workflow }}-${{ github.head_ref || (github.ref == 'refs/heads/main' && github.sha) || github.ref }} @@ -25,95 +6,104 @@ concurrency: on: push: branches: - - '*' + - 'main' + - '**maintenance' + paths-ignore: + - 'package*.json' pull_request: - types: [closed, opened, synchronize, reopened] branches: - '*' permissions: contents: read +env: + FORCE_COLOR: 2 jobs: - applications: - name: ${{ matrix.audit-framework }}, ${{ matrix.build-tool }}, ${{ matrix.suite }} (${{ matrix.os }}) + build-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.build.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - id: build + run: | + npm install + ./cli/cli.cjs github-build-matrix + samples: + name: ${{ matrix.job-name || matrix.sample }} runs-on: ${{ matrix.os }} + needs: build-matrix defaults: run: - shell: bash working-directory: ${{ github.workspace }}/app - if: github.event.action != 'closed' timeout-minutes: 30 strategy: fail-fast: false - matrix: - os: [ubuntu-22.04] - build-tool: [maven, gradle] - audit-framework: [custom, javers] - suite: - - postgresql-mvc-jwt.jdl + matrix: ${{fromJson(needs.build-matrix.outputs.matrix)}} steps: - #---------------------------------------------------------------------- - # Install all tools and check configuration - #---------------------------------------------------------------------- - - uses: jhipster/actions/create-app-path@v0 - - uses: jhipster/actions/setup-git@v0 - - name: 'SETUP: checkout generator-jhipster-entity-audit' - uses: actions/checkout@v4 + - uses: actions/checkout@v4 with: path: generator-jhipster-entity-audit fetch-depth: 2 - - name: 'SETUP: setup node' - uses: actions/setup-node@v4 - with: - node-version: 20 - - uses: actions/setup-java@v4 + - uses: jhipster/actions/setup-runner@v0 with: - distribution: 'temurin' - java-version: '17' - - name: 'SETUP: install generator-jhister-entity-audit' - run: | - npm ci - npm link + java-version: ${{ matrix.java-version }} + node-version: ${{ matrix.node-version }} + maven-cache: true + gradle-cache: true + binary-dir: ${{ github.workspace }}/generator-jhipster-entity-audit/cli/ + - run: npm install working-directory: ${{ github.workspace }}/generator-jhipster-entity-audit - - name: 'SETUP: get date' - id: get-date - run: echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" - - name: 'SETUP: load cache' - uses: actions/cache@v4 - with: - path: | - ~/.npm - ~/.cache/Cypress/ - ~/.m2/repository - key: ${{ runner.os }}-app-${{ matrix.suite }}-${{ steps.get-date.outputs.date }}-${{ hashFiles('generator-jhipster-entity-audit/package*.json') }} - #---------------------------------------------------------------------- - # Install JHipster and generate project+entities - #---------------------------------------------------------------------- - - name: 'PROJECT: generate' - run: 'jhipster-entity-audit generate-sample ${{ matrix.suite }} --build ${{ matrix.build-tool }} --audit-framework ${{ matrix.audit-framework }} --audit-page --no-insight --skip-commit-hook --skip-jhipster-dependencies --no-cypress-audit --audit-update-type all' + - run: cli.cjs generate-sample ${{ matrix.sample }} --skip-jhipster-dependencies --skip-install ${{ matrix.extra-args }} - uses: jhipster/actions/compare-sample@v0 + id: compare + if: >- + github.event.pull_request && + !contains(github.event.pull_request.labels.*.name, 'pr: disable-compare') with: generator-path: generator-jhipster-entity-audit - cmd: 'jhipster-entity-audit generate-sample ${{ matrix.suite }} --build ${{ matrix.build-tool }} --audit-framework ${{ matrix.audit-framework }} --audit-page --no-insight --skip-git --skip-commit-hook --skip-jhipster-dependencies --no-cypress-audit --audit-update-type all --skip-install' - - name: 'TESTS: backend tests' - run: npm run ci:backend:test - - name: 'TESTS: frontend tests' - run: npm run ci:frontend:test - - name: 'TESTS: packaging' - run: npm run ci:e2e:package - - name: 'TESTS: start docker dependencies' - run: npm run ci:e2e:prepare - - name: 'TESTS: run e2e' - run: npm run ci:e2e:run --if-present - check-applications: + cmd: cli.cjs generate-sample ${{ matrix.sample-file }} --build ${{ matrix.build-tool }} --audit-framework ${{ matrix.audit-framework }} --audit-page --no-insight --skip-git --skip-commit-hook --skip-jhipster-dependencies --no-cypress-audit --audit-update-type all --skip-install + - run: npm run ci:backend:test + if: steps.compare.outputs.equals != 'true' + id: backend + - run: npm run ci:e2e:package + if: steps.compare.outputs.equals != 'true' + - run: npm run ci:frontend:test --if-present + if: steps.compare.outputs.equals != 'true' + - run: npm run ci:e2e:prepare + if: steps.compare.outputs.equals != 'true' + - run: npm run ci:e2e:run --if-present + if: steps.compare.outputs.equals != 'true' + id: e2e + - name: Store backend test failure logs + uses: actions/upload-artifact@v4 + if: always() && steps.backend.outcome == 'failure' + with: + name: log-${{ matrix.job-name || matrix.sample }} + path: | + ${{ github.workspace }}/app/build/test-results/**/*.xml + ${{ github.workspace }}/app/target/surefire-reports + - name: Store cypress screenshots + uses: actions/upload-artifact@v4 + if: always() && steps.e2e.outcome == 'failure' + with: + name: screenshots-${{ matrix.job-name || matrix.sample }} + path: ${{ github.workspace }}/app/**/cypress/screenshots + - name: Dump docker logs + if: always() + uses: jwalton/gh-docker-logs@v2 + check-samples: permissions: contents: none runs-on: ubuntu-latest - needs: [applications] + needs: [samples] if: always() steps: - run: | echo '${{ toJSON(needs) }}' - if [ 'skipped' == '${{ needs.applications.result }}' ] || [ 'success' == '${{ needs.applications.result }}' ] || [ 'closed' == '${{ github.event.action }}' ]; then + if [ 'skipped' == '${{ needs.samples.result }}' ] || [ 'success' == '${{ needs.samples.result }}' ] || [ 'closed' == '${{ github.event.action }}' ]; then exit 0 fi exit 1 diff --git a/README.md b/README.md index bf3eabf..4bc0cbe 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,26 @@ jhipster-entity-audit app --help And looking for `(blueprint option: entity-audit)` like +## JDL + +JHipster entity-audit blueprint supports JDL as following + +```jdl +application { + config { + baseName sample + blueprints [generator-jhipster-entity-audit] + } + + config(generator-jhipster-entity-audit) { + auditFramework javers + } + + entities * +} + +``` + ## Pre-release To use an unreleased version, install it using git. diff --git a/generators/angular-audit/generator.spec.js b/generators/angular-audit/generator.spec.js index 30e2fda..f265eb6 100644 --- a/generators/angular-audit/generator.spec.js +++ b/generators/angular-audit/generator.spec.js @@ -14,8 +14,9 @@ describe('SubGenerator angular-audit of entity-audit JHipster blueprint', () => .withOptions({ ignoreNeedlesError: true, }) - .withJHipsterLookup() - .withParentBlueprintLookup(); + .withJHipsterGenerators() + .withConfiguredBlueprint() + .withBlueprintConfig(); }); it('should succeed', () => { diff --git a/generators/client/command.js b/generators/client/command.js index ea17f84..3da64fd 100644 --- a/generators/client/command.js +++ b/generators/client/command.js @@ -1,5 +1,20 @@ import { asCommand } from 'generator-jhipster'; export default asCommand({ - configs: {}, + configs: { + auditPage: { + description: 'Generate client page', + cli: { + type: Boolean, + }, + prompt: { + type: 'confirm', + message: 'Do you want to add an audit log page for entities?', + }, + configure: gen => { + gen.blueprintConfig.auditPage = (gen.blueprintConfig.auditFramework ?? 'no') !== 'no'; + }, + scope: 'blueprint', + }, + }, }); diff --git a/generators/client/generator.spec.js b/generators/client/generator.spec.js index 3b9f674..d76e801 100644 --- a/generators/client/generator.spec.js +++ b/generators/client/generator.spec.js @@ -13,10 +13,10 @@ describe('SubGenerator client of entity-audit JHipster blueprint', () => { .withJHipsterConfig() .withOptions({ ignoreNeedlesError: true, - blueprint: ['entity-audit'], }) - .withJHipsterLookup() - .withParentBlueprintLookup(); + .withJHipsterGenerators() + .withConfiguredBlueprint() + .withBlueprintConfig(); }); it('should succeed', () => { diff --git a/generators/java-audit/command.js b/generators/java-audit/command.js index fc474d6..4d5577c 100644 --- a/generators/java-audit/command.js +++ b/generators/java-audit/command.js @@ -28,18 +28,6 @@ export default asCommand({ ], scope: 'blueprint', }, - auditPage: { - description: 'Generate client page', - cli: { - type: Boolean, - }, - prompt: { - type: 'confirm', - message: 'Do you want to add an audit log page for entities?', - }, - default: true, - scope: 'blueprint', - }, auditUpdateType: { cli: { type: String, diff --git a/generators/java-audit/generator.js b/generators/java-audit/generator.js index e04fc4e..8b3c345 100644 --- a/generators/java-audit/generator.js +++ b/generators/java-audit/generator.js @@ -73,10 +73,18 @@ export default class extends BaseApplicationGenerator { get [BaseApplicationGenerator.CONFIGURING_EACH_ENTITY]() { return this.asConfiguringEachEntityTaskGroup({ - async configureEntity({ entityName, entityConfig }) { - const auditedEntities = this.auditUpdateType === 'all' ? this.getExistingEntities().map(e => e.name) : this.auditedEntities; - entityConfig.enableAudit = auditedEntities?.includes(entityName) || entityConfig.enableAudit; - if (!entityConfig.enableAudit) return; + async configureEntity({ entityName, entityConfig, entityStorage }) { + entityConfig.annotations ??= {}; + if (entityConfig.enableAudit !== undefined) { + entityConfig.annotations.enableAudit ??= entityConfig.enableAudit; + delete entityConfig.enableAudit; + } + if (entityConfig.annotations.enableAudit === undefined) { + const auditedEntities = this.auditUpdateType === 'all' ? this.getExistingEntities().map(e => e.name) : this.auditedEntities; + entityConfig.annotations.enableAudit = auditedEntities?.includes(entityName); + entityStorage.save(); + } + if (!entityConfig.annotations.enableAudit) return; const fieldNames = entityConfig.fields.map(f => f.fieldName); const fieldsToAdd = ADDITIONAL_FIELDS.filter(f => !fieldNames.includes(f.fieldName)).map(f => ({ ...f }));