From 86f03c768bf647eda223febda77db996a87c5357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Mino?= Date: Tue, 17 Dec 2024 23:53:59 +0100 Subject: [PATCH 1/2] feat(liquibase): new module for configuring a liquibase linter executed as a maven plugin --- .../LiquibaseApplicationService.java | 4 ++ .../domain/LiquibaseModuleFactory.java | 36 +++++++++++++++ .../primary/LiquibaseModuleConfiguration.java | 27 +++++++++-- .../lite/module/domain/JHipsterModule.java | 4 ++ .../domain/file/JHipsterDestination.java | 1 + .../shared/slug/domain/JHLiteModuleSlug.java | 1 + .../resources/generator/dependencies/pom.xml | 10 +++- .../liquibase/liquibase-linter.jsonc | 5 ++ .../springboot/dbmigration/liquibase.feature | 7 +++ .../domain/LiquibaseModuleFactoryTest.java | 46 +++++++++++++++++++ tests-ci/generate.sh | 1 + 11 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 src/main/resources/generator/server/springboot/dbmigration/liquibase/liquibase-linter.jsonc diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/application/LiquibaseApplicationService.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/application/LiquibaseApplicationService.java index 94d52cad217..d69e790f3c0 100644 --- a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/application/LiquibaseApplicationService.java +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/application/LiquibaseApplicationService.java @@ -21,4 +21,8 @@ public JHipsterModule buildModule(JHipsterModuleProperties properties) { public JHipsterModule buildAsyncModule(JHipsterModuleProperties properties) { return factory.buildAsyncModule(properties); } + + public JHipsterModule buildLinterModule(JHipsterModuleProperties properties) { + return factory.buildLinterModule(properties); + } } diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/domain/LiquibaseModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/domain/LiquibaseModuleFactory.java index 1db7717728f..36ebd0f5d94 100644 --- a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/domain/LiquibaseModuleFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/domain/LiquibaseModuleFactory.java @@ -3,12 +3,15 @@ import static tech.jhipster.lite.module.domain.JHipsterModule.artifactId; import static tech.jhipster.lite.module.domain.JHipsterModule.from; import static tech.jhipster.lite.module.domain.JHipsterModule.groupId; +import static tech.jhipster.lite.module.domain.JHipsterModule.mavenPlugin; import static tech.jhipster.lite.module.domain.JHipsterModule.moduleBuilder; +import static tech.jhipster.lite.module.domain.JHipsterModule.pluginExecution; import static tech.jhipster.lite.module.domain.JHipsterModule.propertyKey; import static tech.jhipster.lite.module.domain.JHipsterModule.propertyValue; import static tech.jhipster.lite.module.domain.JHipsterModule.to; import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcMainJava; import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcTestJava; +import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcTestResources; import static tech.jhipster.lite.module.domain.JHipsterModule.versionSlug; import static tech.jhipster.lite.module.domain.properties.SpringConfigurationFormat.PROPERTIES; import static tech.jhipster.lite.module.domain.properties.SpringConfigurationFormat.YAML; @@ -16,6 +19,8 @@ import tech.jhipster.lite.module.domain.JHipsterModule; import tech.jhipster.lite.module.domain.LogLevel; import tech.jhipster.lite.module.domain.file.JHipsterSource; +import tech.jhipster.lite.module.domain.mavenplugin.MavenPlugin; +import tech.jhipster.lite.module.domain.mavenplugin.MavenPlugin.MavenPluginOptionalBuilder; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; import tech.jhipster.lite.shared.error.domain.Assert; @@ -76,4 +81,35 @@ public JHipsterModule buildAsyncModule(JHipsterModuleProperties properties) { .build(); //@formatter:on } + + public JHipsterModule buildLinterModule(JHipsterModuleProperties properties) { + //@formatter:off + return moduleBuilder(properties) + .mavenPlugins() + .plugin(liquibaseLinterMavenPlugin().build()) + .pluginManagement(liquibaseLinterMavenPluginManagement()) + .and() + .files() + .add(SOURCE.append("liquibase-linter.jsonc"), toSrcTestResources().append("liquibase-linter.jsonc")) + .and() + .build(); + //@formatter:on + } + + private MavenPlugin liquibaseLinterMavenPluginManagement() { + return liquibaseLinterMavenPlugin() + .versionSlug("liquibase-linter-maven-plugin") + .configuration( + """ + src/main/resources/config/liquibase/master.xml + src/test/resources/liquibase-linter.jsonc + """ + ) + .addExecution(pluginExecution().goals("lint")) + .build(); + } + + private static MavenPluginOptionalBuilder liquibaseLinterMavenPlugin() { + return mavenPlugin().groupId("io.github.liquibase-linter").artifactId("liquibase-linter-maven-plugin"); + } } diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/infrastructure/primary/LiquibaseModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/infrastructure/primary/LiquibaseModuleConfiguration.java index 503ec62db4b..00d10df4266 100644 --- a/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/infrastructure/primary/LiquibaseModuleConfiguration.java +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/infrastructure/primary/LiquibaseModuleConfiguration.java @@ -4,7 +4,9 @@ import static tech.jhipster.lite.shared.slug.domain.JHLiteFeatureSlug.JPA_PERSISTENCE; import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.LIQUIBASE; import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.LIQUIBASE_ASYNC; +import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.LIQUIBASE_LINTER; import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.LOGS_SPY; +import static tech.jhipster.lite.shared.slug.domain.JHLiteModuleSlug.MAVEN_JAVA; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -16,19 +18,25 @@ @Configuration class LiquibaseModuleConfiguration { + private static final String SPRING_BOOT_DATABASE_MIGRATION = "Spring Boot - Database Migration"; + @Bean JHipsterModuleResource liquibaseModule(LiquibaseApplicationService liquibase) { return JHipsterModuleResource.builder() .slug(LIQUIBASE) .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().addIndentation().addSpringConfigurationFormat().build()) - .apiDoc("Spring Boot - Database Migration", "Add Liquibase") + .apiDoc(SPRING_BOOT_DATABASE_MIGRATION, "Add Liquibase") .organization( JHipsterModuleOrganization.builder().feature(DATABASE_MIGRATION).addDependency(JPA_PERSISTENCE).addDependency(LOGS_SPY).build() ) - .tags("server", "spring", "spring-boot", "database", "migration", "liquibase") + .tags(liquibaseTags()) .factory(liquibase::buildModule); } + private String[] liquibaseTags() { + return new String[] { "liquibase", "database", "migration", "spring", "spring-boot" }; + } + @Bean JHipsterModuleResource liquibaseAsyncModule(LiquibaseApplicationService liquibase) { return JHipsterModuleResource.builder() @@ -36,9 +44,20 @@ JHipsterModuleResource liquibaseAsyncModule(LiquibaseApplicationService liquibas .propertiesDefinition( JHipsterModulePropertiesDefinition.builder().addIndentation().addBasePackage().addSpringConfigurationFormat().build() ) - .apiDoc("Spring Boot - Database Migration", "Support updating the database asynchronously with Liquibase") + .apiDoc(SPRING_BOOT_DATABASE_MIGRATION, "Support updating the database asynchronously with Liquibase") .organization(JHipsterModuleOrganization.builder().addDependency(LIQUIBASE).build()) - .tags("server", "spring", "spring-boot", "database", "migration", "liquibase") + .tags(liquibaseTags()) .factory(liquibase::buildAsyncModule); } + + @Bean + JHipsterModuleResource liquibaseLinterModule(LiquibaseApplicationService liquibase) { + return JHipsterModuleResource.builder() + .slug(LIQUIBASE_LINTER) + .propertiesDefinition(JHipsterModulePropertiesDefinition.EMPTY) + .apiDoc(SPRING_BOOT_DATABASE_MIGRATION, "Configure a linter for the Liquibase migration scripts") + .organization(JHipsterModuleOrganization.builder().addDependency(LIQUIBASE).addDependency(MAVEN_JAVA).build()) + .tags("server", "database", "migration", "liquibase", "linter") + .factory(liquibase::buildLinterModule); + } } diff --git a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java index 0d4f881c663..19b8d822cf4 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java +++ b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java @@ -237,6 +237,10 @@ public static JHipsterDestination toSrcMainResources() { return JHipsterDestination.SRC_MAIN_RESOURCES; } + public static JHipsterDestination toSrcTestResources() { + return JHipsterDestination.SRC_TEST_RESOURCES; + } + public static JHipsterFileMatcher filesWithExtension(String extension) { return path -> StringUtils.endsWithIgnoreCase(path.get(), "." + extension); } diff --git a/src/main/java/tech/jhipster/lite/module/domain/file/JHipsterDestination.java b/src/main/java/tech/jhipster/lite/module/domain/file/JHipsterDestination.java index da6aa216ffb..93c4153d232 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/file/JHipsterDestination.java +++ b/src/main/java/tech/jhipster/lite/module/domain/file/JHipsterDestination.java @@ -13,6 +13,7 @@ public class JHipsterDestination { public static final JHipsterDestination SRC_TEST_JAVA = new JHipsterDestination("src/test/java"); public static final JHipsterDestination SRC_MAIN_DOCKER = new JHipsterDestination("src/main/docker"); public static final JHipsterDestination SRC_MAIN_RESOURCES = new JHipsterDestination("src/main/resources"); + public static final JHipsterDestination SRC_TEST_RESOURCES = new JHipsterDestination("src/test/resources"); private static final String MUSTACHE_EXTENSION = ".mustache"; diff --git a/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteModuleSlug.java b/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteModuleSlug.java index d2d75d25665..c2a49bfa40d 100644 --- a/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteModuleSlug.java +++ b/src/main/java/tech/jhipster/lite/shared/slug/domain/JHLiteModuleSlug.java @@ -78,6 +78,7 @@ public enum JHLiteModuleSlug implements JHipsterModuleSlugFactory { LICENSE_MIT("license-mit"), LIQUIBASE("liquibase"), LIQUIBASE_ASYNC("liquibase-async"), + LIQUIBASE_LINTER("liquibase-linter"), LOGSTASH("logstash"), LOGS_SPY("logs-spy"), MAVEN_JAVA("maven-java"), diff --git a/src/main/resources/generator/dependencies/pom.xml b/src/main/resources/generator/dependencies/pom.xml index 3a4b73d6b39..c50a967ac9e 100644 --- a/src/main/resources/generator/dependencies/pom.xml +++ b/src/main/resources/generator/dependencies/pom.xml @@ -40,6 +40,8 @@ 2.1.0-M2 2.1.0-M4 2.2.1 + 0.36.2 + 3.19.16 5.11.4 3.26.3 @@ -69,8 +71,7 @@ 3.1.1 0.0.21 1.0.3 - 0.36.2 - 3.19.16 + 0.8.0 @@ -416,6 +417,11 @@ langchain4j-open-ai-spring-boot-starter ${langchain4j.version} + + io.github.liquibase-linter + liquibase-linter-maven-plugin + ${liquibase-linter-maven-plugin.version} + diff --git a/src/main/resources/generator/server/springboot/dbmigration/liquibase/liquibase-linter.jsonc b/src/main/resources/generator/server/springboot/dbmigration/liquibase/liquibase-linter.jsonc new file mode 100644 index 00000000000..749dfdccc61 --- /dev/null +++ b/src/main/resources/generator/server/springboot/dbmigration/liquibase/liquibase-linter.jsonc @@ -0,0 +1,5 @@ +{ + "rules": { + "isolate-ddl-changes": true + } +} diff --git a/src/test/features/server/springboot/dbmigration/liquibase.feature b/src/test/features/server/springboot/dbmigration/liquibase.feature index 1b306506d1e..fa4734fbcb9 100644 --- a/src/test/features/server/springboot/dbmigration/liquibase.feature +++ b/src/test/features/server/springboot/dbmigration/liquibase.feature @@ -11,3 +11,10 @@ Feature: Liquibase module | packageName | tech.jhipster.chips | Then I should have files in "src/main/java/tech/jhipster/chips/wire/liquibase/infrastructure/secondary" | AsyncSpringLiquibase.java | + + Scenario: Should apply liquibase-linter module + When I apply "liquibase-linter" module to default project with maven file + | packageName | tech.jhipster.chips | + Then I should have "liquibase-linter-maven-plugin" in "pom.xml" + Then I should have files in "src/test/resources/" + | liquibase-linter.jsonc | diff --git a/src/test/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/domain/LiquibaseModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/domain/LiquibaseModuleFactoryTest.java index 5af09a7f27a..a434ab29106 100644 --- a/src/test/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/domain/LiquibaseModuleFactoryTest.java +++ b/src/test/java/tech/jhipster/lite/generator/server/springboot/dbmigration/liquibase/domain/LiquibaseModuleFactoryTest.java @@ -117,4 +117,50 @@ void shouldBuildModuleWithPropertiesSpringConfigurationFormat() { .notContaining("YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();"); } } + + @Nested + class LiquibaseLinterModule { + + @Test + void shouldBuildModule() { + JHipsterModuleProperties properties = JHipsterModulesFixture.propertiesBuilder(tmpDirForTest()) + .basePackage("tech.jhipster.jhlitest") + .build(); + + JHipsterModule module = factory.buildLinterModule(properties); + + assertThatModuleWithFiles(module, pomFile()) + .hasFile("pom.xml") + .containing( + """ + + io.github.liquibase-linter + liquibase-linter-maven-plugin + + """ + ) + .containing( + """ + + io.github.liquibase-linter + liquibase-linter-maven-plugin + ${liquibase-linter-maven-plugin.version} + + + + lint + + + + + src/main/resources/config/liquibase/master.xml + src/test/resources/liquibase-linter.jsonc + + + """ + ) + .and() + .hasFile("src/test/resources/liquibase-linter.jsonc"); + } + } } diff --git a/tests-ci/generate.sh b/tests-ci/generate.sh index 2e70a405011..75fc68579c3 100755 --- a/tests-ci/generate.sh +++ b/tests-ci/generate.sh @@ -168,6 +168,7 @@ elif [[ $application == 'fullapp' ]]; then apply_modules \ "jpa-postgresql" \ "liquibase" \ + "liquibase-linter" \ "liquibase-async" apply_modules \ From 474417cec9f3d2ddbf40b1fde891cf0c5da450e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Mino?= Date: Wed, 18 Dec 2024 00:02:39 +0100 Subject: [PATCH 2/2] fix(prettier): correctly handle jsonc files --- .lintstagedrc.js | 2 +- .prettierrc | 6 ++++++ .../generator/prettier/domain/PrettierModuleFactory.java | 2 +- src/main/resources/generator/prettier/.prettierrc.mustache | 6 ++++++ .../prettier/domain/PrettierModuleFactoryTest.java | 4 ++-- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.lintstagedrc.js b/.lintstagedrc.js index d43be151739..f33b94d46b1 100644 --- a/.lintstagedrc.js +++ b/.lintstagedrc.js @@ -2,5 +2,5 @@ export default { '*.{js,cjs,ts,tsx,vue}': ['eslint --fix', 'prettier --write'], '*.{css,scss}': ['stylelint --fix --allow-empty-input', 'prettier --write'], '*.pug': ['eslint --fix', 'prettier --write'], - '*.{md,json,yml,html,java,xml,feature,sh}': ['prettier --write'], + '*.{md,json*,yml,html,java,xml,feature,sh}': ['prettier --write'], }; diff --git a/.prettierrc b/.prettierrc index 186ff55dd83..9fe754c8769 100644 --- a/.prettierrc +++ b/.prettierrc @@ -22,3 +22,9 @@ bracketSameLine: false # xml rules: xmlWhitespaceSensitivity: ignore + +# https://github.com/prettier/prettier/issues/15956 +overrides: + - files: ['*.jsonc'] + options: + trailingComma: none diff --git a/src/main/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactory.java index 55b330b2bc7..d66267417cd 100644 --- a/src/main/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactory.java @@ -53,7 +53,7 @@ public JHipsterModule buildModule(JHipsterModuleProperties properties) { .postActions() .add(context -> npmLazyInstaller.runInstallIn(context.projectFolder())) .and() - .preCommitActions(stagedFilesFilter("*.{md,json,yml,html,css,scss,java,xml,feature}"), preCommitCommands("['prettier --write']")) + .preCommitActions(stagedFilesFilter("*.{md,json*,yml,html,css,scss,java,xml,feature}"), preCommitCommands("['prettier --write']")) .build(); //@formatter:on } diff --git a/src/main/resources/generator/prettier/.prettierrc.mustache b/src/main/resources/generator/prettier/.prettierrc.mustache index 33f34cf353a..cd193c27437 100644 --- a/src/main/resources/generator/prettier/.prettierrc.mustache +++ b/src/main/resources/generator/prettier/.prettierrc.mustache @@ -21,3 +21,9 @@ bracketSameLine: false # xml rules: xmlWhitespaceSensitivity: ignore + +# https://github.com/prettier/prettier/issues/15956 +overrides: + - files: ['*.jsonc'] + options: + trailingComma: none diff --git a/src/test/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactoryTest.java index ad59ca3668b..8933a51fbcb 100644 --- a/src/test/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactoryTest.java +++ b/src/test/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactoryTest.java @@ -43,7 +43,7 @@ void shouldBuildModuleWithoutPrettierLintStaged() { .containing( """ module.exports = { - '*.{md,json,yml,html,css,scss,java,xml,feature}': ['prettier --write'], + '*.{md,json*,yml,html,css,scss,java,xml,feature}': ['prettier --write'], '*.pug': ['eslint --fix', 'prettier --write'], }; """ @@ -83,7 +83,7 @@ void shouldBuildModuleWithEmptyLintStaged() { .containing( """ module.exports = { - '*.{md,json,yml,html,css,scss,java,xml,feature}': ['prettier --write'], + '*.{md,json*,yml,html,css,scss,java,xml,feature}': ['prettier --write'], }; """ );