name: static-deploy description: Conventions for static deploy automation Python CLIs in scripts/static-deploy/. Use when working with deployment scripts, AWS S3/CloudFront automation, or Python CLIs in the static-deploy directory.
Static Deploy — Python CLI Conventions
Language & Style
- Use
typingeverywhere (arg/return types,TypedDict/Protocol/Enumwhere helpful) - Google-style docstrings on all public functions/classes
- Keep functions small and pure; isolate I/O and side-effects
- Prefer frozen
dataclassesfor config/value objects; avoid global state - Use
pathlib.Path, notos.pathstrings - Use
subprocess.run(..., check=True, text=True)for shelling out; return structured results - Raise custom exceptions (
ValueErrorfor validation,RuntimeErrorfor runtime failures) - Use a single
rich.console.Console()instance — create once and reuse
Tooling
- Ruff handles formatting + linting (per
pyproject.toml) - uv manages Python/venv and runs scripts (e.g.,
uv run python deploy.py ...) - Provide Makefile entry points (
.PHONYtargets) callinguv run ... - pytest for testing with descriptive function names (not test classes unless needed)
- boto3 for AWS; isolate AWS calls from business logic for testability
CLI Shape
- Use
argparsefrom stdlib with clear help text and argument validation - Support a
--dry-runflag for safe testing - Accept
--aws-profilefor local runs; in CI accept env and required inputs via args - Exit with explicit codes; return
intfrommain()and callraise SystemExit(main()) - If in CI, write markdown summaries to
GITHUB_OUTPUTwhen the env var is set - Separate parsing/validation logic from execution — create testable config objects
Environment Parity
Same code path runs locally and in CI. Only entry points differ:
- Local: dev sets flags manually (
--aws-profile, etc.) - CI: wrapper or Make target builds the same args from CI env
Configuration should be static and deterministic — avoid runtime environment detection.
Rich Console UX
Use rich.console.Console for all human output:
style="red"for errorsstyle="yellow"for warningsstyle="green"for successstyle="blue"for infostyle="green bold"for major success- Use
console.rule,Statusspinners for long-running steps,Tablefor summaries - Test console output by mocking
console.printcalls
Testing Strategy
- Test parsing and configuration logic without mocking tightly-coupled external deps
- Use real configuration objects in tests rather than mocks for integration between components
- Isolate external service calls (AWS) from business logic
- Write focused unit tests for individual functions
- Use descriptive test function names explaining the scenario
Structure
- Layout:
./for library code,./tests/for tests - Separate concerns: parsing/validation, configuration resolution, external service operations
- CLI composes these steps, handles args, Rich output, and error mapping
- Keep deployment-specific logic (AWS) separate from configuration and parsing
- Make functions testable by avoiding tight coupling to external services