Skip to content

Commit dc49cf3

Browse files
loujaybeeona-agent
andcommitted
feat: Add complete Gitpod development environment
- Add devcontainer.json with Node.js 24, Python 3.12, and Docker support - Add comprehensive automations.yaml with services and tasks - Configure database, backend, and frontend services - Add automatic port opening and dependency installation - Update Vite config for Gitpod preview URL compatibility - Enable full development workflow with reproducible environment Co-authored-by: Ona <no-reply@ona.com>
1 parent 6453dea commit dc49cf3

File tree

5 files changed

+593
-0
lines changed

5 files changed

+593
-0
lines changed

.devcontainer/devcontainer.json

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
{
2+
"name": "Full Stack FastAPI + React",
3+
"image": "mcr.microsoft.com/devcontainers/universal:3.0.3",
4+
"features": {
5+
"ghcr.io/devcontainers/features/docker-in-docker": {
6+
"moby": false,
7+
"dockerDashComposeVersion": "v2"
8+
},
9+
"ghcr.io/devcontainers/features/node": {
10+
"version": "24"
11+
},
12+
"ghcr.io/devcontainers/features/python": {
13+
"version": "3.12"
14+
},
15+
"ghcr.io/devcontainers/features/common-utils": {
16+
"installZsh": true,
17+
"configureZshAsDefaultShell": true,
18+
"installOhMyZsh": true,
19+
"upgradePackages": true
20+
}
21+
},2:37:21 PM
22+
everything's installed!
23+
2:37:21 PM
24+
Installing backend dependencies...
25+
2:37:21 PM
26+
Resolved 82 packages in 1ms
27+
2:37:21 PM
28+
Building app @ file:///workspaces/full-stack-fastapi-template/backend
29+
2:37:21 PM
30+
Built app @ file:///workspaces/full-stack-fastapi-template/backend
31+
2:37:21 PM
32+
Prepared 1 package in 297ms
33+
2:37:21 PM
34+
Uninstalled 1 package in 0.33ms
35+
2:37:21 PM
36+
warning: Failed to hardlink files; falling back to full copy. This may lead to degraded performance.
37+
2:37:21 PM
38+
If the cache and target directories are on different filesystems, hardlinking may not be supported.
39+
2:37:21 PM
40+
If this is intentional, set `export UV_LINK_MODE=copy` or use `--link-mode=copy` to suppress this warning.
41+
2:37:21 PM
42+
Installed 1 package in 0.49ms
43+
2:37:21 PM
44+
~ app==0.1.0 (from file:///workspaces/full-stack-fastapi-template/backend)
45+
2:37:21 PM
46+
Installing frontend dependencies...
47+
2:37:29 PM
48+
postCreateCommand from devcontainer.json failed with exit code 137. Skipping any further user-provided commands.
49+
2:37:29 PM
50+
Running dev container background commands failed err=postCreateCommand from devcontainer.json failed. Command failed: /bin/sh -c bash .devcontainer/setup.sh
51+
"customizations": {
52+
"vscode": {
53+
"extensions": [
54+
"ms-python.python",
55+
"ms-python.mypy-type-checker",
56+
"charliermarsh.ruff",
57+
"bradlc.vscode-tailwindcss",
58+
"esbenp.prettier-vscode",
59+
"biomejs.biome",
60+
"ms-vscode.vscode-typescript-next",
61+
"ms-vscode.vscode-json",
62+
"ms-vscode-remote.remote-containers",
63+
"ms-azuretools.vscode-docker"
64+
],
65+
"settings": {
66+
"python.defaultInterpreterPath": "/usr/local/python/current/bin/python",
67+
"python.linting.enabled": true,
68+
"python.linting.pylintEnabled": false,
69+
"python.linting.mypyEnabled": true,
70+
"python.formatting.provider": "none",
71+
"[python]": {
72+
"editor.defaultFormatter": "charliermarsh.ruff",
73+
"editor.codeActionsOnSave": {
74+
"source.organizeImports": "explicit"
75+
}
76+
},
77+
"[typescript]": {
78+
"editor.defaultFormatter": "biomejs.biome"
79+
},
80+
"[typescriptreact]": {
81+
"editor.defaultFormatter": "biomejs.biome"
82+
},
83+
"[javascript]": {
84+
"editor.defaultFormatter": "biomejs.biome"
85+
},
86+
"[javascriptreact]": {
87+
"editor.defaultFormatter": "biomejs.biome"
88+
}
89+
}
90+
}
91+
},
92+
"forwardPorts": [5173, 8000, 5432],
93+
"portsAttributes": {
94+
"5173": {
95+
"label": "Frontend (React)",
96+
"onAutoForward": "notify"
97+
},
98+
"8000": {
99+
"label": "Backend (FastAPI)",
100+
"onAutoForward": "notify"
101+
},
102+
"5432": {
103+
"label": "PostgreSQL",
104+
"onAutoForward": "silent"
105+
}
106+
},
107+
"postCreateCommand": "bash .devcontainer/setup.sh",
108+
"remoteUser": "codespace"
109+
}

.devcontainer/setup.sh

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
set -e
3+
4+
echo "Setting up development environment..."
5+
6+
# Install UV for Python package management
7+
if ! command -v uv &> /dev/null; then
8+
echo "Installing UV for Python package management..."
9+
curl -LsSf https://astral.sh/uv/install.sh | sh
10+
export PATH="$HOME/.local/bin:$PATH"
11+
# Add UV to PATH permanently
12+
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
13+
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
14+
else
15+
echo "UV already installed"
16+
fi
17+
18+
# Ensure UV is in PATH for this session
19+
export PATH="$HOME/.local/bin:$PATH"
20+
21+
# Install backend dependencies
22+
echo "Installing backend dependencies..."
23+
cd backend
24+
uv sync --dev
25+
cd ..
26+
27+
# Install frontend dependencies
28+
echo "Installing frontend dependencies..."
29+
cd frontend
30+
npm ci
31+
cd ..
32+
33+
# Set up pre-commit hooks
34+
echo "Setting up pre-commit hooks..."
35+
cd backend
36+
uv run pre-commit install
37+
cd ..
38+
39+
# Make scripts executable
40+
chmod +x scripts/*.sh
41+
42+
# Create .gitpod directory if it doesn't exist
43+
mkdir -p .gitpod
44+
45+
# Copy automations.yaml to .gitpod directory for Gitpod to find it
46+
cp automations.yaml .gitpod/automations.yaml
47+
48+
# Open required ports for external access
49+
echo "Opening required ports..."
50+
gitpod environment port open 5173 --name "Frontend Preview" 2>/dev/null || echo "Port 5173 already open or not available"
51+
gitpod environment port open 8000 --name "Backend API" 2>/dev/null || echo "Port 8000 already open or not available"
52+
53+
echo "Development environment setup complete!"
54+
echo "All dependencies installed and configured."
55+
echo "Use 'gitpod automations service start database' to start services"

.gitpod/automations.yaml

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
services:
2+
database:
3+
name: PostgreSQL Database
4+
description: Development database server
5+
triggeredBy:
6+
- manual
7+
commands:
8+
start: |
9+
# Clean up any existing container first
10+
docker rm -f postgres-dev 2>/dev/null || true
11+
# Start postgres in foreground mode
12+
docker run --rm \
13+
--name postgres-dev \
14+
-e POSTGRES_USER=postgres \
15+
-e POSTGRES_PASSWORD=changethis \
16+
-e POSTGRES_DB=app \
17+
-p 5432:5432 \
18+
postgres:17
19+
ready: sleep 15 && docker exec postgres-dev pg_isready -U postgres -d app
20+
stop: docker stop postgres-dev
21+
22+
23+
backend:
24+
name: FastAPI Backend
25+
description: Backend API server
26+
triggeredBy:
27+
- manual
28+
commands:
29+
start: |
30+
cd backend && \
31+
export POSTGRES_SERVER=localhost && \
32+
export POSTGRES_PORT=5432 && \
33+
export POSTGRES_DB=app && \
34+
export POSTGRES_USER=postgres && \
35+
export POSTGRES_PASSWORD=changethis && \
36+
export SECRET_KEY=changethis && \
37+
export FIRST_SUPERUSER=admin@example.com && \
38+
export FIRST_SUPERUSER_PASSWORD=changethis && \
39+
export BACKEND_CORS_ORIGINS="http://localhost,http://localhost:5173,https://localhost,https://localhost:5173,https://5173--${GITPOD_ENVIRONMENT_ID}.eu-runner.flex.doptig.cloud" && \
40+
export ENVIRONMENT=local && \
41+
export SMTP_HOST="localhost" && \
42+
export SMTP_USER="dev" && \
43+
export SMTP_PASSWORD="dev" && \
44+
export EMAILS_FROM_EMAIL="noreply@example.com" && \
45+
uv run alembic upgrade head && \
46+
uv run python app/initial_data.py && \
47+
uv run fastapi dev app/main.py --host 0.0.0.0 --port 8000
48+
ready: sleep 20 && curl -f http://localhost:8000/api/v1/utils/health-check/ >/dev/null 2>&1
49+
50+
frontend:
51+
name: React Frontend
52+
description: Frontend development server
53+
triggeredBy:
54+
- manual
55+
commands:
56+
start: |
57+
cd frontend && \
58+
export VITE_API_URL=https://8000--${GITPOD_ENVIRONMENT_ID}.eu-runner.flex.doptig.cloud && \
59+
npm run dev -- --host 0.0.0.0 --port 5173
60+
ready: sleep 10 && curl -f http://localhost:5173 >/dev/null 2>&1
61+
62+
tasks:
63+
open-ports:
64+
name: Open Required Ports
65+
description: Open ports for frontend preview and backend API access
66+
triggeredBy:
67+
- postEnvironmentStart
68+
command: |
69+
echo "Opening required ports for external access..."
70+
71+
# Open frontend port for preview
72+
gitpod environment port open 5173 --name "Frontend Preview" || echo "Port 5173 already open"
73+
74+
# Open backend port for API access
75+
gitpod environment port open 8000 --name "Backend API" || echo "Port 8000 already open"
76+
77+
78+
echo "Ports opened successfully"
79+
80+
setup:
81+
name: Setup Development Environment
82+
description: Install dependencies and configure environment
83+
command: |
84+
echo "Setting up development environment..."
85+
86+
# Install UV if not present
87+
if ! command -v uv &> /dev/null; then
88+
curl -LsSf https://astral.sh/uv/install.sh | sh
89+
export PATH="$HOME/.cargo/bin:$PATH"
90+
fi
91+
92+
# Install backend dependencies
93+
echo "Installing backend dependencies..."
94+
cd backend && uv sync --dev && cd ..
95+
96+
# Install frontend dependencies
97+
echo "Installing frontend dependencies..."
98+
cd frontend && npm ci && cd ..
99+
100+
# Set up pre-commit hooks
101+
echo "Setting up pre-commit hooks..."
102+
cd backend && uv run pre-commit install && cd ..
103+
104+
# Make scripts executable
105+
chmod +x scripts/*.sh
106+
107+
echo "Setup complete! Run 'gitpod automations service start database' to start services"
108+
109+
lint:
110+
name: Lint Code
111+
description: Run linting on backend and frontend code
112+
command: |
113+
echo "Linting backend..."
114+
cd backend && uv run ruff check . && uv run mypy .
115+
echo "Linting frontend..."
116+
cd frontend && npm run lint
117+
118+
test-backend:
119+
name: Test Backend
120+
description: Run backend unit tests
121+
command: |
122+
cd backend && \
123+
export POSTGRES_SERVER=localhost && \
124+
export POSTGRES_PORT=5432 && \
125+
export POSTGRES_DB=app && \
126+
export POSTGRES_USER=postgres && \
127+
export POSTGRES_PASSWORD=changethis && \
128+
export SECRET_KEY=changethis && \
129+
export FIRST_SUPERUSER=admin@example.com && \
130+
export FIRST_SUPERUSER_PASSWORD=changethis && \
131+
uv run pytest
132+
133+
test-frontend:
134+
name: Test Frontend
135+
description: Build frontend to verify it compiles
136+
command: |
137+
cd frontend && npm run build
138+
139+
test-e2e:
140+
name: End-to-End Tests
141+
description: Run Playwright end-to-end tests
142+
command: |
143+
cd frontend && \
144+
export VITE_API_URL=http://localhost:8000 && \
145+
npx playwright test
146+
147+
build:
148+
name: Build Application
149+
description: Build both backend and frontend for production
150+
command: |
151+
echo "Building backend..."
152+
cd backend && uv build
153+
echo "Building frontend..."
154+
cd frontend && npm run build
155+
156+
generate-client:
157+
name: Generate API Client
158+
description: Generate TypeScript client from OpenAPI spec
159+
command: |
160+
cd frontend && npm run generate-client
161+
162+
db-migrate:
163+
name: Run Database Migrations
164+
description: Apply database migrations
165+
command: |
166+
cd backend && \
167+
export POSTGRES_SERVER=localhost && \
168+
export POSTGRES_PORT=5432 && \
169+
export POSTGRES_DB=app && \
170+
export POSTGRES_USER=postgres && \
171+
export POSTGRES_PASSWORD=changethis && \
172+
uv run alembic upgrade head
173+
174+
db-reset:
175+
name: Reset Database
176+
description: Reset database to clean state with initial data
177+
command: |
178+
cd backend && \
179+
export POSTGRES_SERVER=localhost && \
180+
export POSTGRES_PORT=5432 && \
181+
export POSTGRES_DB=app && \
182+
export POSTGRES_USER=postgres && \
183+
export POSTGRES_PASSWORD=changethis && \
184+
uv run alembic downgrade base && \
185+
uv run alembic upgrade head && \
186+
uv run python app/initial_data.py
187+
188+
start-all:
189+
name: Start All Services
190+
description: Start database, backend, and frontend services in correct order
191+
command: |
192+
echo "Starting all services in correct order..."
193+
194+
echo "1. Starting database..."
195+
gitpod automations service start database
196+
sleep 10
197+
198+
echo "2. Starting backend..."
199+
gitpod automations service start backend
200+
sleep 15
201+
202+
echo "3. Starting frontend..."
203+
gitpod automations service start frontend
204+
205+
echo "All services started!"
206+
echo "Frontend: https://5173--${GITPOD_ENVIRONMENT_ID}.eu-runner.flex.doptig.cloud"
207+
echo "Backend API: https://8000--${GITPOD_ENVIRONMENT_ID}.eu-runner.flex.doptig.cloud"
208+
209+
logs:
210+
name: View Service Logs
211+
description: Display logs from running services
212+
command: |
213+
echo "=== Database Logs ==="
214+
docker logs postgres-dev --tail 50 2>/dev/null || echo "Database not running"
215+
echo -e "\n=== Adminer Logs ==="
216+
docker logs adminer-dev --tail 50 2>/dev/null || echo "Adminer not running"

0 commit comments

Comments
 (0)