Skip to content

Commit 2ce06fc

Browse files
authored
fix: #118 (#120)
* using toml lib+configs instead of dotenv stuff * feat: secrets.toml is used * chore: docs update - toml stuff added
1 parent 5105ada commit 2ce06fc

39 files changed

Lines changed: 400 additions & 333 deletions

.github/workflows/docs.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ jobs:
4242
- name: Install backend dependencies
4343
run: cd backend && uv sync --frozen
4444

45+
- name: Set up config for OpenAPI generation
46+
run: cp backend/secrets.example.toml backend/secrets.toml
47+
4548
- name: Generate OpenAPI spec
4649
run: ./deploy.sh openapi
4750

.github/workflows/stack-tests.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ jobs:
4848
uv python install 3.12
4949
uv sync --frozen
5050
51+
- name: Set up config
52+
run: cp backend/secrets.example.toml backend/secrets.toml
53+
5154
- name: Run unit tests
5255
timeout-minutes: 5
5356
run: |
@@ -211,7 +214,9 @@ jobs:
211214
uses: ./.github/actions/k3s-setup
212215

213216
- name: Use test environment config
214-
run: cp backend/.env.test backend/.env
217+
run: |
218+
cp backend/config.test.toml backend/config.toml
219+
cp backend/secrets.example.toml backend/secrets.toml
215220
216221
- name: Start stack
217222
run: ./deploy.sh dev --wait
@@ -322,7 +327,9 @@ jobs:
322327
uses: ./.github/actions/k3s-setup
323328

324329
- name: Use test environment config
325-
run: cp backend/.env.test backend/.env
330+
run: |
331+
cp backend/config.test.toml backend/config.toml
332+
cp backend/secrets.example.toml backend/secrets.toml
326333
327334
- name: Start stack
328335
run: ./deploy.sh dev --wait

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ dmypy.json
6464
.env.*.local
6565
*.local.env
6666

67+
# TOML secrets (dev values — production mounts from K8s Secret)
68+
secrets.toml
69+
6770
# Certificates (generated locally)
6871
certs/
6972
*.pem

backend/.env

Lines changed: 0 additions & 84 deletions
This file was deleted.

backend/.env.test

Lines changed: 0 additions & 82 deletions
This file was deleted.

backend/Dockerfile

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ FROM base
55
COPY ./app /app/app
66
COPY ./workers /app/workers
77
COPY ./scripts /app/scripts
8-
COPY .env /app/.env
8+
COPY config.toml /app/config.toml
99
COPY openssl.cnf /app/openssl.cnf
1010

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

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

3029
exec gunicorn 'app.main:create_app()' \
3130
-k uvicorn.workers.UvicornWorker \
3231
--bind 0.0.0.0:443 \
33-
--workers ${WEB_CONCURRENCY:-4} \
34-
--threads ${WEB_THREADS:-1} \
35-
--timeout ${WEB_TIMEOUT:-60} \
32+
--workers 4 \
33+
--threads 4 \
34+
--timeout 60 \
3635
--graceful-timeout 30 \
3736
--keep-alive 2 \
38-
--backlog ${WEB_BACKLOG:-2048} \
37+
--backlog 2048 \
3938
--log-level info \
4039
--access-logfile - \
4140
--error-logfile - \

backend/Dockerfile.base

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ RUN uv sync --locked --no-dev --no-install-project
2424
# Set paths: PYTHONPATH for imports, PATH for venv binaries (no uv run needed at runtime)
2525
ENV PYTHONPATH=/app
2626
ENV PATH="/app/.venv/bin:$PATH"
27+
ENV KUBECONFIG=/app/kubeconfig.yaml

backend/app/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def create_app(settings: Settings | None = None) -> FastAPI:
4848
4949
Args:
5050
settings: Optional pre-configured settings (e.g., TestSettings for testing).
51-
If None, creates Settings() which reads from env vars then .env file.
51+
If None, loads from config.toml.
5252
"""
5353
settings = settings or Settings()
5454
logger = setup_logger(settings.LOG_LEVEL)

backend/app/settings.py

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,53 @@
1+
import tomllib
2+
from pathlib import Path
13
from typing import Literal
24

3-
from pydantic import Field
4-
from pydantic_settings import BaseSettings, SettingsConfigDict
5+
from pydantic import BaseModel, ConfigDict, Field
56

67
from app.domain.execution import LanguageInfoDomain
78
from app.runtime_registry import EXAMPLE_SCRIPTS as EXEC_EXAMPLE_SCRIPTS
89
from app.runtime_registry import SUPPORTED_RUNTIMES as RUNTIME_MATRIX
910

1011

11-
class Settings(BaseSettings):
12+
class Settings(BaseModel):
13+
"""Application settings loaded from TOML configuration files.
14+
15+
All config is read from TOML — no environment variables, no .env files.
16+
17+
Load order (each layer overrides the previous):
18+
1. config_path — base settings (committed to git)
19+
2. secrets_path — sensitive overrides (gitignored, mounted from K8s Secret in prod)
20+
3. override_path — per-worker service overrides (TRACING_SERVICE_NAME, etc.)
21+
22+
Usage:
23+
Settings() # config.toml + secrets
24+
Settings(config_path="config.test.toml") # test config (has own secrets)
25+
Settings(override_path="config.coordinator.toml") # base + secrets + worker
26+
"""
27+
28+
model_config = ConfigDict(extra="forbid")
29+
30+
def __init__(
31+
self,
32+
config_path: str = "config.toml",
33+
override_path: str | None = None,
34+
secrets_path: str = "secrets.toml",
35+
) -> None:
36+
with open(config_path, "rb") as f:
37+
data = tomllib.load(f)
38+
if Path(secrets_path).is_file():
39+
with open(secrets_path, "rb") as f:
40+
data |= tomllib.load(f)
41+
if override_path:
42+
with open(override_path, "rb") as f:
43+
data |= tomllib.load(f)
44+
super().__init__(**data)
45+
1246
PROJECT_NAME: str = "integr8scode"
1347
DATABASE_NAME: str = "integr8scode_db"
1448
API_V1_STR: str = "/api/v1"
1549
SECRET_KEY: str = Field(
16-
..., # Actual key be loaded from .env file
50+
...,
1751
min_length=32,
1852
description="Secret key for JWT token signing. Must be at least 32 characters.",
1953
)
@@ -145,27 +179,14 @@ class Settings(BaseSettings):
145179
OTEL_RESOURCE_ATTRIBUTES: str | None = None
146180

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

155-
# Additional MongoDB settings (for docker-compose compatibility)
156-
MONGO_ROOT_USER: str | None = None
157-
MONGO_ROOT_PASSWORD: str | None = None
158-
159187
# Development mode detection
160188
DEVELOPMENT_MODE: bool = False
161-
SECURE_COOKIES: bool = True # Can be overridden in .env for development
189+
SECURE_COOKIES: bool = True
162190

163191
# Logging configuration
164192
LOG_LEVEL: str = Field(default="DEBUG", description="Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)")
165-
166-
model_config = SettingsConfigDict(
167-
env_file=".env",
168-
env_file_encoding="utf-8",
169-
case_sensitive=True,
170-
extra="forbid", # Raise error on extra fields
171-
)

backend/config.coordinator.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
TRACING_SERVICE_NAME = "execution-coordinator"
2+
KAFKA_CONSUMER_GROUP_ID = "execution-coordinator"

0 commit comments

Comments
 (0)