Report PostgreSQL collation drift in live smoke
This commit is contained in:
@@ -7,6 +7,14 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## Sprint 36 PostgreSQL collation maintenance visibility (2026-06-17)
|
||||
|
||||
- Added database collation version reporting to `scripts/live_migration_smoke.sh`.
|
||||
- The live smoke now prints `COLLATION_VERSION_MISMATCH` plus the exact `ALTER DATABASE ... REFRESH COLLATION VERSION` acknowledgement command when an old PostGIS volume is reused on a newer runtime.
|
||||
- Documented the Unraid maintenance procedure and backup/index review guidance.
|
||||
- Added regression coverage for the collation mismatch reporting path.
|
||||
- No API contracts, migrations, product features, provider fetching or AI behavior were introduced.
|
||||
|
||||
## Sprint 35 Docker runtime secret hygiene (2026-06-17)
|
||||
|
||||
- Removed embedded PostGIS database name/user/password defaults from `deploy/unraid/Dockerfile.all-in-one` image metadata.
|
||||
|
||||
@@ -22,3 +22,13 @@ def test_live_migration_smoke_checks_required_runtime_schema_objects() -> None:
|
||||
assert '"public.detections"' in content
|
||||
assert '"public.segmentations"' in content
|
||||
assert '"public.ix_segmentations_geometry"' in content
|
||||
|
||||
|
||||
def test_live_migration_smoke_reports_collation_version_mismatch_without_failing() -> None:
|
||||
script = Path(__file__).resolve().parents[2] / "scripts" / "live_migration_smoke.sh"
|
||||
content = script.read_text(encoding="utf-8")
|
||||
|
||||
assert "pg_database_collation_actual_version(oid)" in content
|
||||
assert "COLLATION_VERSION_MISMATCH" in content
|
||||
assert "REFRESH COLLATION VERSION" in content
|
||||
assert "Database collation version: ok" in content
|
||||
|
||||
@@ -91,6 +91,22 @@ curl -I "http://192.168.10.150:${GEOINTEL_FRONTEND_PORT:-1202}/geointel-icon.svg
|
||||
curl -I "http://192.168.10.150:${GEOINTEL_FRONTEND_PORT:-1202}/geointel-icon.png"
|
||||
```
|
||||
|
||||
The live migration smoke also checks PostgreSQL database collation metadata.
|
||||
When reusing a PostGIS volume created by an older Debian/glibc runtime, it may
|
||||
print `COLLATION_VERSION_MISMATCH`. This is a maintenance warning, not an app
|
||||
startup failure. Review backups first, then acknowledge the new runtime
|
||||
collation version inside the running container:
|
||||
|
||||
```bash
|
||||
docker exec -it geointel psql -U "${GEOINTEL_POSTGRES_USER:-geointel}" -d "${GEOINTEL_POSTGRES_DB:-geointel}"
|
||||
ALTER DATABASE "geointel" REFRESH COLLATION VERSION;
|
||||
```
|
||||
|
||||
If you rely on text indexes with locale-specific ordering, plan a maintenance
|
||||
window and rebuild the affected indexes before acknowledging the version. The
|
||||
current GeoIntel V1 spatial workflows primarily use UUIDs, JSON metadata and
|
||||
PostGIS geometry indexes, but the warning should still be tracked explicitly.
|
||||
|
||||
## Change the browser port
|
||||
|
||||
Edit `.env`:
|
||||
|
||||
@@ -1627,3 +1627,30 @@ Limitations:
|
||||
|
||||
Next recommended pass:
|
||||
- Run release readiness, rebuild/deploy Tower and verify browser/GIS/demo smoke again.
|
||||
|
||||
## Sprint 36 PostgreSQL collation maintenance visibility (2026-06-17)
|
||||
|
||||
Changed:
|
||||
- Added PostgreSQL database collation version reporting to `scripts/live_migration_smoke.sh`.
|
||||
- The live smoke now prints `COLLATION_VERSION_MISMATCH` with stored and actual versions when a reused PostGIS volume was created under an older libc/collation runtime.
|
||||
- The smoke also prints the exact `ALTER DATABASE "... " REFRESH COLLATION VERSION;` acknowledgement command, but does not run it automatically.
|
||||
- Documented the Unraid maintenance procedure and backup/index review guidance.
|
||||
- Added regression coverage for the collation reporting path.
|
||||
|
||||
Tested:
|
||||
- `cd backend && python -m pytest tests/test_live_migration_smoke_script.py -q`
|
||||
- `bash -n scripts/live_migration_smoke.sh`
|
||||
- `python -m compileall backend/app`
|
||||
- `cd backend && python -m pytest -W error::DeprecationWarning`
|
||||
- `cd frontend && npm run typecheck`
|
||||
- `cd frontend && npm run build`
|
||||
- `bash scripts/run_readiness_check.sh`
|
||||
|
||||
Open:
|
||||
- Run the updated smoke against Tower to confirm whether the reused volume still reports a collation mismatch.
|
||||
|
||||
Limitations:
|
||||
- The smoke reports and documents the maintenance action. It intentionally does not mutate collation metadata automatically.
|
||||
|
||||
Next recommended pass:
|
||||
- Run release readiness, deploy Tower and decide whether to manually acknowledge the current collation version.
|
||||
|
||||
@@ -13,6 +13,7 @@ This file now starts with the current implementation status. Older preparation/b
|
||||
- [x] Add Unraid Compose template assets with editable ports, storage path and app icon.
|
||||
- [x] Add single-container Unraid runtime with embedded PostGIS, backend and frontend.
|
||||
- [x] Remove embedded PostGIS password defaults from all-in-one Docker image metadata.
|
||||
- [x] Report reused-volume PostgreSQL collation mismatches in live migration smoke.
|
||||
|
||||
## Current implementation status
|
||||
|
||||
|
||||
@@ -69,6 +69,26 @@ required_objects = [
|
||||
with get_engine().connect() as connection:
|
||||
postgis_version = connection.execute(text("SELECT PostGIS_Version()")).scalar()
|
||||
print(f"PostGIS version: {postgis_version}")
|
||||
collation_row = connection.execute(
|
||||
text(
|
||||
"SELECT datname, datcollversion, pg_database_collation_actual_version(oid) AS actual_version "
|
||||
"FROM pg_database WHERE datname = current_database()"
|
||||
)
|
||||
).mappings().one()
|
||||
stored_version = collation_row["datcollversion"]
|
||||
actual_version = collation_row["actual_version"]
|
||||
if stored_version != actual_version:
|
||||
database_name = str(collation_row["datname"]).replace('"', '""')
|
||||
print(
|
||||
"COLLATION_VERSION_MISMATCH: "
|
||||
f"database={collation_row['datname']} stored={stored_version} actual={actual_version}"
|
||||
)
|
||||
print(
|
||||
"After reviewing backups and indexes, acknowledge with: "
|
||||
f'ALTER DATABASE "{database_name}" REFRESH COLLATION VERSION;'
|
||||
)
|
||||
else:
|
||||
print("Database collation version: ok")
|
||||
|
||||
missing = [
|
||||
object_name
|
||||
@@ -154,6 +174,26 @@ required_objects = [
|
||||
with get_engine().connect() as connection:
|
||||
postgis_version = connection.execute(text("SELECT PostGIS_Version()")).scalar()
|
||||
print(f"PostGIS version: {postgis_version}")
|
||||
collation_row = connection.execute(
|
||||
text(
|
||||
"SELECT datname, datcollversion, pg_database_collation_actual_version(oid) AS actual_version "
|
||||
"FROM pg_database WHERE datname = current_database()"
|
||||
)
|
||||
).mappings().one()
|
||||
stored_version = collation_row["datcollversion"]
|
||||
actual_version = collation_row["actual_version"]
|
||||
if stored_version != actual_version:
|
||||
database_name = str(collation_row["datname"]).replace('"', '""')
|
||||
print(
|
||||
"COLLATION_VERSION_MISMATCH: "
|
||||
f"database={collation_row['datname']} stored={stored_version} actual={actual_version}"
|
||||
)
|
||||
print(
|
||||
"After reviewing backups and indexes, acknowledge with: "
|
||||
f'ALTER DATABASE "{database_name}" REFRESH COLLATION VERSION;'
|
||||
)
|
||||
else:
|
||||
print("Database collation version: ok")
|
||||
|
||||
missing = [
|
||||
object_name
|
||||
@@ -267,6 +307,26 @@ required_objects = [
|
||||
with get_engine().connect() as connection:
|
||||
postgis_version = connection.execute(text("SELECT PostGIS_Version()")).scalar()
|
||||
print(f"PostGIS version: {postgis_version}")
|
||||
collation_row = connection.execute(
|
||||
text(
|
||||
"SELECT datname, datcollversion, pg_database_collation_actual_version(oid) AS actual_version "
|
||||
"FROM pg_database WHERE datname = current_database()"
|
||||
)
|
||||
).mappings().one()
|
||||
stored_version = collation_row["datcollversion"]
|
||||
actual_version = collation_row["actual_version"]
|
||||
if stored_version != actual_version:
|
||||
database_name = str(collation_row["datname"]).replace('"', '""')
|
||||
print(
|
||||
"COLLATION_VERSION_MISMATCH: "
|
||||
f"database={collation_row['datname']} stored={stored_version} actual={actual_version}"
|
||||
)
|
||||
print(
|
||||
"After reviewing backups and indexes, acknowledge with: "
|
||||
f'ALTER DATABASE "{database_name}" REFRESH COLLATION VERSION;'
|
||||
)
|
||||
else:
|
||||
print("Database collation version: ok")
|
||||
|
||||
missing = [
|
||||
object_name
|
||||
|
||||
Reference in New Issue
Block a user