2c52b1634f
Fusion-Task-Id: FN-011 Fusion-Task-Lineage: 4a9aca6f-9d91-43aa-8d2a-d59657c1541a
198 lines
4.5 KiB
Markdown
198 lines
4.5 KiB
Markdown
# Development Guide
|
|
|
|
## Prerequisites
|
|
|
|
- **Node.js** ≥ 20 and **pnpm** ≥ 9
|
|
- **Python** ≥ 3.11 with `venv` support
|
|
- **Docker** and **Docker Compose** (for local services)
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
# Install Node dependencies and Python virtualenv + packages
|
|
make install
|
|
|
|
# Or manually:
|
|
pnpm install
|
|
cd apps/api && python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
|
|
```
|
|
|
|
## Environment Setup
|
|
|
|
Copy the root environment example and fill in local values:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
Copy the frontend environment example:
|
|
|
|
```bash
|
|
cp apps/web/.env.example apps/web/.env
|
|
```
|
|
|
|
## Running Locally
|
|
|
|
### Frontend only
|
|
|
|
```bash
|
|
cd apps/web
|
|
pnpm dev # Vite dev server on http://localhost:5173
|
|
```
|
|
|
|
### Backend only
|
|
|
|
```bash
|
|
cd apps/api
|
|
.venv/bin/uvicorn app.main:app --reload --port 8000
|
|
```
|
|
|
|
### Both (via root script)
|
|
|
|
```bash
|
|
pnpm dev # Runs frontend and backend in parallel
|
|
```
|
|
|
|
### With Docker Compose
|
|
|
|
```bash
|
|
docker compose up --build -d
|
|
```
|
|
|
|
### Alembic Migrations
|
|
|
|
Generate a new migration after modifying models:
|
|
```bash
|
|
cd apps/api
|
|
.venv/bin/alembic revision --autogenerate -m "description"
|
|
```
|
|
|
|
Apply migrations:
|
|
```bash
|
|
cd apps/api
|
|
.venv/bin/alembic upgrade head
|
|
```
|
|
|
|
Downgrade one revision:
|
|
```bash
|
|
cd apps/api
|
|
.venv/bin/alembic downgrade -1
|
|
```
|
|
|
|
Or use the Makefile targets:
|
|
```bash
|
|
cd apps/api
|
|
make revision msg="description"
|
|
make upgrade
|
|
make downgrade
|
|
```
|
|
|
|
## Testing
|
|
|
|
### Frontend
|
|
|
|
```bash
|
|
pnpm --filter @headquarter/web test
|
|
```
|
|
|
|
Uses **Vitest** + **Testing Library** + **jsdom**.
|
|
|
|
### Backend
|
|
|
|
```bash
|
|
pnpm --filter @headquarter/api test
|
|
```
|
|
|
|
Or directly with pytest:
|
|
|
|
```bash
|
|
cd apps/api && .venv/bin/pytest
|
|
```
|
|
|
|
### All tests
|
|
|
|
```bash
|
|
make test
|
|
# or
|
|
pnpm test
|
|
```
|
|
|
|
## CI / Testing
|
|
|
|
A GitHub Actions workflow (`.github/workflows/ci.yml`) runs on every push and pull request to `main`. It executes two jobs in parallel:
|
|
|
|
- **web-ci** — checks out the repo, installs Node.js ≥ 20 and pnpm, then runs `lint`, `typecheck`, and `test` for `@headquarter/web`.
|
|
- **api-ci** — checks out the repo, sets up Python 3.11, installs API dev dependencies (`pytest`, `ruff`, `mypy`, `httpx`), starts a PostgreSQL service container, then runs `ruff check`, `mypy`, and `pytest` for the API.
|
|
|
|
The workflow reports pass/fail status directly on pull requests as required status checks. All commands must pass before a PR can be merged.
|
|
|
|
## Linting and Type Checking
|
|
|
|
### Frontend
|
|
|
|
```bash
|
|
pnpm --filter @headquarter/web lint
|
|
pnpm --filter @headquarter/web typecheck
|
|
```
|
|
|
|
### Backend
|
|
|
|
```bash
|
|
pnpm --filter @headquarter/api lint
|
|
pnpm --filter @headquarter/api typecheck
|
|
```
|
|
|
|
### All
|
|
|
|
```bash
|
|
make lint
|
|
make typecheck
|
|
```
|
|
|
|
## Building
|
|
|
|
```bash
|
|
make build
|
|
# or
|
|
pnpm build
|
|
```
|
|
|
|
## Project Layout
|
|
|
|
```text
|
|
├── apps/
|
|
│ ├── web/ # Vite React TypeScript frontend
|
|
│ └── api/ # FastAPI Python backend
|
|
├── packages/ # Shared packages (future)
|
|
├── docs/ # Documentation
|
|
├── deploy/ # Deployment skeleton files
|
|
├── docker-compose.yml
|
|
└── package.json # Root monorepo scripts
|
|
```
|
|
|
|
## Conventions
|
|
|
|
- **Frontend**: React functional components, TypeScript strict mode, ESLint + Ruff-like rules.
|
|
- **Backend**: FastAPI, Pydantic settings, pytest, ruff, mypy.
|
|
- **Commits**: Conventional commits with task ID prefix, e.g. `feat(FN-002): description`.
|
|
|
|
## Git Abstraction
|
|
|
|
The `app/git/` package in the backend provides provider-independent Git
|
|
orchestration. It is split into two layers so that remote provider API logic
|
|
and local CLI operations evolve independently:
|
|
|
|
| Module | Responsibility |
|
|
|--------|--------------|
|
|
| `types` | Enumerations (`ProviderKind`, `CredentialKind`, `ConnectionStatus`, `SshKeyStatus`) |
|
|
| `provider` | Abstract `GitProvider` — remote operations (`validate_connection`, `list_repositories`, `create_deploy_key`, …) |
|
|
| `credentials` | `GitCredential` / `AccessTokenCredential` models and `CredentialStorage` ABC |
|
|
| `ssh_key` | `SshKeyPair` model and `SshKeyLifecycle` (Ed25519 generation via `cryptography`) |
|
|
| `connection` | `RepositoryConnection` ORM mapping and `ConnectionManager` orchestration |
|
|
| `operations` | Abstract `GitOperations` and concrete `LocalGitOperations` (subprocess-based `get_status`) |
|
|
|
|
Security rules for the package:
|
|
- Credential models store **only** `encrypted_payload` — no plaintext `token` or `private_key` fields.
|
|
- SSH private keys are encrypted before storage; the field uses `repr=False`.
|
|
- Real encryption of the payload is deferred to FN-009; the current placeholder is base64-only.
|