Skip to content

Latest commit

 

History

History
310 lines (234 loc) · 7.39 KB

File metadata and controls

310 lines (234 loc) · 7.39 KB

Contributing

Guide for setting up a local development environment for roji.

Prerequisites

  • Docker & Docker Compose
  • Go 1.25+ (for local builds without Docker)
  • mkcert (optional - for custom certificates)

Quick Start

1. Create the roji network

docker network create roji

2. TLS certificates

Certificates are automatically generated on first startup. You can also use mkcert for custom certificates:

# Option 1: Auto-generation (default)
# Just start roji - certificates will be created automatically
# Set ROJI_AUTO_CERT=true in .env (default)

# Option 2: Using mkcert (optional)
# Install mkcert (first time only)
# macOS: brew install mkcert
# Linux: sudo apt install mkcert

# Install root CA to system (first time only)
mkcert -install

# Generate certificates
mkdir -p certs
mkcert -cert-file certs/cert.pem -key-file certs/key.pem \
  "*.dev.localhost" dev.localhost localhost 127.0.0.1

# Disable auto-generation in .env
# ROJI_AUTO_CERT=false

3. Configure environment (optional)

# Copy example env file
cp .env.example .env

# Edit .env to customize settings

4. Start development server

# Start with hot reload
docker compose up

# Or run in background
docker compose up -d
docker compose logs -f

The development server uses air for hot reload. Any changes to .go files will automatically trigger a rebuild.

5. Start test services

mkdir -p test
cat > test/docker-compose.yml << 'EOF'
services:
  web:
    image: nginx:alpine
    networks:
      - roji

  api:
    image: nginx:alpine
    labels:
      - "roji.host=api.dev.localhost"
    networks:
      - roji

networks:
  roji:
    external: true
EOF

cd test && docker compose up -d

6. Verify

# Check routes in logs
docker compose logs roji-dev

# Access via browser or curl
curl -k https://web.dev.localhost
curl -k https://api.dev.localhost

# View dashboard
open https://dev.localhost

# Check status
curl -k https://dev.localhost/_api/status | jq

# Check health
curl -k https://dev.localhost/_api/health | jq

# List routes via API
curl -k https://dev.localhost/_api/routes | jq

7. Test CLI commands

# List routes (requires roji to be running)
docker compose exec roji-dev roji routes

# Show version
docker compose exec roji-dev roji version

# Get help
docker compose exec roji-dev roji --help

Development Workflow

Hot reload

The development container mounts the source code and uses air for automatic rebuilding:

# Watch logs while developing
docker compose logs -f

# Rebuild container if Dockerfile or go.mod changes
docker compose up --build

Running tests

# Run all tests
go test ./...

# Run tests with coverage
go test -v -race -coverprofile=coverage.out ./...

# View coverage report
go tool cover -html=coverage.out

# Run tests in container
docker compose exec roji-dev go test ./...

# Run specific package tests
go test ./proxy/...
go test ./docker/...

Testing checklist

Before submitting a PR, ensure:

  • All tests pass: go test ./...
  • Code is formatted: go fmt ./...
  • No linting errors: go vet ./...
  • New features have tests
  • Documentation is updated

Building production image

# Build production image
docker build --target production -t roji:latest .

# Run production image
docker run -d \
  -p 80:80 -p 443:443 \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -v ./certs:/certs \
  --network roji \
  roji:latest

Environment variables

Configure via .env file (gitignored) or directly in shell:

Variable Description Default
ROJI_NETWORK Docker network to watch roji
ROJI_DOMAIN Base domain dev.localhost
ROJI_HTTP_PORT HTTP port 80
ROJI_HTTPS_PORT HTTPS port 443
ROJI_CERTS_DIR Certificate directory /certs
ROJI_DASHBOARD Dashboard hostname roji.{domain}
ROJI_LOG_LEVEL Log level (debug/info/warn/error) debug

Project Structure

roji/
├── cmd/roji/
│   ├── main.go              # Entry point
│   └── cmd/                 # Cobra commands
│       ├── root.go          # Root command (server)
│       ├── server.go        # Server implementation
│       ├── routes.go        # Routes list command
│       ├── version.go       # Version command
│       ├── health.go        # Health check command
│       ├── config.go        # Config management command
│       ├── doctor.go        # Environment diagnostics command
│       └── ca.go            # CA certificate management command
├── docker/
│   ├── client.go            # Docker API wrapper
│   └── watcher.go           # Events watcher
├── proxy/
│   ├── handler.go           # ReverseProxy implementation
│   ├── router.go            # Routing + SSE Pub/Sub
│   └── templates/           # HTML/CSS/JS (embed.FS)
├── certgen/
│   ├── generator.go         # TLS certificate generator
│   ├── installer.go         # CAInstaller interface
│   ├── installer_darwin.go  # macOS Keychain
│   ├── installer_linux.go   # Linux (Debian/RHEL)
│   ├── installer_windows.go # Windows certutil
│   └── installer_wsl.go     # WSL→Windows
├── config/
│   ├── labels.go            # Label parser
│   ├── paths.go             # XDG path utilities
│   └── settings.go          # Configuration loading
├── doctor/
│   ├── check.go             # Doctor interface
│   └── checks/              # Individual checks
├── project/
│   └── store.go             # Project history storage
├── test/                    # Integration/E2E tests
├── Dockerfile               # Multi-stage build (development/testing)
├── docker-compose.yml       # Development and testing
├── docker-compose.dev.yml   # Development with Air hot reload
├── Makefile                 # Build shortcuts
├── .air.toml                # Hot reload configuration
├── .env.example             # Environment template
├── go.mod
└── go.sum

Troubleshooting

.localhost domain doesn't resolve

OS Solution
macOS Automatically resolves to 127.0.0.1
Linux Add to /etc/hosts or configure systemd-resolved
Windows (WSL2) Add to Windows hosts file
# Linux: add to /etc/hosts
echo "127.0.0.1 web.dev.localhost api.dev.localhost dev.localhost" | sudo tee -a /etc/hosts

Ports 80/443 already in use

Edit .env to use different ports:

ROJI_HTTP_PORT=8080
ROJI_HTTPS_PORT=8443

Container not detected

  1. Check network connection:

    docker network inspect roji
  2. Check container port configuration:

    docker inspect <container> | jq '.[0].Config.ExposedPorts'
  3. Ensure container doesn't have roji.self=true label

Certificate errors

# Reinstall root CA
mkcert -install

# Regenerate certificates
mkcert -cert-file certs/cert.pem -key-file certs/key.pem \
  "*.dev.localhost" dev.localhost localhost 127.0.0.1

# Restart browser

Hot reload not working

# Check air logs
docker compose logs -f

# Rebuild container
docker compose up --build