Getting Started
Development Environment Setup

Development Environment Setup

This guide covers setting up a local development environment for contributing to the OEC.sh platform. Follow these steps to get a fully functional development environment running on your machine.


Overview

OEC.sh uses a modern development stack:

ComponentTechnologyDevelopment Mode
BackendFastAPI (Python 3.11)Docker Compose
FrontendNext.js 14 + TailAdminnpm run dev (hot reload)
DatabasePostgreSQL 15Docker container
CacheRedis 7Docker container
Task QueueARQDocker container (Worker)

Quick Start

Get up and running in under 5 minutes:

# 1. Clone the repository
git clone <repository-url>
cd 87-oecsh-pln
 
# 2. Setup virtual environment and install dependencies
make setup && source venv/bin/activate
 
# 3. Start backend services (database, redis, backend, worker)
docker compose -f docker-compose.prod.yml build backend
docker compose -f docker-compose.prod.yml up -d backend
 
# 4. Run database migrations
cd backend && alembic upgrade head && cd ..
 
# 5. Start frontend with hot reload
cd frontend && npm run dev

Your development environment is now running:


Prerequisites

Before starting, ensure you have installed:

Required Software

SoftwareVersionInstallation
Python3.11+brew install [email protected] or system package manager
Node.js18+ LTSbrew install node or nodejs.org (opens in a new tab)
Docker24.0+docker.com/get-docker (opens in a new tab)
Docker Compose2.0+Included with Docker Desktop
MakeAnyUsually pre-installed on Linux/macOS
Git2.0+Pre-installed on most systems

Verify Installation

# Check versions
python3 --version    # Python 3.11.x
node --version       # v18.x.x or higher
docker --version     # Docker version 24.x.x
docker compose version  # Docker Compose version v2.x.x
make --version       # GNU Make 4.x
git --version        # git version 2.x.x

Step 1: Initial Setup

Clone Repository

git clone <repository-url>
cd 87-oecsh-pln

Setup Virtual Environment

The make setup command handles Python virtual environment creation and dependency installation:

make setup

This command:

  1. Creates a Python virtual environment in ./venv
  2. Installs backend dependencies from requirements.txt
  3. Installs development dependencies

Activate Virtual Environment

Important: Always activate the virtual environment before working on the backend:

source venv/bin/activate

You should see (venv) prefix in your terminal prompt.

Critical Rule: NEVER use system Python. Always work within the virtual environment.


Step 2: Environment Configuration

Environment File

OEC.sh uses .env.production for configuration. This file contains all environment variables for local development and production.

# Copy example if needed
cp .env.example .env.production

Key Environment Variables

# Database
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/oecsh
 
# Redis
REDIS_URL=redis://localhost:6379
 
# JWT Secret (generate a secure random string)
JWT_SECRET_KEY=your-secret-key-here
 
# Frontend URL
FRONTEND_URL=http://localhost:3000
 
# API URL
API_URL=http://localhost:8000

Note: We are using .env.production for the current development work.


Step 3: Backend Development

Start Backend Services

The backend runs in Docker containers. Use Docker Compose to start all required services:

# Build backend image
docker compose -f docker-compose.prod.yml build backend
 
# Start backend and dependencies (postgres, redis, worker)
docker compose -f docker-compose.prod.yml up -d backend

This starts:

  • PostgreSQL 15: Database on port 5432
  • Redis 7: Cache/queue on port 6379
  • Backend: FastAPI on port 8000
  • Worker: ARQ background task processor

Verify Backend is Running

# Check container status
docker compose -f docker-compose.prod.yml ps
 
# View backend logs
docker compose -f docker-compose.prod.yml logs -f backend
 
# Test API endpoint
curl http://localhost:8000/api/v1/health

Rebuild Backend After Code Changes

docker compose -f docker-compose.prod.yml build backend && \
docker compose -f docker-compose.prod.yml up -d backend

Important: After making backend code changes, you must rebuild and restart the container.


Step 4: Database Migrations

Run Migrations

Always run migrations before testing new database models:

cd backend && alembic upgrade head

Create New Migration

When you modify database models:

cd backend
alembic revision --autogenerate -m "Description of changes"

Migration Best Practices

  1. Revision IDs: Must be 32 characters or less (alembic_version column limit)
  2. Column names: Check column names exist before referencing in migrations
  3. Field naming: Use create_date (NOT created_at) for project_environments table
  4. Chain migrations: Set down_revision to previous migration ID

Step 5: Frontend Development

Install Dependencies

cd frontend
npm install

Start Development Server

cd frontend && npm run dev

This starts the Next.js development server with hot reload:

Critical Rule: NEVER rebuild Docker for frontend changes. Always use npm run dev for development.

Frontend Development Workflow

  1. Edit frontend code in frontend/src/
  2. Changes automatically reflect in browser (hot reload)
  3. No restart or rebuild needed

Step 6: Running Tests

Backend Tests

Run the full test suite:

cd backend && pytest tests/ -v

Run Specific Tests

# Run a specific test file
cd backend && pytest tests/test_environments.py -v
 
# Run tests matching a pattern
cd backend && pytest tests/ -k "test_create" -v
 
# Run with coverage
cd backend && pytest tests/ --cov=app --cov-report=html

RBAC Security Tests

After any access rights changes, verify the RBAC matrix:

cd backend && pytest tests/security/test_rbac_matrix.py -v

RBAC Test Users

For testing role-based access control, use these pre-configured test users:

Seed Test Users

Run the seed script to create test users:

docker exec oecsh-backend python /app/scripts/seed_test_users.py

Test Credentials

All test users belong to organization: rbac-test-org

