jan/docs/src/pages/api-reference/development.mdx
2025-10-28 17:26:27 +07:00

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/janhq/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
```