Skip to main content

Development Environment

Set up your local development environment for working on Easy AppServer.

Prerequisites

Before setting up your development environment, ensure you have:

  • Go 1.22+ installed and configured
  • Docker and Docker Compose for infrastructure
  • Git for version control
  • Make for running build commands
  • IDE/Editor (VS Code, GoLand, or similar)
  • Node.js 18+ and pnpm (for SDK development)

Quick Setup

1. Clone the Repository

git clone <repository-url>
cd easy.appserver

2. Install Go Dependencies

# Download all Go modules
go mod download

# Verify modules
go mod verify

3. Start Development Environment

# Start infrastructure and appserver
make run-dev

This command will:

  1. Start all Docker infrastructure services
  2. Wait for services to be ready
  3. Start the AppServer in development mode

4. Verify Setup

# Check appserver health
curl http://localhost:8080/health

# Check infrastructure
make docker-ps

Makefile Commands

The project includes a comprehensive Makefile for common development tasks.

Infrastructure Commands

Start Infrastructure

# Start core infrastructure services
make docker-up

Starts all Docker services:

  • PostgreSQL, Redis, RabbitMQ
  • Kratos (identity), Hydra (OAuth2), OpenFGA (authorization), Oathkeeper (proxy)
  • Observability stack (OpenTelemetry Collector, Prometheus, Loki, Tempo, Grafana)

Stop Infrastructure

# Stop services (preserve volumes)
make docker-down

# Stop and remove volumes (clean slate)
make docker-clean

View Logs

# View all service logs
make docker-logs

# View specific service logs
docker-compose -f docker/docker-compose.yml logs -f kratos
docker-compose -f docker/docker-compose.yml logs -f postgres

Check Status

# View running containers
make docker-ps

# Restart all services
make docker-restart

AppServer Commands

Run AppServer

# Run appserver (requires infrastructure)
make run

# Run complete dev environment (infrastructure + appserver)
make run-dev

Build Binary

# Build for multiple platforms
make build

# Build production binary (Linux amd64, optimized)
make build-prod

# Build for ARM v7
make build-armv7

Build output locations:

  • bin/amd64/main - Linux AMD64
  • bin/arm/main - Linux ARM
  • bin/armv7/main - Linux ARM v7
  • bin/windows/main.exe - Windows AMD64

Testing Commands

Run Tests

# Run all tests
make test

# Run tests with docker-compose infrastructure
make docker-test

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

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

Test Specific Packages

# Test a specific package
go test ./pkg/v2/application/...

# Run with verbose output
go test -v ./pkg/v2/application/marketplace/...

# Run specific test
go test -v -run TestAppRegistration ./pkg/v2/application/marketplace/...

Docker Development Workflow

Docker Compose Commands

# Start all services
docker-compose -f docker/docker-compose.yml up -d

# Start specific service
docker-compose -f docker/docker-compose.yml up -d postgres

# Stop all services
docker-compose -f docker/docker-compose.yml down

# View logs (all services)
docker-compose -f docker/docker-compose.yml logs -f

# View logs (specific service)
docker-compose -f docker/docker-compose.yml logs -f appserver

# Rebuild service
docker-compose -f docker/docker-compose.yml up -d --build appserver

# Execute command in container
docker-compose -f docker/docker-compose.yml exec postgres psql -U partner

# Remove all containers and volumes
docker-compose -f docker/docker-compose.yml down -v

Database Access

PostgreSQL

# Connect to PostgreSQL
docker exec -it appserver-postgres psql -U partner

# Connect to specific database
docker exec -it appserver-postgres psql -U partner -d appserver

# List databases
docker exec -it appserver-postgres psql -U partner -c "\l"

# List tables in appserver database
docker exec -it appserver-postgres psql -U partner -d appserver -c "\dt"

# Execute SQL query
docker exec -it appserver-postgres psql -U partner -d appserver \
-c "SELECT * FROM apps LIMIT 10;"

# Backup database
docker exec appserver-postgres pg_dump -U partner appserver > backup.sql

# Restore database
docker exec -i appserver-postgres psql -U partner appserver < backup.sql

Redis

# Connect to Redis CLI
docker exec -it appserver-redis redis-cli

# Test connection
docker exec appserver-redis redis-cli ping

# Get all keys
docker exec appserver-redis redis-cli keys '*'

# Get value
docker exec appserver-redis redis-cli get "key-name"

# Flush all data (⚠️ use with caution)
docker exec appserver-redis redis-cli flushall

RabbitMQ

# Check status
docker exec appserver-rabbitmq rabbitmqctl status

# List queues
docker exec appserver-rabbitmq rabbitmqctl list_queues

# List exchanges
docker exec appserver-rabbitmq rabbitmqctl list_exchanges

# Management UI
open http://localhost:15672 # guest/guest

Service Health Checks

# Check all services
make docker-ps

# AppServer
curl http://localhost:8080/health

# Kratos
curl http://localhost:4433/health/ready

# Hydra
curl http://localhost:4444/health/ready

