446 lines
9.2 KiB
Plaintext
446 lines
9.2 KiB
Plaintext
---
|
|
title: Development
|
|
description: Development setup, workflow, and contribution guidelines for Jan Server.
|
|
---
|
|
|
|
## Development Setup
|
|
|
|
### Prerequisites
|
|
|
|
- **Go**: 1.24.6 or later
|
|
- **Docker**: For containerization
|
|
- **minikube**: Local Kubernetes development
|
|
- **Helm**: Package management
|
|
- **Make**: Build automation
|
|
|
|
### Initial Setup
|
|
|
|
|
|
1. **Clone Repository**
|
|
```bash
|
|
git clone https://github.com/menloresearch/jan-server
|
|
cd jan-server
|
|
```
|
|
|
|
2. **Install Development Tools**
|
|
```bash
|
|
cd apps/jan-api-gateway/application
|
|
make install
|
|
```
|
|
|
|
3. **Generate Code**
|
|
```bash
|
|
make setup
|
|
```
|
|
|
|
4. **Start Development Environment**
|
|
```bash
|
|
# From project root
|
|
./scripts/run.sh
|
|
```
|
|
|
|
## API Gateway Development
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
apps/jan-api-gateway/application/
|
|
├── cmd/server/ # Entry point and dependency injection
|
|
│ ├── server.go # Main server setup
|
|
│ ├── wire.go # DI configuration
|
|
│ └── wire_gen.go # Generated DI code
|
|
├── app/ # Core application logic
|
|
│ ├── domain/ # Business entities
|
|
│ ├── repository/ # Data access layer
|
|
│ ├── service/ # Business logic
|
|
│ └── handler/ # HTTP handlers
|
|
├── config/ # Configuration management
|
|
└── docs/ # Generated API documentation
|
|
```
|
|
|
|
### Build Commands
|
|
|
|
```bash
|
|
# Install development dependencies
|
|
make install
|
|
|
|
# Generate API documentation
|
|
make doc
|
|
|
|
# Generate dependency injection code
|
|
make wire
|
|
|
|
# Complete setup (doc + wire)
|
|
make setup
|
|
|
|
# Build application
|
|
go build -o jan-api-gateway ./cmd/server
|
|
```
|
|
|
|
### Code Generation
|
|
|
|
Jan Server uses code generation for several components:
|
|
|
|
**Swagger Documentation:**
|
|
```bash
|
|
# Generates docs/swagger.json and docs/swagger.yaml
|
|
swag init --parseDependency -g cmd/server/server.go -o docs
|
|
```
|
|
|
|
**Dependency Injection:**
|
|
```bash
|
|
# Generates wire_gen.go from wire.go providers
|
|
wire ./cmd/server
|
|
```
|
|
|
|
**Database Models:**
|
|
```bash
|
|
# Generate GORM models (when schema changes)
|
|
go run cmd/codegen/gorm/gorm.go
|
|
```
|
|
|
|
### Local Development
|
|
|
|
#### Running API Gateway Locally
|
|
|
|
```bash
|
|
cd apps/jan-api-gateway/application
|
|
|
|
# Set environment variables
|
|
export JAN_INFERENCE_MODEL_URL=http://localhost:8101
|
|
export JWT_SECRET=your-jwt-secret
|
|
export DB_POSTGRESQL_WRITE_DSN="host=localhost user=jan-user password=jan-password dbname=jan port=5432 sslmode=disable"
|
|
|
|
# Run the server
|
|
go run ./cmd/server
|
|
```
|
|
|
|
#### Database Setup
|
|
|
|
For local development, you can run PostgreSQL directly:
|
|
|
|
```bash
|
|
# Using Docker
|
|
docker run -d \
|
|
--name jan-postgres \
|
|
-e POSTGRES_DB=jan \
|
|
-e POSTGRES_USER=jan-user \
|
|
-e POSTGRES_PASSWORD=jan-password \
|
|
-p 5432:5432 \
|
|
postgres:14
|
|
```
|
|
|
|
## Testing
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
# Run all tests
|
|
go test ./...
|
|
|
|
# Run tests with coverage
|
|
go test -cover ./...
|
|
|
|
# Run specific test package
|
|
go test ./app/service/...
|
|
```
|
|
|
|
### Test Structure
|
|
|
|
```
|
|
app/
|
|
├── service/
|
|
│ ├── auth_service.go
|
|
│ ├── auth_service_test.go
|
|
│ ├── conversation_service.go
|
|
│ └── conversation_service_test.go
|
|
└── handler/
|
|
├── auth_handler.go
|
|
├── auth_handler_test.go
|
|
├── chat_handler.go
|
|
└── chat_handler_test.go
|
|
```
|
|
|
|
### Writing Tests
|
|
|
|
Example service test:
|
|
|
|
```go
|
|
func TestAuthService_ValidateToken(t *testing.T) {
|
|
// Setup
|
|
service := NewAuthService(mockRepo, mockConfig)
|
|
|
|
// Test cases
|
|
tests := []struct {
|
|
name string
|
|
token string
|
|
expectValid bool
|
|
expectError bool
|
|
}{
|
|
{"valid token", "valid.jwt.token", true, false},
|
|
{"invalid token", "invalid.token", false, true},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
valid, err := service.ValidateToken(tt.token)
|
|
assert.Equal(t, tt.expectValid, valid)
|
|
assert.Equal(t, tt.expectError, err != nil)
|
|
})
|
|
}
|
|
}
|
|
```
|
|
|
|
## Docker Development
|
|
|
|
### Building Images
|
|
|
|
```bash
|
|
# Build API gateway
|
|
docker build -t jan-api-gateway:dev ./apps/jan-api-gateway
|
|
|
|
# Build inference model
|
|
docker build -t jan-inference-model:dev ./apps/jan-inference-model
|
|
```
|
|
|
|
### Development Compose
|
|
|
|
For local development without Kubernetes:
|
|
|
|
```yaml
|
|
# docker-compose.dev.yml
|
|
version: '3.8'
|
|
services:
|
|
postgres:
|
|
image: postgres:14
|
|
environment:
|
|
POSTGRES_DB: jan
|
|
POSTGRES_USER: jan-user
|
|
POSTGRES_PASSWORD: jan-password
|
|
ports:
|
|
- "5432:5432"
|
|
|
|
api-gateway:
|
|
build: ./apps/jan-api-gateway
|
|
ports:
|
|
- "8080:8080"
|
|
environment:
|
|
- JAN_INFERENCE_MODEL_URL=http://inference-model:8101
|
|
- DB_POSTGRESQL_WRITE_DSN=host=postgres user=jan-user password=jan-password dbname=jan port=5432 sslmode=disable
|
|
depends_on:
|
|
- postgres
|
|
|
|
inference-model:
|
|
build: ./apps/jan-inference-model
|
|
ports:
|
|
- "8101:8101"
|
|
```
|
|
|
|
## Debugging
|
|
|
|
### Go Debugging
|
|
|
|
For VS Code debugging, add to `.vscode/launch.json`:
|
|
|
|
```json
|
|
{
|
|
"version": "0.2.0",
|
|
"configurations": [
|
|
{
|
|
"name": "Launch Jan API Gateway",
|
|
"type": "go",
|
|
"request": "launch",
|
|
"mode": "auto",
|
|
"program": "${workspaceFolder}/apps/jan-api-gateway/application/cmd/server",
|
|
"env": {
|
|
"JAN_INFERENCE_MODEL_URL": "http://localhost:8101",
|
|
"JWT_SECRET": "development-secret"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Application Logs
|
|
|
|
```bash
|
|
# View API gateway logs
|
|
kubectl logs deployment/jan-server-jan-api-gateway -f
|
|
|
|
# View inference model logs
|
|
kubectl logs deployment/jan-server-jan-inference-model -f
|
|
|
|
# View PostgreSQL logs
|
|
kubectl logs statefulset/jan-server-postgresql -f
|
|
```
|
|
|
|
### Log Levels
|
|
|
|
Set log level via environment variable:
|
|
|
|
```bash
|
|
export LOG_LEVEL=debug # debug, info, warn, error
|
|
```
|
|
|
|
## Code Style and Standards
|
|
|
|
### Go Standards
|
|
|
|
- Follow [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments)
|
|
- Use `gofmt` for formatting
|
|
- Run `go vet` for static analysis
|
|
- Use meaningful variable and function names
|
|
|
|
### API Standards
|
|
|
|
- RESTful endpoint design
|
|
- OpenAPI/Swagger annotations for all endpoints
|
|
- Consistent error response format
|
|
- Proper HTTP status codes
|
|
|
|
### Git Workflow
|
|
|
|
```bash
|
|
# Create feature branch
|
|
git checkout -b feature/your-feature-name
|
|
|
|
# Make changes and commit
|
|
git add .
|
|
git commit -m "feat: add new authentication endpoint"
|
|
|
|
# Push and create PR
|
|
git push origin feature/your-feature-name
|
|
```
|
|
|
|
### Commit Message Format
|
|
|
|
Follow conventional commits:
|
|
|
|
```
|
|
feat: add new feature
|
|
fix: resolve bug in authentication
|
|
docs: update API documentation
|
|
test: add unit tests for service layer
|
|
refactor: improve error handling
|
|
```
|
|
|
|
## Performance Testing
|
|
|
|
### Load Testing
|
|
|
|
Use [k6](https://k6.io) for API load testing:
|
|
|
|
```javascript
|
|
// load-test.js
|
|
import http from 'k6/http';
|
|
|
|
export default function () {
|
|
const response = http.post('http://localhost:8080/api/v1/chat/completions', {
|
|
model: 'jan-v1-4b',
|
|
messages: [
|
|
{ role: 'user', content: 'Hello!' }
|
|
]
|
|
}, {
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': 'Bearer your-token'
|
|
}
|
|
});
|
|
|
|
check(response, {
|
|
'status is 200': (r) => r.status === 200,
|
|
'response time < 5000ms': (r) => r.timings.duration < 5000,
|
|
});
|
|
}
|
|
```
|
|
|
|
Run load test:
|
|
```bash
|
|
k6 run --vus 10 --duration 30s load-test.js
|
|
```
|
|
|
|
### Memory Profiling
|
|
|
|
Enable Go profiling endpoints:
|
|
|
|
```go
|
|
import _ "net/http/pprof"
|
|
|
|
// In main.go
|
|
go func() {
|
|
log.Println(http.ListenAndServe("localhost:6060", nil))
|
|
}()
|
|
```
|
|
|
|
Profile memory usage:
|
|
```bash
|
|
go tool pprof http://localhost:6060/debug/pprof/heap
|
|
```
|
|
|
|
## Contributing
|
|
|
|
### Pull Request Process
|
|
|
|
1. **Fork the repository**
|
|
2. **Create feature branch** from `main`
|
|
3. **Make changes** following code standards
|
|
4. **Add tests** for new functionality
|
|
5. **Update documentation** if needed
|
|
6. **Submit pull request** with clear description
|
|
|
|
### Code Review Checklist
|
|
|
|
- [ ] Code follows Go standards
|
|
- [ ] Tests added for new features
|
|
- [ ] Documentation updated
|
|
- [ ] API endpoints have Swagger annotations
|
|
- [ ] No breaking changes without version bump
|
|
- [ ] Security considerations addressed
|
|
|
|
### Issues and Bug Reports
|
|
|
|
When reporting bugs, include:
|
|
|
|
- **Environment**: OS, Go version, minikube version
|
|
- **Steps to reproduce**: Clear, minimal reproduction steps
|
|
- **Expected behavior**: What should happen
|
|
- **Actual behavior**: What actually happens
|
|
- **Logs**: Relevant error messages or logs
|
|
|
|
For security issues, please report privately to the maintainers instead of creating public issues.
|
|
|
|
## Release Process
|
|
|
|
### Version Management
|
|
|
|
Jan Server uses semantic versioning (semver):
|
|
|
|
- **Major**: Breaking changes
|
|
- **Minor**: New features, backward compatible
|
|
- **Patch**: Bug fixes, backward compatible
|
|
|
|
### Building Releases
|
|
|
|
```bash
|
|
# Tag release
|
|
git tag -a v1.2.3 -m "Release v1.2.3"
|
|
|
|
# Build release images
|
|
docker build -t jan-api-gateway:v1.2.3 ./apps/jan-api-gateway
|
|
docker build -t jan-inference-model:v1.2.3 ./apps/jan-inference-model
|
|
|
|
# Push tags
|
|
git push origin v1.2.3
|
|
```
|
|
|
|
### Deployment
|
|
|
|
Production deployments follow the same Helm chart structure:
|
|
|
|
```bash
|
|
# Deploy specific version
|
|
helm install jan-server ./charts/umbrella-chart \
|
|
--set jan-api-gateway.image.tag=v1.2.3 \
|
|
--set jan-inference-model.image.tag=v1.2.3
|
|
```
|