From 34f713f5fa9cca38ab329cc33ba5356ac0d97922 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 1 Nov 2025 21:51:23 +0000 Subject: [PATCH 1/7] Initial plan From b34a0b559957c0fd6c7eca06fc73800cd0fe8d7f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 1 Nov 2025 22:01:13 +0000 Subject: [PATCH 2/7] Set up monorepo structure with CLI and API packages Co-authored-by: alexinslc <127081+alexinslc@users.noreply.github.com> --- .gitignore | 53 +++++++++ .python-version | 1 + README.md | 149 +++++++++++++++++++++++- packages/api/README.md | 17 +++ packages/api/pyproject.toml | 18 +++ packages/api/src/opsctl_api/__init__.py | 3 + packages/api/src/opsctl_api/main.py | 43 +++++++ packages/api/tests/__init__.py | 1 + packages/api/tests/test_api.py | 30 +++++ packages/cli/README.md | 15 +++ packages/cli/pyproject.toml | 20 ++++ packages/cli/src/opsctl_cli/__init__.py | 3 + packages/cli/src/opsctl_cli/main.py | 32 +++++ packages/cli/tests/__init__.py | 1 + packages/cli/tests/test_cli.py | 28 +++++ pyproject.toml | 32 +++++ 16 files changed, 444 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 .python-version create mode 100644 packages/api/README.md create mode 100644 packages/api/pyproject.toml create mode 100644 packages/api/src/opsctl_api/__init__.py create mode 100644 packages/api/src/opsctl_api/main.py create mode 100644 packages/api/tests/__init__.py create mode 100644 packages/api/tests/test_api.py create mode 100644 packages/cli/README.md create mode 100644 packages/cli/pyproject.toml create mode 100644 packages/cli/src/opsctl_cli/__init__.py create mode 100644 packages/cli/src/opsctl_cli/main.py create mode 100644 packages/cli/tests/__init__.py create mode 100644 packages/cli/tests/test_cli.py create mode 100644 pyproject.toml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92b3d81 --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual environments +venv/ +env/ +ENV/ +.venv + +# uv +.uv/ +uv.lock + +# Testing +.pytest_cache/ +.coverage +htmlcov/ +.tox/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Mypy +.mypy_cache/ +.dmypy.json +dmypy.json diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/README.md b/README.md index 0d73c72..7c730a2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,147 @@ -# opsctl -opsctl +# OpsCtl - Platform Engineering Template + +A template repository for platform engineering projects using a monorepo structure with separate CLI and API packages. + +## ๐Ÿš€ Technologies + +- **CLI**: [Typer](https://typer.tiangolo.com/) - Modern CLI framework +- **API**: [FastAPI](https://fastapi.tiangolo.com/) - High-performance web framework +- **Package Management**: [uv](https://docs.astral.sh/uv/) - Fast Python package manager +- **Testing**: [pytest](https://docs.pytest.org/) - Testing framework +- **Linting**: [ruff](https://docs.astral.sh/ruff/) - Fast Python linter +- **Type Checking**: [mypy](https://mypy-lang.org/) - Static type checker + +## ๐Ÿ“ Project Structure + +``` +opsctl/ +โ”œโ”€โ”€ packages/ +โ”‚ โ”œโ”€โ”€ api/ # FastAPI application +โ”‚ โ”‚ โ”œโ”€โ”€ src/ +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ opsctl_api/ +โ”‚ โ”‚ โ”œโ”€โ”€ tests/ +โ”‚ โ”‚ โ””โ”€โ”€ pyproject.toml +โ”‚ โ””โ”€โ”€ cli/ # Typer CLI application +โ”‚ โ”œโ”€โ”€ src/ +โ”‚ โ”‚ โ””โ”€โ”€ opsctl_cli/ +โ”‚ โ”œโ”€โ”€ tests/ +โ”‚ โ””โ”€โ”€ pyproject.toml +โ”œโ”€โ”€ pyproject.toml # Workspace configuration +โ””โ”€โ”€ pytest.ini # Test configuration +``` + +## ๐Ÿ› ๏ธ Setup + +### Prerequisites + +- Python 3.12+ +- uv (install with `pip install uv`) + +### Installation + +1. Clone this repository: +```bash +git clone +cd opsctl +``` + +2. Install dependencies: +```bash +uv sync +``` + +3. Install packages in development mode: +```bash +uv pip install -e packages/cli -e packages/api +``` + +## ๐Ÿ“ Usage + +### CLI + +Run the CLI: +```bash +opsctl hello +opsctl hello World +opsctl version +opsctl --help +``` + +### API + +Start the API server: +```bash +uvicorn opsctl_api.main:app --reload +``` + +The API will be available at: +- Main: http://localhost:8000 +- Docs: http://localhost:8000/docs +- ReDoc: http://localhost:8000/redoc + +Try the endpoints: +```bash +curl http://localhost:8000/ +curl http://localhost:8000/health +curl http://localhost:8000/hello/World +``` + +## ๐Ÿงช Testing + +Run all tests: +```bash +uv run pytest +``` + +Run tests with coverage: +```bash +uv run pytest --cov=packages +``` + +Run tests for a specific package: +```bash +uv run pytest packages/cli/tests +uv run pytest packages/api/tests +``` + +## ๐Ÿ” Linting and Type Checking + +Run ruff linter: +```bash +uv run ruff check . +``` + +Auto-fix linting issues: +```bash +uv run ruff check --fix . +``` + +Format code: +```bash +uv run ruff format . +``` + +Run type checking: +```bash +uv run mypy packages/cli/src packages/api/src +``` + +## ๐Ÿ“ฆ Building + +Build the packages: +```bash +uv build packages/cli +uv build packages/api +``` + +## ๐Ÿค Contributing + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Run tests and linting +5. Submit a pull request + +## ๐Ÿ“„ License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/packages/api/README.md b/packages/api/README.md new file mode 100644 index 0000000..cf508c1 --- /dev/null +++ b/packages/api/README.md @@ -0,0 +1,17 @@ +# API Package + +This is the API package built with FastAPI. + +## Installation + +```bash +uv pip install -e packages/api +``` + +## Usage + +```bash +uvicorn opsctl_api.main:app --reload +``` + +The API will be available at http://localhost:8000 diff --git a/packages/api/pyproject.toml b/packages/api/pyproject.toml new file mode 100644 index 0000000..dcb69f4 --- /dev/null +++ b/packages/api/pyproject.toml @@ -0,0 +1,18 @@ +[project] +name = "opsctl-api" +version = "0.1.0" +description = "API service built with FastAPI" +readme = "README.md" +authors = [ + { name = "Alex Lutz", email = "alex@example.com" } +] +requires-python = ">=3.12" +dependencies = [ + "fastapi>=0.109.0", + "uvicorn[standard]>=0.27.0", + "pydantic>=2.0.0", +] + +[build-system] +requires = ["uv_build>=0.9.7,<0.10.0"] +build-backend = "uv_build" diff --git a/packages/api/src/opsctl_api/__init__.py b/packages/api/src/opsctl_api/__init__.py new file mode 100644 index 0000000..4c12ec2 --- /dev/null +++ b/packages/api/src/opsctl_api/__init__.py @@ -0,0 +1,3 @@ +"""API package built with FastAPI.""" + +__version__ = "0.1.0" diff --git a/packages/api/src/opsctl_api/main.py b/packages/api/src/opsctl_api/main.py new file mode 100644 index 0000000..cf6d888 --- /dev/null +++ b/packages/api/src/opsctl_api/main.py @@ -0,0 +1,43 @@ +"""Main API application using FastAPI.""" + +from fastapi import FastAPI +from pydantic import BaseModel + +from opsctl_api import __version__ + +app = FastAPI( + title="OpsCtl API", + description="Platform engineering API service", + version=__version__, +) + + +class HealthResponse(BaseModel): + """Health check response model.""" + + status: str + version: str + + +class HelloResponse(BaseModel): + """Hello response model.""" + + message: str + + +@app.get("/") +async def root() -> dict[str, str]: + """Root endpoint.""" + return {"message": "Welcome to OpsCtl API"} + + +@app.get("/health", response_model=HealthResponse) +async def health() -> HealthResponse: + """Health check endpoint.""" + return HealthResponse(status="healthy", version=__version__) + + +@app.get("/hello/{name}", response_model=HelloResponse) +async def hello(name: str) -> HelloResponse: + """Say hello to someone.""" + return HelloResponse(message=f"Hello {name}!") diff --git a/packages/api/tests/__init__.py b/packages/api/tests/__init__.py new file mode 100644 index 0000000..4e1edc0 --- /dev/null +++ b/packages/api/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for the API package.""" diff --git a/packages/api/tests/test_api.py b/packages/api/tests/test_api.py new file mode 100644 index 0000000..b3af09e --- /dev/null +++ b/packages/api/tests/test_api.py @@ -0,0 +1,30 @@ +"""Tests for API main module.""" + +from fastapi.testclient import TestClient +from opsctl_api.main import app + +client = TestClient(app) + + +def test_root() -> None: + """Test root endpoint.""" + response = client.get("/") + assert response.status_code == 200 + assert response.json() == {"message": "Welcome to OpsCtl API"} + + +def test_health() -> None: + """Test health endpoint.""" + response = client.get("/health") + assert response.status_code == 200 + data = response.json() + assert data["status"] == "healthy" + assert data["version"] == "0.1.0" + + +def test_hello() -> None: + """Test hello endpoint.""" + response = client.get("/hello/World") + assert response.status_code == 200 + data = response.json() + assert data["message"] == "Hello World!" diff --git a/packages/cli/README.md b/packages/cli/README.md new file mode 100644 index 0000000..e88d920 --- /dev/null +++ b/packages/cli/README.md @@ -0,0 +1,15 @@ +# CLI Package + +This is the CLI package built with Typer. + +## Installation + +```bash +uv pip install -e packages/cli +``` + +## Usage + +```bash +opsctl --help +``` diff --git a/packages/cli/pyproject.toml b/packages/cli/pyproject.toml new file mode 100644 index 0000000..d640db2 --- /dev/null +++ b/packages/cli/pyproject.toml @@ -0,0 +1,20 @@ +[project] +name = "opsctl-cli" +version = "0.1.0" +description = "CLI tool built with Typer" +readme = "README.md" +authors = [ + { name = "Alex Lutz", email = "alex@example.com" } +] +requires-python = ">=3.12" +dependencies = [ + "typer>=0.9.0", + "rich>=13.0.0", +] + +[project.scripts] +opsctl = "opsctl_cli.main:app" + +[build-system] +requires = ["uv_build>=0.9.7,<0.10.0"] +build-backend = "uv_build" diff --git a/packages/cli/src/opsctl_cli/__init__.py b/packages/cli/src/opsctl_cli/__init__.py new file mode 100644 index 0000000..3b07252 --- /dev/null +++ b/packages/cli/src/opsctl_cli/__init__.py @@ -0,0 +1,3 @@ +"""CLI package built with Typer.""" + +__version__ = "0.1.0" diff --git a/packages/cli/src/opsctl_cli/main.py b/packages/cli/src/opsctl_cli/main.py new file mode 100644 index 0000000..e6adef7 --- /dev/null +++ b/packages/cli/src/opsctl_cli/main.py @@ -0,0 +1,32 @@ +"""Main CLI application using Typer.""" + +import typer +from rich.console import Console + +app = typer.Typer( + name="opsctl", + help="Platform engineering CLI tool", + add_completion=True, +) +console = Console() + + +@app.command() +def hello(name: str | None = typer.Argument(None, help="Name to greet")) -> None: + """Say hello to someone.""" + if name: + console.print(f"[bold green]Hello {name}![/bold green]") + else: + console.print("[bold green]Hello from opsctl![/bold green]") + + +@app.command() +def version() -> None: + """Show the version.""" + from opsctl_cli import __version__ + + console.print(f"[bold blue]opsctl version:[/bold blue] {__version__}") + + +if __name__ == "__main__": + app() diff --git a/packages/cli/tests/__init__.py b/packages/cli/tests/__init__.py new file mode 100644 index 0000000..edf17b9 --- /dev/null +++ b/packages/cli/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for the CLI package.""" diff --git a/packages/cli/tests/test_cli.py b/packages/cli/tests/test_cli.py new file mode 100644 index 0000000..ca66b0d --- /dev/null +++ b/packages/cli/tests/test_cli.py @@ -0,0 +1,28 @@ +"""Tests for CLI main module.""" + +from opsctl_cli.main import app +from typer.testing import CliRunner + +runner = CliRunner() + + +def test_hello_without_name() -> None: + """Test hello command without a name.""" + result = runner.invoke(app, ["hello"]) + assert result.exit_code == 0 + assert "Hello from opsctl!" in result.stdout + + +def test_hello_with_name() -> None: + """Test hello command with a name.""" + result = runner.invoke(app, ["hello", "World"]) + assert result.exit_code == 0 + assert "Hello World!" in result.stdout + + +def test_version() -> None: + """Test version command.""" + result = runner.invoke(app, ["version"]) + assert result.exit_code == 0 + assert "opsctl version:" in result.stdout + assert "0.1.0" in result.stdout diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..abedffc --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,32 @@ +[tool.uv.workspace] +members = ["packages/cli", "packages/api"] + +[dependency-groups] +dev = [ + "pytest>=8.0.0", + "pytest-cov>=4.1.0", + "ruff>=0.3.0", + "mypy>=1.8.0", + "httpx>=0.27.0", +] + +[tool.pytest.ini_options] +testpaths = ["packages/cli/tests", "packages/api/tests"] +python_files = "test_*.py" +python_classes = "Test*" +python_functions = "test_*" +addopts = "-v --tb=short --strict-markers --import-mode=importlib" + +[tool.ruff] +line-length = 100 +target-version = "py312" + +[tool.ruff.lint] +select = ["E", "F", "I", "N", "W", "B", "UP"] +ignore = [] + +[tool.mypy] +python_version = "3.12" +warn_return_any = true +warn_unused_configs = true +disallow_untyped_defs = true From f7415b76ca9b65a950200c2ac2d22046c90c699b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 1 Nov 2025 22:04:00 +0000 Subject: [PATCH 3/7] Add development tools, docs, CI/CD, and Docker support Co-authored-by: alexinslc <127081+alexinslc@users.noreply.github.com> --- .github/workflows/ci.yml | 43 +++++++ CONTRIBUTING.md | 59 ++++++++++ DEVELOPMENT.md | 234 +++++++++++++++++++++++++++++++++++++++ Dockerfile.api | 20 ++++ Makefile | 45 ++++++++ README.md | 59 +++++++++- docker-compose.yml | 14 +++ 7 files changed, 469 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 CONTRIBUTING.md create mode 100644 DEVELOPMENT.md create mode 100644 Dockerfile.api create mode 100644 Makefile create mode 100644 docker-compose.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5279a33 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,43 @@ +name: CI + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.12"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install uv + run: pip install uv + + - name: Install dependencies + run: uv sync + + - name: Run linting + run: uv run ruff check . + + - name: Run type checking + run: uv run mypy packages/cli/src packages/api/src + + - name: Run tests + run: uv run pytest -v --cov=packages --cov-report=xml --cov-report=term + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + file: ./coverage.xml + fail_ci_if_error: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..05083d0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,59 @@ +# Contributing to OpsCtl + +Thank you for considering contributing to this project! + +## How to Contribute + +1. **Fork the repository** +2. **Create a new branch** for your feature or bugfix +3. **Make your changes** following our coding standards +4. **Add tests** for your changes +5. **Run tests and linting** to ensure everything passes +6. **Submit a pull request** + +## Development Setup + +See [DEVELOPMENT.md](DEVELOPMENT.md) for detailed setup instructions. + +## Code Style + +This project uses: +- **ruff** for linting and formatting +- **mypy** for type checking +- **pytest** for testing + +Before submitting a PR, ensure: + +```bash +# All tests pass +uv run pytest + +# Code is formatted +uv run ruff format . + +# No linting errors +uv run ruff check . + +# No type errors +uv run mypy packages/cli/src packages/api/src +``` + +## Pull Request Guidelines + +- Write clear, descriptive commit messages +- Keep PRs focused on a single feature or bugfix +- Update documentation if needed +- Add tests for new functionality +- Ensure all CI checks pass + +## Reporting Issues + +When reporting issues, please include: +- A clear description of the problem +- Steps to reproduce +- Expected vs actual behavior +- Your environment (OS, Python version, etc.) + +## Questions? + +Feel free to open an issue for questions or discussions! diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..d97ec3c --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,234 @@ +# Development Guide + +## Getting Started + +This guide will help you get started with developing in this monorepo template. + +## Setup + +1. **Install uv** (if not already installed): + ```bash + pip install uv + ``` + +2. **Clone the repository**: + ```bash + git clone + cd opsctl + ``` + +3. **Install dependencies**: + ```bash + uv sync + ``` + +This will create a virtual environment at `.venv/` and install all dependencies. + +## Development Workflow + +### Running the CLI + +```bash +# Activate the virtual environment (optional, uv run will handle this) +source .venv/bin/activate # On Unix/macOS +# or +.venv\Scripts\activate # On Windows + +# Run the CLI +uv run opsctl --help +uv run opsctl hello +uv run opsctl hello "Your Name" +uv run opsctl version +``` + +### Running the API + +Start the API server in development mode with auto-reload: + +```bash +uv run uvicorn opsctl_api.main:app --reload +``` + +The API will be available at: +- Swagger UI: http://localhost:8000/docs +- ReDoc: http://localhost:8000/redoc +- OpenAPI JSON: http://localhost:8000/openapi.json + +### Testing + +Run all tests: +```bash +uv run pytest +``` + +Run tests with coverage: +```bash +uv run pytest --cov=packages --cov-report=html +``` + +Run tests for a specific package: +```bash +cd packages/cli && uv run pytest +cd packages/api && uv run pytest +``` + +### Linting and Formatting + +Check code with ruff: +```bash +uv run ruff check . +``` + +Auto-fix linting issues: +```bash +uv run ruff check --fix . +``` + +Format code: +```bash +uv run ruff format . +``` + +### Type Checking + +Run mypy for type checking: +```bash +uv run mypy packages/cli/src packages/api/src +``` + +## Project Structure + +``` +opsctl/ +โ”œโ”€โ”€ packages/ +โ”‚ โ”œโ”€โ”€ api/ # FastAPI application +โ”‚ โ”‚ โ”œโ”€โ”€ src/ +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ opsctl_api/ # API source code +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ main.py # FastAPI app +โ”‚ โ”‚ โ”œโ”€โ”€ tests/ # API tests +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ test_api.py +โ”‚ โ”‚ โ”œโ”€โ”€ pyproject.toml # API package config +โ”‚ โ”‚ โ””โ”€โ”€ README.md +โ”‚ โ””โ”€โ”€ cli/ # Typer CLI application +โ”‚ โ”œโ”€โ”€ src/ +โ”‚ โ”‚ โ””โ”€โ”€ opsctl_cli/ # CLI source code +โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”‚ โ””โ”€โ”€ main.py # Typer app +โ”‚ โ”œโ”€โ”€ tests/ # CLI tests +โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”‚ โ””โ”€โ”€ test_cli.py +โ”‚ โ”œโ”€โ”€ pyproject.toml # CLI package config +โ”‚ โ””โ”€โ”€ README.md +โ”œโ”€โ”€ pyproject.toml # Workspace configuration +โ”œโ”€โ”€ .gitignore +โ”œโ”€โ”€ .python-version # Python version +โ””โ”€โ”€ README.md +``` + +## Adding Dependencies + +### Workspace (dev) dependencies + +Edit `pyproject.toml` at the root and add to the `[dependency-groups]` section: + +```toml +[dependency-groups] +dev = [ + "pytest>=8.0.0", + "new-package>=1.0.0", # Add new dev dependency here +] +``` + +Then run: +```bash +uv sync +``` + +### Package-specific dependencies + +Edit the respective `pyproject.toml` in `packages/cli/` or `packages/api/`: + +```toml +[project] +dependencies = [ + "existing-package>=1.0.0", + "new-package>=2.0.0", # Add new dependency here +] +``` + +Then run: +```bash +uv sync +``` + +## Creating New Commands (CLI) + +Add new commands in `packages/cli/src/opsctl_cli/main.py`: + +```python +@app.command() +def new_command(arg: str) -> None: + """Description of your new command.""" + console.print(f"[bold]You passed: {arg}[/bold]") +``` + +## Creating New Endpoints (API) + +Add new endpoints in `packages/api/src/opsctl_api/main.py`: + +```python +@app.get("/new-endpoint") +async def new_endpoint() -> dict[str, str]: + """Description of your endpoint.""" + return {"message": "Response from new endpoint"} +``` + +## Best Practices + +1. **Write Tests**: Always add tests for new functionality +2. **Type Hints**: Use type hints for all functions +3. **Documentation**: Add docstrings to functions and classes +4. **Linting**: Run ruff before committing +5. **Type Checking**: Run mypy to catch type errors early +6. **Commit Often**: Make small, focused commits + +## Troubleshooting + +### Virtual Environment Issues + +If you encounter issues with the virtual environment: + +```bash +# Remove the virtual environment +rm -rf .venv + +# Recreate it +uv sync +``` + +### Import Errors + +Make sure you're running commands with `uv run` or have activated the virtual environment: + +```bash +source .venv/bin/activate # On Unix/macOS +``` + +### Port Already in Use + +If the API server fails to start because port 8000 is in use: + +```bash +# Use a different port +uv run uvicorn opsctl_api.main:app --reload --port 8001 +``` + +## Resources + +- [uv Documentation](https://docs.astral.sh/uv/) +- [Typer Documentation](https://typer.tiangolo.com/) +- [FastAPI Documentation](https://fastapi.tiangolo.com/) +- [pytest Documentation](https://docs.pytest.org/) +- [ruff Documentation](https://docs.astral.sh/ruff/) diff --git a/Dockerfile.api b/Dockerfile.api new file mode 100644 index 0000000..cba3888 --- /dev/null +++ b/Dockerfile.api @@ -0,0 +1,20 @@ +# Dockerfile for API +FROM python:3.12-slim + +WORKDIR /app + +# Install uv +RUN pip install uv + +# Copy workspace files +COPY pyproject.toml . +COPY packages/api packages/api + +# Install dependencies +RUN uv sync + +# Expose port +EXPOSE 8000 + +# Run the API +CMD ["uv", "run", "uvicorn", "opsctl_api.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d894b0d --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +.PHONY: help install test lint format typecheck clean run-cli run-api all + +help: ## Show this help message + @echo 'Usage: make [target]' + @echo '' + @echo 'Available targets:' + @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-15s %s\n", $$1, $$2}' $(MAKEFILE_LIST) + +install: ## Install dependencies + uv sync + +test: ## Run all tests + uv run pytest -v + +test-cov: ## Run tests with coverage + uv run pytest --cov=packages --cov-report=html --cov-report=term + +lint: ## Run linting checks + uv run ruff check . + +lint-fix: ## Fix linting issues automatically + uv run ruff check --fix . + +format: ## Format code with ruff + uv run ruff format . + +typecheck: ## Run type checking with mypy + uv run mypy packages/cli/src packages/api/src + +clean: ## Clean up cache and build artifacts + rm -rf .venv + rm -rf .pytest_cache + rm -rf .mypy_cache + rm -rf .ruff_cache + rm -rf htmlcov + find . -type d -name __pycache__ -exec rm -rf {} + + find . -type f -name "*.pyc" -delete + +run-cli: ## Run the CLI + uv run opsctl --help + +run-api: ## Run the API server + uv run uvicorn opsctl_api.main:app --reload + +all: lint typecheck test ## Run lint, typecheck, and test diff --git a/README.md b/README.md index 7c730a2..4da323e 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,26 @@ A template repository for platform engineering projects using a monorepo structu ``` opsctl/ +โ”œโ”€โ”€ .github/ +โ”‚ โ””โ”€โ”€ workflows/ +โ”‚ โ””โ”€โ”€ ci.yml # GitHub Actions CI workflow โ”œโ”€โ”€ packages/ -โ”‚ โ”œโ”€โ”€ api/ # FastAPI application +โ”‚ โ”œโ”€โ”€ api/ # FastAPI application โ”‚ โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ opsctl_api/ โ”‚ โ”‚ โ”œโ”€โ”€ tests/ โ”‚ โ”‚ โ””โ”€โ”€ pyproject.toml -โ”‚ โ””โ”€โ”€ cli/ # Typer CLI application +โ”‚ โ””โ”€โ”€ cli/ # Typer CLI application โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”‚ โ””โ”€โ”€ opsctl_cli/ โ”‚ โ”œโ”€โ”€ tests/ โ”‚ โ””โ”€โ”€ pyproject.toml -โ”œโ”€โ”€ pyproject.toml # Workspace configuration -โ””โ”€โ”€ pytest.ini # Test configuration +โ”œโ”€โ”€ pyproject.toml # Workspace configuration +โ”œโ”€โ”€ Makefile # Common development tasks +โ”œโ”€โ”€ docker-compose.yml # Docker Compose for development +โ”œโ”€โ”€ Dockerfile.api # Dockerfile for API service +โ”œโ”€โ”€ DEVELOPMENT.md # Detailed development guide +โ””โ”€โ”€ CONTRIBUTING.md # Contribution guidelines ``` ## ๐Ÿ› ๏ธ Setup @@ -48,6 +55,8 @@ cd opsctl 2. Install dependencies: ```bash uv sync +# or +make install ``` 3. Install packages in development mode: @@ -65,6 +74,8 @@ opsctl hello opsctl hello World opsctl version opsctl --help +# or +make run-cli ``` ### API @@ -72,6 +83,8 @@ opsctl --help Start the API server: ```bash uvicorn opsctl_api.main:app --reload +# or +make run-api ``` The API will be available at: @@ -86,16 +99,27 @@ curl http://localhost:8000/health curl http://localhost:8000/hello/World ``` +### Using Docker Compose + +Run the API with Docker Compose: +```bash +docker-compose up +``` + ## ๐Ÿงช Testing Run all tests: ```bash uv run pytest +# or +make test ``` Run tests with coverage: ```bash -uv run pytest --cov=packages +uv run pytest --cov=packages --cov-report=html +# or +make test-cov ``` Run tests for a specific package: @@ -109,21 +133,34 @@ uv run pytest packages/api/tests Run ruff linter: ```bash uv run ruff check . +# or +make lint ``` Auto-fix linting issues: ```bash uv run ruff check --fix . +# or +make lint-fix ``` Format code: ```bash uv run ruff format . +# or +make format ``` Run type checking: ```bash uv run mypy packages/cli/src packages/api/src +# or +make typecheck +``` + +Run all checks: +```bash +make all ``` ## ๐Ÿ“ฆ Building @@ -134,6 +171,16 @@ uv build packages/cli uv build packages/api ``` +Build Docker image for API: +```bash +docker build -t opsctl-api -f Dockerfile.api . +``` + +## ๐Ÿ“š Documentation + +- [DEVELOPMENT.md](DEVELOPMENT.md) - Detailed development guide +- [CONTRIBUTING.md](CONTRIBUTING.md) - How to contribute to this project + ## ๐Ÿค Contributing 1. Fork the repository @@ -142,6 +189,8 @@ uv build packages/api 4. Run tests and linting 5. Submit a pull request +See [CONTRIBUTING.md](CONTRIBUTING.md) for more details. + ## ๐Ÿ“„ License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..53d1a24 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +services: + api: + image: python:3.12-slim + working_dir: /app + volumes: + - .:/app + ports: + - "8000:8000" + command: > + sh -c "pip install uv && + uv sync && + uv run uvicorn opsctl_api.main:app --host 0.0.0.0 --reload" + environment: + - PYTHONUNBUFFERED=1 From 07c4a553ea5de41a085849600a2c24bea04d685a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 1 Nov 2025 22:05:01 +0000 Subject: [PATCH 4/7] Add comprehensive template guide Co-authored-by: alexinslc <127081+alexinslc@users.noreply.github.com> --- TEMPLATE_GUIDE.md | 162 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 TEMPLATE_GUIDE.md diff --git a/TEMPLATE_GUIDE.md b/TEMPLATE_GUIDE.md new file mode 100644 index 0000000..6deceab --- /dev/null +++ b/TEMPLATE_GUIDE.md @@ -0,0 +1,162 @@ +# Template Repository Guide + +This is a complete platform engineering template repository. Here's what's included and how to use it. + +## What's Included + +### Core Structure +- โœ… **Monorepo Layout**: Workspace with separate CLI and API packages +- โœ… **CLI Package**: Built with Typer, includes commands and tests +- โœ… **API Package**: Built with FastAPI, includes endpoints and tests +- โœ… **Package Manager**: uv for fast dependency management + +### Development Tools +- โœ… **Testing**: pytest with coverage support +- โœ… **Linting**: ruff for fast linting and formatting +- โœ… **Type Checking**: mypy for static type analysis +- โœ… **Make**: Convenient commands via Makefile +- โœ… **CI/CD**: GitHub Actions workflow included + +### Documentation +- โœ… **README.md**: Overview and quick start guide +- โœ… **DEVELOPMENT.md**: Detailed development guide +- โœ… **CONTRIBUTING.md**: Contribution guidelines +- โœ… **Package READMEs**: Individual docs for CLI and API + +### Docker Support +- โœ… **docker-compose.yml**: Quick start for development +- โœ… **Dockerfile.api**: Production-ready API container + +## Quick Start + +1. **Use this template** on GitHub to create a new repository +2. **Clone your new repository**: + ```bash + git clone + cd + ``` +3. **Install dependencies**: + ```bash + make install + ``` +4. **Run tests**: + ```bash + make test + ``` +5. **Try the CLI**: + ```bash + make run-cli + ``` +6. **Start the API**: + ```bash + make run-api + ``` + +## Customization + +### Rename the Project + +1. Update package names in: + - `packages/cli/pyproject.toml` (name and scripts) + - `packages/api/pyproject.toml` (name) + - `packages/cli/src/opsctl_cli/` โ†’ rename directory + - `packages/api/src/opsctl_api/` โ†’ rename directory + +2. Update imports in test files + +3. Update README and documentation + +### Add New Features + +**CLI Commands**: Edit `packages/cli/src/opsctl_cli/main.py` +```python +@app.command() +def my_command() -> None: + """My new command.""" + console.print("Hello!") +``` + +**API Endpoints**: Edit `packages/api/src/opsctl_api/main.py` +```python +@app.get("/my-endpoint") +async def my_endpoint() -> dict[str, str]: + """My new endpoint.""" + return {"message": "Hello!"} +``` + +### Add Dependencies + +**Development dependencies** (testing, linting, etc.): +Edit root `pyproject.toml` โ†’ `[dependency-groups] dev` + +**CLI dependencies**: +Edit `packages/cli/pyproject.toml` โ†’ `[project] dependencies` + +**API dependencies**: +Edit `packages/api/pyproject.toml` โ†’ `[project] dependencies` + +Then run: `make install` + +## Available Commands + +```bash +make help # Show all available commands +make install # Install/update dependencies +make test # Run all tests +make test-cov # Run tests with coverage report +make lint # Check code style +make lint-fix # Auto-fix code style issues +make format # Format code +make typecheck # Run type checking +make run-cli # Run the CLI +make run-api # Start the API server +make all # Run lint, typecheck, and test +make clean # Remove all cache and build files +``` + +## CI/CD + +The template includes a GitHub Actions workflow (`.github/workflows/ci.yml`) that: +- Runs on push and pull requests +- Tests on Python 3.12 +- Runs linting, type checking, and tests +- Uploads coverage to Codecov + +## Docker + +**Development**: +```bash +docker-compose up +``` + +**Production**: +```bash +docker build -t my-api -f Dockerfile.api . +docker run -p 8000:8000 my-api +``` + +## Best Practices + +1. **Keep tests updated** - Add tests for all new features +2. **Run checks often** - Use `make all` before committing +3. **Type everything** - Use type hints for better code quality +4. **Document changes** - Update README and docs when needed +5. **Small commits** - Make focused, atomic commits + +## Getting Help + +- Check `DEVELOPMENT.md` for detailed development info +- Check `CONTRIBUTING.md` for contribution guidelines +- Open an issue for questions or problems + +## Next Steps + +1. Customize the template for your project +2. Add your own commands/endpoints +3. Update documentation +4. Set up your CI/CD secrets (if needed) +5. Start building! + +--- + +**Happy coding!** ๐Ÿš€ From 86f3b0975be1d45d5ad6f4b4a88d31150b947af1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 1 Nov 2025 22:07:31 +0000 Subject: [PATCH 5/7] Fix security: Add explicit permissions to GitHub Actions workflow Co-authored-by: alexinslc <127081+alexinslc@users.noreply.github.com> --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5279a33..aaafd4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,9 @@ on: pull_request: branches: [ main, develop ] +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest From 65ec0369b21bced9575e5ff7e3d6b05442088eff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 1 Nov 2025 22:17:01 +0000 Subject: [PATCH 6/7] Add cross-platform support for macOS and Windows in documentation Co-authored-by: alexinslc <127081+alexinslc@users.noreply.github.com> --- DEVELOPMENT.md | 69 ++++++++++++++++++++-- README.md | 143 +++++++++++++++++++++++++++++++++++++++++++--- TEMPLATE_GUIDE.md | 57 ++++++++++++++++++ 3 files changed, 256 insertions(+), 13 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index d97ec3c..270b389 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -7,9 +7,26 @@ This guide will help you get started with developing in this monorepo template. ## Setup 1. **Install uv** (if not already installed): + + **macOS/Linux:** ```bash pip install uv ``` + + Or using the official installer: + ```bash + curl -LsSf https://astral.sh/uv/install.sh | sh + ``` + + **Windows:** + ```powershell + pip install uv + ``` + + Or using PowerShell with the official installer: + ```powershell + powershell -c "irm https://astral.sh/uv/install.ps1 | iex" + ``` 2. **Clone the repository**: ```bash @@ -28,11 +45,34 @@ This will create a virtual environment at `.venv/` and install all dependencies. ### Running the CLI +**macOS/Linux:** ```bash # Activate the virtual environment (optional, uv run will handle this) -source .venv/bin/activate # On Unix/macOS -# or -.venv\Scripts\activate # On Windows +source .venv/bin/activate + +# Run the CLI +uv run opsctl --help +uv run opsctl hello +uv run opsctl hello "Your Name" +uv run opsctl version +``` + +**Windows (PowerShell):** +```powershell +# Activate the virtual environment (optional, uv run will handle this) +.venv\Scripts\Activate.ps1 + +# Run the CLI +uv run opsctl --help +uv run opsctl hello +uv run opsctl hello "Your Name" +uv run opsctl version +``` + +**Windows (Command Prompt):** +```cmd +# Activate the virtual environment (optional, uv run will handle this) +.venv\Scripts\activate.bat # Run the CLI uv run opsctl --help @@ -200,6 +240,7 @@ async def new_endpoint() -> dict[str, str]: If you encounter issues with the virtual environment: +**macOS/Linux:** ```bash # Remove the virtual environment rm -rf .venv @@ -208,12 +249,32 @@ rm -rf .venv uv sync ``` +**Windows (PowerShell):** +```powershell +# Remove the virtual environment +Remove-Item -Recurse -Force .venv + +# Recreate it +uv sync +``` + ### Import Errors Make sure you're running commands with `uv run` or have activated the virtual environment: +**macOS/Linux:** ```bash -source .venv/bin/activate # On Unix/macOS +source .venv/bin/activate +``` + +**Windows (PowerShell):** +```powershell +.venv\Scripts\Activate.ps1 +``` + +**Windows (Command Prompt):** +```cmd +.venv\Scripts\activate.bat ``` ### Port Already in Use diff --git a/README.md b/README.md index 4da323e..26fe7fd 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ A template repository for platform engineering projects using a monorepo structure with separate CLI and API packages. +> **Cross-Platform Support**: This template works on macOS, Linux, and Windows. Commands are provided for both Unix-like systems and Windows where they differ. + ## ๐Ÿš€ Technologies - **CLI**: [Typer](https://typer.tiangolo.com/) - Modern CLI framework @@ -42,24 +44,68 @@ opsctl/ ### Prerequisites - Python 3.12+ -- uv (install with `pip install uv`) +- uv package manager + +**Installing uv:** + +
+macOS/Linux + +```bash +pip install uv +``` + +Or using the official installer: +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +``` +
+ +
+Windows + +```powershell +pip install uv +``` + +Or using PowerShell with the official installer: +```powershell +powershell -c "irm https://astral.sh/uv/install.ps1 | iex" +``` +
### Installation 1. Clone this repository: + +**macOS/Linux:** ```bash git clone cd opsctl ``` +**Windows:** +```powershell +git clone +cd opsctl +``` + 2. Install dependencies: + +**macOS/Linux:** ```bash uv sync # or make install ``` -3. Install packages in development mode: +**Windows (PowerShell):** +```powershell +uv sync +# Note: Makefile commands require Make for Windows or use uv directly +``` + +3. Install packages in development mode (optional): ```bash uv pip install -e packages/cli -e packages/api ``` @@ -69,36 +115,63 @@ uv pip install -e packages/cli -e packages/api ### CLI Run the CLI: + +**macOS/Linux:** ```bash -opsctl hello -opsctl hello World -opsctl version -opsctl --help -# or +uv run opsctl hello +uv run opsctl hello World +uv run opsctl version +uv run opsctl --help +# or using make make run-cli ``` +**Windows (PowerShell):** +```powershell +uv run opsctl hello +uv run opsctl hello World +uv run opsctl version +uv run opsctl --help +``` + ### API Start the API server: + +**macOS/Linux:** ```bash -uvicorn opsctl_api.main:app --reload -# or +uv run uvicorn opsctl_api.main:app --reload +# or using make make run-api ``` +**Windows (PowerShell):** +```powershell +uv run uvicorn opsctl_api.main:app --reload +``` + The API will be available at: - Main: http://localhost:8000 - Docs: http://localhost:8000/docs - ReDoc: http://localhost:8000/redoc Try the endpoints: + +**macOS/Linux:** ```bash curl http://localhost:8000/ curl http://localhost:8000/health curl http://localhost:8000/hello/World ``` +**Windows (PowerShell):** +```powershell +Invoke-WebRequest http://localhost:8000/ +Invoke-WebRequest http://localhost:8000/health +Invoke-WebRequest http://localhost:8000/hello/World +# Or install curl for Windows and use curl commands +``` + ### Using Docker Compose Run the API with Docker Compose: @@ -109,19 +182,33 @@ docker-compose up ## ๐Ÿงช Testing Run all tests: + +**macOS/Linux:** ```bash uv run pytest # or make test ``` +**Windows (PowerShell):** +```powershell +uv run pytest +``` + Run tests with coverage: + +**macOS/Linux:** ```bash uv run pytest --cov=packages --cov-report=html # or make test-cov ``` +**Windows (PowerShell):** +```powershell +uv run pytest --cov=packages --cov-report=html +``` + Run tests for a specific package: ```bash uv run pytest packages/cli/tests @@ -131,38 +218,76 @@ uv run pytest packages/api/tests ## ๐Ÿ” Linting and Type Checking Run ruff linter: + +**macOS/Linux:** ```bash uv run ruff check . # or make lint ``` +**Windows (PowerShell):** +```powershell +uv run ruff check . +``` + Auto-fix linting issues: + +**macOS/Linux:** ```bash uv run ruff check --fix . # or make lint-fix ``` +**Windows (PowerShell):** +```powershell +uv run ruff check --fix . +``` + Format code: + +**macOS/Linux:** ```bash uv run ruff format . # or make format ``` +**Windows (PowerShell):** +```powershell +uv run ruff format . +``` + Run type checking: + +**macOS/Linux:** ```bash uv run mypy packages/cli/src packages/api/src # or make typecheck ``` +**Windows (PowerShell):** +```powershell +uv run mypy packages/cli/src packages/api/src +``` + Run all checks: + +**macOS/Linux:** ```bash make all ``` +**Windows (PowerShell):** +```powershell +# Run each command separately +uv run ruff check . +uv run mypy packages/cli/src packages/api/src +uv run pytest +``` + ## ๐Ÿ“ฆ Building Build the packages: diff --git a/TEMPLATE_GUIDE.md b/TEMPLATE_GUIDE.md index 6deceab..e3667b3 100644 --- a/TEMPLATE_GUIDE.md +++ b/TEMPLATE_GUIDE.md @@ -30,26 +30,67 @@ This is a complete platform engineering template repository. Here's what's inclu ## Quick Start 1. **Use this template** on GitHub to create a new repository + 2. **Clone your new repository**: ```bash git clone cd ``` + 3. **Install dependencies**: + + **macOS/Linux:** ```bash make install + # or + uv sync + ``` + + **Windows (PowerShell):** + ```powershell + uv sync ``` + 4. **Run tests**: + + **macOS/Linux:** ```bash make test + # or + uv run pytest + ``` + + **Windows (PowerShell):** + ```powershell + uv run pytest ``` + 5. **Try the CLI**: + + **macOS/Linux:** ```bash make run-cli + # or + uv run opsctl hello ``` + + **Windows (PowerShell):** + ```powershell + uv run opsctl hello + ``` + 6. **Start the API**: + + **macOS/Linux:** ```bash make run-api + # or + uv run uvicorn opsctl_api.main:app --reload + ``` + + **Windows (PowerShell):** + ```powershell + uv run uvicorn opsctl_api.main:app --reload ``` ## Customization @@ -99,6 +140,7 @@ Then run: `make install` ## Available Commands +**macOS/Linux (using Make):** ```bash make help # Show all available commands make install # Install/update dependencies @@ -114,6 +156,21 @@ make all # Run lint, typecheck, and test make clean # Remove all cache and build files ``` +**Windows (using uv directly):** +```powershell +uv sync # Install/update dependencies +uv run pytest # Run all tests +uv run pytest --cov=packages --cov-report=html # Run tests with coverage +uv run ruff check . # Check code style +uv run ruff check --fix . # Auto-fix code style issues +uv run ruff format . # Format code +uv run mypy packages/cli/src packages/api/src # Run type checking +uv run opsctl --help # Run the CLI +uv run uvicorn opsctl_api.main:app --reload # Start the API server +``` + +> **Note for Windows users**: The Makefile requires Make for Windows (e.g., via Chocolatey: `choco install make`) or you can use the `uv` commands directly as shown above. + ## CI/CD The template includes a GitHub Actions workflow (`.github/workflows/ci.yml`) that: From 3e34bc94d61b99400e6ae4a48316d4546dd8ff63 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 1 Nov 2025 22:25:41 +0000 Subject: [PATCH 7/7] Add Dev Container support for platform-agnostic development Co-authored-by: alexinslc <127081+alexinslc@users.noreply.github.com> --- .devcontainer/Dockerfile | 20 +++++++++ .devcontainer/README.md | 63 ++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 70 +++++++++++++++++++++++++++++++ .devcontainer/docker-compose.yml | 11 +++++ DEVELOPMENT.md | 45 +++++++++++++++++++- README.md | 71 +++++++++++++++++++++++++++----- TEMPLATE_GUIDE.md | 29 +++++++++++++ 7 files changed, 297 insertions(+), 12 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/README.md create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/docker-compose.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..4f3270c --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/devcontainers/python:3.12 + +# Install uv +RUN pip install --no-cache-dir uv + +# Install additional tools +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends \ + make \ + curl \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* + +# Set up workspace +WORKDIR /workspace + +# Create a non-root user (vscode user is already created by base image) +# Ensure proper permissions +RUN chown -R vscode:vscode /workspace + +USER vscode diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000..1d6490e --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,63 @@ +# Dev Container Configuration + +This directory contains the configuration for developing in a containerized environment using Visual Studio Code's Dev Containers feature. + +## What's Included + +### Pre-installed Tools +- Python 3.12 +- uv package manager +- make +- git +- curl +- zsh with Oh My Zsh + +### VS Code Extensions +The following extensions are automatically installed: +- Python (Microsoft) +- Pylance (Microsoft) +- Ruff (Linter and Formatter) +- Mypy Type Checker +- Even Better TOML +- GitHub Copilot + +### VS Code Settings +Pre-configured settings for: +- Python interpreter pointing to workspace `.venv` +- Automatic formatting with Ruff on save +- pytest test discovery +- Linting and type checking integration + +### Port Forwarding +- Port 8000 is automatically forwarded for the FastAPI server + +### Automatic Setup +When the container is created, `uv sync` runs automatically to install all dependencies. + +## Usage + +1. Open this repository in VS Code +2. Install the "Dev Containers" extension if you haven't already +3. Press `F1` and select "Dev Containers: Reopen in Container" +4. Wait for the container to build (first time only) +5. Start coding! + +## Customization + +Edit the following files to customize your dev container: + +- `devcontainer.json` - Main configuration (extensions, settings, ports) +- `Dockerfile` - Add system packages or tools +- `docker-compose.yml` - Modify Docker Compose configuration + +## Benefits + +- **Consistent Environment**: Everyone on your team uses the same development environment +- **No Local Setup**: No need to install Python, uv, or other tools locally +- **Isolated**: Each project has its own containerized environment +- **Cross-Platform**: Works identically on macOS, Linux, and Windows + +## Learn More + +- [VS Code Dev Containers Documentation](https://code.visualstudio.com/docs/devcontainers/containers) +- [Dev Containers Tutorial](https://code.visualstudio.com/docs/devcontainers/tutorial) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..bd551c3 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,70 @@ +{ + "name": "OpsCtl Development", + "dockerComposeFile": "docker-compose.yml", + "service": "devcontainer", + "workspaceFolder": "/workspace", + + // Configure tool-specific properties + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance", + "charliermarsh.ruff", + "ms-python.mypy-type-checker", + "tamasfe.even-better-toml", + "github.copilot" + ], + "settings": { + "python.defaultInterpreterPath": "/workspace/.venv/bin/python", + "python.terminal.activateEnvironment": true, + "python.testing.pytestEnabled": true, + "python.testing.pytestArgs": ["-v"], + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.fixAll": "explicit" + } + }, + "mypy-type-checker.args": [ + "--config-file=pyproject.toml" + ], + "ruff.lint.args": [ + "--config=pyproject.toml" + ] + } + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally + "forwardPorts": [8000], + "portsAttributes": { + "8000": { + "label": "FastAPI", + "onAutoForward": "notify" + } + }, + + // Use 'postCreateCommand' to run commands after the container is created + "postCreateCommand": "uv sync", + + // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root + "remoteUser": "vscode", + + "features": { + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": true, + "installOhMyZsh": true, + "upgradePackages": true, + "username": "vscode", + "userUid": "1000", + "userGid": "1000" + }, + "ghcr.io/devcontainers/features/git:1": { + "version": "latest", + "ppa": true + } + } +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 0000000..3a73384 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,11 @@ +services: + devcontainer: + build: + context: .. + dockerfile: .devcontainer/Dockerfile + volumes: + - ..:/workspace:cached + command: sleep infinity + network_mode: host + environment: + - PYTHONUNBUFFERED=1 diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 270b389..7d67d2a 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -4,7 +4,50 @@ This guide will help you get started with developing in this monorepo template. -## Setup +## Setup Options + +### Option 1: Dev Container (Recommended) + +The easiest way to get started with a consistent development environment across all platforms. + +**Prerequisites:** +- [Docker Desktop](https://www.docker.com/products/docker-desktop) +- [VS Code](https://code.visualstudio.com/) +- [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) + +**Steps:** + +1. **Clone the repository**: + ```bash + git clone + cd opsctl + ``` + +2. **Open in VS Code**: + ```bash + code . + ``` + +3. **Reopen in Container**: + - Click "Reopen in Container" when prompted + - Or press `F1` and select "Dev Containers: Reopen in Container" + +4. **Start developing**: + The container will automatically install all dependencies via the `postCreateCommand`. Once ready: + ```bash + make test # Run tests + make run-cli # Run the CLI + make run-api # Start the API + ``` + +**Benefits:** +- โœ… Works identically on macOS, Linux, and Windows +- โœ… No need to install Python or uv locally +- โœ… Pre-configured VS Code extensions and settings +- โœ… Isolated environment per project +- โœ… Automatic port forwarding + +### Option 2: Local Setup 1. **Install uv** (if not already installed): diff --git a/README.md b/README.md index 26fe7fd..e902b15 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A template repository for platform engineering projects using a monorepo structure with separate CLI and API packages. -> **Cross-Platform Support**: This template works on macOS, Linux, and Windows. Commands are provided for both Unix-like systems and Windows where they differ. +> **๐ŸŽฏ Recommended**: Use the included [Dev Container](#-setup-with-dev-container-recommended) for the best cross-platform development experience! ## ๐Ÿš€ Technologies @@ -17,29 +17,78 @@ A template repository for platform engineering projects using a monorepo structu ``` opsctl/ +โ”œโ”€โ”€ .devcontainer/ +โ”‚ โ”œโ”€โ”€ devcontainer.json # Dev Container configuration +โ”‚ โ”œโ”€โ”€ docker-compose.yml # Dev Container Docker Compose +โ”‚ โ””โ”€โ”€ Dockerfile # Dev Container Dockerfile โ”œโ”€โ”€ .github/ โ”‚ โ””โ”€โ”€ workflows/ -โ”‚ โ””โ”€โ”€ ci.yml # GitHub Actions CI workflow +โ”‚ โ””โ”€โ”€ ci.yml # GitHub Actions CI workflow โ”œโ”€โ”€ packages/ -โ”‚ โ”œโ”€โ”€ api/ # FastAPI application +โ”‚ โ”œโ”€โ”€ api/ # FastAPI application โ”‚ โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ opsctl_api/ โ”‚ โ”‚ โ”œโ”€โ”€ tests/ โ”‚ โ”‚ โ””โ”€โ”€ pyproject.toml -โ”‚ โ””โ”€โ”€ cli/ # Typer CLI application +โ”‚ โ””โ”€โ”€ cli/ # Typer CLI application โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”‚ โ””โ”€โ”€ opsctl_cli/ โ”‚ โ”œโ”€โ”€ tests/ โ”‚ โ””โ”€โ”€ pyproject.toml -โ”œโ”€โ”€ pyproject.toml # Workspace configuration -โ”œโ”€โ”€ Makefile # Common development tasks -โ”œโ”€โ”€ docker-compose.yml # Docker Compose for development -โ”œโ”€โ”€ Dockerfile.api # Dockerfile for API service -โ”œโ”€โ”€ DEVELOPMENT.md # Detailed development guide -โ””โ”€โ”€ CONTRIBUTING.md # Contribution guidelines +โ”œโ”€โ”€ pyproject.toml # Workspace configuration +โ”œโ”€โ”€ Makefile # Common development tasks +โ”œโ”€โ”€ docker-compose.yml # Docker Compose for development +โ”œโ”€โ”€ Dockerfile.api # Dockerfile for API service +โ”œโ”€โ”€ DEVELOPMENT.md # Detailed development guide +โ””โ”€โ”€ CONTRIBUTING.md # Contribution guidelines ``` -## ๐Ÿ› ๏ธ Setup +## ๐Ÿ› ๏ธ Setup with Dev Container (Recommended) + +The easiest and most consistent way to develop across all platforms (macOS, Linux, Windows). + +### Prerequisites + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) (or Docker Engine + Docker Compose) +- [VS Code](https://code.visualstudio.com/) with the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) + +### Quick Start + +1. Clone this repository: + ```bash + git clone + cd opsctl + ``` + +2. Open in VS Code: + ```bash + code . + ``` + +3. When prompted, click **"Reopen in Container"** (or press `F1` and select "Dev Containers: Reopen in Container") + +4. VS Code will build the container and set up the environment automatically. Once ready, you can: + ```bash + # Run tests + make test + + # Run the CLI + uv run opsctl hello + + # Start the API + make run-api + ``` + +**Benefits:** +- โœ… Identical environment across all platforms +- โœ… No local Python installation needed +- โœ… Pre-configured VS Code settings and extensions +- โœ… All dependencies pre-installed +- โœ… Port forwarding configured automatically + +## ๐Ÿ› ๏ธ Local Setup (Alternative) + +If you prefer to develop locally without containers: ### Prerequisites diff --git a/TEMPLATE_GUIDE.md b/TEMPLATE_GUIDE.md index e3667b3..9146708 100644 --- a/TEMPLATE_GUIDE.md +++ b/TEMPLATE_GUIDE.md @@ -11,6 +11,7 @@ This is a complete platform engineering template repository. Here's what's inclu - โœ… **Package Manager**: uv for fast dependency management ### Development Tools +- โœ… **Dev Container**: Pre-configured development container for VS Code (recommended) - โœ… **Testing**: pytest with coverage support - โœ… **Linting**: ruff for fast linting and formatting - โœ… **Type Checking**: mypy for static type analysis @@ -24,11 +25,39 @@ This is a complete platform engineering template repository. Here's what's inclu - โœ… **Package READMEs**: Individual docs for CLI and API ### Docker Support +- โœ… **Dev Container**: Full VS Code development container setup - โœ… **docker-compose.yml**: Quick start for development - โœ… **Dockerfile.api**: Production-ready API container ## Quick Start +### Recommended: Using Dev Container + +1. **Prerequisites**: + - Install [Docker Desktop](https://www.docker.com/products/docker-desktop) + - Install [VS Code](https://code.visualstudio.com/) + - Install [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) + +2. **Clone and open**: + ```bash + git clone + cd + code . + ``` + +3. **Reopen in Container**: + - Click "Reopen in Container" when prompted + - Wait for container to build and dependencies to install + +4. **Start developing**: + ```bash + make test # Run tests + make run-cli # Run CLI + make run-api # Start API + ``` + +### Alternative: Local Setup + 1. **Use this template** on GitHub to create a new repository 2. **Clone your new repository**: