Skip to content
Open

bump #165

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
8e0e527
feat: separate web and compute job state
totallynotdavid Aug 30, 2026
568960b
api: refactor job persistence, artifact delivery, and testing
totallynotdavid Aug 30, 2026
7df8821
tsdhn: refactor pipeline execution and improve tests
totallynotdavid Aug 30, 2026
191f47f
ci: scope dependency audit, update configuration and dependencies
totallynotdavid Aug 30, 2026
b930045
api: change job persistence and artifact delivery
totallynotdavid Aug 30, 2026
0e25b54
web: split simulations module into focused components
totallynotdavid Aug 30, 2026
79ef017
web: add tests for new simulation modules
totallynotdavid Aug 30, 2026
f312ce4
web: remove obsolete modules replaced by new modules
totallynotdavid Aug 30, 2026
0344581
web: wire up new modules in routes and pages
totallynotdavid Aug 30, 2026
e93c052
web: update configuration and setup for test infrastructure
totallynotdavid Aug 30, 2026
9f484cb
api: refactor repository module for cleaner database queries
totallynotdavid Aug 30, 2026
8968998
api: refactor storage module for artifact handling
totallynotdavid Aug 30, 2026
866f9cd
api: refactor tasks and job state management
totallynotdavid Aug 30, 2026
6bdff24
api: add web grants module for permission management
totallynotdavid Aug 30, 2026
d3e8043
api: update schema and settings for new structure
totallynotdavid Aug 30, 2026
dd5cfa8
api: update routes, schemas, security, and worker
totallynotdavid Aug 30, 2026
8769ecb
api: update migrations and database infrastructure
totallynotdavid Aug 30, 2026
bdb8cba
api: add test infrastructure and update existing tests
totallynotdavid Aug 30, 2026
bd23de1
tsdhn: add comprehensive documentation
totallynotdavid Aug 30, 2026
a7bddff
tsdhn: add comprehensive test coverage
totallynotdavid Aug 30, 2026
1a57a69
tsdhn: update existing tests for new patterns
totallynotdavid Aug 30, 2026
aa7d4be
tsdhn: update implementation for new patterns
totallynotdavid Aug 30, 2026
8231db9
tsdhn: update README with new structure and patterns
totallynotdavid Aug 30, 2026
87d9e27
ci: update CI/CD workflows for new architecture
totallynotdavid Aug 30, 2026
cd335f9
deploy: update Docker and compose configuration
totallynotdavid Aug 30, 2026
317a838
scripts: add integration test and database utilities
totallynotdavid Aug 30, 2026
7f4817b
config: update development environment configuration
totallynotdavid Aug 30, 2026
7a50497
client: regenerate API client from updated OpenAPI schema
totallynotdavid Aug 30, 2026
9eb34a1
docs: add architecture documentation and update READMEs
totallynotdavid Aug 30, 2026
42c219f
deps: update dependency lock files
totallynotdavid Aug 30, 2026
f841d22
fix: restore files deleted during conflict resolution
totallynotdavid Aug 30, 2026
622f92c
fix: restore API core modules from original branch
totallynotdavid Aug 30, 2026
83a43bc
fix: sync all files to match bump branch exactly
totallynotdavid Aug 30, 2026
1e2f65a
fix: regenerate API client and format docs
totallynotdavid Aug 30, 2026
7752928
ci: add PostgreSQL build dependencies for integration tests
totallynotdavid Aug 30, 2026
d8fb1bf
ci: use GitHub PostgreSQL service instead of building from source
totallynotdavid Aug 30, 2026
3fb907b
test: mark infrastructure entry points as no-cover for diff coverage
totallynotdavid Aug 30, 2026
b4967e5
ci: configure PostgreSQL for GitHub Actions
totallynotdavid Aug 30, 2026
4d9f405
Clarify comments and documentation for legibility
totallynotdavid Aug 30, 2026
396a54b
Fix line length in settings.py comment
totallynotdavid Aug 30, 2026
d92f97a
Simplify tsunami warning logic by removing redundant conditions
totallynotdavid Aug 30, 2026
0883f48
Fix implicit string concatenation in SVG element list
totallynotdavid Aug 30, 2026
2f119a4
Remove unused logger import from db module
totallynotdavid Aug 30, 2026
90aef46
Use slicing instead of unpacking unused variable in test
totallynotdavid Aug 30, 2026
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
17 changes: 10 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# Shared secret the SvelteKit BFF uses to call the FastAPI backend.
# openssl rand -hex 32
BACKEND_SERVICE_TOKEN=
# Generate with: openssl rand -hex 32
COMPUTE_API_TOKEN=

