added preflight check
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
"""Command line for ``python build/run.py release``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
_BUILD_ROOT = Path(__file__).resolve().parents[1]
|
||||
if str(_BUILD_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(_BUILD_ROOT))
|
||||
|
||||
from common.paths import REPO_ROOT # noqa: E402
|
||||
from common.verify.wheel import ( # noqa: E402
|
||||
DEFAULT_RUNTIME_CONFIG,
|
||||
default_verification_video,
|
||||
verify_wheel_assets,
|
||||
verify_wheel_runtime,
|
||||
)
|
||||
from common.verify.wheel_contents import inspect_wheel # noqa: E402
|
||||
from release.preflight import PreflightOptions, run_preflight # noqa: E402
|
||||
|
||||
|
||||
def _cmd_preflight(argv: list[str]) -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="build/run.py release preflight",
|
||||
description="Gate a release locally: version, tests, wheel content, runtime.",
|
||||
)
|
||||
parser.add_argument("--version", help="release version (default: pyproject's dynamic version)")
|
||||
parser.add_argument("--wheel-dir", type=Path, help="directory to inspect (default: SDK/<version>)")
|
||||
parser.add_argument("--video", type=Path, help="clip for the end-to-end runtime check")
|
||||
parser.add_argument("--config", default=DEFAULT_RUNTIME_CONFIG, help="config name for that check")
|
||||
parser.add_argument("--frames", type=int, default=40, help="frames to process (default: 40)")
|
||||
parser.add_argument("--skip-tests", action="store_true", help="skip pytest (recorded in the report)")
|
||||
parser.add_argument("--longrun", action="store_true", help="include the slow long-run stability test")
|
||||
parser.add_argument("--allow-dirty", action="store_true", help="allow a dirty working tree")
|
||||
parser.add_argument("--force", action="store_true", help="allow re-staging an existing SDK/<version>")
|
||||
parser.add_argument("--check-pypi", action="store_true", help="read PyPI and fail if the version exists")
|
||||
parser.add_argument(
|
||||
"--all-wheel-pythons",
|
||||
action="store_true",
|
||||
help="verify cp310/cp311/cp312 wheels, each in its own conda env",
|
||||
)
|
||||
parser.add_argument("--offline", action="store_true", help="reuse parent-env deps instead of PyPI")
|
||||
parser.add_argument("--no-runtime", action="store_true", help="skip the isolated runtime check")
|
||||
parser.add_argument("--no-assets", action="store_true", help="skip the bundled-asset check")
|
||||
parser.add_argument("--keep-going", action="store_true", help="collect every failure instead of stopping")
|
||||
parser.add_argument("--report-dir", type=Path, help="override build/release/reports")
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
options = PreflightOptions(
|
||||
version=args.version,
|
||||
wheel_dir=args.wheel_dir,
|
||||
video=args.video,
|
||||
config_name=args.config,
|
||||
frames=args.frames,
|
||||
skip_tests=args.skip_tests,
|
||||
longrun=args.longrun,
|
||||
allow_dirty=args.allow_dirty,
|
||||
force=args.force,
|
||||
check_pypi=args.check_pypi,
|
||||
all_wheel_pythons=args.all_wheel_pythons,
|
||||
offline=args.offline,
|
||||
keep_going=args.keep_going,
|
||||
report_dir=args.report_dir,
|
||||
no_runtime=args.no_runtime,
|
||||
no_assets=args.no_assets,
|
||||
)
|
||||
return run_preflight(options, repo_root=REPO_ROOT)
|
||||
|
||||
|
||||
def _cmd_audit(argv: list[str]) -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="build/run.py release audit",
|
||||
description="Inspect one built wheel without a release context.",
|
||||
)
|
||||
parser.add_argument("wheel", type=Path, help="path to an .whl")
|
||||
parser.add_argument("--expected-version", help="assert the wheel reports this version")
|
||||
parser.add_argument(
|
||||
"--strict-bundle",
|
||||
action="store_true",
|
||||
help="treat bundled-file drift from the current source tree as a failure",
|
||||
)
|
||||
parser.add_argument("--runtime", action="store_true", help="also install and run the wheel")
|
||||
parser.add_argument("--assets", action="store_true", help="also assert bundled assets load")
|
||||
parser.add_argument("--video", type=Path, help="clip for --runtime")
|
||||
parser.add_argument("--config", default=DEFAULT_RUNTIME_CONFIG)
|
||||
parser.add_argument("--frames", type=int, default=40)
|
||||
parser.add_argument("--offline", action="store_true")
|
||||
parser.add_argument(
|
||||
"--python",
|
||||
type=Path,
|
||||
default=None,
|
||||
help="interpreter to build the verification venv from (default: the running one)",
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
wheel = args.wheel
|
||||
if not wheel.is_file():
|
||||
print(f"[ERROR] wheel not found: {wheel}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
exit_code = 0
|
||||
|
||||
result = inspect_wheel(
|
||||
wheel,
|
||||
expected_version=args.expected_version,
|
||||
repo_root=REPO_ROOT,
|
||||
strict_bundle=args.strict_bundle,
|
||||
)
|
||||
print(result.render())
|
||||
if not result.ok:
|
||||
exit_code = 1
|
||||
|
||||
if args.assets or args.runtime:
|
||||
try:
|
||||
print(verify_wheel_assets(wheel, python_executable=args.python))
|
||||
except Exception as exc:
|
||||
print(f"[FAIL] bundled assets: {type(exc).__name__}: {exc}")
|
||||
exit_code = 1
|
||||
|
||||
if args.runtime:
|
||||
video = args.video or default_verification_video(REPO_ROOT)
|
||||
if video is None:
|
||||
print("[FAIL] runtime: no verification clip; pass --video or set ORISYS_VERIFY_VIDEO")
|
||||
return 1
|
||||
try:
|
||||
info = verify_wheel_runtime(
|
||||
wheel,
|
||||
video=video,
|
||||
config_name=args.config,
|
||||
frames=args.frames,
|
||||
python_executable=args.python,
|
||||
offline=args.offline,
|
||||
)
|
||||
print(f"[ok ] runtime: {info}")
|
||||
except Exception as exc:
|
||||
print(f"[FAIL] runtime: {type(exc).__name__}: {exc}")
|
||||
exit_code = 1
|
||||
|
||||
return exit_code
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
argv = list(sys.argv[1:] if argv is None else argv)
|
||||
if not argv or argv[0] in ("-h", "--help"):
|
||||
print(__doc__)
|
||||
print("Commands: preflight | audit")
|
||||
return 0
|
||||
|
||||
command, rest = argv[0], argv[1:]
|
||||
if command == "preflight":
|
||||
return _cmd_preflight(rest)
|
||||
if command == "audit":
|
||||
return _cmd_audit(rest)
|
||||
|
||||
print(f"Unknown release command: {command!r}", file=sys.stderr)
|
||||
print("Choose from: preflight, audit", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user