| """CLI group for local release verification."""
|
|
|
| from __future__ import annotations
|
|
|
| import json
|
| from pathlib import Path
|
| from typing import Annotated
|
|
|
| import typer
|
|
|
| from dataforge.release.doctor import DEFAULT_KAGGLE_CREDENTIALS, run_doctor
|
| from dataforge.release.full_vision import (
|
| DEFAULT_BACKEND_URL as FULL_VISION_BACKEND_URL,
|
| )
|
| from dataforge.release.full_vision import (
|
| DEFAULT_FRONTEND_URL as FULL_VISION_FRONTEND_URL,
|
| )
|
| from dataforge.release.full_vision import (
|
| run_full_vision_gate,
|
| )
|
| from dataforge.release.gate import run_release_gate
|
|
|
| release_app = typer.Typer(help="Release verification utilities.", no_args_is_help=True)
|
|
|
|
|
| @release_app.command(name="doctor")
|
| def doctor(
|
| json_output: Annotated[
|
| bool,
|
| typer.Option("--json", help="Print machine-readable JSON."),
|
| ] = False,
|
| core: Annotated[
|
| bool,
|
| typer.Option("--core", help="Run OSS core release checks."),
|
| ] = False,
|
| maintainer_deploy: Annotated[
|
| bool,
|
| typer.Option(
|
| "--maintainer-deploy",
|
| help="Run maintainer-specific deploy/auth checks.",
|
| ),
|
| ] = False,
|
| kaggle_credentials: Annotated[
|
| Path,
|
| typer.Option(
|
| "--kaggle-credentials",
|
| help="Path to Kaggle OAuth credentials.json. Legacy kaggle.json is never read.",
|
| ),
|
| ] = DEFAULT_KAGGLE_CREDENTIALS,
|
| ) -> None:
|
| """Verify local release/deploy auth without printing secrets."""
|
| run_core = core or not maintainer_deploy
|
| report = run_doctor(
|
| kaggle_credentials=kaggle_credentials,
|
| core=run_core,
|
| maintainer_deploy=maintainer_deploy,
|
| )
|
| if json_output:
|
| typer.echo(json.dumps(report.to_dict(), indent=2, sort_keys=True))
|
| else:
|
| for check in report.checks:
|
| status = "ok" if check.ok else "fail"
|
| typer.echo(f"{status:4} {check.name}: {check.detail}")
|
| raise typer.Exit(code=0 if report.ok else 2)
|
|
|
|
|
| @release_app.command(name="gate")
|
| def gate(
|
| json_output: Annotated[
|
| bool,
|
| typer.Option("--json", help="Print machine-readable JSON."),
|
| ] = False,
|
| keep_artifacts: Annotated[
|
| bool,
|
| typer.Option(
|
| "--keep-artifacts",
|
| help="Copy the temporary gate workspace to dist/release-gate-latest.",
|
| ),
|
| ] = False,
|
| ) -> None:
|
| """Build, audit, offline-install, and smoke-test the release wheel."""
|
| report = run_release_gate(keep_artifacts=keep_artifacts)
|
| if json_output:
|
| typer.echo(json.dumps(report.to_dict(), indent=2, sort_keys=True))
|
| else:
|
| for step in report.steps:
|
| status = "ok" if step.ok else "fail"
|
| typer.echo(f"{status:4} {step.name}: {step.detail}")
|
| raise typer.Exit(code=0 if report.ok else 1)
|
|
|
|
|
| @release_app.command(name="full-vision")
|
| def full_vision(
|
| json_output: Annotated[
|
| bool,
|
| typer.Option("--json", help="Print machine-readable JSON."),
|
| ] = False,
|
| evidence_root: Annotated[
|
| Path | None,
|
| typer.Option("--evidence-root", help="Directory containing external proof manifests."),
|
| ] = None,
|
| frontend_url: Annotated[
|
| str,
|
| typer.Option("--frontend-url", help="Cloudflare Workers Playground URL."),
|
| ] = FULL_VISION_FRONTEND_URL,
|
| backend_url: Annotated[
|
| str,
|
| typer.Option("--backend-url", help="Hugging Face Playground backend URL."),
|
| ] = FULL_VISION_BACKEND_URL,
|
| expected_git_sha: Annotated[
|
| str | None,
|
| typer.Option("--expected-git-sha", help="Release git SHA expected in backend health."),
|
| ] = None,
|
| ) -> None:
|
| """Verify the external gates for the full original DataForge vision."""
|
| report = run_full_vision_gate(
|
| evidence_root=evidence_root,
|
| frontend_url=frontend_url,
|
| backend_url=backend_url,
|
| expected_git_sha=expected_git_sha,
|
| )
|
| if json_output:
|
| typer.echo(json.dumps(report.to_dict(), indent=2, sort_keys=True))
|
| else:
|
| for check in report.checks:
|
| status = "ok" if check.ok else "fail"
|
| typer.echo(f"{status:4} {check.name}: {check.detail}")
|
| raise typer.Exit(code=0 if report.ok else 1)
|
|
|
|
|
| @release_app.command(name="playground-check")
|
| def playground_check(
|
| json_output: Annotated[
|
| bool,
|
| typer.Option("--json", help="Print machine-readable JSON."),
|
| ] = False,
|
| frontend_url: Annotated[
|
| str,
|
| typer.Option("--frontend-url", help="Cloudflare Playground frontend URL."),
|
| ] = "https://dataforge.praneshrajan15.workers.dev/playground",
|
| backend_url: Annotated[
|
| str,
|
| typer.Option("--backend-url", help="Hugging Face Playground backend URL."),
|
| ] = "https://Praneshrajan15-dataforge-playground.hf.space",
|
| latency_threshold_ms: Annotated[
|
| float,
|
| typer.Option("--latency-threshold-ms", help="Warm health latency threshold."),
|
| ] = 5_000.0,
|
| ) -> None:
|
| """Verify the deployed Playground release checklist."""
|
| from dataforge.release.playground_check import report_to_json, run_playground_check
|
|
|
| report = run_playground_check(
|
| frontend_url=frontend_url,
|
| backend_url=backend_url,
|
| latency_threshold_ms=latency_threshold_ms,
|
| include_doctor=True,
|
| include_smoke=True,
|
| )
|
| if json_output:
|
| typer.echo(report_to_json(report))
|
| else:
|
| for check in report.checks:
|
| status = "ok" if check.ok else "fail"
|
| typer.echo(f"{status:4} {check.name}: {check.detail}")
|
| raise typer.Exit(code=0 if report.ok else 1)
|
|
|