# Better Auth session secret for the web app. openssl rand -base64 32
# Generate with: openssl rand -base64 32
BETTER_AUTH_SECRET=

# Public origin of the web app (used by Better Auth + SvelteKit).
ORIGIN=http://localhost:3000

# Optional: comma-separated browser origins allowed to call the API directly.
# Normally empty. The browser talks to the BFF, not FastAPI.
# Leave empty unless a browser calls the API directly.
ALLOWED_ORIGINS=

# Password for the runtime web role. Generate with: openssl rand -hex 32
APP_DB_PASSWORD=

# Browser-reachable MinIO endpoint for output download URLs.
MINIO_PUBLIC_ENDPOINT=localhost:9000
135 changes: 123 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ env:
UV_VERSION: "0.11.27"
PYTHON_VERSION: "3.14"

# Least-privilege by default. Each job opts into what it needs.
permissions: {}

jobs:
Expand Down Expand Up @@ -43,6 +42,8 @@ jobs:
runs-on: ubuntu-latest
env:
TSDHN_MODEL_DIR: ${{ github.workspace }}/model
# Coverage.py cannot trace Numba's compiled kernels.
NUMBA_DISABLE_JIT: "1"
strategy:
fail-fast: false
matrix:
Expand All @@ -57,13 +58,10 @@ jobs:
enable-cache: true
cache-dependency-glob: "uv.lock"

# libgmt is needed by pygmt (a runtime dep of `tsdhn`).
# Install the system lib and create the libgmt.so symlink that
# pygmt expects. The symlink step is idempotent.
- name: Install GMT (libgmt) for pygmt
- name: Install GMT (libgmt) and Ghostscript for pygmt
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends gmt libgmt-dev
sudo apt-get install -y --no-install-recommends gmt libgmt-dev ghostscript
SO=$(ls /usr/lib/**/libgmt.so.* 2>/dev/null | head -n1)
if [ -z "$SO" ]; then
echo "::error::libgmt.so.* not found after apt install"
Expand All @@ -75,7 +73,10 @@ jobs:
- run: uv sync --all-packages --group dev

- name: Run tests with coverage
run: uv run pytest -n auto --maxfail=1 -q --cov=packages --cov-report= --cov-fail-under=0
run: |
uv run pytest -n auto --maxfail=1 -q -m "not integration" \
--cov=packages/tsdhn/tsdhn --cov=packages/api/api \
--cov-report= --cov-fail-under=0

- name: Name coverage data
if: always()
Expand All @@ -94,14 +95,19 @@ jobs:
if-no-files-found: ignore

coverage:
name: Coverage gate
name: Diff coverage gate
runs-on: ubuntu-latest
needs: test
needs: [test, api-integration]
if: always()
permissions:
contents: read
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Fetch master for the diff base
run: git fetch origin master:refs/remotes/origin/master

- uses: astral-sh/setup-uv@6a191366842ac1502ba6c07e9b5acd5c2d9d8db3 # 8.3.2
with:
Expand All @@ -119,13 +125,22 @@ jobs:
pattern: coverage-data-*
merge-multiple: true

- name: Combine coverage and enforce baseline
- name: Combine coverage and report the total
run: |
uv run coverage combine
uv run coverage html --skip-covered --skip-empty
uv run coverage report --format=markdown --fail-under=0 >> "$GITHUB_STEP_SUMMARY"
uv run coverage xml
uv run coverage report --format=markdown >> "$GITHUB_STEP_SUMMARY"
uv run coverage report