# OpenFGA
curl http://localhost:8090/healthz

# Prometheus
curl http://localhost:9090/-/healthy

# Grafana
curl http://localhost:3000/api/health

Development Tools

gRPC Development

Install grpcurl

# macOS
brew install grpcurl

# Linux
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest

Enable gRPC Reflection

Add to your config or environment:

export APPSERVER_GRPC_REFLECTION_ENABLED=true

Use grpcurl

# List services
grpcurl -plaintext localhost:9090 list

# List methods
grpcurl -plaintext localhost:9090 list easy.marketplace.v2.Marketplace

# Describe service
grpcurl -plaintext localhost:9090 describe easy.marketplace.v2.Marketplace

# Call method
grpcurl -plaintext -d '{"name": "de.easy-m.test"}' \
localhost:9090 easy.marketplace.v2.Marketplace/GetApp

GraphQL Development

Enable GraphQL Playground

export APPSERVER_GRAPHQL_PLAYGROUND_ENABLED=true

Then visit: http://localhost:8080/graphql

GraphQL CLI Queries

# Install graphql-cli
npm install -g graphql-cli

# Query using curl
curl -X POST http://localhost:8080/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ apps { edges { node { id name } } } }"}'

Database Migrations

Run Migrations

# Run all pending migrations
go run cmd/appserver-v2/main.go migrate up

# Check migration status
go run cmd/appserver-v2/main.go migrate status

# Rollback last migration
go run cmd/appserver-v2/main.go migrate down

# Force migration version (if stuck)
go run cmd/appserver-v2/main.go migrate force <version>

Create New Migration

Migrations are in pkg/v2/migrations/ as embedded SQL files:

-- pkg/v2/migrations/000X_description.up.sql
CREATE TABLE example (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);

-- pkg/v2/migrations/000X_description.down.sql
DROP TABLE example;

Debugging

Enable Debug Logging

# Set log level to debug
export APPSERVER_LOG_LEVEL=debug

# Run appserver
make run

Attach Debugger (VS Code)

Create .vscode/launch.json:

{
"version": "0.2.0",
"configurations": [
{
"name": "Debug AppServer (v2)",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/cmd/appserver-v2",
"args": [],
"env": {
"APPSERVER_DB_HOST": "localhost",
"APPSERVER_DB_PASSWORD": "changeme-in-production",
"APPSERVER_SETTINGS_ENCRYPTION_KEY": "changeme-32-char-encryption-key",
"APPSERVER_LOG_LEVEL": "debug"
}
}
]
}

Press F5 to start debugging.

Attach Debugger (GoLand)

  1. Go to Run → Edit Configurations
  2. Add Go Build
  3. Set:
    • Run kind: File
    • Files: cmd/appserver-v2/main.go
    • Program arguments: (leave empty for v2)
    • Environment: Add required env vars (including APPSERVER_SETTINGS_ENCRYPTION_KEY)
  4. Click Debug

Debug with Delve

# Install delve
go install github.com/go-delve/delve/cmd/dlv@latest

# Start appserver with debugger (v2 needs no arguments)
dlv debug cmd/appserver-v2/main.go

# Or use legacy CLI with serve subcommand
dlv debug cmd/app/main.go -- serve

View Application Logs

# AppServer logs (if running via make run)
# Logs appear in terminal

# View with log levels
export APPSERVER_LOG_LEVEL=debug
make run

# View infrastructure logs
make docker-logs

# View specific service
docker-compose -f docker/docker-compose.yml logs -f kratos

Distributed Tracing

View traces in Grafana:

  1. Open http://localhost:3000
  2. Login: admin/admin
  3. Go to ExploreTempo
  4. Search by:
    • Service name: appserver
    • Trace ID
    • Tags (e.g., http.method=POST)

Log Aggregation

View logs in Grafana:

  1. Open http://localhost:3000
  2. Go to ExploreLoki
  3. Query examples:
# All appserver logs
{service_name="appserver"}

# Error logs only
{service_name="appserver"} |= "error"

# Logs for specific trace
{service_name="appserver"} | json | trace_id="abc123"

Hot Reload

Air - Live Reload for Go

Install Air:

go install github.com/cosmtrek/air@latest

Create .air.toml in project root:

root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
args_bin = ["serve"]
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ./cmd/appserver-v2"
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata", "web"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
kill_delay = "0s"
log = "build-errors.log"
send_interrupt = false
stop_on_error = true

