Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ jobs:
- name: Install backend dependencies
run: cd backend && uv sync --frozen

- name: Set up config for OpenAPI generation
run: cp backend/secrets.example.toml backend/secrets.toml

- name: Generate OpenAPI spec
run: ./deploy.sh openapi

Expand Down
11 changes: 9 additions & 2 deletions .github/workflows/stack-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ jobs:
uv python install 3.12
uv sync --frozen

- name: Set up config
run: cp backend/secrets.example.toml backend/secrets.toml

- name: Run unit tests
timeout-minutes: 5
run: |
Expand Down Expand Up @@ -211,7 +214,9 @@ jobs:
uses: ./.github/actions/k3s-setup

- name: Use test environment config
run: cp backend/.env.test backend/.env
run: |
cp backend/config.test.toml backend/config.toml
cp backend/secrets.example.toml backend/secrets.toml

- name: Start stack
run: ./deploy.sh dev --wait
Expand Down Expand Up @@ -322,7 +327,9 @@ jobs:
uses: ./.github/actions/k3s-setup

- name: Use test environment config
run: cp backend/.env.test backend/.env
run: |
cp backend/config.test.toml backend/config.toml
cp backend/secrets.example.toml backend/secrets.toml

- name: Start stack
run: ./deploy.sh dev --wait
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ dmypy.json
.env.*.local
*.local.env

# TOML secrets (dev values — production mounts from K8s Secret)
secrets.toml

# Certificates (generated locally)
certs/
*.pem
Expand Down
84 changes: 0 additions & 84 deletions backend/.env

This file was deleted.

82 changes: 0 additions & 82 deletions backend/.env.test

This file was deleted.

11 changes: 5 additions & 6 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ FROM base
COPY ./app /app/app
COPY ./workers /app/workers
COPY ./scripts /app/scripts
COPY .env /app/.env
COPY config.toml /app/config.toml
COPY openssl.cnf /app/openssl.cnf

# Ensure the certs directory exists
Expand All @@ -25,17 +25,16 @@ while [ ! -f /app/certs/server.key ]; do
done

echo "Starting application..."
[ -f /app/kubeconfig.yaml ] && export KUBECONFIG=/app/kubeconfig.yaml

exec gunicorn 'app.main:create_app()' \
-k uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:443 \
--workers ${WEB_CONCURRENCY:-4} \
--threads ${WEB_THREADS:-1} \
--timeout ${WEB_TIMEOUT:-60} \
--workers 4 \
--threads 4 \
--timeout 60 \
--graceful-timeout 30 \
--keep-alive 2 \
--backlog ${WEB_BACKLOG:-2048} \
--backlog 2048 \
--log-level info \
--access-logfile - \
--error-logfile - \
Expand Down
1 change: 1 addition & 0 deletions backend/Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ RUN uv sync --locked --no-dev --no-install-project
# Set paths: PYTHONPATH for imports, PATH for venv binaries (no uv run needed at runtime)
ENV PYTHONPATH=/app
ENV PATH="/app/.venv/bin:$PATH"
ENV KUBECONFIG=/app/kubeconfig.yaml
2 changes: 1 addition & 1 deletion backend/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def create_app(settings: Settings | None = None) -> FastAPI:

Args:
settings: Optional pre-configured settings (e.g., TestSettings for testing).
If None, creates Settings() which reads from env vars then .env file.
If None, loads from config.toml.
"""
settings = settings or Settings()
logger = setup_logger(settings.LOG_LEVEL)
Expand Down
57 changes: 39 additions & 18 deletions backend/app/settings.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,53 @@
import tomllib
from pathlib import Path
from typing import Literal

from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import BaseModel, ConfigDict, Field

from app.domain.execution import LanguageInfoDomain
from app.runtime_registry import EXAMPLE_SCRIPTS as EXEC_EXAMPLE_SCRIPTS
from app.runtime_registry import SUPPORTED_RUNTIMES as RUNTIME_MATRIX


class Settings(BaseSettings):
class Settings(BaseModel):
"""Application settings loaded from TOML configuration files.

