chore: unique ports (3900/3901) + broader CI caches (#20)
Two unrelated tweaks grouped into one PR to keep churn low. ## Ports Backend 8000 → 3900, Vite dev 5173 → 3901, 3902 reserved for future IPC. Port 8000 conflicts with Django/Rails/Jupyter/Airflow on most dev machines; the uncommon 3900 range dodges that. Touched: - frontend/src-tauri/src/lib.rs (BACKEND_PORT) - frontend/src-tauri/tauri.conf.json (devUrl) - frontend/vite.config.js (server.port) - frontend/src/api/client.ts (hardcoded API base) - frontend/src/App.jsx (PREVIEW_API fallback) - backend/main.py (CORS allowlist + uvicorn.run default) Rust sidecar launcher and FastAPI uvicorn port stay in sync via the `BACKEND_PORT` constant + explicit port=3900. ## CI caches Build time shaves across ci.yml and release.yml: - `astral-sh/setup-uv@v3` → `enable-cache: true` keyed on uv.lock (~45 s saved per run after uv.lock stabilises) - `awalsh128/cache-apt-pkgs-action` for ffmpeg (~25 s saved) - `actions/cache@v4` on `~/.bun/install/cache` keyed on bun.lock (~15 s saved; applied to both test gate and build matrix) Expected warm test job: ~45-60 s (was ~2-3 min). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
e57448f704
commit
90ef02b2e4
@@ -30,8 +30,13 @@ jobs:
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
# enable-cache persists ~/.cache/uv across runs, keyed on uv.lock —
|
||||
# turns `uv sync` from ~45 s cold to ~5 s warm.
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "uv.lock"
|
||||
|
||||
# Node 22 is needed for --experimental-strip-types so node:test can
|
||||
# import .ts files directly from frontend/src/api/*.
|
||||
@@ -43,10 +48,12 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
|
||||
# apt install ffmpeg is ~30 s every run; cache the resolved .debs.
|
||||
- name: System deps (ffmpeg)
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ffmpeg
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
packages: ffmpeg
|
||||
version: 1.0
|
||||
|
||||
- name: Install Python deps
|
||||
run: uv sync
|
||||
@@ -54,6 +61,16 @@ jobs:
|
||||
- name: Run pytest
|
||||
run: uv run pytest tests/ -q --tb=short
|
||||
|
||||
# Cache ~/.bun/install/cache keyed on bun.lock — `bun install` drops
|
||||
# from ~15 s cold to near-instant on warm cache.
|
||||
- name: Cache bun deps
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.bun/install/cache
|
||||
key: ${{ runner.os }}-bun-${{ hashFiles('frontend/bun.lock', 'bun.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bun-
|
||||
|
||||
- name: Install frontend deps
|
||||
working-directory: frontend
|
||||
run: bun install
|
||||
|
||||
@@ -50,8 +50,12 @@ jobs:
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
# enable-cache persists ~/.cache/uv keyed on uv.lock.
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "uv.lock"
|
||||
|
||||
# Node 22 is needed for --experimental-strip-types so node:test can
|
||||
# import .ts files directly from frontend/src/api/*.
|
||||
@@ -63,13 +67,13 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
|
||||
# Backend tests need ffmpeg (subprocess calls in fixtures) + the minimal
|
||||
# apt deps pydub/imageio pull in. Model weights are mocked so no HF
|
||||
# downloads happen.
|
||||
# Backend tests need ffmpeg (subprocess calls in fixtures). Cache the
|
||||
# resolved .debs so warm runs skip the apt-get update + install.
|
||||
- name: System deps (ffmpeg)
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ffmpeg
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
packages: ffmpeg
|
||||
version: 1.0
|
||||
|
||||
- name: Install Python deps
|
||||
run: uv sync
|
||||
@@ -77,6 +81,14 @@ jobs:
|
||||
- name: Run pytest
|
||||
run: uv run pytest tests/ -q --tb=short
|
||||
|
||||
- name: Cache bun deps
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.bun/install/cache
|
||||
key: ${{ runner.os }}-bun-${{ hashFiles('frontend/bun.lock', 'bun.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bun-
|
||||
|
||||
- name: Install frontend deps
|
||||
working-directory: frontend
|
||||
run: bun install
|
||||
@@ -170,6 +182,14 @@ jobs:
|
||||
libasound2-dev ffmpeg
|
||||
|
||||
# ── Frontend build ─────────────────────────────────────────────────
|
||||
- name: Cache bun deps
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.bun/install/cache
|
||||
key: ${{ runner.os }}-bun-${{ hashFiles('frontend/bun.lock', 'bun.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bun-
|
||||
|
||||
- name: Install frontend deps
|
||||
working-directory: frontend
|
||||
run: bun install
|
||||
|
||||
+5
-3
@@ -157,7 +157,7 @@ async def global_exception_handler(request: Request, exc: Exception):
|
||||
|
||||
_allowed = os.environ.get(
|
||||
"OMNIVOICE_ALLOWED_ORIGINS",
|
||||
"http://localhost:5173,http://127.0.0.1:5173,tauri://localhost,http://tauri.localhost",
|
||||
"http://localhost:3901,http://127.0.0.1:3901,tauri://localhost,http://tauri.localhost",
|
||||
).split(",")
|
||||
|
||||
app.add_middleware(
|
||||
@@ -191,8 +191,10 @@ if os.path.exists(frontend_path):
|
||||
else:
|
||||
@app.get("/")
|
||||
def _dev_fallback():
|
||||
return RedirectResponse(url="http://localhost:5173")
|
||||
return RedirectResponse(url="http://localhost:3901")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
# Port 3900 picked to dodge common 8000 conflicts (Django/Rails/Jupyter).
|
||||
# Rust sidecar launcher in lib.rs::BACKEND_PORT must stay in sync.
|
||||
uvicorn.run(app, host="0.0.0.0", port=3900)
|
||||
|
||||
@@ -7,7 +7,11 @@ use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use tauri::Manager;
|
||||
|
||||
const BACKEND_PORT: u16 = 8000;
|
||||
// Unique port range (3900-3902) chosen to avoid common conflicts:
|
||||
// 8000 collides with Django/Rails/Jupyter/Airflow on most dev machines.
|
||||
// 3900 is the backend (FastAPI + uvicorn), 3901 is the Vite dev server,
|
||||
// 3902 is reserved for future IPC / websocket listeners.
|
||||
const BACKEND_PORT: u16 = 3900;
|
||||
|
||||
// Version of the Astral `uv` binary we download at first run when no system
|
||||
// uv is on PATH. Pinned for reproducibility — bump alongside the uv.lock
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"identifier": "com.debpalash.omnivoice-studio",
|
||||
"build": {
|
||||
"frontendDist": "../dist",
|
||||
"devUrl": "http://localhost:5173",
|
||||
"devUrl": "http://localhost:3901",
|
||||
"beforeDevCommand": "bun run dev",
|
||||
"beforeBuildCommand": "bun run build"
|
||||
},
|
||||
|
||||
@@ -68,7 +68,7 @@ const doubleClickMaximize = () => {
|
||||
* We upload to the backend's /preview endpoint and serve via HTTP instead.
|
||||
* Falls back to createObjectURL for regular browsers.
|
||||
*/
|
||||
const _PREVIEW_API = import.meta.env.VITE_OMNIVOICE_API || 'http://localhost:8000';
|
||||
const _PREVIEW_API = import.meta.env.VITE_OMNIVOICE_API || 'http://localhost:3900';
|
||||
const fileToMediaUrl = async (file, prevUrls) => {
|
||||
// Revoke previous blob URLs if they exist
|
||||
if (prevUrls?.videoUrl?.startsWith('blob:')) URL.revokeObjectURL(prevUrls.videoUrl);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Backend always listens on localhost:8000 — both in dev (Vite @ 5173 talking
|
||||
// Backend always listens on localhost:3900 — both in dev (Vite @ 3901 talking
|
||||
// to a separate uvicorn) and in the built .app (Tauri webview @ tauri://localhost
|
||||
// talking to the bundled frozen backend sidecar). Relative fetches against
|
||||
// talking to the venv-bootstrapped sidecar). Relative fetches against
|
||||
// tauri://localhost don't reach the sidecar, so we hardcode the absolute host.
|
||||
export const API = 'http://localhost:8000';
|
||||
// Port 3900 chosen to avoid common 8000 conflicts (Django/Rails/Jupyter).
|
||||
export const API = 'http://localhost:3900';
|
||||
|
||||
export class ApiError extends Error {
|
||||
status?: number;
|
||||
|
||||
@@ -13,7 +13,7 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
server: {
|
||||
port: 5173,
|
||||
port: 3901,
|
||||
strictPort: true,
|
||||
host: false,
|
||||
watch: {
|
||||
|
||||
Reference in New Issue
Block a user