[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"

[log]
time = false

[misc]
clean_on_exit = false

Run with hot reload:

air

Reflex - Alternative

# Install reflex
go install github.com/cespare/reflex@latest

# Run with reflex
reflex -r '\.go$' -s -- sh -c 'go run cmd/appserver-v2/main.go serve'

IDE Setup

VS Code

Install these extensions:

  • Go (golang.go) - Official Go extension
  • Docker (ms-azuretools.vscode-docker)
  • PostgreSQL (ckolkman.vscode-postgres)
  • GraphQL (graphql.vscode-graphql)
  • REST Client (humao.rest-client)
  • YAML (redhat.vscode-yaml)
  • Proto 3 (zxh404.vscode-proto3)

Workspace Settings

Create .vscode/settings.json:

{
"go.testFlags": ["-v"],
"go.testTimeout": "60s",
"go.coverOnSave": false,
"go.lintTool": "golangci-lint",
"go.lintOnSave": "workspace",
"go.buildOnSave": "off",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"files.exclude": {
"**/.git": true,
"**/node_modules": true,
"**/bin": true,
"**/tmp": true
}
}

Tasks

Create .vscode/tasks.json:

{
"version": "2.0.0",
"tasks": [
{
"label": "Start Infrastructure",
"type": "shell",
"command": "make docker-up",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "new"
}
},
{
"label": "Run AppServer",
"type": "shell",
"command": "make run",
"group": "build",
"dependsOn": ["Start Infrastructure"]
}
]
}

GoLand / IntelliJ IDEA

Enable Go Modules

  1. Go to Settings → Go → Go Modules
  2. Enable Enable Go modules integration
  3. Set Proxy: https://proxy.golang.org,direct

Database Tools

  1. Open Database tool window
  2. Add PostgreSQL data source:
    • Host: localhost
    • Port: 5432
    • Database: appserver
    • User: partner
    • Password: changeme-in-production

Docker Integration

  1. Open Services tool window
  2. Add Docker Compose:
    • Path: docker/docker-compose.yml

Run Configurations

Create run configurations for:

  • AppServer: cmd/appserver-v2/main.go serve
  • Tests: All packages with coverage
  • Docker Compose: Start infrastructure

SDK Development

Node.js SDK

Located in web/v2/packages/appserver-sdk/

Setup

cd web/v2/packages/appserver-sdk

# Install dependencies
pnpm install

# Build
pnpm build

# Run tests
pnpm test

# Type check
pnpm type-check

Watch Mode

# Watch for changes and rebuild
pnpm build:watch

Frontend SDK

Located in web/v2/packages/appserver-frontend-sdk/

cd web/v2/packages/appserver-frontend-sdk

pnpm install
pnpm build
pnpm test
# In SDK directory
cd web/v2/packages/appserver-sdk
pnpm link

# In your app
cd /path/to/your-app
pnpm link @easy/appserver-sdk

Testing Strategies

Unit Tests

# Run all tests
go test ./...

# Test specific package
go test ./pkg/v2/marketplace

# Run with coverage
go test ./... -cover

# Generate coverage report
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.out

Integration Tests

# With docker-compose infrastructure
make docker-test

# Or manually
USE_DOCKER_COMPOSE=true go test ./pkg/v2/integration/...

E2E Tests

Located in web/v2/packages/appserver-sdk/test/e2e/:

# Run E2E tests (Node.js/TypeScript)
cd web/v2/packages/appserver-sdk
pnpm test:e2e

Test Docker Orchestrator

# Build orchestrator
go build -o bin/orchestrator cmd/orchestrator/main.go

# Run with test config
./bin/orchestrator --config test/orchestrator-test.yml

Performance Profiling

CPU Profiling

# Run with CPU profiling
go test -cpuprofile=cpu.prof ./pkg/v2/marketplace

# Analyze profile
go tool pprof cpu.prof

Memory Profiling

# Run with memory profiling
go test -memprofile=mem.prof ./pkg/v2/marketplace

# Analyze profile
go tool pprof mem.prof

Live Profiling

Enable pprof endpoint:

import _ "net/http/pprof"

go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()

Access profiles:

Common Issues & Solutions

Port Already in Use

# Find process using port
lsof -i :8080

# Kill process
kill -9 <PID>

Docker Containers Won't Start

# Clean everything and restart
make docker-clean
make docker-up

# Check logs for errors
make docker-logs

Go Module Issues

# Clean module cache
go clean -modcache

# Re-download modules
go mod download

# Verify modules
go mod verify

# Tidy modules
go mod tidy

Database Connection Errors

# Test PostgreSQL connection
docker exec appserver-postgres pg_isready -U partner

# Check if database exists
docker exec appserver-postgres psql -U partner -c "\l"

# Restart database
docker-compose -f docker/docker-compose.yml restart postgres

gRPC Reflection Not Working

# Ensure reflection is enabled
export APPSERVER_GRPC_REFLECTION_ENABLED=true

# Restart appserver
make run

Best Practices

Code Organization

  • Keep business logic in pkg/v2/
  • Put commands in cmd/
  • Store migrations in pkg/v2/migrations/
  • Write tests alongside code (*_test.go)

Git Workflow

# Create feature branch
git checkout -b feature/my-feature

# Make changes and commit
git add .
git commit -m "feat: add new feature"

# Push to remote
git push origin feature/my-feature

# Create pull request

Environment Variables

Use .env file for local development:

# Create .env file
cp docker/.env.example .env

# Load env vars
export $(cat .env | xargs)

Logging

Use structured logging:

log.Info().
Str("app_id", appID).
Str("state", state).
Msg("App state changed")

Additional Resources