fix(deploy): configure pnpm allowBuilds and add Cloudflare deployment setup
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
# Gitea Actions mirror of .github/workflows/ci.yml.
|
||||||
|
# Typecheck / test / build on every push & PR; deploy the SPA to Cloudflare
|
||||||
|
# Workers (static assets) on pushes to main.
|
||||||
|
#
|
||||||
|
# Required Gitea config (Repo → Settings → Actions → Secrets / Variables):
|
||||||
|
# Variable VITE_API_BASE_URL — Laravel API base URL baked into the build
|
||||||
|
# Secret CLOUDFLARE_API_TOKEN — token with "Edit Cloudflare Workers" scope
|
||||||
|
# Secret CLOUDFLARE_ACCOUNT_ID — Cloudflare account id
|
||||||
|
#
|
||||||
|
# Requires an act_runner registered with the `ubuntu-latest` label, using an
|
||||||
|
# image that has git + node bootstrapping (e.g. catthehacker/ubuntu:act-22.04).
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ci-${{ gitea.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
name: Typecheck, test & build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
cache: pnpm
|
||||||
|
- run: pnpm install --frozen-lockfile
|
||||||
|
- run: pnpm run generate-routes
|
||||||
|
- run: pnpm run typecheck
|
||||||
|
- run: pnpm test
|
||||||
|
- run: pnpm run build
|
||||||
|
env:
|
||||||
|
VITE_API_BASE_URL: ${{ vars.VITE_API_BASE_URL }}
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
name: Deploy to Cloudflare Workers
|
||||||
|
needs: check
|
||||||
|
if: gitea.ref == 'refs/heads/main'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
cache: pnpm
|
||||||
|
- run: pnpm install --frozen-lockfile
|
||||||
|
- run: pnpm run generate-routes
|
||||||
|
# cf:build runs `vite build` then copies the TanStack Start SPA shell
|
||||||
|
# (_shell.html) to index.html so Cloudflare's single-page-application
|
||||||
|
# fallback (wrangler.jsonc) returns it for every client route.
|
||||||
|
- name: Build SPA
|
||||||
|
run: pnpm run cf:build
|
||||||
|
env:
|
||||||
|
VITE_API_BASE_URL: ${{ vars.VITE_API_BASE_URL }}
|
||||||
|
- name: Deploy
|
||||||
|
uses: cloudflare/wrangler-action@v3
|
||||||
|
with:
|
||||||
|
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
# Typecheck / test / build on every push & PR; deploy the SPA to Cloudflare
|
||||||
|
# Workers (static assets) on pushes to main.
|
||||||
|
#
|
||||||
|
# Required GitHub config (Settings → Secrets and variables → Actions):
|
||||||
|
# Variable VITE_API_BASE_URL — Laravel API base URL baked into the build
|
||||||
|
# Secret CLOUDFLARE_API_TOKEN — token with "Edit Cloudflare Workers" scope
|
||||||
|
# Secret CLOUDFLARE_ACCOUNT_ID — Cloudflare account id
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ci-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
name: Typecheck, test & build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
cache: pnpm
|
||||||
|
- run: pnpm install --frozen-lockfile
|
||||||
|
- run: pnpm run generate-routes
|
||||||
|
- run: pnpm run typecheck
|
||||||
|
- run: pnpm test
|
||||||
|
- run: pnpm run build
|
||||||
|
env:
|
||||||
|
VITE_API_BASE_URL: ${{ vars.VITE_API_BASE_URL }}
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
name: Deploy to Cloudflare Workers
|
||||||
|
needs: check
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
cache: pnpm
|
||||||
|
- run: pnpm install --frozen-lockfile
|
||||||
|
- run: pnpm run generate-routes
|
||||||
|
# cf:build runs `vite build` then copies the TanStack Start SPA shell
|
||||||
|
# (_shell.html) to index.html so Cloudflare's single-page-application
|
||||||
|
# fallback (wrangler.jsonc) returns it for every client route.
|
||||||
|
- name: Build SPA
|
||||||
|
run: pnpm run cf:build
|
||||||
|
env:
|
||||||
|
VITE_API_BASE_URL: ${{ vars.VITE_API_BASE_URL }}
|
||||||
|
- name: Deploy
|
||||||
|
uses: cloudflare/wrangler-action@v3
|
||||||
|
with:
|
||||||
|
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
@@ -11,3 +11,5 @@ dist-ssr
|
|||||||
.vinxi
|
.vinxi
|
||||||
__unconfig*
|
__unconfig*
|
||||||
todos.json
|
todos.json
|
||||||
|
*.profraw
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,41 @@ ddev exec php artisan tinker storage/app/e2e-admin-seed.php
|
|||||||
| `pnpm test` | vitest (API client envelope/refresh/error tests) |
|
| `pnpm test` | vitest (API client envelope/refresh/error tests) |
|
||||||
| `pnpm gen:api` | regenerate `src/api/types.gen.ts` from the backend's scribe-admin OpenAPI spec (`../gig-platform/public/api-docs/admin/openapi.yaml`; run `ddev exec php artisan scribe:generate --config scribe-admin` there first) |
|
| `pnpm gen:api` | regenerate `src/api/types.gen.ts` from the backend's scribe-admin OpenAPI spec (`../gig-platform/public/api-docs/admin/openapi.yaml`; run `ddev exec php artisan scribe:generate --config scribe-admin` there first) |
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
The app is a client-rendered SPA served as static assets by a Cloudflare Worker
|
||||||
|
(`wrangler.jsonc`, `not_found_handling: single-page-application`). The build
|
||||||
|
emits `_shell.html`, which is copied to `index.html` so Cloudflare's SPA
|
||||||
|
fallback returns it for every client route.
|
||||||
|
|
||||||
|
**Manual deploy** (needs `wrangler login` or `CLOUDFLARE_API_TOKEN` /
|
||||||
|
`CLOUDFLARE_ACCOUNT_ID` in your env):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm cf:deploy # vite build → copy shell to index.html → wrangler deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
**CI/CD** — every push & PR runs typecheck + test + build; pushes to `main`
|
||||||
|
build and deploy to Cloudflare. Two mirrored pipelines are provided:
|
||||||
|
|
||||||
|
| Platform | Workflow |
|
||||||
|
| --- | --- |
|
||||||
|
| GitHub Actions | `.github/workflows/ci.yml` |
|
||||||
|
| Gitea Actions | `.gitea/workflows/ci.yml` |
|
||||||
|
|
||||||
|
Configure these on the repo before the first deploy:
|
||||||
|
|
||||||
|
| Type | Name | Value |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Variable | `VITE_API_BASE_URL` | backend API origin baked into the build |
|
||||||
|
| Secret | `CLOUDFLARE_API_TOKEN` | token with "Edit Cloudflare Workers" scope |
|
||||||
|
| Secret | `CLOUDFLARE_ACCOUNT_ID` | Cloudflare account id |
|
||||||
|
|
||||||
|
- GitHub: *Settings → Secrets and variables → Actions*.
|
||||||
|
- Gitea: *Repo → Settings → Actions → Secrets / Variables*. Actions must be
|
||||||
|
enabled and an `act_runner` registered with the `ubuntu-latest` label (use an
|
||||||
|
image such as `catthehacker/ubuntu:act-22.04`).
|
||||||
|
|
||||||
## Architecture notes
|
## Architecture notes
|
||||||
|
|
||||||
- **Auth**: Bearer tokens in localStorage (zustand persist). `src/api/client.ts`
|
- **Auth**: Bearer tokens in localStorage (zustand persist). `src/api/client.ts`
|
||||||
|
|||||||
+5
-8
@@ -12,7 +12,9 @@
|
|||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"gen:api": "node scripts/gen-api.mjs",
|
"gen:api": "node scripts/gen-api.mjs",
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit",
|
||||||
|
"cf:build": "vite build && node -e \"require('fs').copyFileSync('.output/public/_shell.html','.output/public/index.html')\"",
|
||||||
|
"cf:deploy": "pnpm cf:build && wrangler deploy"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.4.0",
|
"@hookform/resolvers": "^5.4.0",
|
||||||
@@ -58,12 +60,7 @@
|
|||||||
"openapi-typescript": "^7.13.0",
|
"openapi-typescript": "^7.13.0",
|
||||||
"typescript": "^6.0.2",
|
"typescript": "^6.0.2",
|
||||||
"vite": "^8.0.0",
|
"vite": "^8.0.0",
|
||||||
"vitest": "^4.1.5"
|
"vitest": "^4.1.5",
|
||||||
},
|
"wrangler": "^4.111.0"
|
||||||
"pnpm": {
|
|
||||||
"onlyBuiltDependencies": [
|
|
||||||
"esbuild",
|
|
||||||
"lightningcss"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+824
-41
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
|||||||
|
allowBuilds:
|
||||||
|
esbuild: true
|
||||||
|
lightningcss: true
|
||||||
|
sharp: true
|
||||||
|
workerd: true
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/wrangler/config-schema.json",
|
||||||
|
"name": "gig-admin",
|
||||||
|
"compatibility_date": "2026-07-15",
|
||||||
|
// Assets-only Worker: gig-admin is a client-rendered SPA (see vite.config.ts
|
||||||
|
// `spa: { enabled: true }`), so there is no server to run — Cloudflare just
|
||||||
|
// serves the static build and falls back to the SPA shell for client routes.
|
||||||
|
// `pnpm cf:build` copies the TanStack Start shell to index.html, which
|
||||||
|
// `single-page-application` handling serves for any non-asset request.
|
||||||
|
"assets": {
|
||||||
|
"directory": ".output/public",
|
||||||
|
"not_found_handling": "single-page-application"
|
||||||
|
},
|
||||||
|
"observability": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user