Repository navigation
fix(sites): stop the integration suites creating a fake default site - #38246
Conversation
…nColumnTest drops the column The test drops contentlet_as_json and lets the upgrade task add it back empty, which empties the JSON of every contentlet in the shared test database. In MainSuite2b that includes the starter default site, so the next call to findDefaultHost finds no default site and creates an unpublished one named noDefault-<millis>. ShortyServletAndTitleImageTest then resolves the request to that site, gets a 503 and fails its first attempt in every run. The test now copies the JSON into a backup table before dropping the column and writes it back afterwards, through a small ContentletAsJsonBackup helper that PopulateContentletAsJSONUtilTest uses too. With the default site as the probe, run after the upgrade test: its JSON rows go 1 -> 0 and the Shorty test fails 4 attempts of 4 before the change; they stay 1 -> 1 and the Shorty class passes 11 of 11 after. Refs #38209
…Test drops the column Each of its three tests drops contentlet_as_json and adds it back, then fills it for only some of the content. After the class the default site lookup finds no default site, so the next findDefaultHost creates an unpublished noDefault-<millis> site. The full MainSuite2b run logged that from Test_populate_host, and ShortyServletAndTitleImageTest failed its first attempt again. The class now copies the JSON before each test and writes it back after it. With the default site as the probe, run around the class: before the change the default becomes noDefault-<millis> and the Shorty test fails 4 attempts of 4; after it the default stays 'default' with its JSON intact and the Shorty class passes 11 of 11. Refs #38209
… is set to HostFactoryImpl.findDefaultHost only searched the contentlet_as_json column when persist.contentlet.as.json was true. That flag decides how new content is written, but a site saved while it was on lives only in the JSON column. With the flag off and an empty site cache the lookup found no default site, so HostAPIImpl created a second one named noDefault-<millis> and cached it, and later callers got that unpublished site instead of the real one. The JSON lookup now depends on the database supporting JSON, not on the flag, and the legacy column is still the fallback. In MainSuite2b this removes the fake site that Task05380ChangeContainerPathToAbsoluteTest left behind. It is not what made ShortyServletAndTitleImageTest fail; that is #38209. Refs #38208
Switches persist.contentlet.as.json off, empties the site cache and checks that findDefaultHost returns the existing default site and does not create a noDefault-<millis> one. It fails four times out of four before the change to HostFactoryImpl and passes after it. Registered at the end of MainSuite2a, which had the shortest median runtime of the MainSuite jobs across three recent PR runs (#38185, #38176, #38149): 2a 25.4 min, 1a 37.5, 1b 40.8, 2b 42.5, 3a 43.6. Refs #38208
…let JSON Inside PopulateContentletAsJSONUtilTest.Test_populate_host the populate util rebuilds the default site's JSON from legacy columns it does not use, so a default site lookup during the test finds none and creates an unpublished noDefault-<millis> site. Restoring the JSON afterwards brought the real default site back but left the fake one next to it and in the site cache, so ShortyServletAndTitleImageTest still failed its first attempt and the default site seen by TagAPITest could change under it. ContentletAsJsonBackup.restore now also archives and deletes any noDefault-<millis> site and empties the site and contentlet caches. Refs #38209
…ery per row ContentletAsJsonBackup.restore filled the column with a correlated scalar subquery against the backup table, which has no index. Postgres runs that subquery once per contentlet and scans the whole backup each time, so the restore grows with the square of the number of contentlets with JSON. It runs four times per suite, and in a late-suite database it could take minutes. The restore now uses UPDATE ... FROM, a single join. It still only touches contentlets that had JSON when the backup was taken. Refs #38209
…iled test If a test failed after dropping contentlet_as_json and before adding it again, ContentletAsJsonBackup.restore threw "column does not exist". In Task211101AddContentletAsJsonColumnTest that exception came from the finally block, replaced the real failure, and left the JSON unrestored for the rest of the suite. restore now adds the column back with Task211101AddContentletAsJsonColumn, which gives it the same type the test re-adds, before copying the JSON in. The backup is AutoCloseable and the upgrade task test uses it in try-with-resources, so a restore that still fails is attached to the test's own failure as a suppressed exception instead of hiding it. Refs #38209
…t fails When HostFactoryImplDefaultSiteTest fails, the lookup has saved a noDefault-<millis> site as the default, and saving it took the default flag off the real default site. The finally block deleted the fake site but left the real one unmarked, so one red run would break the default site for every test after it in the suite. The finally block now marks the site that was the default before the test as the default again if it lost the flag, then removes the fake site and empties the site cache. Also adds Javadoc to prepare(). Refs #38208
dotCMS-Machine-User
left a comment
There was a problem hiding this comment.
✅ dotbot review: all reviewer models (meta/muse-spark-1.3, ~z-ai/glm-latest) agree — patch is correct.
approved automatically by dotbot
|
Claude finished @swicken's task in 1m 52s —— View job Code Review — PR #38246
The product fix is sound. Switching the JSON-column lookup gate from New Issues
Resolved
Notes (non-blocking)
Everything else — the try-with-resources wiring in • branch |
|
|
|
…only The helper uses UPDATE ... FROM and the -> / ->> JSON operators. The integration suite only runs on PostgreSQL (docker.image.postgres, PostgreSQL driver in dotcms-integration/pom.xml), so no MSSQL variant is added; the Javadoc now says so.
|
On the Postgres-specific SQL in ContentletAsJsonBackup: agreed that the helper is narrower than the product code, but the integration suite is Postgres-only (parent/pom.xml:337, dotcms-integration/pom.xml:461, docs/testing/INTEGRATION_TESTS.md:13), so I documented that in the class Javadoc instead of adding MSSQL branches that could not be run (282bcd5). |
dotCMS-Machine-User
left a comment
There was a problem hiding this comment.
✅ dotbot review: all reviewer models (meta/muse-spark-1.3, ~z-ai/glm-latest) agree — patch is correct.
approved automatically by dotbot
# Conflicts: # dotcms-integration/src/test/java/com/dotcms/MainSuite2a.java
dotCMS-Machine-User
left a comment
There was a problem hiding this comment.
✅ dotbot review: all reviewer models (meta/muse-spark-1.3, ~z-ai/glm-latest) agree — patch is correct.
approved automatically by dotbot
|
dotbot code review:
Product fix correctly gates JSON lookup on DB capability with legacy fallback preserved, and test helpers restore column state and clean up fake sites. No P0/P1 defect introduced by this patch was found. Tip: comment with "/dotbot address comments" to attempt automated fixes for unresolved review threads. reviewed by dotbot · meta/muse-spark-1.3 · medium |
|
dotbot code review:
The product change correctly gates the JSON lookup in HostFactoryImpl.findDefaultHost on isJsonSupportedDatabase() (Postgres-or-MSSQL), making the removed IllegalStateException unreachable and the new if/else exhaustive, while preserving the legacy-column fallback when no JSON row is found. The test helpers snapshot and restore contentlet_as_json around each column drop, re-add the column if a test fails mid-flight, remove leftover fake noDefault- sites, and flush the host/contentlet caches; the Postgres-only SQL is documented and matches the Postgres-only integration suite. No qualifying defects were introduced by this patch. Tip: comment with "/dotbot address comments" to attempt automated fixes for unresolved review threads. reviewed by dotbot · ~z-ai/glm-latest · medium |
dotCMS-Machine-User
left a comment
There was a problem hiding this comment.
✅ dotbot review: all reviewer models (meta/muse-spark-1.3, ~z-ai/glm-latest) agree — patch is correct.
approved automatically by dotbot
Proposed Changes
This PR stops the integration suites from creating a fake default site partway through a run. That fake site is behind the ShortyServletAndTitleImageTest flake, which fails its first attempt in about 8 of 10 MainSuite 2b runs (#38209). It is very likely behind the TagAPITest flake as well (#38215). This PR also fixes a product defect in how the default site is found (#38208). Part of epic #34645.
The cause
Task211101AddContentletAsJsonColumnTest and PopulateContentletAsJSONUtilTest each drop and re-add, or empty, the
contentlet_as_jsoncolumn for the whole shared test database. That wipes the starter default site's data. The nextfindDefaultHostthen finds no default and creates an unpublishednoDefault-<millis>site, and the site cache keeps serving it. Shorty then sees an unpublished current host and answers 503. CI logs show exactly two "NO DEFAULT HOST, creating a fake one" errors in every recent MainSuite 2b run.Test fixes (#38209)
@After.ContentletAsJsonBackuphelper also removes any leftovernoDefault-site and flushes the site and contentlet caches.update ... from <backup>join instead of a subquery per row. On a throwaway Postgres 18, the old form took 8.74 s at 20,000 rows and the join took 63 ms.Product fix (#38208)
HostFactoryImpl.findDefaultHostonly ran its JSON-column lookup whenpersist.contentlet.as.jsonwas on. With the flag off, a default site stored only in JSON could not be found, and a fake one was created. The lookup now runs on every database that supports it (Postgres and MSSQL, the only supported databases), and the legacy-column fallback is unchanged.HostFactoryImplDefaultSiteTestis added at the end of MainSuite2a, the shortest suite. If it fails, it puts the real default site back, so one red test can't cascade through the rest of the suite.Verification
What to look for in CI:
#38216 (the StoryBlockMapTest grid test) may share this cause. It has never failed locally, so it stays open until CI shows otherwise.
Fixes #38208
Fixes #38209
Refs #38215
Refs #38216
This PR fixes: #38209