Repository navigation
Conversation
Move each package's and playground's `build` script into `run.tasks.build` in its vite.config.ts, so `vp run` caches it, locally and in the remote cache, with automatically tracked inputs and outputs. - Build packages in dependency order with a root `build` task instead of `--parallel`, so no build reads a dependency's outputs while they are rebuilt or restored. @void/md builds last: it and void depend on each other. - @void/platform: run `vp pack` as its own `build:pack` task. The runtime build tracks VOID_PLATFORM_SOURCE_REVISION and Git's HEAD and refs, which its manifest records, and waits for @void/isr, whose build output the dispatch Worker bundles. - playground/astro: pass NODE_EXTRA_CA_CERTS to the build without fingerprinting it, for Miniflare's `Request.cf` download behind a TLS-intercepting proxy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read the remote cache endpoint from the VP_REMOTE_CACHE_URL repository variable. Pushes upload results, authenticated with a GitHub Actions OIDC token; pull requests only download them. Without the variable the remote cache stays off. Set VOID_PLATFORM_SOURCE_REVISION to the commit, so the cached platform runtime build records it without running `git`, whose reads of the whole checkout would otherwise become inputs of the task. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ules Install vite-plus, its core, and prompts at 0.0.0-commit.80a3cbc3 from the Vite+ registry bridge: the preview of voidzero-dev/vite-plus#3113, which bumps vite-task to the feat/rebuildable-cache-rules branch. That vite-task caches tasks that write files they read and restores outputs a hit can rebuild, which the build tasks need. Drop this commit once a vite-plus release includes those rules. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wan9chi
force-pushed
the
feat/remote-cache-build-all
branch
from
October 19, 2026 06:47
57dcba9 to
a2fc5b4
Compare
Pull requests from this repository now upload their task results too, so a pull request's later runs reuse its earlier ones and the cache can be seen working before merging. The cache server accepts them only once void's namespace opts in to pull request uploads (voidzero-dev/vite-plus-remote-cache-cloudflare#16 tracks scoping them to the pull request). Fork pull requests get no OIDC token and stay read-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The runtime build recorded the source revision in its manifest, so it fingerprinted VOID_PLATFORM_SOURCE_REVISION and Git's HEAD and refs and reran on every commit. It now writes the manifest without a revision, and an uncached `build` step records the revision afterwards, so a new commit reruns only that step. - `build:runtime` runs scripts/build-runtime.mjs after `build:pack` and `@void/isr#build`, with default caching. - `build` runs scripts/stamp-source-revision.mjs with `cache: false`. It resolves the revision as before, from VOID_PLATFORM_SOURCE_REVISION or `git`, and validates the manifest again. An uncached task gets the full environment, so CI's VOID_PLATFORM_SOURCE_REVISION still reaches it. - Drop the `.git/HEAD` and `.git/refs/**` inputs. In a linked Git worktree, where `.git` is a file, they made the cache lookup fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It was set so the cached runtime build would record the commit without running `git`. The revision is now stamped by an uncached step, which can run `git` itself. Set at job level, the variable reached every task, and the playgrounds whose builds fingerprint the whole environment (react-router, tanstack-start, astro, sveltekit) missed on every commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Prerendering starts Miniflare, which downloads Cloudflare's `Request.cf` data. Instead of forwarding NODE_EXTRA_CA_CERTS as an untracked env, the task runs with NODE_USE_SYSTEM_CA=1, so a TLS-intercepting proxy whose CA is in the system store works without per-machine paths, and the task's environment is the same everywhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wan9chi
added a commit
to voidzero-dev/vite-plus-remote-cache-cloudflare
that referenced
this pull request
Oct 19, 2026
…ith void (#17) ## Motivation [voidzero-dev/void#492](voidzero-dev/void#492) caches every task `build:all` runs, and its PR CI should show remote cache reuse before it merges. void#492 already makes same-repository PR runs read-write, but the production cache only accepts uploads from default-branch `push` jobs, so those PR uploads get `403 write_policy`. The decision is to let void's same-repository PR CI upload to its namespace (`https://voidzero-remote-cache.voidzero-docs.workers.dev/projects/void`) for now. Every other namespace keeps the main-branch-push-only policy. ## Design - **Opt-in per namespace, off by default.** Migration `0002_pull_requests.sql` adds `scopes.pull_requests` (0/1, default 0) and recreates the `changed_policy` trigger with that column, so turning the opt-in on or off bumps `policy_version` and stops uploads admitted under the old policy. - **Write policy (`src/auth.ts`).** `push` tokens work as before. For an opted-in namespace, a `pull_request` token passes the same audience, `repository_id`, `repository_owner_id`, and `repository_visibility: public` checks, and also needs: - `ref` matching `refs/pull/<number>/merge` - `ref_type` `branch` - `base_ref` equal to the registered default branch's short name (`main`, not `refs/heads/main`) These are the values GitHub signs for a PR's merge-branch run: see the [`ref` description](https://docs.github.com/en/actions/reference/workflows-and-actions/variables) ("for pull request events except `pull_request_target` that were not merged, it is `refs/pull/<pr_number>/merge`"), `GITHUB_BASE_REF` ("for example, `main`"), the [OIDC claim reference](https://docs.github.com/en/actions/reference/security/oidc), and the decoded `pull_request` token in [github/actions-oidc-debugger](https://github.com/github/actions-oidc-debugger) (`"ref": "refs/pull/27/merge"`, `"ref_type": "branch"`, `"base_ref": "main"`). `pull_request_target`, `workflow_run`, tags, PRs to other branches, the `closed` run of a merged PR (whose `ref` is the base branch), and workflows in fork repositories are still denied. - **Configuration.** A `.github/production-repositories.jsonc` entry can now be `{ "repository": "owner/repo", "pullRequests": true }` as well as `"owner/repo"`, which means `pullRequests: false`. Only `void` uses the object form. `pnpm ci:deploy production` sets every namespace's opt-in from the list on each run, the same way it already handles `enabled`/`writes_enabled`. Self-hosters use `pnpm operator policy --pull-requests on|off`, or `setup --pull-requests on` when creating a namespace. `status` already prints the full row. - **Staging** keeps `pull_requests = 0`, so PR staging runs still check that PR tokens are rejected. - **Logging.** Verified writes now also log `event_name` and `head_ref`. `base_ref` always equals the default branch, and the PR number is already in `workflow_ref`. ## Risk PR entries share the namespace with default-branch entries. Code from any same-repository PR, including Renovate dependency branches, runs before review and can publish an entry that a later default-branch build restores. That's why the opt-in is off by default and only on for void. The README, self-hosting guide, e2e plan, and RFC describe it as interim and link the long-term fix, #16 (scope pull request uploads to the pull request). The server can't tell fork PRs from same-repository PRs: fork PR runs carry the base repository's IDs. It relies on GitHub not granting `id-token: write` to fork PR workflows. GitHub only does that when "Send write tokens to workflows from pull requests" is enabled, a setting it offers for private repositories only. The docs state this dependency. ## After merge Production changes only after a maintainer runs **Actions → Remote cache production** on `main`. That run applies migration 0002 and enables PR uploads for `void`. Its log should print `Enabled pull request uploads for namespace void`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… run --cache Move every `build` back into package.json scripts, as on main, and turn caching on where build:all runs (the `test:all` task and CI's build job) with `vp run --cache build:all`. `--cache` caches package.json scripts too, and reaches the nested `vp run` calls, so no package needs a vite.config task to be cached. Each step of an `&&` chain is cached on its own. - Root `build` script: build packages in dependency order instead of `--parallel`, @void/md last, since it and void depend on each other. - @void/platform: `vp pack && node scripts/build-runtime.mjs && vp run build:stamp`. `build:stamp`, the only vite.config task left, records the source revision with `cache: false`, so a new commit reruns only that step. - @void/platform: add @void/isr as a dev dependency. The runtime build bundles `@void/isr/runtime` from isr's build output, and the dependency makes the root build run isr first. - playground/astro: `NODE_USE_SYSTEM_CA=1 astro build`, for Miniflare's `Request.cf` download behind a TLS-intercepting proxy. - Delete the vite.config.ts files that only held the build task. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
vp run build:all(38 package and playground builds) runs every build from scratch on every CI run and every local run. This caches those builds, locally and in CI's remote cache, by runningvp run --cache build:all. Inputs and outputs are tracked automatically, so a hit restoresdist/,.void/,.output/and so on.Important
Depends on the vite-plus preview build from voidzero-dev/vite-plus#3113, which bumps vite-task to its
feat/rebuildable-cache-rulesbranch. Those rules cache tasks that write files they read, and restore outputs that a hit can rebuild. Don't merge before a vite-plus release includes them. Drop the commit that switches to the preview build then.What's configured
buildstays a package.json script, as on main.--cacheturns caching on for package.json scripts as well as vite.config tasks, and nestedvp runcalls without a cache flag inherit it, so no package needs a vite.config task to be cached. Each step of an&&chain is cached on its own. Plainvp run build:all, and every othervp run, still caches no scripts, sodevand friends are unaffected.vp run --cache build:allis used wherebuild:allruns: the roottest:alltask and the CIchecksjob.build:allitself is unchanged.buildscript builds packages in dependency order instead of--parallel:vp run --filter './packages/**' --filter '!./packages/md' build && vp run --filter ./packages/md build. With--parallel, a build could read a dependency's outputs while they were still being restored or rebuilt.@void/mdbuilds last because it andvoiddepend on each other.@void/platform'sbuildscript isvp pack && node scripts/build-runtime.mjs && vp run build:stamp, so a new commit reruns only a small uncached step:scripts/build-runtime.mjs(admin client, five Workers, migrations) writesdist/runtime/manifest.jsonwithsourceRevision: nulland is cached like the other steps.build:stamp, the only vite.config task, runs the newscripts/stamp-source-revision.mjswithcache: false. It setssourceRevisionas before, fromVOID_PLATFORM_SOURCE_REVISIONor elsegit(with-dirtyfor a dirty tree), validates the manifest again withparsePlatformRuntimeManifestand writes it back. An uncached task gets the full environment, so the variable needs no declaration.VOID_PLATFORM_SOURCE_REVISIONor Git state. Nothing else reads the manifest at build time, and its SHA-256 is computed by the CLI from the installed file, so the stamp doesn't invalidate other tasks.@void/isris a new dev dependency of@void/platform: the dispatch Worker bundles@void/isr/runtimefrom isr's build output, and the dependency makes the rootbuildrun isr first. isr depends only on@void/edgeand@void/deploy-core, so this adds no cycle.playground/astro's script isNODE_USE_SYSTEM_CA=1 astro build. Miniflare downloadsRequest.cfwhile prerendering; trusting the system CA store makes that work behind a TLS-intercepting proxy whose CA is installed there, without forwarding a per-machineNODE_EXTRA_CA_CERTSpath.CI (second commit), for reviewers
checksjob reads the endpoint from theVP_REMOTE_CACHE_URLrepository variable, which is now set. Pushes and pull requests from this repository upload (read-write); fork pull requests, which get no OIDC token, only download (read). Without the variable, remote caching is off.id-token: writepermissions on thechecksjob and onpublish.yml'sci:caller; a reusable workflow can't request more than its caller grants. Please check these.VOID_PLATFORM_SOURCE_REVISION; the uncached stamp step runsgititself. Set at job level, the variable reached every task, and the playgrounds that fingerprint the whole environment (react-router, tanstack-start, astro, sveltekit) missed on every commit because its value changes with each one. The release workflows (publish.yml,prepublish-test.yml) still set it, as on main.Validation (macOS, preview build)
vp run --cache build:allno previous cache entry, none refused (26 s)'dist' added in 'packages/void'(listing issue below)'packages/platform/dist/runtime/manifest.json' modified(stamped-manifest issue below); the manifest records the new revisionvp run build:allwithout--cachecache disabled(24 s)The stamp runs every time.
node test/check-playground-build-artifacts.mjspasses.Known issues
.gitis a file, so a.git/HEADinput fails withNot a directory (os error 20). The failure isn't reported as an error:vp run build/build:coreskipped the platform runtime andvoidbuilds and still exited 0. void no longer has.gitinputs, andvp run build:corein a linked worktree now runs all 9 tasks. The silent skip remains a vite-task bug.vp pack/vp build, so each of those tasks misses withargs changedat another path. CI checks out at the same path every run, so CI isn't affected. Path-embedding playgrounds (astro, nuxt, …) can't cross paths anyway.dist,node_modules/.vite-temp, the dashboard's generated.void/tsconfig.jsonornode_modules/.pnpm-workspace-state-v1.jsonappear later, the step misses once (about 5 s).scripts/build-runtime.mjsreruns while an earlierdist/runtimeis still there, removing the old folder counts as reading the oldmanifest.json, so the entry records the manifest as the step left it, withsourceRevision: null. The stamp then changes it, and each later run misses with'packages/platform/dist/runtime/manifest.json' modifiedand records the same again. Locally this starts when the runtime step reruns whilevp packhits, for example after editing a platform Worker, and ends after a run withoutdist/runtime. In CI,preparerunsbuild:coreuncached beforebuild:all, which always leaves a stampeddist/runtime, so once uploads are accepted the runtime step would miss on every run. Avoiding it needs either the stamp to write the revision outside the runtime step's outputs, or vite-task to not treat a path a task deleted and recreated as one it read.🤖 Generated with Claude Code