From d2380b621af069b8b75e5cedd10db1a3409de72d Mon Sep 17 00:00:00 2001 From: Justin Visser Date: Sun, 9 Aug 2026 20:59:58 +0200 Subject: [PATCH] feat: add single-image compose deliverable and CI --- .env.example | 4 ++++ .github/workflows/ci.yml | 38 ++++++++++++++++++++++++++++++++++++++ backend/Dockerfile | 16 ++++++++++++++++ docker-compose.yml | 12 ++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 .env.example create mode 100644 .github/workflows/ci.yml create mode 100644 backend/Dockerfile create mode 100644 docker-compose.yml diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..999659a --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# Copy to .env and adjust. Without a .env the app starts in demo mode. +# Credential variables get added here as the features that need them land. + +APP_MODE=demo diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ef6a6a1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,38 @@ +name: ci + +on: + push: + branches: [main] + pull_request: + +jobs: + backend: + runs-on: ubuntu-latest + defaults: + run: + working-directory: backend + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v5 + - run: uv sync --frozen + - run: uv run ruff check . + - run: uv run ruff format --check . + - run: uv run mypy app + - run: uv run pytest + + frontend: + runs-on: ubuntu-latest + defaults: + run: + working-directory: frontend + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: frontend/package-lock.json + - run: npm ci + - run: npm run typecheck + - run: npm run lint + - run: npm run build diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..be491c8 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,16 @@ +# Build context is the repository root: one image serves API + built SPA. +FROM node:20-slim AS frontend +WORKDIR /build +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci +COPY frontend/ ./ +RUN npm run build + +FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim +WORKDIR /srv +COPY backend/pyproject.toml backend/uv.lock ./ +RUN uv sync --frozen --no-dev --no-install-project +COPY backend/app ./app +COPY --from=frontend /build/dist ./app/static +EXPOSE 8000 +CMD ["uv", "run", "--no-sync", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1c38478 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +services: + app: + build: + context: . + dockerfile: backend/Dockerfile + env_file: + - path: .env + required: false + ports: + # host port is fixed: the registered Spotify redirect URI + # (http://127.0.0.1:8888/callback) must match exactly + - "127.0.0.1:8888:8000"