121 lines
3.9 KiB
Python
121 lines
3.9 KiB
Python
import argparse
|
|
import json
|
|
import os
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description="Formal launch governance database helper")
|
|
parser.add_argument("command", choices=["import", "snapshot"])
|
|
parser.add_argument("--database-url", default=None)
|
|
parser.add_argument("--bootstrap-mode", choices=["none", "sqlite_governance"], default="none")
|
|
parser.add_argument("--tenant-id", default="tenant-demo-001")
|
|
parser.add_argument("--user-id", default=None)
|
|
parser.add_argument("--username", default="admin@example.com")
|
|
parser.add_argument("--display-name", default="治理导入脚本")
|
|
parser.add_argument("--batch-name", default=None)
|
|
return parser.parse_args()
|
|
|
|
|
|
def configure_env(database_url: str | None) -> None:
|
|
if database_url:
|
|
os.environ["DATABASE_URL"] = database_url
|
|
|
|
|
|
def bootstrap_sqlite_governance() -> None:
|
|
from sqlalchemy import create_engine
|
|
|
|
from app.db import Base
|
|
from app.models.governance_asset import GovernanceAsset
|
|
from app.models.governance_evidence import GovernanceEvidence
|
|
from app.models.governance_gate_run import GovernanceGateRun
|
|
from app.models.governance_release_batch import GovernanceReleaseBatch
|
|
from app.models.governance_review_assignment import GovernanceReviewAssignment
|
|
from app.models.governance_review_decision import GovernanceReviewDecision
|
|
|
|
database_url = os.environ["DATABASE_URL"]
|
|
engine = create_engine(database_url, future=True)
|
|
try:
|
|
Base.metadata.create_all(
|
|
engine,
|
|
tables=[
|
|
GovernanceAsset.__table__,
|
|
GovernanceReviewAssignment.__table__,
|
|
GovernanceReviewDecision.__table__,
|
|
GovernanceEvidence.__table__,
|
|
GovernanceReleaseBatch.__table__,
|
|
GovernanceGateRun.__table__,
|
|
],
|
|
)
|
|
finally:
|
|
engine.dispose()
|
|
|
|
|
|
def build_current_user(args: argparse.Namespace) -> dict:
|
|
return {
|
|
"id": args.user_id,
|
|
"tenant_id": args.tenant_id,
|
|
"role": "admin",
|
|
"display_name": args.display_name,
|
|
"username": args.username,
|
|
}
|
|
|
|
|
|
def run_command(args: argparse.Namespace) -> dict:
|
|
if args.bootstrap_mode == "sqlite_governance":
|
|
bootstrap_sqlite_governance()
|
|
|
|
from app.db import SessionLocal
|
|
from app.services.governance_service import GovernanceService
|
|
|
|
session = SessionLocal()
|
|
try:
|
|
service = GovernanceService(session)
|
|
current_user = build_current_user(args)
|
|
if args.command == "import":
|
|
data = service.import_formal_launch(current_user, batch_name=args.batch_name)
|
|
status = "PASS"
|
|
else:
|
|
data = service.get_formal_launch_database_snapshot(current_user)
|
|
status = data.get("status", "BLOCKED")
|
|
return {
|
|
"status": status,
|
|
"command": args.command,
|
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
"tenant_id": args.tenant_id,
|
|
"data": data,
|
|
}
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
def main() -> int:
|
|
args = parse_args()
|
|
configure_env(args.database_url)
|
|
|
|
repo_backend_root = Path(__file__).resolve().parents[1]
|
|
if str(repo_backend_root) not in sys.path:
|
|
sys.path.insert(0, str(repo_backend_root))
|
|
|
|
try:
|
|
payload = run_command(args)
|
|
except Exception as exc: # noqa: BLE001
|
|
payload = {
|
|
"status": "FAIL",
|
|
"command": args.command,
|
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
"tenant_id": args.tenant_id,
|
|
"error": str(exc),
|
|
}
|
|
print(json.dumps(payload, ensure_ascii=False))
|
|
return 1
|
|
|
|
print(json.dumps(payload, ensure_ascii=False))
|
|
return 0 if payload["status"] != "FAIL" else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|