- name: Enforce diff coverage on new/changed lines
run: |
uv run diff-cover coverage.xml \
--compare-branch=origin/master \
--markdown-report diff-coverage.md \
--fail-under=80
cat diff-coverage.md >> "$GITHUB_STEP_SUMMARY"

- name: Upload HTML coverage report
if: failure()
uses: actions/upload-artifact@v7
Expand All @@ -150,6 +165,103 @@ jobs:
- run: bun run fmt:check
- run: bun --filter web check

web-test:
name: Web tests (diff coverage gate)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Fetch master for the diff base
run: git fetch origin master:refs/remotes/origin/master

- uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.14"

- uses: astral-sh/setup-uv@6a191366842ac1502ba6c07e9b5acd5c2d9d8db3 # 8.3.2
with:
version: ${{ env.UV_VERSION }}
python-version: ${{ env.PYTHON_VERSION }}
enable-cache: true
cache-dependency-glob: "uv.lock"

- run: bun install --frozen-lockfile
- run: uv sync --group dev --no-install-project

- run: bun --filter web test:coverage

- name: Enforce diff coverage on new/changed lines
run: |
# lcov paths are relative to apps/web; diff-cover runs at the root.
sed -i 's|^SF:|SF:apps/web/|' apps/web/coverage/lcov.info
uv run diff-cover apps/web/coverage/lcov.info \
--compare-branch=origin/master \
--markdown-report diff-coverage-web.md \
--fail-under=80
cat diff-coverage-web.md >> "$GITHUB_STEP_SUMMARY"

api-integration:
name: Persistence integration
runs-on: ubuntu-latest
permissions:
contents: read
services:
postgres:
image: postgres:18
env:
POSTGRES_USER: tsdhn
POSTGRES_PASSWORD: tsdhn
POSTGRES_DB: tsdhn
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v7

- uses: astral-sh/setup-uv@6a191366842ac1502ba6c07e9b5acd5c2d9d8db3 # 8.3.2
with:
version: ${{ env.UV_VERSION }}
python-version: ${{ env.PYTHON_VERSION }}
enable-cache: true
cache-dependency-glob: "uv.lock"

- run: uv sync --all-packages --group dev

- uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.14"

- run: bun install --frozen-lockfile

- name: Run disposable database integration tests
run: bash scripts/integration.sh --coverage
env:
COMPUTE_DATABASE_URL: postgresql://tsdhn:tsdhn@localhost:5432/tsdhn

- name: Name coverage data
if: always()
run: |
if [ -f .coverage ]; then
mv .coverage .coverage.integration
fi

- name: Upload coverage data
if: always()
uses: actions/upload-artifact@v7
with:
name: coverage-data-integration
path: .coverage.integration
include-hidden-files: true
if-no-files-found: ignore

contract:
name: API client contract (no drift)
runs-on: ubuntu-latest
Expand All @@ -165,7 +277,6 @@ jobs:
enable-cache: true
cache-dependency-glob: "uv.lock"

# api.main imports pygmt through tsdhn, which needs libgmt at import time.
- name: Install GMT (libgmt) for pygmt
run: |
sudo apt-get update
Expand Down
83 changes: 83 additions & 0 deletions .github/workflows/crash-recovery.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Crash-recovery e2e

# Run the crash-recovery scenarios against the real Compose stack.
on:
workflow_dispatch:

concurrency:
group: crash-recovery-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions: {}

jobs:
crash-recovery:
name: Crash-recovery e2e (real toolchain)
runs-on: ubuntu-latest
timeout-minutes: 90
permissions:
contents: read
env:
COMPUTE_API_TOKEN: compose-e2e-token
APP_DB_PASSWORD: compose-e2e-app-db-password
BETTER_AUTH_SECRET: compose-e2e-better-auth-secret
ORIGIN: http://localhost:3000
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
MINIO_BUCKET: tsdhn-results
steps:
- uses: actions/checkout@v7

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0

- name: Build toolchain image (cached)
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
file: deploy/toolchain.Dockerfile
tags: localhost/tsdhn-toolchain:crash-recovery-ci
load: true
cache-from: type=gha,scope=toolchain
cache-to: type=gha,mode=max,scope=toolchain

