Team Ai
Apppublic

openenv/coding_env

sourceHugging Faceupdated 3mo agoView on Hugging Face
21likes
validate.py199 linesDownload Raw Back to commands
1# Copyright (c) Meta Platforms, Inc. and affiliates.2# All rights reserved.3#4# This source code is licensed under the BSD-style license found in the5# LICENSE file in the root directory of this source tree.6 7"""8OpenEnv validate command.9 10This module provides the 'openenv validate' command to check if environments11are properly configured for multi-mode deployment.12"""13 14import json15from pathlib import Path16from typing import Annotated17 18import typer19from openenv.cli._validation import (20    build_local_validation_json_report,21    format_validation_report,22    get_deployment_modes,23    validate_multi_mode_deployment,24    validate_running_environment,25)26 27 28def _looks_like_url(value: str) -> bool:29    """Return True when the value appears to be a URL target."""30    candidate = value.strip().lower()31    return candidate.startswith("http://") or candidate.startswith("https://")32 33 34def validate(35    target: Annotated[36        str | None,37        typer.Argument(38            help=(39                "Path to the environment directory (default: current directory) "40                "or a running OpenEnv URL (http://... or https://...)"41            ),42        ),43    ] = None,44    url: Annotated[45        str | None,46        typer.Option(47            "--url",48            help="Validate a running OpenEnv server by base URL (e.g. http://localhost:8000)",49        ),50    ] = None,51    json_output: Annotated[52        bool,53        typer.Option(54            "--json",55            help="Output local validation report as JSON (runtime validation is JSON by default)",56        ),57    ] = False,58    timeout: Annotated[59        float,60        typer.Option(61            "--timeout",62            help="HTTP timeout in seconds for runtime validation",63            min=0.1,64        ),65    ] = 5.0,66    verbose: Annotated[67        bool, typer.Option("--verbose", "-v", help="Show detailed information")68    ] = False,69) -> None:70    """71    Validate local environments and running OpenEnv servers.72 73    Local validation checks if an environment is properly configured with:74    - Required files (pyproject.toml, openenv.yaml, server/app.py, etc.)75    - Docker deployment support76    - uv run server capability77    - python -m module execution78 79    Runtime validation checks if a live OpenEnv server conforms to the80    versioned runtime API contract and returns a criteria-based JSON report.81 82    Examples:83        # Validate current directory (recommended)84        $ cd my_env85        $ openenv validate86 87        # Validate a running environment and return JSON criteria88        $ openenv validate --url http://localhost:800089        $ openenv validate https://my-env.hf.space90 91        # Validate with detailed output92        $ openenv validate --verbose93 94        # Validate specific environment95        $ openenv validate envs/echo_env96    """97    runtime_target = url98    if (99        runtime_target is not None100        and target is not None101        and not _looks_like_url(target)102    ):103        typer.echo(104            "Error: Cannot combine a local path argument with --url runtime validation",105            err=True,106        )107        raise typer.Exit(1)108 109    if target is not None and _looks_like_url(target):110        if runtime_target is not None and runtime_target != target:111            typer.echo(112                "Error: Conflicting runtime targets provided via argument and --url",113                err=True,114            )115            raise typer.Exit(1)116        runtime_target = target117 118    if runtime_target is not None:119        try:120            report = validate_running_environment(runtime_target, timeout_s=timeout)121        except ValueError as exc:122            typer.echo(f"Error: {exc}", err=True)123            raise typer.Exit(1) from exc124 125        typer.echo(json.dumps(report, indent=2))126        if not report.get("passed", False):127            raise typer.Exit(1)128        return129 130    # Determine environment path (default to current directory)131    if target is None:132        env_path_obj = Path.cwd()133    else:134        env_path_obj = Path(target)135 136    if not env_path_obj.exists():137        typer.echo(f"Error: Path does not exist: {env_path_obj}", err=True)138        raise typer.Exit(1)139 140    if not env_path_obj.is_dir():141        typer.echo(f"Error: Path is not a directory: {env_path_obj}", err=True)142        raise typer.Exit(1)143 144    # Check for openenv.yaml to confirm this is an environment directory145    openenv_yaml = env_path_obj / "openenv.yaml"146    if not openenv_yaml.exists():147        typer.echo(148            f"Error: Not an OpenEnv environment directory (missing openenv.yaml): {env_path_obj}",149            err=True,150        )151        typer.echo(152            "Hint: Run this command from the environment root directory or specify the path",153            err=True,154        )155        raise typer.Exit(1)156 157    env_name = env_path_obj.name158    if env_name.endswith("_env"):159        base_name = env_name[:-4]160    else:161        base_name = env_name162 163    # Run validation164    is_valid, issues = validate_multi_mode_deployment(env_path_obj)165    modes = get_deployment_modes(env_path_obj)166 167    if json_output:168        report = build_local_validation_json_report(169            env_name=base_name,170            env_path=env_path_obj,171            is_valid=is_valid,172            issues=issues,173            deployment_modes=modes if verbose else None,174        )175        typer.echo(json.dumps(report, indent=2))176        if not is_valid:177            raise typer.Exit(1)178        return179 180    # Show validation report181    report = format_validation_report(base_name, is_valid, issues)182    typer.echo(report)183 184    # Show deployment modes if verbose185    if verbose:186        typer.echo("\nSupported deployment modes:")187        for mode, supported in modes.items():188            status = "[YES]" if supported else "[NO]"189            typer.echo(f"  {status} {mode}")190 191        if is_valid:192            typer.echo("\nUsage examples:")193            typer.echo(f"  cd {env_path_obj.name} && uv run server")194            typer.echo(f"  cd {env_path_obj.name} && openenv build")195            typer.echo(f"  cd {env_path_obj.name} && openenv push")196 197    if not is_valid:198        raise typer.Exit(1)199