diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f2a3bc..513e46a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,8 @@ on: workflow_dispatch: env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} + GHCR_REGISTRY: ghcr.io + PRIVATE_REGISTRY: registry.cklnet.com jobs: # ── Phase 1: Lint ────────────────────────────────────────────────────── @@ -169,6 +169,14 @@ jobs: contents: read packages: write + strategy: + matrix: + include: + - context: ./backend + image_name: gmail-puller/backend + - context: ./frontend + image_name: gmail-puller/frontend + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -176,18 +184,28 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - - name: Log in to Container Registry + - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GHCR_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + # Requires PRIVATE_REGISTRY_USERNAME and PRIVATE_REGISTRY_PASSWORD secrets + - name: Log in to private registry + uses: docker/login-action@v3 + with: + registry: ${{ env.PRIVATE_REGISTRY }} + username: ${{ secrets.PRIVATE_REGISTRY_USERNAME }} + password: ${{ secrets.PRIVATE_REGISTRY_PASSWORD }} + - name: Extract metadata (tags, labels) id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: | + ${{ env.GHCR_REGISTRY }}/${{ github.repository_owner }}/${{ matrix.image_name }} + ${{ env.PRIVATE_REGISTRY }}/${{ matrix.image_name }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} @@ -199,7 +217,7 @@ jobs: id: build-push uses: docker/build-push-action@v5 with: - context: . + context: ${{ matrix.context }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 7040aa3..f4a5d47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgraded `sqlalchemy` from `2.0.25` to `2.0.48` to fix `AssertionError: Class ... directly inherits TypingOnly but has additional attributes` on Python 3.14 (`__static_attributes__`, `__firstlineno__`) ### Added +- **Dual-registry Docker deployment**: CI now builds separate backend and frontend images and pushes to both GHCR (`ghcr.io`) and private registry (`registry.cklnet.com`) using a matrix strategy - **Database-backed configuration**: `AppSetting` model and `ConfigService` for hybrid config (DB-first, env-var fallback) - Admin API endpoints for managing settings (`GET/PUT/DELETE /api/v1/settings`) - Default settings seeded into database on first startup (SMTP, processing, Gmail API, notifications) diff --git a/docs/TODO.md b/docs/TODO.md index 7f623ab..fba9ac2 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -103,7 +103,7 @@ Comprehensive task breakdown for repository improvements and production readines - [ ] Set up Codecov integration ### Not Started 📋 -- [ ] Add deployment workflow (staging/production) +- [x] Add deployment workflow (dual-registry: GHCR + private registry) - [ ] Add release workflow with automated changelog - [ ] Configure status checks for PRs - [ ] Add performance regression detection