Skip to content

void deploy in CI fails when the project build opens a Cloudflare remote session (Astro prerender with ai) #425

Closed

Description

@Brooooooklyn

Problem

A direct Cloudflare app whose build opens a remote-bindings session cannot be
deployed from CI, even with CLOUDFLARE_API_TOKEN set. Known cases:

  • Astro (@astrojs/cloudflare 14.x) with at least one prerendered page and an
    ai binding (Void writes ai: { binding, remote: true } into the project
    config during dev for apps that import void/ai).
  • SvelteKit 2 with adapter-cloudflare 7.x and prerendered pages (code only;
    kit 3 / adapter 8 has no build-time platform emulation).

The build stops with:

Establishing remote connection...
Failed to start the remote proxy session. ... In a non-interactive environment,
it's necessary to set a CLOUDFLARE_API_TOKEN environment variable for cf to work.

The user did set the token, so the message is misleading.

Locally this is fixed by #424: the Void plugin selects the void cloudflare login
session for direct Cloudflare apps, so a local build's remote session uses the
same login as void deploy. CI has no stored login, and the deploy build removes
the token from the project build on purpose (see Cause).

Repro

  1. Astro 7 app with @astrojs/cloudflare 14.3.4, voidPlugin(), .void/project.json
    { "platform": "cloudflare" }, a route importing void/ai, and one page with
    export const prerender = true. Run vp dev once (adds the remote ai binding).
  2. In CI (no cf login, CI=1), set CLOUDFLARE_API_TOKEN and run
    void deploy --platform cloudflare.
  3. The build fails as above. A plain astro build with the token in the
    environment should work, because nothing removes the token there (expected
    from the auth order, not run).

The void deploy path is traced in code, not run. A plain astro build with no
token and CI=1 shows the same failure live.

Cause

  • packages/void/src/cli/deploy-cloudflare-build.ts:76-78 builds the child env
    with scrubWranglerAuthCredentials(deployChildEnv(...)) and runs the project
    build with it (:103).
  • packages/void/src/cli/deploy-transport.ts:225-235 deletes every name in
    WRANGLER_AUTH_CREDENTIAL_ENV_VARS (packages/void/src/shared/untrusted-env.ts:4-17),
    including CLOUDFLARE_API_TOKEN. This is on purpose: the build runs project
    code (Vite config, plugins, adapters), and the orchestrator keeps its API
    credentials away from it (buildCloudflareWorker doc comment, :43).
  • @astrojs/cloudflare dist/prerenderer.js:107-121 starts vite.preview()
    with the Cloudflare plugin; @cloudflare/vite-plugin 1.64.0
    dist/index.mjs:96433 -> 95823 -> 92706 starts a remote session because ai
    is never local (pickRemoteBindings, :92698). With no token and no stored
    login in CI, authentication fails.

Options

  1. Pass the token to the build only when needed. Simple, but it hands the
    deploy credential to project code, which the build isolation exists to prevent.
    Not recommended.
  2. Turn off remote bindings for the deploy build when the deploy uses an
    environment token.
    Set CLOUDFLARE_VITE_FORCE_LOCAL=true in buildChildEnv
    (@cloudflare/vite-plugin dist/index.mjs:71972 maps it to
    remoteBindings: false). Pages that do not call AI at build time would
    prerender. Gaps: Wrangler's getPlatformProxy (SvelteKit 2) has no env
    switch, only a remoteBindings option the adapter owns; a page that calls
    AI while prerendering would fail with a missing-binding error instead.
    Needs a check of how the plugin treats a never-local binding when remote
    bindings are off.
  3. Strip remote: true / the dev-only ai binding from the config the
    deploy build reads.
    Void writes that binding for dev; the build does not
    need it, because production gets the binding at upload. Needs care: the
    adapter copies ai into the prerender Worker, and AI is remote even
    without the flag, so the binding itself would have to be dropped for the
    build and restored for dev.
  4. Document it. In CI, run the deploy from a job that does not prerender
    pages needing remote bindings, or mark such pages dynamic.

Recommendation: try option 2 behind a test that runs the Astro prerender with
the deploy build env, and keep option 4 as the interim docs note.

🤖 Generated with Claude Code

https://claude.ai/code/session_0123r5HnanmW2VUrZ7VWDufH

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions