Skip to content

release: 0.43.0 - Polish Under Pressure (day-two batch) #106

release: 0.43.0 - Polish Under Pressure (day-two batch)

release: 0.43.0 - Polish Under Pressure (day-two batch) #106

Workflow file for this run

name: PR Tests
on:
pull_request:
paths:
- "src/**"
- "tests/**"
- "alembic/**"
- "alembic.ini"
- "dashboard/**"
- "deploy/cookbooks/**"
- "cf-sandbox-worker/**"
- "Dockerfile"
- "Dockerfile.runner"
- "e2b.Dockerfile"
- "docker-compose*.yml"
- "docker-compose*.yaml"
- ".dockerignore"
- ".env.example"
- "pyproject.toml"
- "uv.lock"
- ".github/workflows/pr-tests.yml"
workflow_dispatch:
concurrency:
group: pr-tests-${{ github.ref }}
cancel-in-progress: true
jobs:
python:
name: Python tests
runs-on: ubuntu-latest
# ~17k tests run in ~13.5 min plus dashboard build and dependency install;
# 20 min leaves headroom over the total setup + run time.
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: dashboard/package-lock.json
- name: Build dashboard (force-included by hatchling)
working-directory: dashboard
run: |
npm ci
npm run build
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
- name: Install package + test extras
run: |
python -m pip install --upgrade pip
pip install -e ".[dev,mcp,memory,otel,parse,report,docker,security]"
- name: Validate Compose files
run: |
python - <<'PY'
from pathlib import Path
import yaml
for name in (
"docker-compose.yml",
"docker-compose.local.yml",
"docker-compose.infra.yml",
"docker-compose.spark.yml",
):
data = yaml.safe_load(Path(name).read_text())
services = data.get("services") or {}
if not services:
raise SystemExit(f"{name} has no services")
print(f"{name}: {', '.join(sorted(services))}")
PY
- name: Run pytest
run: |
python -m pytest tests/ -q --tb=line --timeout=60
docker-build:
name: Docker images + API smoke test
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Build application image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
load: true
tags: sandcastle-ai:ci
cache-from: type=gha,scope=sandcastle-main
cache-to: type=gha,mode=max,scope=sandcastle-main
- name: Build sandbox runner image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile.runner
load: true
tags: sandcastle-runner:ci
cache-from: type=gha,scope=sandcastle-runner
cache-to: type=gha,mode=max,scope=sandcastle-runner
- name: Build E2B sandbox image
uses: docker/build-push-action@v6
with:
context: .
file: e2b.Dockerfile
load: false
tags: sandcastle-e2b:ci
cache-from: type=gha,scope=sandcastle-e2b
cache-to: type=gha,mode=max,scope=sandcastle-e2b
- name: Start local-mode API and wait for health endpoint
run: |
docker run -d --name sandcastle-smoke \
-p 127.0.0.1:18080:8080 \
-e SANDCASTLE_ALLOW_INSECURE_BIND=true \
-e AUTO_UPDATE_CHECK=false \
sandcastle-ai:ci
for attempt in $(seq 1 45); do
if curl --fail --silent --show-error http://127.0.0.1:18080/api/health >/dev/null; then
exit 0
fi
sleep 2
done
docker logs sandcastle-smoke
exit 1
- name: Collect smoke-test logs and clean up
if: always()
run: |
docker logs sandcastle-smoke || true
docker rm --force sandcastle-smoke || true
postgres-migrations:
name: PostgreSQL migrations
runs-on: ubuntu-latest
timeout-minutes: 10
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: sandcastle
POSTGRES_PASSWORD: sandcastle
POSTGRES_DB: sandcastle
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U sandcastle -d sandcastle"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DATABASE_URL: postgresql+asyncpg://sandcastle:sandcastle@localhost:5432/sandcastle
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
- name: Install package
run: |
python -m pip install --upgrade pip
# hatchling force-includes dashboard/dist; an empty dir satisfies it
# without pulling the whole Node toolchain into this job.
mkdir -p dashboard/dist
pip install -e ".[dev]"
- name: Apply migrations (customer CLI path)
run: python -m sandcastle db migrate
- name: Re-run migrations (container restart scenario)
run: python -m sandcastle db migrate
- name: Check migration metadata drift
run: python -m alembic check
- name: Smoke PostgreSQL enum persistence
run: |
POSTGRES_MIGRATIONS_DATABASE_URL="$DATABASE_URL" \
python -m pytest tests/test_postgres_enum_smoke.py -q --tb=short --timeout=120
- name: Verify current revision is the migration head
run: |
current_revision="$(python -m alembic current)"
head_revision="$(python -m alembic heads | awk 'NR == 1 { print $1 }')"
printf '%s\n' "$current_revision"
grep -Fq "$head_revision" <<< "$current_revision"
dashboard:
name: Dashboard build + tests
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: dashboard/package-lock.json
- name: Install
working-directory: dashboard
run: npm ci
- name: TypeScript typecheck
working-directory: dashboard
run: npx tsc -b --noEmit
- name: ESLint (advisory - existing baseline has unresolved errors)
working-directory: dashboard
run: npm run lint || echo "::warning::ESLint reported issues; advisory only until baseline cleanup PR lands"
continue-on-error: true
- name: Vitest
working-directory: dashboard
run: npx vitest run
- name: Production build
working-directory: dashboard
run: npm run build
cf-sandbox-worker:
name: Cloudflare Sandbox worker
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: cf-sandbox-worker
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: cf-sandbox-worker/package-lock.json
- name: Install
run: npm ci
- name: TypeScript typecheck
run: npx tsc --noEmit
- name: Validate Wrangler configuration
# The Docker build below validates the image; skipping rollout keeps
# this dry-run account-independent.
run: npx wrangler deploy --dry-run --containers-rollout=none --outdir /tmp/wrangler-dry
- name: Build Sandbox container
run: docker build -t sandcastle-cf-sandbox-test .