# .gitea/workflows/deploy.yml name: Build and Deploy Backend run-name: ${{ gitea.actor }} deploying backend on Gitea Actions 🚀 on: # Triggers the workflow on push events but only for the main branch push: branches: [ main ] paths: - 'backend/**' - 'interfaces/nativeapp/**' - '.gitea/workflows/deploy.yml' - 'backend/docker-compose.deploy.yml' # Allows running of this workflow manually from the Actions tab workflow_dispatch: # Ensures the project will never be out of date by running a cron for this job # Currently set to every Sunday at 3 AM UTC schedule: - cron: '0 3 * * 0' jobs: # ======================================================================== # Job to run backend unit tests. # ======================================================================== test-backend: name: Run Linters and Tests (Backend) runs-on: ubuntu-latest steps: # Checks out the repo under $GITHUB_WORKSPACE - name: Checkout code uses: actions/checkout@v4 # Sets up Python 3.12 environment - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.12' # Cache pip dependencies for faster reruns # - name: Cache pip dependencies # uses: actions/cache@v3 # with: # path: ~/.cache/pip # key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }} # restore-keys: | # ${{ runner.os }}-pip- - name: Install dependencies working-directory: ./backend run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install -r requirements-dev.txt - name: Lint with Ruff working-directory: ./backend run: | ruff check . - name: Check formatting with Black working-directory: ./backend run: | black --check . - name: Run Pytest working-directory: ./backend run: | pytest # ======================================================================== # Job to build the backend Docker image. # ======================================================================== build-backend: name: Build (Backend) runs-on: ubuntu-latest needs: test-backend # Ensure tests pass before deploying # Only run this job if triggered by a push to main or manual dispatch/schedule if: gitea.event_name == 'push' || gitea.event_name == 'workflow_dispatch' || gitea.event_name == 'schedule' steps: # Checks out the repo under $GITHUB_WORKSPACE - name: Checkout code uses: actions/checkout@v4 # ------------------------------------------------------------------ # Login to Container Registry (Using GHCR) # ------------------------------------------------------------------ - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ secrets.DOCKER_REGISTRY_USERNAME }} # Uses the username stored in secrets password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} # Uses the PAT stored in secrets # ------------------------------------------------------------------ # Set up Docker Buildx for advanced build features # ------------------------------------------------------------------ - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 # ------------------------------------------------------------------ # Build and Push Docker Image # ------------------------------------------------------------------ - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: ./backend file: ./backend/Dockerfile # Explicit path to Dockerfile push: true # Push the image after building tags: | # Use SHA for version specific, latest for general ghcr.io/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia:${{ gitea.sha }} ghcr.io/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia:latest # Pull latest base image updates when building (good for scheduled runs) pull: true # ======================================================================== # Job to build the frontend Nginx image. # ======================================================================== build-frontend-web: name: Build (Frontend Web) runs-on: ubuntu-latest # needs: test-frontend if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '18' - name: Install frontend dependencies working-directory: ./interfaces/nativeapp run: npm ci - name: Build Expo web assets working-directory: ./interfaces/nativeapp run: npx expo export --platform web --output-dir dist - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ secrets.DOCKER_REGISTRY_USERNAME }} password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and push frontend nginx image uses: docker/build-push-action@v5 with: # Context is the frontend dir where Dockerfile.nginx, nginx.conf and dist/ are context: ./interfaces/nativeapp file: ./interfaces/nativeapp/Dockerfile.nginx # Path to the Nginx Dockerfile push: true tags: | ghcr.io/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia-frontend:${{ gitea.sha }} ghcr.io/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia-frontend:latest pull: true # Pull base nginx image updates # ======================================================================== # Build Native Android App (Trigger EAS Build) # ======================================================================== build-native-android: name: Build Native Android App (EAS) runs-on: ubuntu-latest # needs: test-frontend # Depends on frontend tests passing # Only run for deploy triggers if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '18' - name: Install frontend dependencies working-directory: ./interfaces/nativeapp run: npm ci - name: Install EAS CLI run: npm install -g eas-cli - name: Trigger EAS Build for Android working-directory: ./interfaces/nativeapp env: EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} # EAS token for authentication run: | eas build --platform android --profile production --non-interactive --no-wait # ======================================================================== # Deploy Backend and Frontend Web to Host # ======================================================================== deploy: name: Deploy to Host runs-on: ubuntu-latest needs: - build-backend # Wait for backend image build - build-frontend-web # Wait for frontend image build if: gitea.event_name == 'push' || gitea.event_name == 'workflow_dispatch' || gitea.event_name == 'schedule' steps: - name: Checkout code uses: actions/checkout@v4 - name: Deploy Locally env: DB_HOST: ${{ vars.DB_HOST }} DB_USER: ${{ vars.DB_USER }} DB_NAME: ${{ vars.DB_NAME }} DB_PASSWORD: ${{ secrets.DB_PASSWORD }} REDIS_URL: ${{ vars.REDIS_URL }} PEPPER: ${{ secrets.PEPPER }} JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }} GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} run: | #!/bin/bash -ex # Define paths and names WORKSPACE_DIR="${{ gitea.workspace }}/backend" # Dir where deploy compose file lives COMPOSE_FILE="${WORKSPACE_DIR}/docker-compose.deploy.yml" PROJECT_NAME="maia" # Project name used by docker compose BACKEND_IMAGE_TAG="${GITEA_SHA}" FRONTEND_IMAGE_TAG="${GITEA_SHA}" # same tag for simplicity echo "--- Start Deployment ---" echo "Using compose file: ${COMPOSE_FILE}" # --- Verify compose file exists --- if [ ! -f "${COMPOSE_FILE}" ]; then echo "ERROR: Compose file not found at ${COMPOSE_FILE}" exit 1 fi # --- Pull specific backend image version --- echo "Pulling backend image ${BACKEND_IMAGE_TAG}..." docker pull ghcr.io/${DOCKER_REGISTRY_USERNAME}/maia:${BACKEND_IMAGE_TAG} echo "Backend pull complete." # --- Pull specific frontend image version --- echo "Pulling frontend image ${FRONTEND_IMAGE_TAG}..." docker pull ghcr.io/${DOCKER_REGISTRY_USERNAME}/maia-frontend:${FRONTEND_IMAGE_TAG} echo "Frontend pull complete." # --- Pull other images defined in compose --- echo "Pulling other compose services for project ${PROJECT_NAME}..." cd "${WORKSPACE_DIR}" || exit 1 docker compose -p "${PROJECT_NAME}" -f "${COMPOSE_FILE##*/}" pull redis db echo "Other service pull complete." # --- Update Backend image tag in compose file --- echo "Updating Backend image tag in ${COMPOSE_FILE##*/}..." sed -i "s|image: ghcr.io/${DOCKER_REGISTRY_USERNAME}/maia:.*|image: ghcr.io/${DOCKER_REGISTRY_USERNAME}/maia:${BACKEND_IMAGE_TAG}|g" "${COMPOSE_FILE##*/}" grep "image: ghcr.io/${DOCKER_REGISTRY_USERNAME}/maia:" "${COMPOSE_FILE##*/}" || echo "Backend image line not found!" # --- Update Frontend image tag in compose file --- echo "Updating Frontend image tag in ${COMPOSE_FILE##*/}..." sed -i "s|image: ghcr.io/${DOCKER_REGISTRY_USERNAME}/maia-frontend:.*|image: ghcr.io/${DOCKER_REGISTRY_USERNAME}/maia-frontend:${FRONTEND_IMAGE_TAG}|g" "${COMPOSE_FILE##*/}" grep "image: ghcr.io/${DOCKER_REGISTRY_USERNAME}/maia-frontend:" "${COMPOSE_FILE##*/}" || echo "Frontend image line not found!" # --- Restart services using updated compose file --- echo "Bringing compose stack down and up for project ${PROJECT_NAME}..." docker compose -p "${PROJECT_NAME}" -f "${COMPOSE_FILE##*/}" up -d --force-recreate --remove-orphans echo "Docker compose up command finished." echo "--- Deployment complete! ---"