From 3f0bb4be736e9ac92b1f7072cf8bdaf534f3fcf9 Mon Sep 17 00:00:00 2001 From: Gabriel Sancho Date: Fri, 27 Mar 2026 16:01:34 -0300 Subject: [PATCH] feat: update Docker configuration and CI/CD workflows for local image builds --- .env.example | 2 +- .gitea/workflows/build.yml | 25 +++++++++++++++++++++++++ .github/agents/infra.agent.md | 10 ++++++---- CLAUDE.md | 13 +++++++------ docker-compose.prod.yml | 10 ++-------- 5 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 .gitea/workflows/build.yml diff --git a/.env.example b/.env.example index b4b88f4..a42c0ff 100644 --- a/.env.example +++ b/.env.example @@ -33,5 +33,5 @@ LLAMA_MODEL=gemma3:4b # ── Application ─────────────────────────────────────────────────────────────── APP_RECIPIENTS=friend1@example.com,friend2@example.com -# ── Frontend (Vite build-time) ──────────────────────────────────────────────── +# ── Frontend (Vite dev proxy) ───────────────────────────────────────────────── VITE_API_BASE_URL=http://localhost diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..ab4e5e5 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,25 @@ +name: Build Production Images + +on: + pull_request_review: + types: [submitted] + +jobs: + build: + name: Build Production Images + if: github.event.review.state == 'approved' && github.event.pull_request.base.ref == 'main' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + github-server-url: http://gitea.lab + ref: ${{ github.event.pull_request.head.sha }} + + - name: Verify Docker CLI + run: docker version + + - name: Build backend image + run: docker build -t condado-newsletter-backend:latest -f backend/Dockerfile ./backend + + - name: Build frontend image + run: docker build -t condado-newsletter-frontend:latest -f frontend/Dockerfile ./frontend \ No newline at end of file diff --git a/.github/agents/infra.agent.md b/.github/agents/infra.agent.md index ebb3f4c..72c05aa 100644 --- a/.github/agents/infra.agent.md +++ b/.github/agents/infra.agent.md @@ -1,6 +1,6 @@ --- name: infra -description: "Use when working on Docker configuration, Docker Compose files, Dockerfiles, Nginx config, Supervisor config, Gitea Actions workflows, CI/CD pipelines, environment variables, or overall project architecture in the condado-news-letter project. Trigger phrases: docker, dockerfile, compose, nginx, ci/cd, gitea actions, build fails, infra, architecture, environment variables, container, supervisor, allinone image." +description: "Use when working on Docker configuration, Docker Compose files, Dockerfiles, Nginx config, Supervisor config, Gitea Actions workflows, CI/CD pipelines, deploy flows, environment variables, or overall project architecture in the condado-news-letter project. Trigger phrases: docker, dockerfile, compose, nginx, ci/cd, gitea actions, deploy, build fails, infra, architecture, environment variables, container, supervisor, allinone image." tools: [read, edit, search, execute, todo] argument-hint: "Describe the infrastructure change or Docker/CI task to implement." --- @@ -22,6 +22,7 @@ You are a senior DevOps / infrastructure engineer and software architect for the | `docker/supervisord.conf` | Supervisor config (manages postgres + java + nginx inside allinone) | | `docker/entrypoint.sh` | Allinone container entrypoint (DB init, env wiring, supervisord start) | | `.gitea/workflows/ci.yml` | CI: backend tests + frontend tests on pull requests to `develop` | +| `.gitea/workflows/build.yml` | Build: create local backend/frontend images on approved PRs to `main` | | `.env.example` | Template for all environment variables | ## System Topology @@ -53,7 +54,7 @@ Docker volume → /var/lib/postgresql/data | Flavour | Command | Notes | |---|---|---| | Dev | `docker compose up --build` | Includes Mailhog on :1025/:8025 | -| Prod (compose) | `docker compose -f docker-compose.prod.yml up --build` | External DB/SMTP | +| Prod (compose) | `docker compose -f docker-compose.prod.yml up -d` | External DB/SMTP using prebuilt local images | | All-in-one | `docker run -p 80:80 -e APP_PASSWORD=... ` | Everything in one container | ## Key Environment Variables @@ -73,15 +74,16 @@ All injected at runtime — never hardcoded in images. | `IMAP_HOST` / `IMAP_PORT` / `IMAP_INBOX_FOLDER` | Backend | IMAP server | | `OPENAI_API_KEY` / `OPENAI_MODEL` | Backend | OpenAI credentials | | `APP_RECIPIENTS` | Backend | Comma-separated recipient emails | -| `VITE_API_BASE_URL` | Frontend (build-time ARG) | Backend API base URL | +| `VITE_API_BASE_URL` | Frontend dev server | Backend API base URL for Vite proxy | ## CI/CD Pipeline | Workflow | Trigger | What it does | |---|---|---| | `ci.yml` | Pull request to `develop` | Backend `./gradlew test` + Frontend `npm run test` | +| `build.yml` | Approved PR review to `main` | Builds `condado-newsletter-backend` and `condado-newsletter-frontend` on the target Docker host | -Legacy publish/version workflows were removed from in-repo automation. +The runner shares the target Docker host, so this workflow produces local images directly on that host. `docker-compose.prod.yml` must reference images and not local build directives. ## Implementation Rules diff --git a/CLAUDE.md b/CLAUDE.md index 3096628..fd8a318 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -83,8 +83,8 @@ The cycle for every step is: | Reverse Proxy | Nginx (serves frontend + proxies `/api` to backend) | | Dev Mail | Mailhog (SMTP trap + web UI) | | All-in-one image | Single Docker image: Nginx + Spring Boot + PostgreSQL + Supervisor | -| Image registry | Not configured (legacy Docker Hub publish workflow removed) | -| CI/CD | Gitea Actions — run backend/frontend tests on pull requests to `develop` | +| Image registry | Local Docker images on the deployment host (`condado-newsletter-backend`, `condado-newsletter-frontend`) | +| CI/CD | Gitea Actions — test PRs to `develop`, deploy approved PRs targeting `main` | ## Deployment Flavours @@ -93,7 +93,7 @@ There are **three ways to run the project**: | Flavour | Command | When to use | |---------------------|---------------------------------|------------------------------------------------| | **Dev** | `docker compose up` | Local development — includes Mailhog | -| **Prod (compose)** | `docker compose -f docker-compose.prod.yml up` | Production with external DB/SMTP | +| **Prod (compose)** | `docker compose -f docker-compose.prod.yml up -d` | Production with prebuilt backend/frontend images | | **All-in-one** | `docker run ...` | Simplest deploy — everything in one container | ### All-in-one Image @@ -312,7 +312,7 @@ npm run test docker compose up --build # Prod -docker compose -f docker-compose.prod.yml up --build +docker compose -f docker-compose.prod.yml up -d # Stop docker compose down @@ -456,7 +456,7 @@ Never hardcode any of these values. | `OPENAI_API_KEY` | Backend | OpenAI API key | | `OPENAI_MODEL` | Backend | OpenAI model (default: `gpt-4o`) | | `APP_RECIPIENTS` | Backend | Comma-separated list of recipient emails | -| `VITE_API_BASE_URL` | Frontend | Backend API base URL (used by Vite at build time) | +| `VITE_API_BASE_URL` | Frontend | Backend API base URL for the Vite dev server proxy | > ⚠️ Never hardcode credentials. Always use environment variables or a `.env` file (gitignored). @@ -575,8 +575,9 @@ Good examples: | Workflow file | Trigger | What it does | |----------------------------|----------------------------|-----------------------------------------------------------| | `.gitea/workflows/ci.yml` | PR to `develop` | Backend tests (`./gradlew test`) + Frontend tests (`npm run test`) | +| `.gitea/workflows/build.yml` | Approved PR review on `main` | Build `condado-newsletter-backend` and `condado-newsletter-frontend` locally on the runner host | -Current policy: old publish/version automation workflows were removed during the Gitea migration. +Build policy: the runner shares the target Docker host, so the build workflow produces local Docker images directly on that host. `docker-compose.prod.yml` is image-based and can be started separately without build directives. --- diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index da14aa1..cc16bfa 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -20,9 +20,7 @@ services: # ── Backend (Spring Boot) ──────────────────────────────────────────────────── backend: - build: - context: ./backend - dockerfile: Dockerfile + image: condado-newsletter-backend:latest restart: always depends_on: postgres: @@ -55,11 +53,7 @@ services: # ── Frontend + Nginx ───────────────────────────────────────────────────────── nginx: - build: - context: ./frontend - dockerfile: Dockerfile - args: - VITE_API_BASE_URL: ${VITE_API_BASE_URL} + image: condado-newsletter-frontend:latest restart: always ports: - "80:80"