Replace the ad-hoc `worker.js` with a self-contained `linearvoid-media` worker under `infrastructure/cloudflare/` that owns `media.linearvoid.tv`. It serves HLS objects from the R2 bucket, enforcing immutable Cache-Control on segments, a short TTL on live manifests, plus HLS CORS, OPTIONS preflight, Range support, and a `/health` probe. Includes wrapper config with production domain, Vitest unit tests, Miniflare R2 integration tests, automated deploy workflow, and docs updates.
108 lines
5.0 KiB
Markdown
108 lines
5.0 KiB
Markdown
# Gitea to Cloudflare Workers — Linear Void
|
|
|
|
## Goal
|
|
|
|
Deploy the Linear Void frontend (Vite + TypeScript SPA) from Gitea to Cloudflare Workers using Gitea Actions and Wrangler.
|
|
|
|
## Prerequisites
|
|
|
|
1. **Cloudflare Worker** for the SPA:
|
|
- Dashboard → Workers & Pages → Create → Worker (or Workers Static Assets).
|
|
- Name it `linearvoid-frontend` (the edge-cache Worker already uses the `linearvoid` name).
|
|
2. **API token** with Workers permissions:
|
|
- Create at <https://dash.cloudflare.com/profile/api-tokens>
|
|
- Permission: `Account → Workers Scripts → Edit` and `Account → Workers Routes → Edit`
|
|
- Store in Gitea → Settings → Secrets as `CLOUDFLARE_API_TOKEN`
|
|
3. **Account ID** from Cloudflare dashboard overview → store as `CLOUDFLARE_ACCOUNT_ID`
|
|
4. **Wrangler config** (`frontend/wrangler.toml`) binding the `frontend/dist` output as static assets.
|
|
|
|
> **Naming:** Workers share a namespace under "Workers & Pages". The media edge Worker is `linearvoid-media` ([`infrastructure/cloudflare/`](../../infrastructure/cloudflare/wrangler.toml), deployed via `.gitea/workflows/workers-media-deploy.yml`) and the SPA Worker is `linearvoid-frontend` (`frontend/wrangler.toml`, deployed via `.gitea/workflows/workers-deploy.yml`).
|
|
|
|
## Project-specific values
|
|
|
|
| Setting | Value |
|
|
| ------------------ | ---------------------------------------------------------- |
|
|
| Framework | Vite + TypeScript |
|
|
| Build command | `cd frontend && npm install && npm run build` |
|
|
| Output directory | `frontend/dist` |
|
|
| Node version | 22 |
|
|
| Multi-page entries | `index.html`, `admin/index.html`, `admin/login/index.html` |
|
|
|
|
## Gitea Actions workflow
|
|
|
|
Build the SPA and deploy with Wrangler:
|
|
|
|
```yaml
|
|
name: Deploy to Cloudflare Workers
|
|
|
|
on:
|
|
workflow_run:
|
|
workflows: [CI]
|
|
types: [completed]
|
|
workflow_dispatch: {}
|
|
|
|
jobs:
|
|
deploy:
|
|
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
|
|
- name: Install dependencies
|
|
run: cd frontend && npm ci
|
|
|
|
- name: Build
|
|
env:
|
|
VITE_PUBLIC_APP_URL: ${{ secrets.VITE_PUBLIC_APP_URL }}
|
|
VITE_PUBLIC_WS_URL: ${{ secrets.VITE_PUBLIC_WS_URL }}
|
|
VITE_PUBLIC_HLS_URL: ${{ secrets.VITE_PUBLIC_HLS_URL }}
|
|
VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR: ${{ secrets.VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR }}
|
|
VITE_PUBLIC_ADMIN_DEFAULT_ROOM: ${{ secrets.VITE_PUBLIC_ADMIN_DEFAULT_ROOM }}
|
|
VITE_PUBLIC_ADMIN_MODERATION_LOG_LIMIT: "50"
|
|
run: cd frontend && npm run build
|
|
|
|
- name: Deploy to Cloudflare Workers
|
|
env:
|
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
run: |
|
|
cd frontend
|
|
npx wrangler deploy
|
|
```
|
|
|
|
## Secrets to add in Gitea
|
|
|
|
| Secret | Value |
|
|
| ------------------------------------- | ------------------------------------ |
|
|
| `CLOUDFLARE_API_TOKEN` | API token with Workers permissions |
|
|
| `CLOUDFLARE_ACCOUNT_ID` | Cloudflare account ID from dashboard |
|
|
| `VITE_PUBLIC_APP_URL` | Public viewer URL |
|
|
| `VITE_PUBLIC_WS_URL` | WebSocket endpoint |
|
|
| `VITE_PUBLIC_HLS_URL` | HLS playlist URL |
|
|
| `VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR` | Default moderator username |
|
|
| `VITE_PUBLIC_ADMIN_DEFAULT_ROOM` | Default chat room |
|
|
|
|
## Verify deployment
|
|
|
|
1. Push to `main` or trigger manually from Gitea Actions.
|
|
2. Check **Gitea Actions** → job logs for the deploy step.
|
|
3. Check **Cloudflare Workers** → `linearvoid-frontend` → Deployments for the new version.
|
|
4. Visit `https://linearvoid-frontend.zwitschi82.workers.dev`, then attach `linearvoid.tv` when ready.
|
|
|
|
## Notes
|
|
|
|
- The existing `ci.yml` already builds the frontend; the Workers deploy workflow is additive and independent.
|
|
- Multi-page SPA (`vite.config.ts`) produces three entry points — Workers static assets serve them correctly.
|
|
- For SPA fallback routing, set Workers static assets `not_found_handling` to `single-page-application` (serve `index.html` for unknown paths).
|
|
- The deploy workflow lives in `.gitea/workflows/workers-deploy.yml` (triggered after CI succeeds).
|
|
|
|
## Related resources
|
|
|
|
- Cloudflare Workers dashboard: `https://dash.cloudflare.com/deb11491c54ec53a24772e98ac6d8128/workers/services/view/linearvoid/production/settings` — for managing the `infrastructure/cloudflare/worker.js` deployment and the SPA Worker
|