EmailRolePassword
[email protected]OwnerTestUser123!
[email protected]AdminTestUser123!
[email protected]DeveloperTestUser123!
[email protected]ViewerTestUser123!

Admin User

For full platform access:

EmailPassword
[email protected]Admin123

Common Commands Reference

Quick Reference

# Setup
make setup && source venv/bin/activate
 
# Frontend (hot reload - use this for development)
cd frontend && npm run dev
 
# Backend (rebuild after changes)
docker compose -f docker-compose.prod.yml build backend && \
docker compose -f docker-compose.prod.yml up -d backend
 
# Database migrations
cd backend && alembic upgrade head
 
# Run tests
cd backend && pytest tests/ -v
 
# View logs
docker compose -f docker-compose.prod.yml logs -f backend
docker compose -f docker-compose.prod.yml logs -f worker
 
# Seed test users
docker exec oecsh-backend python /app/scripts/seed_test_users.py

Docker Commands

# Start all services
docker compose -f docker-compose.prod.yml up -d
 
# Stop all services
docker compose -f docker-compose.prod.yml down
 
# Restart a specific service
docker compose -f docker-compose.prod.yml restart backend
 
# View running containers
docker compose -f docker-compose.prod.yml ps
 
# Follow logs
docker compose -f docker-compose.prod.yml logs -f backend worker
 
# Execute command in container
docker exec -it oecsh-backend bash

Development Workflow

Typical Development Session

# 1. Start your session
source venv/bin/activate
 
# 2. Start backend services (if not running)
docker compose -f docker-compose.prod.yml up -d backend
 
# 3. Start frontend with hot reload
cd frontend && npm run dev
 
# 4. Make changes to code
# - Frontend changes: instant hot reload
# - Backend changes: rebuild required
 
# 5. Run tests before committing
cd backend && pytest tests/ -v
 
# 6. Commit when ready
git add -A && git commit -m "Description of changes"

Backend Code Changes

When you modify backend code:

# Rebuild and restart backend
docker compose -f docker-compose.prod.yml build backend && \
docker compose -f docker-compose.prod.yml up -d backend

Database Model Changes

When you modify SQLAlchemy models:

# 1. Create migration
cd backend && alembic revision --autogenerate -m "Add new field"
 
# 2. Apply migration
alembic upgrade head
 
# 3. Rebuild backend
docker compose -f docker-compose.prod.yml build backend && \
docker compose -f docker-compose.prod.yml up -d backend

Troubleshooting

Virtual Environment Issues

Problem: ModuleNotFoundError or wrong Python version

Solution:

# Deactivate current venv
deactivate
 
# Remove old venv
rm -rf venv
 
# Recreate
make setup && source venv/bin/activate

Database Connection Failed

Problem: Cannot connect to PostgreSQL

Solution:

# Check if postgres container is running
docker compose -f docker-compose.prod.yml ps postgres
 
# Restart postgres
docker compose -f docker-compose.prod.yml restart postgres
 
# Check postgres logs
docker compose -f docker-compose.prod.yml logs postgres

Port Already in Use

Problem: Port 3000 or 8000 already in use

Solution:

# Find process using port
lsof -i :3000
lsof -i :8000
 
# Kill process
kill -9 <PID>

Frontend Build Errors

Problem: npm install fails or build errors

Solution:

cd frontend
 
# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install
 
# Clear Next.js cache
rm -rf .next
npm run dev

Backend Container Won't Start

Problem: Backend container exits immediately

Solution:

# View error logs
docker compose -f docker-compose.prod.yml logs backend
 
# Common issues:
# - Missing environment variables
# - Database migration needed
# - Port conflict
 
# Fix and rebuild
docker compose -f docker-compose.prod.yml build backend
docker compose -f docker-compose.prod.yml up -d backend

Migration Errors

Problem: Alembic migration fails

Solution:

# Check current migration status
cd backend && alembic current
 
# View migration history
alembic history
 
# If needed, reset to specific revision
alembic downgrade <revision_id>
alembic upgrade head

Code Standards

Logging

Every function must include logging:

import logging
 
logger = logging.getLogger(__name__)
 
async def my_function():
    logger.info("Starting operation", extra={"key": "value"})
    try:
        # ... code
        logger.info("Operation completed successfully")
    except Exception as e:
        logger.error(f"Operation failed: {e}", exc_info=True)
        raise

Enum Rules

Follow the 7 Golden Rules for enums (see backend/docs/ENUM_MEMORY_AND_RULES.md):

  1. Lowercase values: PENDING = "pending"
  2. Model = Schema values identical
  3. Use values_callable in SQLEnum
  4. No hardcoded strings
  5. Cast in migrations: status::text
  6. Check hasattr before .value
  7. Verify PostgreSQL types
# Correct pattern
class Status(enum.Enum):
    PENDING = "pending"
    ACTIVE = "active"
 
status = Column(SQLEnum(Status, values_callable=lambda obj: [e.value for e in obj]))
value = data.status.value if hasattr(data.status, "value") else data.status

Field Mappings

Be aware of field name differences between layers:

DatabaseSchema/API
git_repo_urlrepository_url
git_branchdefault_branch
create_datecreated_at (NOTE: NOT in project_environments table!)

Next Steps

After setting up your development environment:

  1. Read the Architecture Guide - Understand the codebase structure
  2. Review RBAC Documentation - Learn about the permission system
  3. Check Open Issues - Find something to work on
  4. Run Full Test Suite - Ensure everything works before making changes
  5. Review PR Guidelines - Understand the contribution process

Related Documentation


Last Updated: January 2026 Document Version: 1.0 Estimated Reading Time: 15 minutes