Collapse the audit roster and add a MySQL/MariaDB archetype seam#15
Collapse the audit roster and add a MySQL/MariaDB archetype seam#15jeffjensen wants to merge 9 commits into
Conversation
|
Warning Review limit reached
Next review available in: 30 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (26)
📝 WalkthroughWalkthroughThis PR adds multi-engine database support to the archetype-generated demo project and refactors Spring integration audit wiring around ChangesAudit Assertion Framework Refactor
Archetype Multi-Engine Database Support
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoCollapse audit assertion wiring via registrar; add MySQL/MariaDB archetype seam
AI Description
Diagram
High-Level Assessment
Files changed (40)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
31 rules 1. DemoDatabaseTestConfig uses forbidden imports
|
| void testDatabaseAuditSuiteBean_ConstructsAgainstCoreAuditConstructors() | ||
| throws SQLException { | ||
| final DataSource dataSource = postgresDataSource(); | ||
| final SqlCapturingStatementInspector capturer = | ||
| configuration.sqlCapturingStatementInspector(); | ||
|
|
||
| final DatabaseAuditSuite suite = configuration.databaseAuditSuite( | ||
| dataSource, mock(EntityManagerFactory.class), capturer); | ||
|
|
||
| assertThat(suite) | ||
| .as("The suite bean constructs against core's audit constructors.") | ||
| .isNotNull(); | ||
| assertThat(configuration.foreignKeyIndexAuditAssertion(suite)) | ||
| .as("The foreignKeyIndexAuditAssertion bean constructs.") | ||
| .isNotNull(); | ||
| assertThat(configuration.foreignKeyNotNullAuditAssertion(suite)) | ||
| .as("The foreignKeyNotNullAuditAssertion bean constructs.") | ||
| .isNotNull(); | ||
| assertThat(configuration.foreignKeyTypeMatchAuditAssertion(suite)) | ||
| .as("The foreignKeyTypeMatchAuditAssertion bean constructs.") | ||
| .isNotNull(); | ||
| assertThat(configuration.primaryKeyPresenceAuditAssertion(suite)) | ||
| .as("The primaryKeyPresenceAuditAssertion bean constructs.") | ||
| .isNotNull(); | ||
| assertThat(configuration.redundantIndexAuditAssertion(suite)) | ||
| .as("The redundantIndexAuditAssertion bean constructs.") | ||
| .isNotNull(); | ||
| assertThat(configuration.schemaEntityValidationAuditAssertion(suite)) | ||
| .as("The schemaEntityValidationAuditAssertion bean constructs.") | ||
| .isNotNull(); | ||
| assertThat(configuration.joinIndexAuditAssertion(suite)) | ||
| .as("The joinIndexAuditAssertion bean constructs.").isNotNull(); | ||
| assertThat(configuration.orderByIndexAuditAssertion(suite)) | ||
| .as("The orderByIndexAuditAssertion bean constructs.") | ||
| .isNotNull(); | ||
| assertThat(configuration.whereClauseIndexAuditAssertion(suite)) | ||
| .as("The whereClauseIndexAuditAssertion bean constructs.") | ||
| .isNotNull(); | ||
| assertThat(configuration.unconditionalMutationAuditAssertion(suite)) | ||
| .as("The unconditionalMutationAuditAssertion bean constructs.") | ||
| .isNotNull(); | ||
| assertThat(configuration.databaseAuditAssertions(suite)) | ||
| .as("The databaseAuditAssertions facade bean constructs.") | ||
| .isNotNull(); | ||
| postgresDataSource(), mock(EntityManagerFactory.class), | ||
| capturer); | ||
|
|
||
| assertThat(suite.all()) | ||
| .as("The suite bean wires every audit assertion against core's constructors.") | ||
| .isNotEmpty(); | ||
| } | ||
|
|
||
| /** | ||
| * The stock registrar publishes every one of the suite's assertions — and | ||
| * the {@link DatabaseAuditAssertions} facade — as a primary bean under its | ||
| * concrete type, so consumers {@code @Autowired} the assertion they need | ||
| * without a per-audit {@code @Bean} method. | ||
| */ | ||
| @Test | ||
| void testAuditAssertionRegistrar_PublishesEveryAssertionAndTheFacadeAsPrimaryBeans() | ||
| throws SQLException { | ||
| final DatabaseAuditSuite suite = new DatabaseAuditSuite( | ||
| postgresDataSource(), mock(EntityManagerFactory.class), | ||
| new SqlCapturingStatementInspector()); | ||
| final DefaultListableBeanFactory beanFactory = | ||
| new DefaultListableBeanFactory(); | ||
| final AuditAssertionRegistrar registrar = | ||
| configuration.auditAssertionRegistrar(suite); | ||
| registrar.setBeanFactory(beanFactory); | ||
|
|
||
| registrar.afterSingletonsInstantiated(); | ||
|
|
||
| for (final AuditAssertion assertion : suite.all()) { | ||
| assertThat(beanFactory.getBean(assertion.getClass())) | ||
| .as("The %s bean is the suite's own assertion instance.", | ||
| assertion.getClass().getSimpleName()) | ||
| .isSameAs(assertion); | ||
| } | ||
| assertThat(beanFactory.getBean(DatabaseAuditAssertions.class)) | ||
| .as("The facade bean is the suite's assertions facade.") | ||
| .isSameAs(suite.assertions()); | ||
| assertThat(beanFactory | ||
| .getBeanDefinition("foreignKeyIndexAuditAssertion").isPrimary()) | ||
| .as("The stock registrar marks its assertion beans primary.") | ||
| .isTrue(); | ||
| } | ||
|
|
||
| /** | ||
| * Guards the roster: every concrete {@code *Audit} in core must have a | ||
| * wired {@code *AuditAssertion} in the suite, so adding a core audit without | ||
| * wiring it here fails the build instead of silently never running. | ||
| */ | ||
| @Test | ||
| void testSuiteAll_WiresAnAssertionForEveryCoreAudit() | ||
| throws SQLException { | ||
| final ClassPathScanningCandidateComponentProvider scanner = | ||
| new ClassPathScanningCandidateComponentProvider(false); | ||
| scanner.addIncludeFilter( | ||
| new RegexPatternTypeFilter(Pattern.compile(".*Audit"))); | ||
| final Set<String> coreAudits = scanner | ||
| .findCandidateComponents("io.github.databaseaudits.audit") | ||
| .stream() | ||
| .map(definition -> simpleName(definition.getBeanClassName())) | ||
| .collect(Collectors.toSet()); | ||
|
|
||
| final DatabaseAuditSuite suite = new DatabaseAuditSuite( | ||
| postgresDataSource(), mock(EntityManagerFactory.class), | ||
| new SqlCapturingStatementInspector()); | ||
| final Set<String> wiredAudits = suite.all().stream() | ||
| .map(DatabaseAuditTestConfigurationIT::auditName) | ||
| .collect(Collectors.toSet()); | ||
|
|
||
| assertThat(wiredAudits).as( | ||
| "Every core *Audit has a wired *AuditAssertion in the suite.") | ||
| .isEqualTo(coreAudits); |
There was a problem hiding this comment.
1. Test names missing required underscores 📘 Rule violation ▣ Testability
Several newly added/modified JUnit test methods do not follow the required naming pattern ^test[A-Z][A-Za-z0-9]*_[A-Za-z0-9]+_[A-Za-z0-9]+$. This reduces consistency and may break tooling that relies on the convention.
Agent Prompt
## Issue description
Test method names must match `^test[A-Z][A-Za-z0-9]*_[A-Za-z0-9]+_[A-Za-z0-9]+$` (three segments separated by exactly two underscores). Newly added/modified tests currently have only one underscore, so they violate the required convention.
## Issue Context
Non-compliant method names include `testDatabaseAuditSuiteBean_ConstructsAgainstCoreAuditConstructors`, `testAuditAssertionRegistrar_PublishesEveryAssertionAndTheFacadeAsPrimaryBeans`, and `testSuiteAll_WiresAnAssertionForEveryCoreAudit`.
## Fix Focus Areas
- integration/src/test/java/io/github/databaseaudits/spring/boot/DatabaseAuditTestConfigurationIT.java[64-140]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.test.context.DynamicPropertyRegistrar; | ||
| #if($databasePlatform == 'mysql') | ||
| import org.testcontainers.mysql.MySQLContainer; | ||
| #elseif($databasePlatform == 'mariadb') | ||
| import org.testcontainers.mariadb.MariaDBContainer; | ||
| #else | ||
| import org.testcontainers.postgresql.PostgreSQLContainer; | ||
| #end | ||
| import org.testcontainers.utility.DockerImageName; |
There was a problem hiding this comment.
2. Demodatabasetestconfig uses forbidden imports 📘 Rule violation § Compliance
The archetype template DemoDatabaseTestConfig imports Spring and Testcontainers types, which violates the restriction that archetype-generated classes may only depend on JUnit and database-audits (besides the Java standard library). This can pull unwanted third-party dependencies into generated projects.
Agent Prompt
## Issue description
Archetype-generated classes must restrict imports (beyond `java.*`/`javax.*`) to JUnit and this project's `database-audits` packages. The new archetype template `DemoDatabaseTestConfig.java` imports Spring (`org.springframework.*`) and Testcontainers (`org.testcontainers.*`).
## Issue Context
This file is under `archetype-resources/`, meaning it is emitted into consumer projects.
## Fix Focus Areas
- archetype/src/main/resources/archetype-resources/src/test/java/app/DemoDatabaseTestConfig.java[12-22]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| #if($databasePlatform == 'mysql') | ||
| private static final MySQLContainer DATABASE = | ||
| new MySQLContainer(DockerImageName.parse("${image}")); | ||
| static { | ||
| DATABASE.start(); | ||
| } | ||
| #elseif($databasePlatform == 'mariadb') | ||
| private static final MariaDBContainer DATABASE = | ||
| new MariaDBContainer(DockerImageName.parse("${image}")); | ||
| static { | ||
| DATABASE.start(); | ||
| } |
There was a problem hiding this comment.
5. Mysql schemaname mismatch 🐞 Bug ≡ Correctness
For databasePlatform=mysql|mariadb, the generated demo container does not set its database name based on schemaName, while the archetype default remains schemaName=public and the catalog ITs pass that schema value into the audits. Generating a MySQL/MariaDB project by only changing databasePlatform will therefore likely run catalog audits against the wrong/non-existent schema unless the user also remembers to override schemaName.
Agent Prompt
## Issue description
When generating a MySQL/MariaDB demo harness, the container’s database name is left at its Testcontainers default, but the archetype still defaults `schemaName` to `public` and the catalog ITs use `schemaName` for audit scope. This makes the generated MySQL/MariaDB demo easy to misconfigure (audits run against the wrong schema) unless the user also overrides `schemaName`.
## Issue Context
The PR adds `databasePlatform=mysql|mariadb` generation, so the previous PostgreSQL-centric `schemaName` default becomes a practical footgun for new platforms.
## Fix Focus Areas
- archetype/src/main/resources/archetype-resources/src/test/java/app/DemoDatabaseTestConfig.java[36-47]
## Implementation notes
- For MySQL/MariaDB, configure the container with a database name matching the archetype’s `schemaName` (e.g., `DATABASE.withDatabaseName("${schemaName}")`) so the default `schemaName=public` remains consistent.
- Alternatively (or additionally), adjust documentation / archetype defaults so MySQL/MariaDB generation defaults `schemaName` to the container’s default database.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
647409f to
3108543
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@integration/src/site/asciidoc/archetype.adoc`:
- Around line 136-140: Clarify the `databasePlatform` description in
`archetype.adoc` so it reflects that the value is used at generation time and
also by the post-generate script in `tests-only` mode. Update the wording in the
`databasePlatform` entry to remove “project only” and “Not used in tests-only
mode,” and make sure it still explains how `databasePlatform` drives the
generated `pom.xml` and which runtime ITs are included, including the
PostgreSQL-only audits.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 8ff40ed4-63b1-4495-9711-374e2a7af39b
📒 Files selected for processing (41)
CLAUDE.mdarchetype/src/main/resources/META-INF/archetype-post-generate.groovyarchetype/src/main/resources/META-INF/maven/archetype-metadata.xmlarchetype/src/main/resources/archetype-resources/pom.xmlarchetype/src/main/resources/archetype-resources/src/test/java/AbstractDatabaseAuditIT.javaarchetype/src/main/resources/archetype-resources/src/test/java/DatabaseAuditDsNameTokenTestConfiguration.javaarchetype/src/main/resources/archetype-resources/src/test/java/app/DemoDatabaseTestConfig.javaarchetype/src/main/resources/archetype-resources/src/test/java/app/DemoPostgresTestConfig.javaarchetype/src/main/resources/archetype-resources/src/test/java/runtime/RepositoryWorkloadIT.javaarchetype/src/main/resources/archetype-resources/src/test/resources/application.propertiesarchetype/src/main/resources/archetype-resources/src/test/resources/db/changelog/db.changelog-master.xmlarchetype/src/test/resources/projects/disabled-tests/archetype.propertiesarchetype/src/test/resources/projects/full-mysql/archetype.propertiesarchetype/src/test/resources/projects/full-mysql/goal.txtarchetype/src/test/resources/projects/full/archetype.propertiesarchetype/src/test/resources/projects/targeted-datasource/archetype.propertiesarchetype/src/test/resources/projects/tests-only-targeted/archetype.propertiesarchetype/src/test/resources/projects/tests-only-with-project-dir/archetype.propertiesarchetype/src/test/resources/projects/tests-only/archetype.propertiesarchetype/src/test/resources/projects/with-parent-class/archetype.propertiesintegration/src/main/java/io/github/databaseaudits/spring/boot/AuditAssertionRegistrar.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditSuite.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditTestConfiguration.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AbstractAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AuditFamily.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AuditScope.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditAssertions.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/ForeignKeyIndexAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/ForeignKeyNotNullAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/ForeignKeyTypeMatchAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/JoinIndexAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/OrderByIndexAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/PrimaryKeyPresenceAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/RedundantIndexAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/SchemaEntityValidationAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UnconditionalMutationAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/WhereClauseIndexAuditAssertion.javaintegration/src/site/asciidoc/archetype.adocintegration/src/test/java/io/github/databaseaudits/spring/boot/DatabaseAuditTestConfigurationIT.java
💤 Files with no reviewable changes (1)
- archetype/src/main/resources/archetype-resources/src/test/java/app/DemoPostgresTestConfig.java
3108543 to
f882026
Compare
…on seam Collapse the parallel per-audit lists behind a family-agnostic AuditAssertion contract, so the facade iterates the suite's roster instead of enumerating each audit, and a forgotten audit fails the build instead of silently never running. * Add AuditAssertion (family() + assertClean(AuditScope)), AuditFamily, and the AuditScope value; every *AuditAssertion implements it while keeping its typed assertClean(...) overloads for direct injection. * DatabaseAuditSuite exposes all() and builds the DatabaseAuditAssertions facade from it; the facade groups its family runs by AuditFamily rather than holding ten fields. * Add a jpaExcludedRelations slot to DatabaseAuditExcludes so JPA exclusions are reachable through assertAllClean (previously unreachable via the facade). * Add a roster guard test: every concrete core *Audit must have a wired *AuditAssertion in suite.all(). This is the first slice of WS2 (collapse the audit roster). The stock config's per-assertion @bean methods and the suite getters are unchanged for now; the programmatic bean registrar and the real by-name config come next. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4hrFd9FTwoUZjZT16worW
…gistrar Replace the ten per-assertion @bean methods (and the facade @bean) in DatabaseAuditTestConfiguration with a single AuditAssertionRegistrar that iterates DatabaseAuditSuite.all() and publishes each *AuditAssertion — plus the DatabaseAuditAssertions facade — as a bean under its concrete type. Adding a core audit no longer touches the config: once the suite wires its assertion, the registrar exposes it. * Add AuditAssertionRegistrar: a SmartInitializingSingleton that, once the suite bean exists, registers a bean definition (instance supplier) per assertion. Params: a bean-name prefix (so a by-name peer datasource's beans do not collide with the primary datasource's) and a primary flag (the primary datasource's beans win an unqualified by-type injection). * DatabaseAuditTestConfiguration registers one with no prefix and primary=true, dropping the ten @bean methods and the facade @bean. * DatabaseAuditSuite drops the ten now-unused typed getters and their fields; all() is built directly from the intrinsic construction lines (the one legitimate enumeration) and backs both the facade and the registrar. * Rework DatabaseAuditTestConfigurationIT: the deleted @bean methods give way to a registrar test asserting every assertion and the facade register as primary beans; the suite-construction and roster-guard tests stay. Completes WS2 step 4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141skitWw3Cdgkf2kP3vve6
… registrar Shrink DatabaseAuditDsNameTokenTestConfiguration from thirteen beans to four: the capturer, the static SqlCapturerRegisteringPostProcessor, the suite, and one AuditAssertionRegistrar that publishes every *AuditAssertion (and the facade) under dsNameToken-prefixed bean names. The ten per-assertion @bean methods and the facade @bean — an untested copy of the stock config's bean list — are gone; the template now mirrors the stock config's own mechanism, so adding a core audit no longer touches it. Completes WS2 step 6. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141skitWw3Cdgkf2kP3vve6
c98d715 to
ec51654
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
archetype/src/test/java/io/github/databaseaudits/archetype/PostGenerateScriptTest.java (1)
353-358: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMinor: template content still hardcodes the class name.
TOKEN_CONFIGis used for the file name at Line 357 but the file content at Line 358 still hardcodes"class DatabaseAuditDsNameTokenTestConfiguration { ... }". Purely cosmetic since the value matches the constant, but referencingTOKEN_CONFIGthere too would keep it single-sourced.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@archetype/src/test/java/io/github/databaseaudits/archetype/PostGenerateScriptTest.java` around lines 353 - 358, The token template setup still hardcodes the configuration class name inside setupTokenTemplate even though TOKEN_CONFIG already defines it. Update the Files.writeString content in PostGenerateScriptTest.setupTokenTemplate to build the class declaration from TOKEN_CONFIG as well, so the filename and generated class stay single-sourced and consistent if the constant changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@archetype/src/main/resources/archetype-resources/src/test/java/app/DemoDatabaseTestConfig.java`:
- Around line 3-11: The custom database image path in DemoDatabaseTestConfig
needs to be marked as a compatible substitute so Testcontainers accepts mirrors
or forks. Update the logic that derives image names from
$databaseImage/$databasePlatform to apply .asCompatibleSubstituteFor(...) only
when a custom override is used, and keep the standard mysql/mariadb/postgres
defaults unchanged. Use the DemoDatabaseTestConfig image selection block and the
MySQLContainer/MariaDBContainer/PostgreSQLContainer setup to place the
compatibility handling where DockerImageName.parse("${image}") is created.
---
Nitpick comments:
In
`@archetype/src/test/java/io/github/databaseaudits/archetype/PostGenerateScriptTest.java`:
- Around line 353-358: The token template setup still hardcodes the
configuration class name inside setupTokenTemplate even though TOKEN_CONFIG
already defines it. Update the Files.writeString content in
PostGenerateScriptTest.setupTokenTemplate to build the class declaration from
TOKEN_CONFIG as well, so the filename and generated class stay single-sourced
and consistent if the constant changes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 2dd83e51-81df-40f1-a201-ece36f69e6d8
📒 Files selected for processing (50)
CLAUDE.mdarchetype/src/main/resources/META-INF/archetype-post-generate.groovyarchetype/src/main/resources/META-INF/maven/archetype-metadata.xmlarchetype/src/main/resources/archetype-resources/pom.xmlarchetype/src/main/resources/archetype-resources/src/test/java/AbstractDatabaseAuditIT.javaarchetype/src/main/resources/archetype-resources/src/test/java/DatabaseAuditDsNameTokenTestConfiguration.javaarchetype/src/main/resources/archetype-resources/src/test/java/app/DemoDatabaseTestConfig.javaarchetype/src/main/resources/archetype-resources/src/test/java/app/DemoPostgresTestConfig.javaarchetype/src/main/resources/archetype-resources/src/test/java/runtime/RepositoryWorkloadIT.javaarchetype/src/main/resources/archetype-resources/src/test/resources/application.propertiesarchetype/src/main/resources/archetype-resources/src/test/resources/db/changelog/db.changelog-master.xmlarchetype/src/test/java/io/github/databaseaudits/archetype/PostGenerateScriptTest.javaarchetype/src/test/resources/projects/disabled-tests/archetype.propertiesarchetype/src/test/resources/projects/full-mysql/archetype.propertiesarchetype/src/test/resources/projects/full-mysql/goal.txtarchetype/src/test/resources/projects/full/archetype.propertiesarchetype/src/test/resources/projects/targeted-datasource/archetype.propertiesarchetype/src/test/resources/projects/tests-only-targeted/archetype.propertiesarchetype/src/test/resources/projects/tests-only-with-project-dir/archetype.propertiesarchetype/src/test/resources/projects/tests-only/archetype.propertiesarchetype/src/test/resources/projects/with-parent-class/archetype.propertiesintegration/src/main/java/io/github/databaseaudits/spring/boot/AuditAssertionRegistrar.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditSuite.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditTestConfiguration.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AbstractAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AuditFamily.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AuditScope.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditAssertions.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/ForeignKeyIndexAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/ForeignKeyNotNullAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/ForeignKeyTypeMatchAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/JoinIndexAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/OrderByIndexAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/PrimaryKeyPresenceAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/RedundantIndexAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/SchemaEntityValidationAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UnconditionalMutationAuditAssertion.javaintegration/src/main/java/io/github/databaseaudits/spring/boot/assertion/WhereClauseIndexAuditAssertion.javaintegration/src/site/asciidoc/adding-a-database.adocintegration/src/site/asciidoc/adding-an-audit.adocintegration/src/site/asciidoc/archetype.adocintegration/src/site/asciidoc/architecture.adocintegration/src/site/asciidoc/audits.adocintegration/src/site/asciidoc/exclusions.adocintegration/src/site/asciidoc/index.adocintegration/src/site/asciidoc/usage.adocintegration/src/site/site.xmlintegration/src/test/java/io/github/databaseaudits/spring/boot/DatabaseAuditTestConfigurationIT.java
💤 Files with no reviewable changes (1)
- archetype/src/main/resources/archetype-resources/src/test/java/app/DemoPostgresTestConfig.java
✅ Files skipped from review due to trivial changes (15)
- archetype/src/test/resources/projects/targeted-datasource/archetype.properties
- integration/src/site/asciidoc/index.adoc
- archetype/src/test/resources/projects/full-mysql/goal.txt
- archetype/src/test/resources/projects/disabled-tests/archetype.properties
- archetype/src/main/resources/archetype-resources/src/test/java/runtime/RepositoryWorkloadIT.java
- archetype/src/test/resources/projects/tests-only-targeted/archetype.properties
- integration/src/site/asciidoc/architecture.adoc
- integration/src/site/asciidoc/audits.adoc
- archetype/src/main/resources/archetype-resources/src/test/java/AbstractDatabaseAuditIT.java
- archetype/src/test/resources/projects/full/archetype.properties
- integration/src/site/asciidoc/adding-a-database.adoc
- archetype/src/test/resources/projects/tests-only/archetype.properties
- integration/src/site/asciidoc/exclusions.adoc
- integration/src/site/asciidoc/adding-an-audit.adoc
- CLAUDE.md
🚧 Files skipped from review as they are similar to previous changes (29)
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AuditAssertion.java
- archetype/src/main/resources/archetype-resources/src/test/resources/application.properties
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AuditScope.java
- archetype/src/main/resources/META-INF/archetype-post-generate.groovy
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/WhereClauseIndexAuditAssertion.java
- archetype/src/main/resources/archetype-resources/src/test/resources/db/changelog/db.changelog-master.xml
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/JoinIndexAuditAssertion.java
- archetype/src/test/resources/projects/tests-only-with-project-dir/archetype.properties
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/RedundantIndexAuditAssertion.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/UnconditionalMutationAuditAssertion.java
- archetype/src/test/resources/projects/with-parent-class/archetype.properties
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/ForeignKeyIndexAuditAssertion.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/SchemaEntityValidationAuditAssertion.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/PrimaryKeyPresenceAuditAssertion.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/ForeignKeyNotNullAuditAssertion.java
- archetype/src/main/resources/archetype-resources/pom.xml
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/ForeignKeyTypeMatchAuditAssertion.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AuditFamily.java
- archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditExcludes.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/AuditAssertionRegistrar.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditTestConfiguration.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/OrderByIndexAuditAssertion.java
- archetype/src/test/resources/projects/full-mysql/archetype.properties
- archetype/src/main/resources/archetype-resources/src/test/java/DatabaseAuditDsNameTokenTestConfiguration.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/DatabaseAuditSuite.java
- integration/src/test/java/io/github/databaseaudits/spring/boot/DatabaseAuditTestConfigurationIT.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/AbstractAuditAssertion.java
- integration/src/main/java/io/github/databaseaudits/spring/boot/assertion/DatabaseAuditAssertions.java
Generated demo suites can now target MySQL or MariaDB, not only PostgreSQL, via a new databasePlatform property (default postgresql). The consumer-facing audit ITs were already platform-neutral; this generalizes the demo harness. * Add databasePlatform (postgresql | mysql | mariadb) and generalize postgresImage to databaseImage (default none, deriving postgres:16 / mysql:8 / mariadb:11) in archetype-metadata.xml. * Rename DemoPostgresTestConfig to DemoDatabaseTestConfig; it selects the PostgreSQL/MySQL/MariaDB Testcontainers container by databasePlatform via Velocity and applies preferQueryMode=simple for PostgreSQL only. The generated pom gates the JDBC driver and Testcontainers module on the platform. * The plan-based runtime audits (Join/OrderBy/WhereClause index) are PostgreSQL-only, so archetype-post-generate.groovy deletes their ITs for other engines. RepositoryWorkloadIT and UnconditionalMutationAuditIT stay for every engine — the mutation audit throws on an empty capture, so its priming workload must still run (the plan draft proposed deleting RepositoryWorkloadIT; that would break the build). * Add the foreign key after its supporting index in the demo changelog, so MySQL and MariaDB (which auto-index an unindexed foreign key) reuse idx_child_parent_id instead of adding a redundant one; the end state is identical on every engine. * Name Liquibase's bookkeeping tables lowercase on MySQL/MariaDB, so the primary-key audit's built-in lowercase exclusion matches the otherwise-uppercase DATABASECHANGELOG. * Add a full-mysql Testcontainers self-test (runs the catalog, JPA, and mutation audits against MySQL); update every existing self-test's archetype.properties. Completes WS3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141skitWw3Cdgkf2kP3vve6
Update the generation guide (site archetype.adoc) property table and command examples, and the project CLAUDE.md, to describe database-engine selection: databasePlatform (postgresql/mysql/mariadb), databaseImage's per-platform defaults, the renamed DemoDatabaseTestConfig, and that the plan-based audits are generated for PostgreSQL only while the catalog, JPA, and unconditional-mutation audits run on every engine. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141skitWw3Cdgkf2kP3vve6
The page already defers to the core audit reference for the full audit descriptions; dropping the leading audit-count/platform summary keeps the count from drifting out of sync with core. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEuiBscyCyDrtzszMwiAo8
The asciidoctor-parser doxia module drops inline NOTE/TIP/WARNING bodies (it logs "Fallback behaviour for node: admonition"), so their text never reached the rendered site. Convert them to bold "*Note:*"/"*Warning:*" lead-in paragraphs — matching the extending guides — so the content shows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEuiBscyCyDrtzszMwiAo8
The post-generate script test repeated the artifact id, the src/test/java path prefix, the audited datasource's name and its derived bean names, and the generated config class names as string literals across its cases. Hoist them into private static final constants (alongside the existing PACKAGE_PATH) so the datasource fixtures read as one set and the structural paths are named once. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEuiBscyCyDrtzszMwiAo8
f3e1c2b to
2a164ec
Compare
Collapses the spring-boot audit roster behind a single registrar and adds a database-selection seam to the archetype. Two workstreams from the scaling plan (WS2 + WS3); every commit is atomic and the branch builds green —
mvnw clean install, archetype Testcontainers self-test included.WS2 — collapse the audit roster
One new audit used to edit ~4 parallel lists, and a forgotten facade wiring failed silently.
AuditAssertionRegistrar(aSmartInitializingSingleton) registers everyDatabaseAuditSuite.all()assertion — and theDatabaseAuditAssertionsfacade — as a bean under its concrete type, replacing the 10 per-assertion@Beanmethods inDatabaseAuditTestConfiguration. It registers bean definitions with an instance supplier sosetPrimaryworks, and takes a name-prefix so a by-name peer datasource's beans don't collide with the primary's.DatabaseAuditDsNameTokenTestConfiguration) shrank from 13 beans to 4 by delegating to the same registrar — no more untested bean-list copy.DatabaseAuditSuitedrops its 10 now-dead typed getters;all()(guarded by the roster test) is the single enumeration.WS3 — archetype database-selection seam
The consumer-facing templates were already platform-neutral; only the demo harness was PostgreSQL-only.
databasePlatformproperty (postgresqldefault,mysql,mariadb) drivesDemoDatabaseTestConfig(container selected via Velocity;preferQueryMode=simplefor PostgreSQL only), the JDBC driver + Testcontainers module in the generated pom, and deletion of the PostgreSQL-only plan ITs for other engines.full-mysqlTestcontainers self-test running the catalog, JPA, and unconditional-mutation audits against MySQL.Notable corrections found during verification
RepositoryWorkloadITfor every engine (the plan draft proposed deleting it for non-PostgreSQL):UnconditionalMutationAuditthrows on an empty capture, so its priming workload must still run.idx_child_parent_idinstead of adding a redundant one. End state identical on every engine.PrimaryKeyPresenceAuditexclusion matches the lowercasedatabasechangelogcase-sensitively but MySQL stores an unquotedDATABASECHANGELOGuppercase. A core follow-up (make that exclusion case-insensitive) is tracked separately.🤖 Generated with Claude Code
https://claude.ai/code/session_0141skitWw3Cdgkf2kP3vve6
Summary by CodeRabbit
databasePlatform(defaulting to PostgreSQL) and optionaldatabaseImageoverride.databasePlatform/databaseImage, and added guides for adding new databases and audits.