Files
geointel/docs/RELEASE_RUNBOOK.md
T
Codex f045dec849
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s
Finalize GeoIntel 1.0.0 release identity
2026-07-19 12:07:04 +02:00

5.5 KiB

GeoIntel Release Runbook

Scope

This runbook releases GeoIntel for Belgium and the Belgian North Sea. Mol and the Kempen remain regression references. A successful release never implies that every theme is operational in every jurisdiction; the coverage API and source provenance remain authoritative.

The repository version is stored in VERSION. The current release is v1.0.0.

Mandatory preconditions

  • clean main worktree at the commit being released;
  • secure non-default PostGIS password in the Tower .env;
  • existing local AI model only when the AI image is enabled;
  • recent checksum-verified backup with SHA-256 storage inventory;
  • Docker, ssh-keygen, Python 3.11, Node 20 and Bash available;
  • one Alembic head and no unsupported metric represented as successful.

No command in this runbook downloads AI weights or implicitly deletes application data.

Repository gate

python -m compileall backend/app
cd backend && python -m pytest
cd ../frontend && npm run test:unit && npm run typecheck && npm run build
cd ..
bash scripts/run_readiness_check.sh
cd backend && python -m alembic heads
python -m alembic upgrade head --sql
cd ..
bash -n scripts/live_migration_smoke.sh
docker compose config

Immutable deployment

On the Codex workstation:

.\scripts\deploy_tower.ps1

On Tower:

cd /mnt/user/appdata/geointel
docker inspect --format \
  '{{index .Config.Labels "org.opencontainers.image.version"}} {{index .Config.Labels "org.opencontainers.image.revision"}}' \
  geointel
curl -fsS http://127.0.0.1:1202/health/ready
bash scripts/live_migration_smoke.sh

Backup and recovery proof

Create an immutable backup. The SHA-256 inventory can take several minutes on large storage:

bash scripts/backup_release_state.sh \
  --container geointel \
  --output-root /mnt/user/appdata/geointel/backups \
  --release-id v1.0.0 \
  --storage-path /mnt/user/appdata/geointel/storage \
  --models-path /mnt/user/appdata/geointel/models \
  --inventory-mode sha256

Verify and restore only into an automatically generated temporary database:

bash scripts/verify_release_backup.sh \
  --backup-dir /mnt/user/appdata/geointel/backups/v1.0.0 \
  --container geointel
bash scripts/restore_release_backup_smoke.sh \
  --backup-dir /mnt/user/appdata/geointel/backups/v1.0.0 \
  --container geointel \
  --confirm-isolated-restore
bash scripts/verify_release_upgrade_smoke.sh \
  --backup-dir /mnt/user/appdata/geointel/backups/v1.0.0 \
  --container geointel \
  --confirm-isolated-upgrade

The restore and upgrade scripts refuse the production database name and remove their generated verification database.

Fresh install, browser and data operations

bash scripts/verify_release_fresh_install.sh \
  geointel-all-in-one:<release-commit>-ai
bash scripts/run_rc8_release_journeys.sh \
  http://127.0.0.1:1202 artifacts/releases/v1.0.0/rc8
bash scripts/run_rc9_ux_audit.sh \
  http://127.0.0.1:1202 artifacts/releases/v1.0.0/rc9
bash scripts/run_rc10_data_operations_audit.sh \
  artifacts/releases/v1.0.0/rc10

The RC10 command is read-only and runs cleanup in dry-run mode only.

Supply-chain evidence

bash scripts/audit_python_dependencies.sh
cd frontend && npm audit --audit-level=high
cd ..
bash scripts/generate_container_sbom.sh \
  geointel-all-in-one:<release-commit>-ai \
  artifacts/releases/v1.0.0/geointel-sbom.spdx.json
bash scripts/scan_container_image.sh \
  geointel-all-in-one:<release-commit>-ai \
  artifacts/releases/v1.0.0/container-vulnerabilities.json

The complete vulnerability report remains evidence. The executable policy gate fails on reachable fixed HIGH/CRITICAL findings.

Rollback proof

The rollback command reuses persistent paths and never downgrades Alembic:

bash deploy/unraid/rollback-dockerman-container.sh
curl -fsS http://127.0.0.1:1202/health/ready
bash deploy/unraid/deploy-release.sh
curl -fsS http://127.0.0.1:1202/health/ready

For a future backward-incompatible migration, restore the verified pre-release backup instead of running an older image against a newer schema.

Tag and signed package

Create an SSH-signed Git tag at the accepted clean commit. Use a configured release key; never add the private key to the repository:

git -c gpg.format=ssh \
  -c user.signingkey=/secure/path/release-key \
  tag -s v1.0.0 -m "GeoIntel v1.0.0"
git push origin v1.0.0

Place the collected evidence files in an ignored package directory and create the detached SSH signature plus complete checksum inventory:

python scripts/build_release_package.py build \
  --output-dir artifacts/releases/v1.0.0 \
  --release-id v1.0.0 \
  --image-name geointel-all-in-one:<release-commit>-ai \
  --image-id sha256:<image-id> \
  --image-revision <release-commit> \
  --signing-key /secure/path/release-key
python scripts/build_release_package.py verify \
  --package-dir artifacts/releases/v1.0.0

The builder refuses a dirty worktree, a tag not pointing at HEAD, a mismatched image revision, missing evidence, symlinks, checksum drift or an invalid signature.

Safe cleanup and shutdown

Stop only the temporary smoke container by its generated name; normal scripts already clean it automatically. To stop GeoIntel without deleting persistent data:

docker stop geointel

Do not use broad Docker volume pruning. Application cleanup remains dry-run by default and requires the exact confirmation, recent backup and delete ceiling documented in DATA_OPERATIONS_RUNBOOK.md.