diff --git a/.gitea/workflows/deploy-beta.yml b/.gitea/workflows/deploy-beta.yml new file mode 100644 index 0000000..59d6d03 --- /dev/null +++ b/.gitea/workflows/deploy-beta.yml @@ -0,0 +1,37 @@ +name: Deploy Beta + +on: + workflow_dispatch: {} + +jobs: + unit-tests: + runs-on: self-hosted + defaults: + run: + working-directory: llm-fe + steps: + - uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install dependencies + run: npm ci + + - name: Run unit tests + run: npm run test:ci + + deploy-beta: + needs: unit-tests + runs-on: self-hosted + env: + SERVER_INFRA_ROOT: /home/westfarn/Documents/repos/server-infra + steps: + - name: Deploy chat_web_app beta + run: | + "$SERVER_INFRA_ROOT/scripts/deploy.sh" \ + --app chat_web_app \ + --env beta \ + --ref "${{ gitea.sha }}" diff --git a/.gitea/workflows/deploy-prod.yml b/.gitea/workflows/deploy-prod.yml new file mode 100644 index 0000000..bb055e3 --- /dev/null +++ b/.gitea/workflows/deploy-prod.yml @@ -0,0 +1,22 @@ +name: Deploy Prod + +# Runs after Unit Tests completes on master. Direct pushes only (not PRs). +on: + workflow_run: + workflows: [Unit Tests] + types: [completed] + branches: [master] + +jobs: + deploy: + if: gitea.event.workflow_run.conclusion == 'success' && gitea.event.workflow_run.event == 'push' + runs-on: self-hosted + env: + SERVER_INFRA_ROOT: /home/westfarn/Documents/repos/server-infra + steps: + - name: Deploy chat_web_app prod + run: | + "$SERVER_INFRA_ROOT/scripts/deploy.sh" \ + --app chat_web_app \ + --env prod \ + --ref "${{ gitea.event.workflow_run.head_sha }}" diff --git a/.gitea/workflows/unit-tests.yml b/.gitea/workflows/unit-tests.yml new file mode 100644 index 0000000..00c774f --- /dev/null +++ b/.gitea/workflows/unit-tests.yml @@ -0,0 +1,28 @@ +name: Unit Tests + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + test: + runs-on: self-hosted + defaults: + run: + working-directory: llm-fe + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install dependencies + run: npm ci + + - name: Run unit tests + run: npm run test:ci diff --git a/README.md b/README.md index e69de29..ef17bd7 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,63 @@ +# Chat Bot Frontend (`chat_web_app`) + +CRA/React app under `llm-fe/`. Production serve is **node-static** (not Docker): +hosts build with npm and write into `/var/www/...`; the shared **web-static** nginx +container serves those roots. Deploy is driven by `server-infra`. + +## Local development + +```bash +cd llm-fe +npm ci +npm start +``` + +Uses `.env.development` (API → local `chat_backend`, usually `http://127.0.0.1:8001`). + +## Environment files (CRA `REACT_APP_*`) + +| File | When used | Backend | +|------|-----------|---------| +| `.env.development` | `npm start` | local backend | +| `.env.production` | `npm run build` / `build:prod` | `https://chatbackend.aimloperations.com` | +| `.env.beta` | `npm run build:beta` | `https://beta.chatbackend.aimloperations.com` | + +Baked into the JS bundle at build time. No host secret file needed for this +frontend (unlike Django apps under `~/Documents/secrets/`). + +Required vars: + +- `REACT_APP_BACKEND_REST_API_BASE_URL` — REST base (trailing `/api/`) +- `REACT_APP_BACKEND_WS_API_BASE_URL` — WebSocket URL (full `ws://` / `wss://` path) + +## Production / beta build (host deploy) + +`server-infra` runs `npm ci` then `npm run build:` in `llm-fe/`. Those +scripts write static assets into: + +| Script | Document root | +|--------|----------------| +| `npm run build:prod` | `/var/www/prod.chat.aimloperations/html` | +| `npm run build:beta` | `/var/www/beta.chat.aimloperations/html` | + +Paths must match `server-infra` `app_catalog.chat_web_app.webroot_pattern`. + +Manual deploy from the control node: + +```bash +~/Documents/repos/server-infra/scripts/deploy.sh \ + --app chat_web_app --env prod --ref +``` + +## CI / CD (Gitea) + +- `.gitea/workflows/unit-tests.yml` — tests on push/PR to `master` +- `.gitea/workflows/deploy-prod.yml` — after green Unit Tests on `master` push +- `.gitea/workflows/deploy-beta.yml` — manual (`workflow_dispatch`) + +## Tests + +```bash +cd llm-fe +npm run test:ci +``` diff --git a/llm-fe/.env.beta b/llm-fe/.env.beta new file mode 100644 index 0000000..bfcd820 --- /dev/null +++ b/llm-fe/.env.beta @@ -0,0 +1,2 @@ +REACT_APP_BACKEND_REST_API_BASE_URL=https://beta.chatbackend.aimloperations.com/api/ +REACT_APP_BACKEND_WS_API_BASE_URL=wss://beta.chatbackend.aimloperations.com/ws/chat_again/ diff --git a/llm-fe/package.json b/llm-fe/package.json index 4073984..a6714c1 100644 --- a/llm-fe/package.json +++ b/llm-fe/package.json @@ -40,6 +40,8 @@ "scripts": { "start": "NODE_ENV=development react-scripts start", "build": "NODE_ENV=production react-scripts build", + "build:prod": "NODE_ENV=production react-scripts build && mkdir -p /var/www/prod.chat.aimloperations/html && cp -r ./build/* /var/www/prod.chat.aimloperations/html/", + "build:beta": "bash -c 'set -a; source .env.beta; set +a; NODE_ENV=production react-scripts build' && mkdir -p /var/www/beta.chat.aimloperations/html && cp -r ./build/* /var/www/beta.chat.aimloperations/html/", "test": "NODE_ENV=development react-scripts test", "test:ci": "CI=true NODE_ENV=development react-scripts test --watchAll=false --coverage=false", "eject": "react-scripts eject" diff --git a/llm-fe/src/axiosApi.js b/llm-fe/src/axiosApi.js index 79fbd08..5eab397 100644 --- a/llm-fe/src/axiosApi.js +++ b/llm-fe/src/axiosApi.js @@ -1,9 +1,7 @@ import axios from "axios"; const Cookies = require("js-cookie"); -const baseURL = "http://localhost:8011/api/"; -//const baseURL = 'https://chatbackend.aimloperations.com/api/'; -//const baseURL = process.env.REACT_APP_BACKEND_REST_API_BASE_URL; +const baseURL = process.env.REACT_APP_BACKEND_REST_API_BASE_URL; export const axiosInstance = axios.create({ baseURL: baseURL, diff --git a/llm-fe/src/llm-fe/contexts/WebSocketContext.js b/llm-fe/src/llm-fe/contexts/WebSocketContext.js index b86292d..7abc398 100644 --- a/llm-fe/src/llm-fe/contexts/WebSocketContext.js +++ b/llm-fe/src/llm-fe/contexts/WebSocketContext.js @@ -70,11 +70,7 @@ function WebSocketProvider({ children }) { useEffect(() => { /* WS initialization and cleanup */ if (account) { - ws.current = new WebSocket(`ws://localhost:8011/ws/chat_again/`); - //ws.current = new WebSocket(`ws://localhost:8011/ws/conditional_chat/`); - //ws.current = new WebSocket('wss://chatbackend.aimloperations.com/ws/chat_again/') - //ws.current = new WebSocket('wss://chatbackend.aimloperations.com/ws/conditional_chat/') - //ws.current = process.env.REACT_APP_BACKEND_WS_API_BASE_URL; + ws.current = new WebSocket(process.env.REACT_APP_BACKEND_WS_API_BASE_URL); ws.current.onopen = () => { setSocket(ws.current);