add(scripts): dev convenience runner (PowerShell + Bash)
Wrap the most common day-to-day commands so we stop typing .venv/Scripts/python.exe -m ... by hand. Mirrors the same tasks on both shells; binaries always resolved from the project's .venv so the host machine's globally-installed Python doesn't leak in. Tasks (both shells): install create .venv, install arautopilot[dev] in editable mode test run pytest (extra args forwarded: e.g. test -k roundtrip) test-cov pytest with branch coverage + HTML report lint ruff check (read-only) fix ruff check --fix + ruff format format ruff format typecheck mypy --strict over core/library/shared check full quality gate: lint + typecheck + test demo run examples/sprint0_demo.py clean remove build/cache artefacts + examples/output Usage: .\scripts\dev.ps1 check (Windows PowerShell) bash scripts/dev.sh check (Git Bash / WSL / Linux) Verification: `bash scripts/dev.sh check` runs lint + typecheck + 80 tests all green in ~0.5s on this machine. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+203
@@ -0,0 +1,203 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# AR-Autopilot — developer convenience script (PowerShell, Windows)
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# Usage (from the repo root):
|
||||||
|
#
|
||||||
|
# .\scripts\dev.ps1 <task> [args...]
|
||||||
|
#
|
||||||
|
# Tasks:
|
||||||
|
#
|
||||||
|
# install Install the package + dev dependencies into .venv (creates venv if needed)
|
||||||
|
# test Run the pytest suite
|
||||||
|
# test-cov Run pytest with branch coverage report
|
||||||
|
# lint Run ruff check (no auto-fix)
|
||||||
|
# fix Run ruff check --fix (auto-fix safe findings) then ruff format
|
||||||
|
# format Run ruff format only
|
||||||
|
# typecheck Run mypy --strict over core/library/shared
|
||||||
|
# check Run lint + typecheck + test (the full quality gate)
|
||||||
|
# demo Run examples/sprint0_demo.py
|
||||||
|
# clean Remove build artefacts, __pycache__/, .pytest_cache/, .mypy_cache/, .ruff_cache/
|
||||||
|
# help Show this message
|
||||||
|
#
|
||||||
|
# All tasks resolve binaries from .\.venv\Scripts\ — they never depend on
|
||||||
|
# what's globally installed on the machine.
|
||||||
|
#
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Position = 0)]
|
||||||
|
[string] $Task = 'help',
|
||||||
|
|
||||||
|
[Parameter(ValueFromRemainingArguments = $true)]
|
||||||
|
[string[]] $Args
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
|
||||||
|
# Resolve repo root regardless of where the script was invoked from.
|
||||||
|
$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot '..')
|
||||||
|
Set-Location $RepoRoot
|
||||||
|
|
||||||
|
$VenvDir = Join-Path $RepoRoot '.venv'
|
||||||
|
$VenvScripts = Join-Path $VenvDir 'Scripts'
|
||||||
|
$Python = Join-Path $VenvScripts 'python.exe'
|
||||||
|
$Pytest = Join-Path $VenvScripts 'pytest.exe'
|
||||||
|
$Ruff = Join-Path $VenvScripts 'ruff.exe'
|
||||||
|
$Mypy = Join-Path $VenvScripts 'mypy.exe'
|
||||||
|
|
||||||
|
function Assert-Venv {
|
||||||
|
if (-not (Test-Path $Python)) {
|
||||||
|
throw "Virtual environment not found at $VenvDir. Run: .\scripts\dev.ps1 install"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Install {
|
||||||
|
if (-not (Test-Path $Python)) {
|
||||||
|
Write-Host "[install] Creating virtual environment at $VenvDir ..."
|
||||||
|
& py -m venv $VenvDir
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "venv creation failed (exit $LASTEXITCODE)" }
|
||||||
|
}
|
||||||
|
Write-Host "[install] Upgrading pip ..."
|
||||||
|
& $Python -m pip install --upgrade pip
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "pip upgrade failed" }
|
||||||
|
|
||||||
|
Write-Host "[install] Installing arautopilot[dev] in editable mode ..."
|
||||||
|
& $Python -m pip install -e ".[dev]"
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "pip install failed" }
|
||||||
|
|
||||||
|
Write-Host "[install] OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Test {
|
||||||
|
Assert-Venv
|
||||||
|
& $Pytest @Args
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-TestCov {
|
||||||
|
Assert-Venv
|
||||||
|
& $Pytest --cov=arautopilot --cov-report=term-missing --cov-report=html @Args
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Lint {
|
||||||
|
Assert-Venv
|
||||||
|
& $Ruff check arautopilot/
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Fix {
|
||||||
|
Assert-Venv
|
||||||
|
& $Ruff check arautopilot/ --fix
|
||||||
|
$check = $LASTEXITCODE
|
||||||
|
& $Ruff format arautopilot/
|
||||||
|
$format = $LASTEXITCODE
|
||||||
|
if ($check -ne 0) { exit $check }
|
||||||
|
exit $format
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Format {
|
||||||
|
Assert-Venv
|
||||||
|
& $Ruff format arautopilot/
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Typecheck {
|
||||||
|
Assert-Venv
|
||||||
|
& $Mypy arautopilot/core arautopilot/library arautopilot/shared
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Check {
|
||||||
|
Assert-Venv
|
||||||
|
Write-Host "[check] (1/3) lint ..."
|
||||||
|
& $Ruff check arautopilot/
|
||||||
|
if ($LASTEXITCODE -ne 0) { Write-Host "[check] FAILED at lint"; exit $LASTEXITCODE }
|
||||||
|
|
||||||
|
Write-Host "[check] (2/3) typecheck ..."
|
||||||
|
& $Mypy arautopilot/core arautopilot/library arautopilot/shared
|
||||||
|
if ($LASTEXITCODE -ne 0) { Write-Host "[check] FAILED at typecheck"; exit $LASTEXITCODE }
|
||||||
|
|
||||||
|
Write-Host "[check] (3/3) tests ..."
|
||||||
|
& $Pytest
|
||||||
|
if ($LASTEXITCODE -ne 0) { Write-Host "[check] FAILED at tests"; exit $LASTEXITCODE }
|
||||||
|
|
||||||
|
Write-Host "[check] OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Demo {
|
||||||
|
Assert-Venv
|
||||||
|
& $Python examples/sprint0_demo.py
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Clean {
|
||||||
|
$patterns = @(
|
||||||
|
'__pycache__', '.pytest_cache', '.mypy_cache', '.ruff_cache',
|
||||||
|
'build', 'dist', '*.egg-info', 'htmlcov', '.coverage'
|
||||||
|
)
|
||||||
|
foreach ($p in $patterns) {
|
||||||
|
Get-ChildItem -Path $RepoRoot -Filter $p -Recurse -Force -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.FullName -notmatch '\\\.venv\\' } |
|
||||||
|
ForEach-Object {
|
||||||
|
Write-Host "[clean] removing $($_.FullName)"
|
||||||
|
Remove-Item -Recurse -Force -LiteralPath $_.FullName -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Get-ChildItem -Path $RepoRoot -Filter '*.pyc' -Recurse -Force -ErrorAction SilentlyContinue |
|
||||||
|
ForEach-Object {
|
||||||
|
Remove-Item -Force -LiteralPath $_.FullName -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
if (Test-Path 'examples/output') {
|
||||||
|
Write-Host "[clean] removing examples/output/"
|
||||||
|
Remove-Item -Recurse -Force 'examples/output' -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
Write-Host "[clean] OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Show-Help {
|
||||||
|
@'
|
||||||
|
AR-Autopilot — dev tasks
|
||||||
|
|
||||||
|
Usage: .\scripts\dev.ps1 <task> [args...]
|
||||||
|
|
||||||
|
Tasks:
|
||||||
|
install Install package + dev deps into .venv (creates venv if needed)
|
||||||
|
test Run pytest
|
||||||
|
test-cov Run pytest with branch coverage
|
||||||
|
lint Run ruff check (read-only)
|
||||||
|
fix Run ruff check --fix + ruff format
|
||||||
|
format Run ruff format
|
||||||
|
typecheck Run mypy --strict
|
||||||
|
check lint + typecheck + test (full quality gate)
|
||||||
|
demo Run examples/sprint0_demo.py
|
||||||
|
clean Remove build / cache artefacts
|
||||||
|
help Show this message
|
||||||
|
|
||||||
|
Tip: any extra args are forwarded to the underlying tool, e.g.
|
||||||
|
.\scripts\dev.ps1 test -k roundtrip
|
||||||
|
.\scripts\dev.ps1 test -v --tb=short
|
||||||
|
'@ | Write-Host
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($Task.ToLower()) {
|
||||||
|
'install' { Invoke-Install }
|
||||||
|
'test' { Invoke-Test }
|
||||||
|
'test-cov' { Invoke-TestCov }
|
||||||
|
'lint' { Invoke-Lint }
|
||||||
|
'fix' { Invoke-Fix }
|
||||||
|
'format' { Invoke-Format }
|
||||||
|
'typecheck' { Invoke-Typecheck }
|
||||||
|
'check' { Invoke-Check }
|
||||||
|
'demo' { Invoke-Demo }
|
||||||
|
'clean' { Invoke-Clean }
|
||||||
|
'help' { Show-Help }
|
||||||
|
default {
|
||||||
|
Write-Host "Unknown task: $Task" -ForegroundColor Red
|
||||||
|
Show-Help
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
}
|
||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# AR-Autopilot — developer convenience script (Git Bash / WSL / Linux)
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# Mirror of scripts/dev.ps1 for Bash environments. From the repo root:
|
||||||
|
#
|
||||||
|
# bash scripts/dev.sh <task> [args...]
|
||||||
|
#
|
||||||
|
# Tasks: install | test | test-cov | lint | fix | format | typecheck
|
||||||
|
# check | demo | clean | help
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
cd "$REPO_ROOT"
|
||||||
|
|
||||||
|
VENV_DIR="$REPO_ROOT/.venv"
|
||||||
|
if [[ -x "$VENV_DIR/Scripts/python.exe" ]]; then
|
||||||
|
# Windows-style venv (Git Bash on Windows)
|
||||||
|
PYTHON="$VENV_DIR/Scripts/python.exe"
|
||||||
|
PYTEST="$VENV_DIR/Scripts/pytest.exe"
|
||||||
|
RUFF="$VENV_DIR/Scripts/ruff.exe"
|
||||||
|
MYPY="$VENV_DIR/Scripts/mypy.exe"
|
||||||
|
else
|
||||||
|
PYTHON="$VENV_DIR/bin/python"
|
||||||
|
PYTEST="$VENV_DIR/bin/pytest"
|
||||||
|
RUFF="$VENV_DIR/bin/ruff"
|
||||||
|
MYPY="$VENV_DIR/bin/mypy"
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_venv() {
|
||||||
|
if [[ ! -x "$PYTHON" ]]; then
|
||||||
|
echo "Virtual environment not found at $VENV_DIR" >&2
|
||||||
|
echo "Run: bash scripts/dev.sh install" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
task_install() {
|
||||||
|
if [[ ! -x "$PYTHON" ]]; then
|
||||||
|
echo "[install] Creating virtual environment at $VENV_DIR ..."
|
||||||
|
python -m venv "$VENV_DIR" || py -m venv "$VENV_DIR"
|
||||||
|
fi
|
||||||
|
echo "[install] Upgrading pip ..."
|
||||||
|
"$PYTHON" -m pip install --upgrade pip
|
||||||
|
echo "[install] Installing arautopilot[dev] in editable mode ..."
|
||||||
|
"$PYTHON" -m pip install -e ".[dev]"
|
||||||
|
echo "[install] OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
task_test() { assert_venv; "$PYTEST" "$@"; }
|
||||||
|
task_test_cov() { assert_venv; "$PYTEST" --cov=arautopilot --cov-report=term-missing --cov-report=html "$@"; }
|
||||||
|
task_lint() { assert_venv; "$RUFF" check arautopilot/; }
|
||||||
|
task_fix() { assert_venv; "$RUFF" check arautopilot/ --fix; "$RUFF" format arautopilot/; }
|
||||||
|
task_format() { assert_venv; "$RUFF" format arautopilot/; }
|
||||||
|
task_typecheck() { assert_venv; "$MYPY" arautopilot/core arautopilot/library arautopilot/shared; }
|
||||||
|
|
||||||
|
task_check() {
|
||||||
|
assert_venv
|
||||||
|
echo "[check] (1/3) lint ..."
|
||||||
|
"$RUFF" check arautopilot/
|
||||||
|
echo "[check] (2/3) typecheck ..."
|
||||||
|
"$MYPY" arautopilot/core arautopilot/library arautopilot/shared
|
||||||
|
echo "[check] (3/3) tests ..."
|
||||||
|
"$PYTEST"
|
||||||
|
echo "[check] OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
task_demo() { assert_venv; "$PYTHON" examples/sprint0_demo.py; }
|
||||||
|
|
||||||
|
task_clean() {
|
||||||
|
find . -type d \( \
|
||||||
|
-name '__pycache__' -o \
|
||||||
|
-name '.pytest_cache' -o \
|
||||||
|
-name '.mypy_cache' -o \
|
||||||
|
-name '.ruff_cache' -o \
|
||||||
|
-name 'build' -o \
|
||||||
|
-name 'dist' -o \
|
||||||
|
-name '*.egg-info' -o \
|
||||||
|
-name 'htmlcov' \
|
||||||
|
\) -not -path './.venv/*' -prune -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
find . -type f -name '*.pyc' -not -path './.venv/*' -delete 2>/dev/null || true
|
||||||
|
rm -f .coverage
|
||||||
|
rm -rf examples/output
|
||||||
|
echo "[clean] OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
task_help() {
|
||||||
|
cat <<'HELP'
|
||||||
|
AR-Autopilot — dev tasks
|
||||||
|
|
||||||
|
Usage: bash scripts/dev.sh <task> [args...]
|
||||||
|
|
||||||
|
Tasks:
|
||||||
|
install Install package + dev deps into .venv
|
||||||
|
test Run pytest
|
||||||
|
test-cov Run pytest with coverage report
|
||||||
|
lint Run ruff check (read-only)
|
||||||
|
fix Run ruff check --fix + ruff format
|
||||||
|
format Run ruff format
|
||||||
|
typecheck Run mypy --strict
|
||||||
|
check lint + typecheck + test (full quality gate)
|
||||||
|
demo Run examples/sprint0_demo.py
|
||||||
|
clean Remove build / cache artefacts
|
||||||
|
help Show this message
|
||||||
|
HELP
|
||||||
|
}
|
||||||
|
|
||||||
|
task="${1:-help}"
|
||||||
|
shift || true
|
||||||
|
case "$task" in
|
||||||
|
install) task_install "$@" ;;
|
||||||
|
test) task_test "$@" ;;
|
||||||
|
test-cov) task_test_cov "$@" ;;
|
||||||
|
lint) task_lint "$@" ;;
|
||||||
|
fix) task_fix "$@" ;;
|
||||||
|
format) task_format "$@" ;;
|
||||||
|
typecheck) task_typecheck "$@" ;;
|
||||||
|
check) task_check "$@" ;;
|
||||||
|
demo) task_demo "$@" ;;
|
||||||
|
clean) task_clean "$@" ;;
|
||||||
|
help|-h|--help) task_help ;;
|
||||||
|
*)
|
||||||
|
echo "Unknown task: $task" >&2
|
||||||
|
task_help
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user