From c13cd5a50e3f798d1442138ac7a377dbfcdd36ba Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sun, 13 Sep 2026 13:39:34 +0800 Subject: [PATCH 1/4] Run the platform lint and typecheck after the builds in CI. `vp run lint:platform` reads the dashboard's generated `.void/tsconfig.json`, which only exists after the dashboard build, and the root `check` typechecks the playgrounds this job never builds. Both deploy workflows call this job first, so it must pass on a fresh checkout. The hunk matches the one on #316. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01WNXbwieSdsSErZwQ7HWRwG --- .github/workflows/platform-ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/platform-ci.yml b/.github/workflows/platform-ci.yml index 2fe7f2cee..99f976f6a 100644 --- a/.github/workflows/platform-ci.yml +++ b/.github/workflows/platform-ci.yml @@ -43,10 +43,14 @@ jobs: node-version-file: .node-version - run: vp fmt --check - run: vp lint - - run: vp run lint:platform - run: vp run build - run: vp run --filter './platform/packages/**' build - - run: vp run check + # After the builds: the type-aware platform lint reads the dashboard's generated + # `.void/tsconfig.json`, which only exists once the dashboard has been built. + - run: vp run lint:platform + # Platform packages only. The framework and the playgrounds are typechecked by ci.yml, and + # the playground typechecks need the playground builds, which this job does not run. + - run: vp run check:platform test: runs-on: blacksmith-4vcpu-ubuntu-2404 From 526e3422a0e0ff9b58975149859d0b315481fffc Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sun, 13 Sep 2026 13:52:52 +0800 Subject: [PATCH 2/4] Document the monorepo platform deploy workflows. Both docs still described the old repo's push-to-`prod` / push-to-`main` deploy model, and the README claimed the task graph builds the SDK for the dashboard. Describe the `platform-*.yml` workflows as they are: manual dispatch, gated on `VOID_PLATFORM_DEPLOY_ENABLED`, with an explicit `vp run build` before the deploy step. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01WNXbwieSdsSErZwQ7HWRwG --- platform/README.md | 2 +- platform/meta/operations.md | 45 ++++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/platform/README.md b/platform/README.md index 6057e22bc..6de8babbc 100644 --- a/platform/README.md +++ b/platform/README.md @@ -144,7 +144,7 @@ Void is one repository with an explicit dependency boundary: | User-facing dashboard | `packages/dashboard/pages/*`, `packages/dashboard/middleware/01.auth.ts`, `packages/dashboard/lib/api.ts` | | Shared internal styling | `packages/ui/src/base.css`, `packages/ui/src/theme.css` | -The dashboard depends on `void` and `@void/react` through normal `workspace:*` dependencies. The monorepo task graph builds those packages before the dashboard when required. +The dashboard depends on `void` and `@void/react` through normal `workspace:*` dependencies. Those packages export only their `dist/` output, so run `vp run build` before `vp run --filter @voidcloud/platform deploy` on a fresh checkout. The platform workflows do this; the task graph does not. ## SDK overview diff --git a/platform/meta/operations.md b/platform/meta/operations.md index e1ac2ff73..2c847884c 100644 --- a/platform/meta/operations.md +++ b/platform/meta/operations.md @@ -27,10 +27,10 @@ Five Cloudflare Workers: Two fully isolated environments. Each has its own CF resources (KV, R2, dispatch namespace, analytics engine) and a separate Hyperdrive configuration pointing to its own PlanetScale PostgreSQL database. -| Environment | API URL | Dashboard | User Sites | Trigger | -| -------------- | ------------------------ | ------------------------- | -------------------- | ---------------------------- | -| **Production** | `api.void.cloud` | `dash.void.cloud` | `*.void.app` | Push to `prod` branch | -| **Staging** | `api.staging.void.cloud` | `dash.staging.void.cloud` | `*.staging.void.app` | Push to `main` branch (auto) | +| Environment | API URL | Dashboard | User Sites | Trigger | +| -------------- | ------------------------ | ------------------------- | -------------------- | --------------------------------------------- | +| **Production** | `api.void.cloud` | `dash.void.cloud` | `*.void.app` | Manual: "Deploy Platform Production" workflow | +| **Staging** | `api.staging.void.cloud` | `dash.staging.void.cloud` | `*.staging.void.app` | Manual: "Deploy Platform Staging" workflow | ## Cloudflare Resources @@ -231,7 +231,7 @@ Two GitHub environments (`Prod` and `Staging`) share the same repo-level secrets | `CF_ACCESS_CLIENT_ID_STAGING` | Staging | CF Access service-token client id for reaching staging (see Staging Access Control) | | `CF_ACCESS_CLIENT_SECRET_STAGING` | Staging | CF Access service-token client secret for reaching staging | -`deploy.yml` (push to `prod`) uses the `Prod` environment; `deploy-staging.yml` (push to `main`) uses `Staging`. +`platform-deploy.yml` uses the `Prod` environment; `platform-deploy-staging.yml` uses `Staging`. Both run only on manual dispatch and only when the repository variable `VOID_PLATFORM_DEPLOY_ENABLED` is `true`. **GitHub Actions `CF_API_TOKEN` permissions** — narrower-scope token used only for wrangler deploys. Separate from the API worker runtime token. @@ -502,28 +502,31 @@ This is a clean cutover. The API only reads project secrets from `project_secret ### GitHub Actions -Three workflows in `.github/workflows/`: +Four platform workflows live in the repository-level `.github/workflows/` directory, prefixed `platform-`. Every deploy and smoke-test job is gated on the repository variable `VOID_PLATFORM_DEPLOY_ENABLED == 'true'`. -**`ci.yml`** — runs on PRs to `main` and as a reusable workflow: +**`platform-ci.yml`** — runs on PRs to `main` that touch `platform/**`, `packages/**`, or the root manifests, and as a reusable workflow: -1. Set up Vite+ and Node.js (from `.node-version`) -2. `vp install --frozen-lockfile` -3. `vp run build:all` (build all platform surfaces that define a build) -4. `vp lint` (oxlint through Vite+) -5. `vp run check` (typecheck all packages) -6. `vp test run` (full test suite) +1. Set up Vite+ and Node.js (from `.node-version`); `setup-vp` runs `vp install` +2. `vp fmt --check`, `vp lint` +3. `vp run build` (SDK packages), then `vp run --filter './platform/packages/**' build` +4. `vp run lint:platform` (type-aware lint; needs the dashboard build output) +5. `vp run check:platform` (typecheck platform packages only) +6. `vp test run --project platform-unit` and `--project platform-api-integration` +7. Builds the API build container image (PRs only) -**`deploy.yml`** — runs on push to `prod` (production, environment: `Prod`): +**`platform-deploy.yml`** — manual dispatch (production, environment: `Prod`): -1. Runs CI workflow first -2. Builds the framework packages used by the dashboard -3. `vp run deploy` (api with drizzle-kit migrations, proxy, tail, dispatch, dashboard) +1. Runs `platform-ci.yml` first +2. `vp run build` (SDK packages the dashboard bundles) +3. `vp run --filter @voidcloud/platform deploy` (api with drizzle-kit migrations, proxy, tail, dispatch, dashboard) -**`deploy-staging.yml`** — runs on push to `main` (staging, environment: `Staging`): +**`platform-deploy-staging.yml`** — manual dispatch (staging, environment: `Staging`): -1. Runs CI workflow first -2. Builds the framework packages used by the dashboard -3. `vp run deploy:staging` (api with drizzle-kit migrations, proxy, tail, dispatch, dashboard — all to staging) +1. Runs `platform-ci.yml` first +2. `vp run build` +3. `vp run --filter @voidcloud/platform deploy:staging` (same order, all to staging) + +**`platform-smoke-test.yml`** — manual dispatch (environment: `Staging`): builds the SDK, deploys `playground/kitchen-sink` to staging with `void deploy`, resets its state, and runs `platform/scripts/kitchen-sink-smoke-test.ts` against `https://kitchen-sink.staging.void.app`. ### Health Checks From 2b146f84a1090b11ff31fe1538d0a95e5ad663c4 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sun, 13 Sep 2026 13:59:12 +0800 Subject: [PATCH 3/4] Name the platform deploy orchestrator and its working directory. `platform/package.json` owns the `deploy*` scripts, not the root manifest, and they only resolve from `platform/` or through `--filter @voidcloud/platform` from the root. Say so once at the top of the README and in the operations runbook, and drop the dashboard bullet that said it deploys outside the platform pipeline: both `deploy` and `deploy:staging` end with the dashboard. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01WNXbwieSdsSErZwQ7HWRwG --- platform/README.md | 4 ++-- platform/meta/operations.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/README.md b/platform/README.md index 6de8babbc..a5e9bd735 100644 --- a/platform/README.md +++ b/platform/README.md @@ -2,7 +2,7 @@ The hosted Void platform lives in `platform/` inside the main Void monorepo. Public SDK packages live in the repository-level `packages/` directory. Both surfaces share one pnpm workspace, lockfile, Vite+ configuration, and commit history. -Paths in this file are relative to `platform/` unless they begin with `../`. For example, `packages/api` is the hosted control plane and `../packages/void` is the public SDK package. +Paths in this file are relative to `platform/` unless they begin with `../`. For example, `packages/api` is the hosted control plane and `../packages/void` is the public SDK package. The bare `vp run deploy*` commands in this file are `platform/package.json` scripts and run from `platform/`; from the repository root, the equivalent is `vp run --filter @voidcloud/platform