From 0bf3a2758936ab67974bd02a88311784cbb13ae3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 18 Jan 2026 19:42:50 +0000 Subject: [PATCH 1/2] Initial plan From 33f4a48be06b6468149543e026fddbd8b0776caf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 18 Jan 2026 19:46:31 +0000 Subject: [PATCH 2/2] Add 2 clearly marked GHCR deploys for backend and frontend Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com> --- .github/workflows/docker-publish.yml | 64 ++++++++++++++++++++-- docs/CI-CD.md | 82 +++++++++++++++++++--------- 2 files changed, 113 insertions(+), 33 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index cce13c6..9c8696c 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -15,7 +15,8 @@ env: IMAGE_NAME: ${{ github.repository }} jobs: - build-and-push: + build-and-push-backend: + name: Build and Push Backend to GHCR runs-on: ubuntu-latest permissions: contents: read @@ -40,11 +41,11 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract metadata (tags, labels) for Docker + - name: Extract metadata (tags, labels) for Backend Docker image id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-backend tags: | type=ref,event=branch type=ref,event=pr @@ -54,7 +55,58 @@ jobs: type=sha type=raw,value=latest,enable={{is_default_branch}} - - name: Build and push Docker image + - name: Build and push Backend Docker image + uses: docker/build-push-action@v5 + with: + context: ./backend + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha,scope=backend + cache-to: type=gha,mode=max,scope=backend + + build-and-push-frontend: + name: Build and Push Frontend to GHCR + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Frontend Docker image + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-frontend + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Frontend Docker image uses: docker/build-push-action@v5 with: context: . @@ -62,8 +114,8 @@ jobs: push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=gha,scope=frontend + cache-to: type=gha,mode=max,scope=frontend build-args: | VITE_FLASK_BACKEND_URL=${{ vars.VITE_FLASK_BACKEND_URL || '' }} VITE_BASE_PATH=${{ vars.VITE_BASE_PATH || '/' }} diff --git a/docs/CI-CD.md b/docs/CI-CD.md index 8654c6f..1893f4e 100644 --- a/docs/CI-CD.md +++ b/docs/CI-CD.md @@ -6,7 +6,7 @@ This repository includes automated CI/CD workflows for building, testing, and de ### 1. Docker Build and Push to GHCR (`docker-publish.yml`) -This workflow automatically builds a Docker image of the application and pushes it to GitHub Container Registry (GHCR). +This workflow automatically builds **two separate Docker images** (backend and frontend) and pushes them to GitHub Container Registry (GHCR). **Triggers:** - Push to `main` branch @@ -14,6 +14,9 @@ This workflow automatically builds a Docker image of the application and pushes - Pull requests to `main` (build only, no push) **Features:** +- Two clearly marked build jobs: + - **Backend**: Python/Flask API (`ghcr.io//-backend`) + - **Frontend**: React/Vite application (`ghcr.io//-frontend`) - Multi-platform Docker image building (AMD64 and ARM64) - Automatic tagging strategy: - `latest` - Latest build from main branch @@ -21,33 +24,46 @@ This workflow automatically builds a Docker image of the application and pushes - `v1.0` - Major.minor version - `v1` - Major version - `main-` - Branch with commit SHA -- Docker layer caching for faster builds -- Automatic push to `ghcr.io//` +- Separate Docker layer caching for each image +- Parallel builds for faster CI/CD **Configuration:** - The workflow uses the `GITHUB_TOKEN` for authentication (automatic) -- Optional: Set `VITE_FLASK_BACKEND_URL` as a repository variable for backend configuration +- Optional: Set `VITE_FLASK_BACKEND_URL` as a repository variable for frontend backend configuration -**Using the Docker Image:** +**Using the Docker Images:** ```bash -# Pull the latest image (will automatically use the correct architecture for your system) -docker pull ghcr.io//:latest +# Backend - Pull and run +docker pull ghcr.io//-backend:latest +docker run -p 5000:5000 ghcr.io//-backend:latest -# Run the container -docker run -p 3000:3000 ghcr.io//:latest +# Frontend - Pull and run +docker pull ghcr.io//-frontend:latest +docker run -p 3000:3000 ghcr.io//-frontend:latest -# Pull a specific version -docker pull ghcr.io//:v1.0.0 +# Pull specific versions +docker pull ghcr.io//-backend:v1.0.0 +docker pull ghcr.io//-frontend:v1.0.0 # Pull for a specific architecture (optional) -docker pull --platform linux/amd64 ghcr.io//:latest -docker pull --platform linux/arm64 ghcr.io//:latest +docker pull --platform linux/amd64 ghcr.io//-backend:latest +docker pull --platform linux/arm64 ghcr.io//-frontend:latest + +# Run full stack with docker-compose +# Create a docker-compose.yml referencing GHCR images: +# backend: +# image: ghcr.io//-backend:latest +# frontend: +# image: ghcr.io//-frontend:latest ``` **Making Images Public:** -1. Go to your package at `https://github.com/users//packages/container//settings` -2. Change visibility to "Public" if you want the image to be publicly accessible +1. Go to your packages at `https://github.com/users//packages` +2. For each image (`-backend` and `-frontend`): + - Click on the package + - Go to "Package settings" + - Change visibility to "Public" if you want the image to be publicly accessible ### 2. Deploy to GitHub Pages (`deploy-pages.yml`) @@ -111,7 +127,7 @@ Both workflows require the following permissions (already configured): **docker-publish.yml:** - `contents: read` - Read repository contents -- `packages: write` - Push to GitHub Container Registry +- `packages: write` - Push to GitHub Container Registry (for both backend and frontend images) - `id-token: write` - OIDC token for security **deploy-pages.yml:** @@ -168,25 +184,36 @@ This will build and push the Docker image with tags: `v1.0.0`, `v1.0`, `v1`, and To test the workflows locally, you can: -1. **Build the Docker image:** +1. **Build the Backend Docker image:** ```bash - docker build -t . - docker run -p 3000:3000 + cd backend + docker build -t -backend . + docker run -p 5000:5000 -backend ``` -2. **Build for multiple architectures (requires Docker Buildx):** +2. **Build the Frontend Docker image:** + ```bash + docker build -t -frontend . + docker run -p 3000:3000 -frontend + ``` + +3. **Build for multiple architectures (requires Docker Buildx):** ```bash # Create a new builder instance (one-time setup) docker buildx create --use - # Build for both AMD64 and ARM64 - docker buildx build --platform linux/amd64,linux/arm64 -t . + # Build backend for both AMD64 and ARM64 + docker buildx build --platform linux/amd64,linux/arm64 -t -backend ./backend + + # Build frontend for both AMD64 and ARM64 + docker buildx build --platform linux/amd64,linux/arm64 -t -frontend . # Build and load for your current architecture - docker buildx build --platform linux/amd64 -t --load . + docker buildx build --platform linux/amd64 -t -backend --load ./backend + docker buildx build --platform linux/amd64 -t -frontend --load . ``` -3. **Build for GitHub Pages:** +4. **Build for GitHub Pages:** ```bash npm ci npm run build @@ -223,7 +250,8 @@ For staging and production environments, consider: ### Backend Deployment -The current workflows focus on the frontend. For backend deployment: -- Consider adding a separate workflow for the Flask backend -- Deploy backend to a service like Heroku, DigitalOcean, or AWS +The workflow now includes automated backend deployment to GHCR: +- Backend image is automatically built from the `/backend` directory +- Image is available at `ghcr.io//-backend` +- Deploy backend to a service like Heroku, DigitalOcean, or AWS using the GHCR image - Update `VITE_FLASK_BACKEND_URL` to point to your deployed backend