Skip to content

Commit 85dd63c

Browse files
JacobCoffeeclaude
andauthored
feat: Phase 1.1 - Extract API Service (#107)
Co-authored-by: Claude <[email protected]>
1 parent 56fc1a4 commit 85dd63c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+13034
-30
lines changed

packages/byte-common/pyproject.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@ readme = "README.md"
1818
license = { text = "MIT" }
1919

2020
[build-system]
21-
requires = ["uv>=0.5.11"]
22-
build-backend = "uv"
21+
requires = ["hatchling"]
22+
build-backend = "hatchling.build"
23+
24+
[tool.hatch.metadata]
25+
allow-direct-references = true

pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ packages = ["byte_bot/"]
7474
[tool.uv.workspace]
7575
members = [
7676
"packages/byte-common",
77+
"services/api",
7778
]
7879

7980
[tool.uv]
@@ -179,7 +180,7 @@ filterwarnings = [
179180
[tool.ty]
180181

181182
[tool.ty.environment]
182-
extra-paths = ["byte_bot/", "tests/", "packages/byte-common/src/", "packages/byte-common/tests/"]
183+
extra-paths = ["byte_bot/", "tests/", "packages/byte-common/src/", "packages/byte-common/tests/", "services/api/src/"]
183184

184185
[tool.slotscheck]
185186
strict-imports = false
@@ -234,6 +235,9 @@ known-first-party = ["byte_bot", "byte_common", "tests"]
234235
"byte_bot/**/*.*" = ["PLR0913", "SLF001", "PLC0415"] # Imports inside functions in monolith
235236
"byte_bot/server/lib/db/base.py" = ["E501"]
236237
"byte_bot/server/lib/db/migrations/versions/*.*" = ["D", "INP", "PGH", "PLC"]
238+
"services/api/src/byte_api/app.py" = ["PLC0415"] # Imports inside create_app() to avoid circular imports
239+
"services/api/src/byte_api/lib/db/migrations/env.py" = ["SLF001"] # Alembic workaround
240+
"services/api/src/byte_api/lib/db/migrations/versions/*.*" = ["D", "INP", "PGH", "PLC"] # Alembic-generated
237241
"tests/**/*.*" = [
238242
"S101",
239243
"D",

services/api/Dockerfile

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# syntax=docker/dockerfile:1
2+
3+
# ============================================================================
4+
# Builder Stage: Install dependencies and build virtual environment
5+
# ============================================================================
6+
FROM python:3.12-slim AS builder
7+
8+
# Set working directory
9+
WORKDIR /app
10+
11+
# Install system dependencies required for building Python packages
12+
RUN apt-get update && apt-get install -y \
13+
gcc \
14+
g++ \
15+
make \
16+
libpq-dev \
17+
&& rm -rf /var/lib/apt/lists/*
18+
19+
# Copy uv binary from official image
20+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
21+
22+
# Set uv environment variables for optimal performance
23+
ENV UV_SYSTEM_PYTHON=1 \
24+
UV_COMPILE_BYTECODE=1 \
25+
UV_LINK_MODE=copy
26+
27+
# Copy workspace configuration files
28+
COPY pyproject.toml uv.lock ./
29+
30+
# Copy shared packages and service code
31+
COPY packages/byte-common ./packages/byte-common
32+
COPY services/api ./services/api
33+
34+
# Install dependencies with frozen lockfile (no dev dependencies)
35+
# This creates a .venv directory with all dependencies
36+
RUN uv sync --frozen --no-dev --no-editable
37+
38+
# ============================================================================
39+
# Runtime Stage: Minimal production image
40+
# ============================================================================
41+
FROM python:3.12-slim
42+
43+
# Set working directory
44+
WORKDIR /app
45+
46+
# Install runtime system dependencies (PostgreSQL client library)
47+
RUN apt-get update && apt-get install -y \
48+
libpq5 \
49+
&& rm -rf /var/lib/apt/lists/*
50+
51+
# Create non-root user for security
52+
RUN groupadd -r appuser && \
53+
useradd -r -g appuser -u 1000 -d /app -s /sbin/nologin appuser
54+
55+
# Copy virtual environment from builder stage
56+
COPY --from=builder --chown=appuser:appuser /app/.venv /app/.venv
57+
58+
# Copy application code from builder stage
59+
COPY --from=builder --chown=appuser:appuser /app/services/api /app/services/api
60+
COPY --from=builder --chown=appuser:appuser /app/packages/byte-common /app/packages/byte-common
61+
62+
# Copy workspace configuration (needed for uv run commands)
63+
COPY --from=builder --chown=appuser:appuser /app/pyproject.toml /app/uv.lock ./
64+
65+
# Set PATH to use virtual environment binaries
66+
ENV PATH="/app/.venv/bin:$PATH" \
67+
PYTHONUNBUFFERED=1 \
68+
PYTHONDONTWRITEBYTECODE=1 \
69+
PYTHONPATH="/app"
70+
71+
# Expose API port
72+
EXPOSE 8000
73+
74+
# Switch to non-root user
75+
USER appuser
76+
77+
# Health check to ensure service is responsive
78+
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
79+
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
80+
81+
# Run database migrations and start server
82+
# Note: In production, consider running migrations separately in an init container
83+
CMD ["sh", "-c", "alembic upgrade head && uvicorn byte_api.app:app --host 0.0.0.0 --port 8000 --workers 2"]

services/api/README.md

Lines changed: 232 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,249 @@
11
# Byte API Service
22

3-
REST API service for the Byte Bot application.
3+
> **Version**: 0.2.0 **Python**: 3.12+ **Framework**: Litestar 2.4.3+
44
55
## Overview
66

7-
This service provides the web API and dashboard functionality including:
7+
The **Byte API Service** is the REST API microservice for Byte Bot, providing HTTP endpoints for guild management,
8+
GitHub integration, and system operations. This service replaces the monolithic web service and operates independently
9+
of the Discord bot.
810

9-
- Litestar REST API
10-
- Web dashboard with Jinja2 templates
11-
- TailwindCSS + DaisyUI frontend
12-
- Database management and migrations
13-
- Authentication and authorization
11+
## Purpose
1412

15-
## Technology Stack
13+
- **REST API Endpoints**: Guild CRUD, GitHub config, forum settings
14+
- **Database Operations**: Primary data store interface via Advanced Alchemy ORM
15+
- **OpenAPI Documentation**: Swagger/ReDoc UI for API exploration
16+
- **Health Monitoring**: System health checks and status endpoints
17+
- **Web Dashboard**: Server-side rendered dashboard (Jinja2 templates)
1618

17-
- Python 3.12+
18-
- Litestar framework
19-
- PostgreSQL (via Advanced Alchemy)
20-
- Jinja2 templates
21-
- TailwindCSS + DaisyUI
22-
- Shared code from `byte-common` package
19+
## Architecture
2320

24-
## Status
21+
The API service is built on:
2522

26-
**Phase 0.1**: Directory structure created. Implementation pending.
23+
- **Litestar**: High-performance ASGI framework
24+
- **Advanced Alchemy**: Repository pattern over SQLAlchemy 2.0
25+
- **PostgreSQL**: Primary database (async via asyncpg)
26+
- **Pydantic**: Request/response validation and settings management
2727

28-
## Future Structure
28+
## Dependencies
2929

30+
### Core Dependencies
31+
32+
- `byte-common`: Shared models, utilities, and database schemas
33+
- `litestar[full]>=2.4.3`: Web framework with full plugin support
34+
- `advanced-alchemy>=0.6.1`: ORM and repository pattern
35+
- `asyncpg>=0.29.0`: Async PostgreSQL driver
36+
- `alembic>=1.13.0`: Database migrations
37+
38+
### Integration Dependencies
39+
40+
- `githubkit[auth-app]`: GitHub API client
41+
- `httpx`: Async HTTP client
42+
- `pydantic>=2.5.2`: Data validation
43+
- `pydantic-settings>=2.1.0`: Configuration management
44+
- `PyJWT>=2.8.0`: JWT token handling
45+
46+
## Installation
47+
48+
```bash
49+
# From repository root
50+
cd services/api
51+
52+
# Install dependencies with uv
53+
uv sync
54+
55+
# Or install as editable package
56+
uv pip install -e .
3057
```
31-
services/api/
32-
├── byte_api/ # API source code
33-
│ ├── domain/ # Domain models
34-
│ ├── lib/ # API utilities
35-
│ ├── templates/ # Jinja2 templates
36-
│ └── static/ # Static assets
37-
├── tests/ # API-specific tests
38-
├── pyproject.toml # API service configuration
39-
└── Dockerfile # API service container
58+
59+
## Configuration
60+
61+
Set the following environment variables (or use `.env` file):
62+
63+
```bash
64+
# Database
65+
DB_URL=postgresql+asyncpg://user:pass@localhost:5432/byte
66+
DB_POOL_DISABLE=True # Use NullPool in production
67+
68+
# Server
69+
SERVER_HOST=0.0.0.0
70+
SERVER_PORT=8000
71+
ENVIRONMENT=dev # dev, test, or prod
72+
SECRET_KEY=your-secret-key
73+
74+
# GitHub Integration
75+
GITHUB_APP_ID=your-app-id
76+
GITHUB_APP_PRIVATE_KEY=your-private-key
77+
GITHUB_APP_CLIENT_ID=your-client-id
78+
GITHUB_APP_CLIENT_SECRET=your-client-secret
79+
80+
# Logging
81+
LOG_LEVEL=INFO
82+
DEBUG=False
83+
```
84+
85+
## Running the Service
86+
87+
```bash
88+
# Development mode with auto-reload
89+
uv run python -m byte_api --reload --debug
90+
91+
# Production mode
92+
uv run python -m byte_api --http-workers 4
93+
94+
# With custom host/port
95+
uv run python -m byte_api --host 0.0.0.0 --port 8080
4096
```
4197

4298
## Development
4399

44-
To be populated during Phase 0.3 (API Service Migration).
100+
### Database Migrations
101+
102+
```bash
103+
# Apply migrations
104+
uv run alembic upgrade head
105+
106+
# Create new migration
107+
uv run alembic revision --autogenerate -m "description"
108+
109+
# Rollback
110+
uv run alembic downgrade -1
111+
```
112+
113+
### Testing
114+
115+
```bash
116+
# Run tests
117+
uv run pytest
118+
119+
# With coverage
120+
uv run pytest --cov=byte_api --cov-report=html
121+
```
122+
123+
### Code Quality
124+
125+
```bash
126+
# Linting
127+
uv run ruff check .
128+
129+
# Formatting
130+
uv run ruff format .
131+
132+
# Type checking
133+
uv run ty check byte_api
134+
```
135+
136+
## API Endpoints
137+
138+
### Guild Management
139+
140+
- `GET /api/guilds` - List all guilds (paginated)
141+
- `POST /api/guilds` - Create guild
142+
- `GET /api/guilds/{guild_id}` - Get guild details
143+
- `PATCH /api/guilds/{guild_id}` - Update guild
144+
- `DELETE /api/guilds/{guild_id}` - Delete guild
145+
146+
### Configuration
147+
148+
- `GET /api/guilds/{guild_id}/github` - GitHub config
149+
- `GET /api/guilds/{guild_id}/sotags` - Stack Overflow tags
150+
- `GET /api/guilds/{guild_id}/allowed-users` - Allowed users
151+
- `GET /api/guilds/{guild_id}/forum` - Forum config
152+
153+
### System
154+
155+
- `GET /health` - Health check
156+
- `GET /api/system/info` - System information
157+
158+
### Documentation
159+
160+
- `GET /api/swagger` - Swagger UI
161+
- `GET /api/redoc` - ReDoc UI
162+
- `GET /api/schema/openapi.json` - OpenAPI schema
163+
164+
## Project Structure
165+
166+
```
167+
services/api/
168+
├── src/
169+
│ └── byte_api/
170+
│ ├── __init__.py
171+
│ ├── __main__.py # Entry point
172+
│ ├── app.py # Litestar app factory
173+
│ ├── lib/ # Infrastructure
174+
│ │ ├── settings.py
175+
│ │ ├── cors.py
176+
│ │ ├── openapi.py
177+
│ │ ├── db/
178+
│ │ └── log/
179+
│ └── domain/ # Business logic
180+
│ ├── guilds/
181+
│ ├── github/
182+
│ ├── system/
183+
│ └── web/
184+
├── tests/
185+
├── pyproject.toml
186+
└── README.md
187+
```
188+
189+
## Migration Notes
190+
191+
This service is part of Phase 1 (API Layer Extraction) of the microservices migration. It consolidates functionality
192+
from:
193+
194+
- `byte_bot/app.py` - Litestar app factory
195+
- `byte_bot/server/` - Web service logic
196+
- `byte_bot/server/domain/` - Business domains
197+
198+
The Discord bot will communicate with this service via HTTP rather than direct database access.
199+
200+
## Deployment
201+
202+
### Docker
203+
204+
```bash
205+
# Build image
206+
docker build -t byte-api:latest .
207+
208+
# Run container
209+
docker run -p 8000:8000 --env-file .env byte-api:latest
210+
```
211+
212+
### Railway
213+
214+
Deploy as a standalone service with PostgreSQL database plugin attached.
215+
216+
## Troubleshooting
217+
218+
### Database Connection Issues
219+
220+
- Verify `DB_URL` format: `postgresql+asyncpg://user:pass@host:port/db`
221+
- Ensure PostgreSQL is running and accessible
222+
- Check firewall/network settings
223+
224+
### Migration Errors
225+
226+
- Ensure database is up to date: `uv run alembic upgrade head`
227+
- Check migration scripts in `byte_common` package
228+
- Verify no other processes are holding locks
229+
230+
### Import Errors
231+
232+
- Install dependencies: `uv sync`
233+
- Verify `byte-common` is installed in same environment
234+
- Check Python version: `python --version` (should be 3.12+)
235+
236+
## Additional Resources
237+
238+
- [Litestar Documentation](https://docs.litestar.dev/)
239+
- [Advanced Alchemy Documentation](https://docs.advanced-alchemy.litestar.dev/)
240+
- [Main Repository](https://github.com/JacobCoffee/byte)
241+
- [Migration Plan](../../PLAN.md)
242+
243+
## License
244+
245+
MIT License - See LICENSE file in repository root.
246+
247+
## Maintainer
248+
249+
Jacob Coffee (@JacobCoffee) - [email protected]

0 commit comments

Comments
 (0)