Skip to content

test(a11y): add migration-phase / store control to ContentletDataGen (#36266)#36268

Open
fabrizzio-dotCMS wants to merge 1 commit into
mainfrom
issue-36266-contentletdatagen-phase-control
Open

test(a11y): add migration-phase / store control to ContentletDataGen (#36266)#36268
fabrizzio-dotCMS wants to merge 1 commit into
mainfrom
issue-36266-contentletdatagen-phase-control

Conversation

@fabrizzio-dotCMS

Copy link
Copy Markdown
Member

Proposed Changes

Closes #36266.

Tests previously had no way to control which search store a contentlet created through ContentletDataGen is indexed into (ES, OpenSearch, or both), which blocked verifying the ES→OS dual-write pipeline from the data-generation layer. This adds a per-checkin migration-phase override to the data-gen and an integration test that asserts store placement.

ContentletDataGen

  • migrationPhase(MigrationPhase) — phase-oriented primary API.
  • targetStore(ES | OS | BOTH) — store-oriented convenience over the phase override (ES→Phase 0, OS→Phase 3, BOTH→Phase 1 dual-write).
  • Per-checkin scope — wraps the checkin() inside persist(), captures and restores the prior FEATURE_FLAG_OPEN_SEARCH_PHASE value (not blindly cleared), restored even when checkin() throws (finally).
  • Backward compatible — with no override the gen respects the globally-active phase, unchanged for existing tests.
  • Applied to both persist(...) overloads and nextPersistedAndPublish().
new ContentletDataGen(type).targetStore(TargetStore.BOTH).setPolicy(WAIT_FOR).nextPersisted();
new ContentletDataGen(type).migrationPhase(PHASE_3_OPENSEARCH_ONLY).nextPersisted();

ContentletDataGenPhaseControlIT

New IT registered in OpenSearchUpgradeSuite. It bootstraps both stores in setup (phase 1 + checkAndInitializeIndex()) and asserts placement by querying the document _id (identifier_languageId_variantId) directly on each provider's working index — noise-free and sidesteps the high-level inferIndexToHit bootstrap gap.

Test Coverage
targetStore(OS) present in OS, absent from ES
per-checkin restore global phase restored after persist
targetStore(BOTH) / targetStore(ES) / migrationPhase(PHASE_1) dual-write / ES-only placement (two-cluster only — see below)

Why these changes are needed

Unblocks ES→OS dual-write verification at the data-gen layer for the migration test suite.

How to test

./mvnw verify -pl :dotcms-integration \
  -Dcoreit.test.skip=false -Dopensearch.upgrade.test=true \
  -Dit.test=ContentletDataGenPhaseControlIT

Verified locally against the live OpenSearch 3.4.0 container: 0 failures / 0 errors, the OS-only placement and per-checkin restore tests pass.

Notes / known limitation

The ES content-write scenarios (targetStore(BOTH), targetStore(ES), migrationPhase(PHASE_1)) skip themselves in the single-cluster opensearch-upgrade profile via assumeFalse(esSameAsOs()): the legacy ES RestHighLevelClient cannot parse an OpenSearch 3.x content bulk-write response (NullPointerException in DocWriteResponse), so ES content writes only work against a truly separate ES cluster. This mirrors the existing migration ITs' skip pattern. Index/admin ops against OS 3.x are unaffected.

🤖 Generated with Claude Code

…36266)

Add per-checkin migration-phase control to ContentletDataGen so tests can
direct a generated contentlet to ElasticSearch, OpenSearch, or both during
the ES->OS migration:

- migrationPhase(MigrationPhase): phase-oriented primary API
- targetStore(ES|OS|BOTH): store-oriented convenience over the phase override
- per-checkin scope: wraps the checkin in persist(), captures and restores the
  prior FEATURE_FLAG_OPEN_SEARCH_PHASE value (restored even on throw)
- backward compatible: no override -> respects the globally-active phase
- applied to both persist(...) overloads and nextPersistedAndPublish()

Add ContentletDataGenPhaseControlIT (registered in OpenSearchUpgradeSuite),
which asserts placement by document _id directly on each provider's working
index. ES content-write scenarios skip in the single-cluster opensearch-upgrade
profile (the legacy ES client cannot content-bulk-write to OS 3.x); the OS-only
placement and per-checkin restore tests run everywhere.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Claude finished @fabrizzio-dotCMS's task in 1m 34s —— View job


Rollback Safety Analysis

  • Read rollback-unsafe categories reference
  • Get full PR diff
  • Analyze diff against all unsafe categories
  • Apply appropriate label: AI: Safe To Rollback

Verdict: ✅ Safe to Rollback

All 3 changed files are exclusively in dotcms-integration/src/test/java/:

File Type Change
OpenSearchUpgradeSuite.java Test suite +2 lines: adds ContentletDataGenPhaseControlIT to suite
ContentletDataGenPhaseControlIT.java New integration test +324 lines: new test class only
ContentletDataGen.java Test data generator +81/-3 lines: adds migrationPhase()/targetStore() API; no production code touched

Against every unsafe category:

  • C-1 Structural Data Model — No DB schema changes. No runonce task. No core entity table touched. ✅
  • C-2 ES Mapping Change — No changes to ESMappingAPIImpl, ESMappingUtilHelper, ESMappingConstants, or putMapping() calls. ✅
  • C-3 Content JSON Model Version — No change to CURRENT_MODEL_VERSION, ImmutableContentlet, or ContentletJsonAPIImpl. ✅
  • C-4 DROP TABLE/Column — No DDL of any kind. ✅
  • H-1 One-Way Data Migration — No data transformation task. ✅
  • H-2 RENAME TABLE/Column — No renames. ✅
  • H-3 PK Restructuring — No PK changes. ✅
  • H-4 New ContentType Field Type — No new field type registered. ✅
  • H-5 Binary Storage Provider — No storage config changes. ✅
  • H-6 DROP PROCEDURE/FUNCTION — None. ✅
  • H-7 NOT NULL Column Without Default — No DDL. ✅
  • H-8 VTL Viewtool Contract — No viewtool class or returned type changed. ✅
  • M-1 Column Type Change — No DDL. ✅
  • M-2 Push Publishing Bundle Format — No bundler/handler changes. ✅
  • M-3 REST/GraphQL API Contract — No REST endpoint changes. ✅
  • M-4 OSGi Interface — No OSGi interface changes. ✅

The only runtime behavior added is a test-time per-checkin Config.setProperty scoped within a finally block in ContentletDataGen, which is a test-only class (dotcms-integration/src/test/) and has no effect on production deployments or rollbacks.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — deepseek.v3.2

[🟡 Medium] dotcms-integration/src/test/java/com/dotcms/datagen/ContentletDataGen.java:532withPhaseOverride(() -> publish(contentlet)) returns Void, but withPhaseOverride expects a Supplier<R> returning R. This will cause a compilation error because publish returns void. Use () -> { publish(contentlet); return null; } or a separate helper.

[🟡 Medium] dotcms-integration/src/test/java/com/dotcms/datagen/ContentletDataGen.java:365withPhaseOverride method uses a generic type R but the publish call in nextPersistedAndPublish passes a void-returning lambda. This mismatch will cause a compilation error. The lambda should return a value (e.g., null).


Run: #27987978396 · tokens: in: 6258 · out: 194 · total: 6452

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : Backend PR changes Java/Maven backend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Add migration-phase / store control to ContentletDataGen for ES→OS dual-write tests

1 participant