Compare commits
31 Commits
44b8760ab2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32ca73701d | ||
|
|
be68fb17bd | ||
|
|
40217173f0 | ||
|
|
682dc9a715 | ||
|
|
2db929289f | ||
|
|
99e2d13aab | ||
|
|
d3fa5d7271 | ||
|
|
40da78d7cd | ||
|
|
7914be4f4d | ||
|
|
72970780e6 | ||
|
|
0c2bb5454b | ||
|
|
d2de21ebeb | ||
|
|
46c6c410b9 | ||
|
|
1a99d6023c | ||
|
|
57741f5f1c | ||
|
|
0391cb3505 | ||
|
|
5e822da407 | ||
|
|
b8c306721a | ||
|
|
dd6637260a | ||
|
|
558243a657 | ||
|
|
65ac965977 | ||
|
|
d05248a89e | ||
|
|
ceef7f8a10 | ||
|
|
d74819ab58 | ||
|
|
aec528a656 | ||
|
|
9d821cd662 | ||
|
|
03758ede76 | ||
|
|
0d718a6055 | ||
|
|
36d373b95c | ||
|
|
df9023016c | ||
|
|
1928293dc6 |
274
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
# .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: 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: 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
|
||||||
|
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 ${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia:${{ gitea.sha }}..."
|
||||||
|
docker pull ghcr.io/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia:${{ gitea.sha }}
|
||||||
|
echo "Backend pull complete."
|
||||||
|
|
||||||
|
# --- Pull specific frontend image version ---
|
||||||
|
echo "Pulling frontend image ${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia-frontend:${{ gitea.sha }}..."
|
||||||
|
docker pull ghcr.io/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia-frontend:${{ gitea.sha }}
|
||||||
|
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/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia:.*|image: ghcr.io/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia:${{ gitea.sha }}|g" "${COMPOSE_FILE##*/}"
|
||||||
|
grep "image: ghcr.io/${{ secrets.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/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia-frontend:.*|image: ghcr.io/${{ secrets.DOCKER_REGISTRY_USERNAME }}/maia-frontend:${{ gitea.sha }}|g" "${COMPOSE_FILE##*/}"
|
||||||
|
grep "image: ghcr.io/${{ secrets.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! ---"
|
||||||
156
.github/workflows/deploy.yml
vendored
@@ -1,156 +0,0 @@
|
|||||||
# .github/workflows/deploy.yml
|
|
||||||
|
|
||||||
name: Build and Deploy Backend
|
|
||||||
on:
|
|
||||||
# Triggers the workflow on push events but only for the main branch
|
|
||||||
push:
|
|
||||||
branches: [ main ]
|
|
||||||
paths: # Only run if backend code or Docker config changes
|
|
||||||
- 'backend/**'
|
|
||||||
- '.github/workflows/deploy.yml'
|
|
||||||
- 'backend/docker-compose.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 unit tests.
|
|
||||||
# ========================================================================
|
|
||||||
test:
|
|
||||||
name: Run Linters and Tests
|
|
||||||
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@v4
|
|
||||||
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 and deploy the Docker image to mara.
|
|
||||||
# ========================================================================
|
|
||||||
build-and-deploy:
|
|
||||||
name: Build and Deploy
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: test # Ensure tests pass before deploying
|
|
||||||
|
|
||||||
# Only run this job if triggered by a push to main or manual dispatch/schedule
|
|
||||||
# This prevents it running for PRs (eventually)
|
|
||||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.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: ${{ github.repository_owner }} # GitHub username
|
|
||||||
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/${{ github.repository_owner }}/maia:${{ github.sha }}
|
|
||||||
ghcr.io/${{ github.repository_owner }}/maia:latest
|
|
||||||
# Pull latest base image updates when building (good for scheduled runs)
|
|
||||||
pull: true
|
|
||||||
cache-from: type=gha # Github Actions cache
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# Deploy to mara via SSH
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
- name: Deploy to Server
|
|
||||||
uses: appleboy/ssh-action@v1.0.3
|
|
||||||
with:
|
|
||||||
host: ${{ secrets.SSH_HOST }}
|
|
||||||
port: ${{ secrets.SSH_PORT }}
|
|
||||||
username: ${{ secrets.SSH_USER }}
|
|
||||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
||||||
script: |
|
|
||||||
set -e # Exit script on first error
|
|
||||||
cd ${{ secrets.DEPLOY_PATH }}
|
|
||||||
echo "Logged into server: $(pwd)"
|
|
||||||
|
|
||||||
# Log into GHCR on mara
|
|
||||||
echo "Logging into GHCR..."
|
|
||||||
echo ${{ secrets.DOCKER_REGISTRY_TOKEN }} | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
|
|
||||||
echo "GHCR login completed."
|
|
||||||
|
|
||||||
|
|
||||||
# Pull the specific image version built in this workflow
|
|
||||||
# Using the Git SHA ensures we deploy exactly what was just built
|
|
||||||
echo "Pulling image ${{ github.sha }}..."
|
|
||||||
docker pull ghcr.io/${{ github.repository_owner }}/maia:${{ github.sha }}
|
|
||||||
|
|
||||||
# Also pull latest for other services to keep up to date
|
|
||||||
docker compose pull redis db
|
|
||||||
|
|
||||||
# Uses sed to update the compose file with the new image tag
|
|
||||||
sed -i 's|image: ghcr.io/${{ github.repository_owner }}/maia:.*|image: ghcr.io/${{ github.repository_owner }}/maia:${{ github.sha }}|g' docker-compose.yml
|
|
||||||
echo "Updated docker-compose.yml image tag"
|
|
||||||
|
|
||||||
# Restart the services using the new image(s)
|
|
||||||
echo "Bringing compose stack down and up with new image..."
|
|
||||||
docker compose up -d --force-recreate --remove-orphans api worker db redis
|
|
||||||
echo "Deployment complete!"
|
|
||||||
4
.gitignore
vendored
@@ -1,13 +1,13 @@
|
|||||||
# backend
|
# backend
|
||||||
backend/env
|
backend/env
|
||||||
backend/.env
|
backend/.env.local
|
||||||
|
backend/.env.prod.bak
|
||||||
backend/db
|
backend/db
|
||||||
backend/redis_data
|
backend/redis_data
|
||||||
|
|
||||||
# frontend
|
# frontend
|
||||||
interfaces/nativeapp/node_modules
|
interfaces/nativeapp/node_modules
|
||||||
interfaces/nativeapp/.expo/
|
interfaces/nativeapp/.expo/
|
||||||
interfaces/nativeapp/dist/
|
|
||||||
interfaces/nativeapp/web-build/
|
interfaces/nativeapp/web-build/
|
||||||
interfaces/nativeapp/expo-env.d.ts
|
interfaces/nativeapp/expo-env.d.ts
|
||||||
interfaces/nativeapp/*.orig.*
|
interfaces/nativeapp/*.orig.*
|
||||||
|
|||||||
10
backend/.env
@@ -1,10 +0,0 @@
|
|||||||
DB_HOST = "db"
|
|
||||||
DB_USER = "maia"
|
|
||||||
DB_PASSWORD = "maia"
|
|
||||||
DB_NAME = "maia"
|
|
||||||
|
|
||||||
REDIS_URL = "redis://redis:6379"
|
|
||||||
|
|
||||||
PEPPER = "LsD7%"
|
|
||||||
JWT_SECRET_KEY="1c8cf3ca6972b365f8108dad247e61abdcb6faff5a6c8ba00cb6fa17396702bf"
|
|
||||||
GOOGLE_API_KEY="AIzaSyBrte_mETZJce8qE6cRTSz_fHOjdjlShBk"
|
|
||||||
@@ -9,9 +9,9 @@ class Settings(BaseSettings):
|
|||||||
# Database settings - reads from environment or .env
|
# Database settings - reads from environment or .env
|
||||||
DB_PORT: int = 5432
|
DB_PORT: int = 5432
|
||||||
DB_NAME: str = "maia"
|
DB_NAME: str = "maia"
|
||||||
DB_HOST: str
|
DB_HOST: str = "localhost"
|
||||||
DB_USER: str
|
DB_USER: str = "maia"
|
||||||
DB_PASSWORD: str
|
DB_PASSWORD: str = "maia"
|
||||||
|
|
||||||
DB_URL: str = ""
|
DB_URL: str = ""
|
||||||
|
|
||||||
@@ -22,11 +22,11 @@ class Settings(BaseSettings):
|
|||||||
JWT_ALGORITHM: str = "HS256"
|
JWT_ALGORITHM: str = "HS256"
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
|
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
|
||||||
REFRESH_TOKEN_EXPIRE_DAYS: int = 7
|
REFRESH_TOKEN_EXPIRE_DAYS: int = 7
|
||||||
PEPPER: str
|
PEPPER: str = "pepper"
|
||||||
JWT_SECRET_KEY: str
|
JWT_SECRET_KEY: str = "secret"
|
||||||
|
|
||||||
# Other settings
|
# Other settings
|
||||||
GOOGLE_API_KEY: str
|
GOOGLE_API_KEY: str = "google_api_key"
|
||||||
EXPO_PUSH_API_URL: str = "https://exp.host/--/api/v2/push/send"
|
EXPO_PUSH_API_URL: str = "https://exp.host/--/api/v2/push/send"
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
|
|||||||
100
backend/docker-compose.deploy.yml
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
services:
|
||||||
|
# ----- Backend API (Uvicorn/FastAPI/Django etc.) -----
|
||||||
|
api:
|
||||||
|
image: ghcr.io/c-d-p/maia:44b8760ab245407ac8dcac435cca6bbfad51284b
|
||||||
|
container_name: MAIA_API
|
||||||
|
restart: unless-stopped
|
||||||
|
command: uvicorn main:app --host 0.0.0.0 --port 8000
|
||||||
|
environment:
|
||||||
|
DB_HOST: ${DB_HOST}
|
||||||
|
DB_USER: ${DB_USER}
|
||||||
|
DB_NAME: ${DB_NAME}
|
||||||
|
DB_PASSWORD: ${DB_PASSWORD}
|
||||||
|
REDIS_URL: ${REDIS_URL}
|
||||||
|
PEPPER: ${PEPPER}
|
||||||
|
JWT_SECRET_KEY: ${JWT_SECRET_KEY}
|
||||||
|
GOOGLE_API_KEY: ${GOOGLE_API_KEY}
|
||||||
|
expose:
|
||||||
|
- "8000"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- redis
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.maia.rule=Host(`maia.depaoli.id.au`)"
|
||||||
|
- "traefik.http.routers.maia.tls=true"
|
||||||
|
- "traefik.http.routers.maia.entrypoints=secureweb"
|
||||||
|
- "traefik.http.routers.maia.tls.certresolver=myresolver"
|
||||||
|
- "traefik.http.services.maia.loadbalancer.server.port=8000"
|
||||||
|
- "traefik.docker.network=host"
|
||||||
|
|
||||||
|
# ----- Celery Worker -----
|
||||||
|
worker:
|
||||||
|
image: ghcr.io/c-d-p/maia:44b8760ab245407ac8dcac435cca6bbfad51284b
|
||||||
|
container_name: MAIA_Worker
|
||||||
|
restart: unless-stopped
|
||||||
|
command: celery -A core.celery_app worker --loglevel=info
|
||||||
|
environment:
|
||||||
|
DB_HOST: ${DB_HOST}
|
||||||
|
DB_USER: ${DB_USER}
|
||||||
|
DB_NAME: ${DB_NAME}
|
||||||
|
DB_PASSWORD: ${DB_PASSWORD}
|
||||||
|
REDIS_URL: ${REDIS_URL}
|
||||||
|
PEPPER: ${PEPPER}
|
||||||
|
JWT_SECRET_KEY: ${JWT_SECRET_KEY}
|
||||||
|
GOOGLE_API_KEY: $GOOGLE_API_KEY}
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- redis
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
|
||||||
|
# ----- Database (PostgreSQL) -----
|
||||||
|
db:
|
||||||
|
image: postgres:15 # Use a specific version
|
||||||
|
container_name: MAIA_DB
|
||||||
|
volumes:
|
||||||
|
- /srv/docker/container/MAIA/db:/var/lib/postgresql/data # Persist data using a named volume
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=${DB_USER}
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
- POSTGRES_DB=${DB_NAME}
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ----- Cache (Redis) -----
|
||||||
|
redis:
|
||||||
|
image: redis:7 # Use a specific version
|
||||||
|
container_name: MAIA_Redis
|
||||||
|
volumes:
|
||||||
|
- /srv/docker/container/MAIA/redis_data:/data
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ----- Frontend (nginx) ------
|
||||||
|
frontend:
|
||||||
|
image: ghcr.io/c-d-p/maia-frontend:latest
|
||||||
|
container_name: MAIA_FRONTEND
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
expose:
|
||||||
|
- "80"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.maia-frontend.rule=Host(`app.maia.depaoli.id.au`)"
|
||||||
|
- "traefik.http.routers.maia-frontend.tls=true"
|
||||||
|
- "traefik.http.routers.maia-frontend.entrypoints=secureweb"
|
||||||
|
- "traefik.http.routers.maia-frontend.tls.certresolver=myresolver"
|
||||||
|
- "traefik.http.services.maia-frontend.loadbalancer.server.port=80"
|
||||||
|
- "traefik.docker.network=host"
|
||||||
|
|
||||||
|
# ----- Network Definition -----
|
||||||
|
networks:
|
||||||
|
default: # Define a custom bridge network
|
||||||
|
driver: bridge
|
||||||
|
name: maia_network
|
||||||
@@ -21,7 +21,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- maia_network
|
- maia_network
|
||||||
env_file:
|
env_file:
|
||||||
- ./.env
|
- ./.env.local
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
# ----- Celery Worker -----
|
# ----- Celery Worker -----
|
||||||
@@ -37,7 +37,7 @@ services:
|
|||||||
- db
|
- db
|
||||||
- redis
|
- redis
|
||||||
env_file:
|
env_file:
|
||||||
- ./.env
|
- ./.env.local
|
||||||
networks:
|
networks:
|
||||||
- maia_network
|
- maia_network
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -53,7 +53,7 @@ services:
|
|||||||
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
- POSTGRES_DB=${DB_NAME}
|
- POSTGRES_DB=${DB_NAME}
|
||||||
env_file:
|
env_file:
|
||||||
- ./.env
|
- ./.env.local
|
||||||
networks:
|
networks:
|
||||||
- maia_network
|
- maia_network
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ app.include_router(router)
|
|||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins=["http://localhost:8081", "exp://*", "https://maia.depaoli.id.au"],
|
allow_origins=["https://app.maia.depaoli.id.au"],
|
||||||
allow_methods=["*"],
|
allow_methods=["*"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
|||||||
16
interfaces/nativeapp/Dockerfile.nginx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# ./frontend/Dockerfile.nginx
|
||||||
|
|
||||||
|
FROM nginx:1.28-alpine
|
||||||
|
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Remove default Nginx welcome page
|
||||||
|
RUN rm /usr/share/nginx/html/*
|
||||||
|
|
||||||
|
# Copy the pre-built Expo web output
|
||||||
|
COPY dist/ /usr/share/nginx/html
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Start Nginx in the foreground
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
1331
interfaces/nativeapp/dist/_expo/static/js/web/index-0ef639b7ebb0f592fe73fd94db0b4205.js
vendored
Normal file
|
After Width: | Height: | Size: 653 B |
BIN
interfaces/nativeapp/dist/assets/node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png
generated
vendored
Normal file
|
After Width: | Height: | Size: 207 B |
BIN
interfaces/nativeapp/dist/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png
generated
vendored
Normal file
|
After Width: | Height: | Size: 220 B |
|
After Width: | Height: | Size: 334 B |
|
After Width: | Height: | Size: 502 B |
|
After Width: | Height: | Size: 645 B |
BIN
interfaces/nativeapp/dist/assets/node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png
generated
vendored
Normal file
|
After Width: | Height: | Size: 141 B |
|
After Width: | Height: | Size: 201 B |
|
After Width: | Height: | Size: 266 B |
|
After Width: | Height: | Size: 332 B |
BIN
interfaces/nativeapp/dist/assets/node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png
generated
vendored
Normal file
|
After Width: | Height: | Size: 928 B |
BIN
interfaces/nativeapp/dist/assets/src/assets/MAIA_ICON.55dab8d84a31f13e7cdf223a69c97d91.png
vendored
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
interfaces/nativeapp/dist/assets/src/assets/fonts/Inter-Bold.8b04b3bd9435341377d7f4b4d68b6ecc.ttf
vendored
Normal file
BIN
interfaces/nativeapp/dist/assets/src/assets/fonts/Inter-Light.65ec965bd90e1a297cdb3be407420abc.ttf
vendored
Normal file
BIN
interfaces/nativeapp/dist/assets/src/assets/fonts/Inter-Medium.4591e900425d177e6ba268d165bf12e8.ttf
vendored
Normal file
BIN
interfaces/nativeapp/dist/assets/src/assets/fonts/Inter-Regular.e48c1217adab2a0e44f8df400d33c325.ttf
vendored
Normal file
BIN
interfaces/nativeapp/dist/assets/src/assets/fonts/Inter-Thin.1e9e30c74648950a240427636b6c1992.ttf
vendored
Normal file
BIN
interfaces/nativeapp/dist/favicon.ico
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
37
interfaces/nativeapp/dist/index.html
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<title>MAIA</title>
|
||||||
|
<!-- The `react-native-web` recommended style reset: https://necolas.github.io/react-native-web/docs/setup/#root-element -->
|
||||||
|
<style id="expo-reset">
|
||||||
|
/* These styles make the body full-height */
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
/* These styles disable body scrolling if you are using <ScrollView> */
|
||||||
|
body {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
/* These styles make the root element full-height */
|
||||||
|
#root {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link rel="shortcut icon" href="/favicon.ico" /></head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- Use static rendering with Expo Router to support running without JavaScript. -->
|
||||||
|
<noscript>
|
||||||
|
You need to enable JavaScript to run this app.
|
||||||
|
</noscript>
|
||||||
|
<!-- The root element for your Expo app. -->
|
||||||
|
<div id="root"></div>
|
||||||
|
<script src="/_expo/static/js/web/index-0ef639b7ebb0f592fe73fd94db0b4205.js" defer></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
interfaces/nativeapp/dist/metadata.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":0,"bundler":"metro","fileMetadata":{}}
|
||||||
36
interfaces/nativeapp/nginx.conf
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name app.maia.depaoli.id.au;
|
||||||
|
|
||||||
|
# Set the root directory for static files
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
# Default file to serve
|
||||||
|
index index.html index.htm;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
# Crucial for SPAs:
|
||||||
|
# - Try to serve the requested file ($uri)
|
||||||
|
# - If it's not found, try it as a directory ($uri/)
|
||||||
|
# - If that's not found, serve index.html (letting client-side routing handle it)
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add gzip compression for better performance
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss text/javascript image/svg+xml;
|
||||||
|
|
||||||
|
# Improve caching for assets
|
||||||
|
location ~* \.(?:css|js|jpg|jpeg|gif|png|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
access_log off; # Don't log access for static assets
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deny access to hidden files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||