All config is read from TOML — no environment variables, no .env files.

Load order (each layer overrides the previous):
1. config_path — base settings (committed to git)
2. secrets_path — sensitive overrides (gitignored, mounted from K8s Secret in prod)
3. override_path — per-worker service overrides (TRACING_SERVICE_NAME, etc.)

Usage:
Settings() # config.toml + secrets
Settings(config_path="config.test.toml") # test config (has own secrets)
Settings(override_path="config.coordinator.toml") # base + secrets + worker
"""

model_config = ConfigDict(extra="forbid")

def __init__(
self,
config_path: str = "config.toml",
override_path: str | None = None,
secrets_path: str = "secrets.toml",
) -> None:
with open(config_path, "rb") as f:
data = tomllib.load(f)
if Path(secrets_path).is_file():
with open(secrets_path, "rb") as f:
data |= tomllib.load(f)
if override_path:
with open(override_path, "rb") as f:
data |= tomllib.load(f)
super().__init__(**data)

PROJECT_NAME: str = "integr8scode"
DATABASE_NAME: str = "integr8scode_db"
API_V1_STR: str = "/api/v1"
SECRET_KEY: str = Field(
..., # Actual key be loaded from .env file
...,
min_length=32,
description="Secret key for JWT token signing. Must be at least 32 characters.",
)
Expand Down Expand Up @@ -145,27 +179,14 @@ class Settings(BaseSettings):
OTEL_RESOURCE_ATTRIBUTES: str | None = None

# Web server (Gunicorn/Uvicorn) concurrency settings
# These are read from environment and used by the runtime entrypoint
# and by app.main when started directly via uvicorn.
WEB_CONCURRENCY: int = 4
WEB_THREADS: int = 1
WEB_TIMEOUT: int = 60
WEB_BACKLOG: int = 2048

# Additional MongoDB settings (for docker-compose compatibility)
MONGO_ROOT_USER: str | None = None
MONGO_ROOT_PASSWORD: str | None = None

# Development mode detection
DEVELOPMENT_MODE: bool = False
SECURE_COOKIES: bool = True # Can be overridden in .env for development
SECURE_COOKIES: bool = True

# Logging configuration
LOG_LEVEL: str = Field(default="DEBUG", description="Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)")

model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=True,
extra="forbid", # Raise error on extra fields
)
2 changes: 2 additions & 0 deletions backend/config.coordinator.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TRACING_SERVICE_NAME = "execution-coordinator"
KAFKA_CONSUMER_GROUP_ID = "execution-coordinator"
2 changes: 2 additions & 0 deletions backend/config.dlq-processor.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TRACING_SERVICE_NAME = "dlq-processor"
KAFKA_CONSUMER_GROUP_ID = "dlq-processor"
2 changes: 2 additions & 0 deletions backend/config.event-replay.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TRACING_SERVICE_NAME = "event-replay"
KAFKA_CONSUMER_GROUP_ID = "event-replay"
2 changes: 2 additions & 0 deletions backend/config.k8s-worker.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TRACING_SERVICE_NAME = "k8s-worker"
KAFKA_CONSUMER_GROUP_ID = "k8s-worker"
2 changes: 2 additions & 0 deletions backend/config.pod-monitor.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TRACING_SERVICE_NAME = "pod-monitor"
KAFKA_CONSUMER_GROUP_ID = "pod-monitor"
2 changes: 2 additions & 0 deletions backend/config.result-processor.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TRACING_SERVICE_NAME = "result-processor"
KAFKA_CONSUMER_GROUP_ID = "result-processor"
2 changes: 2 additions & 0 deletions backend/config.saga-orchestrator.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TRACING_SERVICE_NAME = "saga-orchestrator"
KAFKA_CONSUMER_GROUP_ID = "saga-orchestrator"
Loading
Loading