- name: Build api image (cached)
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
file: deploy/api.Dockerfile
build-args: TOOLCHAIN_IMAGE=localhost/tsdhn-toolchain:crash-recovery-ci
tags: localhost/tsdhn-api:crash-recovery-ci
load: true
cache-from: type=gha,scope=api
cache-to: type=gha,mode=max,scope=api

- name: Start compute stack
env:
API_IMAGE: localhost/tsdhn-api:crash-recovery-ci
run: docker compose up -d --no-build postgres minio compute-migrate api worker

- name: Run crash-recovery e2e scenarios
env:
API_IMAGE: localhost/tsdhn-api:crash-recovery-ci
run: bash scripts/e2e/crash_recovery_e2e.sh

- name: Capture compose diagnostics
if: always()
run: |
mkdir -p e2e-artifacts
docker compose ps -a > e2e-artifacts/compose-ps.txt || true
docker compose logs --no-color > e2e-artifacts/compose.log || true
cp -f ./*.json e2e-artifacts/ 2>/dev/null || true

- name: Upload diagnostics
if: always()
uses: actions/upload-artifact@v7
with:
name: crash-recovery-diagnostics
path: e2e-artifacts
if-no-files-found: ignore

- name: Stop stack
if: always()
run: docker compose down -v --remove-orphans
55 changes: 55 additions & 0 deletions .github/workflows/golden.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Golden pipeline regression

# Run the full pipeline regression against the real scientific toolchain.
on:
workflow_dispatch:

concurrency:
group: golden-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions: {}

jobs:
golden:
name: Golden pipeline (real toolchain)
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
steps:
- uses: actions/checkout@v7

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0

- name: Build toolchain image (cached)
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
file: deploy/toolchain.Dockerfile
tags: localhost/tsdhn-toolchain:golden-ci
load: true
cache-from: type=gha,scope=toolchain
cache-to: type=gha,mode=max,scope=toolchain

- name: Build api image (cached)
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
file: deploy/api.Dockerfile
build-args: TOOLCHAIN_IMAGE=localhost/tsdhn-toolchain:golden-ci
tags: localhost/tsdhn-api:golden-ci
load: true
cache-from: type=gha,scope=api
cache-to: type=gha,mode=max,scope=api

- name: Run golden suite against the real toolchain
run: |
docker run --rm \
localhost/tsdhn-api:golden-ci \
sh -c '
set -eu
uv sync --frozen --group dev --all-packages
uv run pytest -m golden -v packages/tsdhn/tests/test_pipeline_golden.py
'
11 changes: 6 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,9 @@ jobs:
env:
API_IMAGE: ghcr.io/${{ github.repository_owner }}/tsdhn-api:candidate-${{ github.run_id }}-${{ github.run_attempt }}
TOOLCHAIN_IMAGE: ghcr.io/${{ github.repository_owner }}/tsdhn-toolchain:candidate-${{ github.run_id }}-${{ github.run_attempt }}
APP_JOB_ID: 4cfe522f-7e7d-46e0-96ca-7b98743fb9f5
BACKEND_SERVICE_TOKEN: compose-e2e-token
SIMULATION_ID: 4cfe522f-7e7d-46e0-96ca-7b98743fb9f5
COMPUTE_API_TOKEN: compose-e2e-token
APP_DB_PASSWORD: compose-e2e-app-db-password
BETTER_AUTH_SECRET: compose-e2e-better-auth-secret
ORIGIN: http://localhost:3000
MINIO_ACCESS_KEY: minioadmin
Expand All @@ -260,11 +261,11 @@ jobs:
- name: Validate compose config
run: docker compose config --quiet

- name: Start backend stack from candidate images
- name: Start compute stack from candidate images
run: docker compose up -d --no-build postgres minio compute-migrate api worker

- name: Run backend smoke test
run: bash scripts/e2e/backend_stack_smoke.sh
- name: Run compute smoke test
run: bash scripts/e2e/compute_stack_smoke.sh

- name: Capture compose diagnostics
if: always()
Expand Down
Loading