# Development Guide This guide covers building, testing, and contributing to Tyto. ## Prerequisites - **Go 1.23+** - **Node.js 22+** - **Docker & Docker Compose** - **Make** (optional) - **protoc** (for gRPC development) ## Getting the Source ```bash git clone https://somegit.dev/vikingowl/tyto.git cd tyto ``` ## Project Structure ``` tyto/ ├── backend/ │ ├── cmd/ │ │ ├── server/ # HTTP/SSE server entry point │ │ ├── agent/ # Lightweight agent entry point │ │ └── tyto/ # CLI tool │ ├── internal/ │ │ ├── api/ # HTTP handlers and routes │ │ ├── alerts/ # Alert management │ │ ├── auth/ # Authentication (local, LDAP) │ │ ├── collectors/ # Metric collectors │ │ │ ├── gpu/ # Multi-vendor GPU support │ │ │ └── logs/ # Log collectors │ │ ├── config/ # Configuration loading │ │ ├── database/ # SQLite/PostgreSQL │ │ ├── history/ # Historical data storage │ │ ├── models/ # Data structures │ │ ├── pki/ # Certificate management │ │ ├── server/ # gRPC hub for agents │ │ └── sse/ # Server-Sent Events broker │ ├── proto/ # gRPC protocol definitions │ ├── go.mod │ └── Dockerfile ├── frontend/ │ ├── src/ │ │ ├── lib/ │ │ │ ├── api/ # API clients │ │ │ ├── components/ # Svelte components │ │ │ ├── stores/ # Svelte stores │ │ │ ├── types/ # TypeScript types │ │ │ └── utils/ # Utility functions │ │ └── routes/ # SvelteKit routes │ ├── package.json │ └── Dockerfile ├── docs/ # Documentation ├── scripts/ # Build and install scripts ├── docker-compose.yml └── docker-compose.prod.yml ``` ## Backend Development ### Running Locally ```bash cd backend # Install dependencies go mod download # Run the server go run ./cmd/server # Run with specific config go run ./cmd/server --config ../config.dev.yaml ``` ### Building ```bash # Build server binary go build -o tyto ./cmd/server # Build agent binary go build -o tyto-agent ./cmd/agent # Build CLI go build -o tyto-cli ./cmd/tyto # Build with optimizations CGO_ENABLED=0 go build -ldflags="-s -w" -o tyto ./cmd/server ``` ### Cross-Compilation ```bash # Linux AMD64 GOOS=linux GOARCH=amd64 go build -o tyto-linux-amd64 ./cmd/server # Linux ARM64 GOOS=linux GOARCH=arm64 go build -o tyto-linux-arm64 ./cmd/server # macOS GOOS=darwin GOARCH=amd64 go build -o tyto-darwin-amd64 ./cmd/server ``` ### Running Tests ```bash # All tests go test ./... # With coverage go test -cover ./... # Specific package go test ./internal/collectors/... # Verbose output go test -v ./internal/api/... ``` ### Linting ```bash # Install golangci-lint go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest # Run linter golangci-lint run ``` ### gRPC Development ```bash # Install protoc plugins go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest # Generate Go code from proto files protoc --go_out=. --go-grpc_out=. proto/*.proto ``` ## Frontend Development ### Running Locally ```bash cd frontend # Install dependencies npm install # Start development server npm run dev # With specific API URL VITE_API_URL=http://localhost:8080 npm run dev ``` ### Building ```bash # Production build npm run build # Preview production build npm run preview ``` ### Running Tests ```bash # Unit tests npm test # Watch mode npm run test:watch # With coverage npm run test:coverage ``` ### Linting & Formatting ```bash # Lint npm run lint # Format npm run format # Type check npm run check ``` ## Docker Development ### Building Images ```bash # Build all images docker compose build # Build specific service docker compose build backend docker compose build frontend # Build without cache docker compose build --no-cache ``` ### Running with Docker ```bash # Start all services docker compose up # Start in background docker compose up -d # View logs docker compose logs -f # Stop services docker compose down ``` ### Development with Hot Reload ```bash # Mount source for hot reload docker compose -f docker-compose.yml -f docker-compose.dev.yml up ``` ## Adding a New Collector 1. Create collector file in `backend/internal/collectors/`: ```go // backend/internal/collectors/example.go package collectors import "github.com/vikingowl/tyto/internal/models" type ExampleCollector struct { // collector state } func NewExampleCollector() *ExampleCollector { return &ExampleCollector{} } func (c *ExampleCollector) Collect() (*models.ExampleStats, error) { // Collect metrics from system return &models.ExampleStats{ // ... }, nil } ``` 2. Add model in `backend/internal/models/`: ```go // backend/internal/models/example.go package models type ExampleStats struct { Available bool `json:"available"` Value int `json:"value"` } ``` 3. Integrate in `backend/internal/collectors/all.go`: ```go func (c *AllCollectors) Collect() *models.AllMetrics { metrics := &models.AllMetrics{ // ...existing... Example: c.example.Collect(), } return metrics } ``` 4. Add frontend component in `frontend/src/lib/components/`. ## Adding a New API Endpoint 1. Add handler in `backend/internal/api/`: ```go // backend/internal/api/example.go package api import ( "github.com/gin-gonic/gin" ) func (s *Server) exampleHandler(c *gin.Context) { // Handle request c.JSON(200, gin.H{"status": "ok"}) } ``` 2. Register route in `backend/internal/api/routes.go`: ```go func (s *Server) setupRoutes() { // ...existing routes... api := s.router.Group("/api/v1") api.GET("/example", s.exampleHandler) } ``` 3. Add frontend API client in `frontend/src/lib/api/`: ```typescript // frontend/src/lib/api/example.ts export async function getExample(): Promise { const response = await fetch('/api/v1/example'); return response.json(); } ``` ## Testing ### Backend Unit Tests ```go // backend/internal/collectors/cpu_test.go package collectors import ( "testing" ) func TestCPUCollector(t *testing.T) { collector := NewCPUCollector("/proc") stats, err := collector.Collect() if err != nil { t.Fatalf("Collect() failed: %v", err) } if len(stats.Cores) == 0 { t.Error("Expected at least one CPU core") } } ``` ### Frontend Component Tests ```typescript // frontend/src/lib/components/CpuCard.test.ts import { render } from '@testing-library/svelte'; import CpuCard from './CpuCard.svelte'; test('renders CPU usage', () => { const { getByText } = render(CpuCard, { props: { cpu: { totalUsage: 50, cores: [] } } }); expect(getByText('50%')).toBeInTheDocument(); }); ``` ### Integration Tests ```bash # Start test environment docker compose -f docker-compose.test.yml up -d # Run integration tests go test -tags=integration ./tests/... # Cleanup docker compose -f docker-compose.test.yml down ``` ## Code Style ### Go - Follow [Effective Go](https://golang.org/doc/effective_go) - Use `gofmt` for formatting - Use meaningful variable names - Keep functions small and focused - Document exported functions and types ### TypeScript/Svelte - Use TypeScript strict mode - Follow Svelte conventions - Use Prettier for formatting - Prefer composition over inheritance - Keep components focused ## Commit Messages Follow [Conventional Commits](https://www.conventionalcommits.org/): ``` feat: add GPU temperature monitoring fix: resolve memory leak in SSE broker docs: update API documentation refactor: simplify collector interface test: add integration tests for auth ``` ## Pull Request Process 1. Fork the repository 2. Create a feature branch: `git checkout -b feature/my-feature` 3. Make changes and commit 4. Run tests: `go test ./...` and `npm test` 5. Run linters: `golangci-lint run` and `npm run lint` 6. Push to your fork 7. Open a Pull Request ### PR Checklist - [ ] Tests pass - [ ] Linting passes - [ ] Documentation updated - [ ] Commit messages follow convention - [ ] No breaking changes (or documented) ## Release Process 1. Update version in `internal/version/version.go` 2. Update CHANGELOG.md 3. Create git tag: `git tag v1.2.3` 4. Push tag: `git push origin v1.2.3` 5. CI builds and publishes releases ## Debugging ### Backend ```bash # Run with debug logging TYTO_LOG_LEVEL=debug go run ./cmd/server # Use delve debugger dlv debug ./cmd/server ``` ### Frontend - Use browser DevTools - React/Svelte DevTools extension - `console.log` for quick debugging ### Docker ```bash # Shell into container docker exec -it tyto-backend /bin/sh # View container logs docker logs tyto-backend -f # Inspect container docker inspect tyto-backend ``` ## Performance Profiling ### Go Profiling ```go import _ "net/http/pprof" // Access at http://localhost:8080/debug/pprof/ ``` ```bash # CPU profile go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30 # Memory profile go tool pprof http://localhost:8080/debug/pprof/heap ``` ### Frontend Performance - Use Lighthouse in Chrome DevTools - React Profiler for component performance - Network tab for API timing