feat: Add staging environment setup guide and configuration files; update .gitignore
All checks were successful
Run Tests / test (push) Successful in 1m49s

This commit is contained in:
2025-10-25 18:01:46 +02:00
parent f3ce095b71
commit e74ec79cc9
7 changed files with 181 additions and 21 deletions

View File

@@ -559,6 +559,26 @@ class DatabaseSetup:
schema_name,
)
def application_role_exists(self) -> bool:
try:
with self._admin_connection(self.config.admin_database) as conn:
with conn.cursor() as cursor:
try:
cursor.execute(
"SELECT 1 FROM pg_roles WHERE rolname = %s",
(self.config.user,),
)
except psycopg2.Error as exc:
message = (
"Unable to inspect existing roles while checking for role '%s'."
" Verify admin permissions."
) % self.config.user
logger.error(message)
raise RuntimeError(message) from exc
return cursor.fetchone() is not None
except RuntimeError:
raise
def _admin_connection(self, database: Optional[str] = None) -> PGConnection:
target_db = database or self.config.admin_database
dsn = self.config.admin_dsn(database)
@@ -1101,13 +1121,26 @@ def main() -> None:
setup = DatabaseSetup(config, dry_run=args.dry_run)
admin_tasks_requested = args.ensure_database or args.ensure_role or args.ensure_schema
application_tasks_requested = args.initialize_schema or args.run_migrations
if admin_tasks_requested:
setup.validate_admin_connection()
app_validated = False
def ensure_application_connection_for(operation: str) -> bool:
nonlocal app_validated
if app_validated:
return True
if setup.dry_run and not setup.application_role_exists():
logger.info(
"Dry run: skipping %s because application role '%s' does not exist yet.",
operation,
setup.config.user,
)
return False
setup.validate_application_connection()
app_validated = True
return True
try:
if args.ensure_database:
setup.ensure_database()
@@ -1117,22 +1150,21 @@ def main() -> None:
setup.ensure_schema()
if args.initialize_schema:
if not app_validated and application_tasks_requested:
setup.validate_application_connection()
app_validated = True
setup.initialize_schema()
if ensure_application_connection_for(
"SQLAlchemy schema initialization"
):
setup.initialize_schema()
if args.run_migrations:
if not app_validated and application_tasks_requested:
setup.validate_application_connection()
app_validated = True
migrations_path = Path(
args.migrations_dir) if args.migrations_dir else None
setup.run_migrations(migrations_path)
if ensure_application_connection_for("migration execution"):
migrations_path = (
Path(args.migrations_dir)
if args.migrations_dir
else None
)
setup.run_migrations(migrations_path)
if args.seed_data:
if not app_validated:
setup.validate_application_connection()
app_validated = True
setup.seed_baseline_data(dry_run=args.dry_run)
if ensure_application_connection_for("baseline data seeding"):
setup.seed_baseline_data(dry_run=args.dry_run)
except Exception:
if not setup.dry_run:
setup.execute_rollbacks()