Skip to content

feat: full-stack deploy — build a commit's worker from the CLI (cf arm) - #584

Open
netanelgilad wants to merge 14 commits into
mainfrom
fullstack/deploy-git-hash
Open

feat: full-stack deploy — build a commit's worker from the CLI (cf arm)#584
netanelgilad wants to merge 14 commits into
mainfrom
fullstack/deploy-git-hash

Conversation

@netanelgilad

@netanelgilad netanelgilad commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Note

Description

Adds the worker (cf) arm of the deployments API so a full-stack framework build (React Router 7, TanStack Start, Astro 6, vinext — anything built through @cloudflare/vite-plugin) can be deployed from the CLI as a Workers deployment addressed by the commit that produced it. The CLI detects the .wrangler/deploy/config.json redirect artifact, resolves and validates the generated wrangler config, collects the unbundled worker modules plus the static assets, POSTs asset buckets straight to Cloudflare under the upload-session JWT, then finalizes with the worker modules.

The worker and static arms are one flow with one createDeployment() call, not two lanes: deployToDeployments() checks for a worker itself, and that changes only what it sends (the worker's config on create, its modules at finalize). Everything downstream follows the server's answer — uploadDeploymentAssets() dispatches on the asset_uploads discriminant, finalizeDeployment() takes whichever payload completes the deployment. Deploy still only builds; nothing here publishes, and re-deploying a commit stays idempotent.

Related Issue

None (pairs with the cf arm of the backend's discriminated create response)

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Other (please describe):

Changes Made

  • One flow (core/site/deployment.ts, replacing static-site.ts): deployToDeployments() — resolve the worker if there is one → manifest → one createDeployment() → upload → finalize. config: worker?.config is the only difference on create, and its presence is what selects the storage target server-side.
  • Transport selection (usesDeploymentsApi()): a detected worker artifact always takes the deployments API (a tar.gz cannot ship a worker) and needs no site.outputDirectory, since the worker brings its own assets directory; a plain static build takes it only behind BASE44_STATIC_DEPLOYMENTS, else the legacy tar.gz upload. Asked after the build, because the artifact is itself a build output.
  • Artifact detection (core/site/wrangler-config.ts): the only trigger is .wrangler/deploy/config.json, with configPath resolved relative to the redirect file's own directory; hand-authored root configs are deliberately not artifacts. The resolved config must be no_bundle: true, and only fields the deploy acts on are declared, so bindings and the worker name ride along ignored.
  • Module collection (core/site/modules.ts): entry module plus the rules globs, relative paths as module names, wrangler.json / .dev.vars / the assets dir excluded, sourcemaps beside modules (all of them under upload_source_maps), 40 MB total cap under the server's 50 MB.
  • Commit address (core/site/git-hash.ts): resolveGitHash() — explicit --git-hash wins, otherwise git rev-parse HEAD; neither available fails fast with guidance. A malformed value is still rejected by the option's argParser before the action runs.
  • cf create arm (core/site/schema.ts): asset_uploads becomes a discriminated union (cf alongside s3), the request carries an optional worker config, and AssetUploadResponseSchema parses Cloudflare's bucket reply.
  • Direct Cloudflare uploads (core/site/upload.ts): buckets POST straight to Cloudflare with ?base64=true and a bearer session JWT — never the app client, which would leak app auth. 401/403 maps to "upload session expired — rerun deploy". The completion token is read from whichever bucket reply carries one, since the server decides completeness by manifest membership and buckets upload concurrently. Both arms now share one UPLOAD_RETRY on ky (the cf arm must name methods: ["post"] or bucket uploads would never retry).
  • One finalize (core/site/api.ts): finalizeDeployment(deploymentId, sessionId, payload) where payload is {modules, completionJwt} or {indexHtml}; the if lives inside the multipart form builder, where the protocol itself differs.
  • Warnings, not silent drops: missing nodejs_compat, wrangler vars, _headers/_redirects and run_worker_first route arrays are surfaced after the task rather than erroring or quietly changing behavior — the config is framework-generated, so the fix belongs in the adapter's settings.
  • Content types (core/site/manifest.ts): per-file MIME lookup for the cf arm's multipart parts; the s3 arm still echoes the server-signed Content-Type verbatim.
  • Command surface (cli/commands/site/deploy.ts): --git-hash and --concurrency are registered unconditionally (a worker build is ungated), the flow keeps saying "site" to the user whether or not there is a worker, and the tar.gz path is now the one that raises "No site configuration found."
  • Docs: docs/deployments.md rewritten to cover the single flow and both arms; docs/resources.md, docs/testing.md, docs/AGENTS.md updated.

Testing

  • I have tested these changes locally
  • I have added/updated tests as needed
  • All tests pass (npm test)

New: tests/cli/fullstack_deploy.spec.ts (manifest/bucket/finalize round trip, null completion token when every asset is already stored, git-hash requirement and argParser rejection, --json, nodejs_compat warning, bucket retry resending the body, session-expired mapping, create failure), tests/core/site-modules.spec.ts, tests/core/site-wrangler-config.spec.ts, transport-precedence cases in site_deploy.spec.ts, a base44 deploy case asserting the lane's flags stay off the unified command, and a retargeted static_site_deployments.spec.ts. Testkit gains mockAssetUpload / mockAssetUploadAfterFailures / mockAssetUploadError and assetUploadRequests, plus a tests/fixtures/fullstack-project/ fixture.

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (if applicable)
  • My changes generate no new warnings
  • I have updated docs/ (AGENTS.md) if I made architectural changes

Additional Notes

  • Two behavior changes against main. (1) main selected the static lane by the presence of --git-hash; here the env gate picks the transport and the commit defaults to HEAD, so with the gate on and no commit available the deploy fails asking for --git-hash instead of silently falling back to tar.gz — a build with no address could never be published. (2) --git-hash / --concurrency now appear on base44 site deploy --help even with the static gate off, because a worker build is ungated.
  • Backwards compatible otherwise. A project with no worker artifact and BASE44_STATIC_DEPLOYMENTS unset keeps the legacy tar.gz upload unchanged, and base44 deploy (unified) is untouched — it still ships the site through deployAll()'s tar.gz step and has neither flag. Adopting the lane there needs a commit address the unified deploy has no way to take.
  • The retry test guards two ky behaviors: POST must be named in retry.methods, and ky clones a pristine request so a FormData body survives being resent.
  • Current limitations, each an explicit error or warning rather than a silent drop: output that still needs bundling (no_bundle !== true) is rejected; wrangler vars are ignored in favor of app secrets; _headers/_redirects and run_worker_first route patterns are not forwarded yet.
  • CI on this head: build, lint, typecheck, knip and publish-preview pass; the four test jobs (ubuntu/windows × npm/binary) were still running when this description was generated, so the testing boxes above are left unchecked rather than asserted.

🤖 Generated by Claude | 2026-08-31 10:33 UTC | 92706a2

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🚀 Package Preview Available!


Install this PR's preview build with npm:

npm i @base44-preview/cli@0.1.12-pr.584.92706a2

Prefer not to change any import paths? Install using npm alias so your code still imports base44:

npm i "base44@npm:@base44-preview/cli@0.1.12-pr.584.92706a2"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "base44": "npm:@base44-preview/cli@0.1.12-pr.584.92706a2"
  }
}

Preview published to npm registry — try new features instantly!

claude added 2 commits August 3, 2026 17:16
…ted)

Adds the deployments core (commit-addressed create/finalize, asset
manifest hashing, presigned uploads) and routes site.outputDirectory
through it when BASE44_STATIC_DEPLOYMENTS is set: POST deployments with
{git_hash, asset_manifest} and no worker config, PUT each requested
file directly to its presigned URL echoing the signed content_type
(the URL also signs content_length), finalize with the index.html
bytes as the completion sentinel. asset_uploads: null means nothing
is owed — re-deploying a commit is idempotent.

The create response is a type-discriminated ADT so the worker (cf)
arm can slot in next to s3 without protocol changes. Gate off keeps
the legacy tar.gz upload byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvhQfqxACcq25XAQRpoSh9
Stacks the worker lane on the deployments API: detect the
@cloudflare/vite-plugin redirect artifact, resolve the generated
wrangler config (no_bundle only), collect modules, and create the
deployment with the worker config — which the server answers with the
cf arm: asset buckets POSTed directly to Cloudflare with the
upload-session jwt (never through the app client), finalize with
payload{completion_jwt} plus the module parts. A full-stack artifact
wins over the static transports; nothing here publishes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvhQfqxACcq25XAQRpoSh9
@netanelgilad
netanelgilad force-pushed the fullstack/deploy-git-hash branch from 5c32b34 to a588d65 Compare August 3, 2026 17:17
@netanelgilad netanelgilad changed the title feat: full-stack deploy — build a commit's worker from the CLI feat: full-stack deploy — build a commit's worker from the CLI (cf arm, stacked on #585) Aug 3, 2026
@netanelgilad
netanelgilad changed the base branch from main to fullstack/static-workers-lane August 3, 2026 17:17
Base automatically changed from fullstack/static-workers-lane to main August 4, 2026 07:31
netanelgilad and others added 7 commits August 4, 2026 11:28
Main landed PR #585 (static-site deploys) in a reworked form after review:
the code moved to `core/site/`, the `.assetsignore` walk switched to globby,
uploads switched to p-map + ky retry, and `--concurrency` was added. This
branch had built the full-stack (cf) arm on top of #585's original layout in
`core/deployments/`.

Resolution: keep this branch's structure and CLI contract, adopt main's
review improvements into it.

Structure — kept `core/deployments/`; the cf arm deploys Workers, which is
not site-specific. Reverted main's duplicate `core/site/{manifest,static-site,
upload}.ts` and the deployment additions to `core/site/{api,schema}.ts`;
`core/site/deploy-app.ts` remains the bridge from the site module.

Adopted from main:
- globby-based `.assetsignore` via `ignoreFiles`, replacing the hand-rolled
  matcher — gains real gitignore semantics including negation. Kept the MIME
  table and `AssetFile.contentType`, which the cf arm's multipart parts need.
- p-map for upload concurrency (both arms) and ky's built-in retry for
  presigned PUTs, so a 403 from an expired URL fails fast.
- `--concurrency <n>` (default 3, max 50) and `isGitCommitHash()` in
  `core/utils/git.ts`; `GIT_HASH_PATTERN` dropped from the deployments schema.
- Main's manifest suite (negation, brace/extglob, anchoring, dotfiles).
- v0.1.8, globby ^16.2.2, p-map ^7.0.6.

Contract kept from this branch — main gated `--git-hash`/`--concurrency`
registration on BASE44_STATIC_DEPLOYMENTS. That cannot hold here: full-stack
deploys are ungated and need `--git-hash`, which now defaults to the
checkout's HEAD. Both flags are therefore always registered, on `deploy` and
`site deploy` alike, from a shared `addDeploymentOptions()`. The env gate now
decides only whether a static output takes the deployments API or the legacy
tar.gz path. Main's flag-hiding tests were dropped as no longer applicable;
its `--git-hash`/`--concurrency` validation tests were ported.

One behavior change: a malformed `--git-hash` is now rejected by the option's
argParser ("Expected a git commit hash") before the action runs, rather than
later by resolveGitHash.

typecheck, lint, and knip clean; 713 tests pass. The suite has a pre-existing
"Body is unusable" flake under parallel load that reproduces on pristine main.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The merge kept the full-stack deploy code in `core/deployments/`, but main
had already settled this: deployments are a transport of the site module, not
a module of their own, and they live in `core/site/`. Follow main.

`core/deployments/` is gone. One flow per file — `full-stack.ts` (Workers, the
cf arm), `static-site.ts` (deployments-API static, the s3 arm), `deploy.ts`
(legacy tar.gz) — over shared `manifest.ts`, `upload.ts`, `modules.ts`,
`wrangler-config.ts`, and `git-hash.ts`. The deployment requests and schemas
merge into the module's existing `api.ts` / `schema.ts` next to the tar.gz
upload, as main has them. `deploy-app.ts` stays the transport picker.

The Workers flow is `full-stack.ts` rather than `deploy.ts` because that name
is already the legacy tar.gz path; it reads as a pair with `static-site.ts`.
Unit tests follow the same naming: `tests/core/site-*.spec.ts`.

No behavior change — moves, import rewrites, and the barrel/doc updates that
follow from them. While merging the two `api.ts` files, the worker-module read
switched to the existing `@/core/utils/fs.js` helper instead of a second raw
`readFile` binding, for typed FileNotFound/FileRead errors.

typecheck, lint, and knip clean; the 8 deploy spec files pass (77 tests).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The s3 arm already used pMap for concurrency and ky's own retry. The cf arm
had a hand-rolled attempt loop, a `sleep()` setTimeout helper, and bespoke
429 bookkeeping alongside it. Two idioms in one file for the same job.

Both arms now share `UPLOAD_RETRY` and let ky do the retrying. ky retries
network errors and its default status codes only (408/413/429/500/502/503/504),
which is what these uploads actually want: an expired credential (401/403)
fails fast instead of burning every attempt, and a 429 waits out the server's
`Retry-After` instead of the flat 15s the old loop invented. The 401/403
"upload session expired" mapping is unchanged.

Two things worth knowing, both now covered:

- POST is absent from ky's default retry `methods`, so the cf arm has to name
  it explicitly or bucket uploads would silently never retry. The new test
  fails if that option is dropped.
- ky clones a pristine request before sending, so the FormData body survives
  being resent. The test asserts every attempt carried the full body, since a
  consumed body would fail as "Body is unusable" only under real retries.

`uploadAssetBucket` moved from api.ts into upload.ts, where it can share the
retry config without a cycle. That also sharpens the split: api.ts is the
app-client (authenticated Base44 API) calls, upload.ts is the direct-to-storage
uploads that deliberately bypass that client.

Dropped: MAX_RATE_LIMIT_WAITS, RATE_LIMIT_DELAY_MS, uploadBucketWithRetry,
sleep(). The 429 fixed-wait behavior they implemented had no test.

typecheck, lint, and knip clean; the deploy specs pass (51 tests, 3 runs).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…omment

Comment and docstring cleanup across the site deploy module — the prose was
carrying its own weight badly: restating what the next line of code already
said, re-explaining the same protocol fact at every call site, and narrating
obvious parameters. Net -108 lines with no behavior change.

Also corrects one comment that was actively wrong. CfAssetUploads said the
*last bucket's* reply carries the completion token. Verified against
Cloudflare's direct-upload docs and wrangler's syncAssets(): the server decides
completeness by manifest membership ("once every file in the manifest has been
uploaded"), so the token goes to whichever request completes the set. Buckets
upload concurrently, so that is usually not buckets[n-1] — indexing the final
bucket would read an empty result and discard a token already in hand. The
implementation was already right; only the comment lied.

typecheck, lint, and knip clean; full suite green (714 tests, 71 files).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`base44 deploy` had grown the whole deployments lane: --git-hash,
--concurrency, full-stack artifact detection, and a deployment summary. It
doesn't need any of it. The fullstack flow is an addition to the existing
*site* deploy flow, so that is where it lives.

`base44 deploy` reverts to what it was: resources plus the legacy tar.gz site
step through `deployAll()`. Reverted to origin/main verbatim —
cli/commands/project/deploy.ts (drops the flags, detectAppDeployKind,
`site: false`, printDeploymentSummary and the deployment JSON output) and
core/project/deploy.ts (drops the `site` option and the buildCommand clause in
hasResourcesToDeploy, which only existed to serve the removed flow).

`base44 site deploy` keeps the lane and is now its only entry point. With one
caller left, the shared addDeploymentOptions() helper was over-abstraction:
the two option definitions and their parsers are inlined and
cli/commands/site/deploy-options.ts is deleted.

Specs for both arms move from the unified deploy to `site deploy`, which also
drops their resource-push mocks — nothing pushes resources there. Added a test
pinning the decision: `base44 deploy` rejects --git-hash and --concurrency as
unknown options and shows neither in --help.

typecheck, lint, and knip clean; full suite green (715 tests, 71 files).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PR #585 pulled the spinner wiring and result shaping out of `deployAction` into
`deployToDeploymentsApi` / `deployTarball`. This branch had undone that: the
action ended in an if/else chain over a result union, and the progress wiring
had moved off to its own cli/commands/site/run-app-deploy.ts. Back to main's
shape, with the full-stack flow folded in as a third helper.

`deployAction` now reads as plan → confirm → build → dispatch, and each
transport owns its own labels, progress and result:

- deployFullStackApp      — Workers, the cf arm
- deployToDeploymentsApi  — deployments-API static, the s3 arm
- deployTarball           — legacy tar.gz (unchanged from main)

`runDeployTask` holds the spinner/progress wiring the two deployments-API
helpers share, and `deploymentResult` the outro + --json document. run-app-deploy.ts
is deleted.

That let core shed an orchestrator it no longer needs: `deployAppSite()` and the
AppDeployResult union are gone, and core/site/deploy-app.ts is just the planner
now — `planAppDeploy()` returns the plan (with outputDir where there is one) and
the command calls deployFullStack / deployStaticSite / deploySite itself. Core
still decides which transport applies; the CLI no longer round-trips through a
second dispatch to find out what it already asked for.

The command plans twice, deliberately: once before the build for the prompt and
the no-config error, once after for the transport it acts on, since a full-stack
artifact is itself a build output.

typecheck, lint, and knip clean; full suite green (715 tests, 71 files).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	docs/deployments.md
#	packages/cli/src/cli/commands/site/deploy.ts
#	packages/cli/tests/cli/static_site_deployments.spec.ts
@netanelgilad netanelgilad changed the title feat: full-stack deploy — build a commit's worker from the CLI (cf arm, stacked on #585) feat: full-stack deploy — build a commit's worker from the CLI (cf arm) Aug 16, 2026
Integrates the session id main's #602 added to the deployments protocol:
create returns `session_id` and finalize now addresses this attempt's
uploads through it, so the cf arm threads `created.sessionId` into
`finalizeDeployment` alongside the static arm.

Conflicts resolved in docs/deployments.md (both arms plus session_id) and
core/site/schema.ts (kept sessionId alongside the cf/s3 upload union).
},
{
message:
"Full-stack apps ship from their build artifact — run your framework's build first",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no need to have full-stack apps in user facing copy.
the copy that is user facing always says "site" as an encompassiong term for what we deploy, whetehr it has the backend worker or not, so there shoudn't be copy changes ideally

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted to main's copy — the second hint is gone, so the error is No site configuration found. with the site.outputDirectory hint exactly as before this branch.

Same for the rest of the command's copy: description back to "Deploy built site files to Base44 hosting", spinner/success/error back to "Deploying site..." / "Site deployed" / "Site deploy failed" (no orange highlight for one of them either). I also dropped "full-stack" from the errors the wrangler and module paths raise — "No Workers build artifact found", "Base44 only deploys pre-bundled Workers output", "exceeds the 40 MB limit for a Base44 deploy" — since those reach the user too.

The one place a word had to be chosen rather than reverted: the spinner's Deploying worker (N modules)… stage, which only appears when there is a worker. Left as "worker" — it names the thing being uploaded rather than a kind of app, and no other stage line changes with the build. Say so if you'd rather it just stayed "Deploying site...".

Recorded the rule in docs/deployments.md so it doesn't drift back.


Generated by Claude Code

const shouldDeploy = await confirm({
message: `Deploy site from ${outputDirectory}?`,
message:
planned.kind === "full-stack"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — the prompt is Deploy site from ${outputDirectory}? again, with no branch on the kind of build.

It does still need a fallback: a project whose build produced a worker has no site.outputDirectory to name (the worker's own assets.directory supersedes it — the fullstack-project fixture has no site config at all), so with nothing to interpolate the prompt is just Deploy site?. That's a missing directory name, not a second kind of deploy.


Generated by Claude Code

const plan = await planAppDeploy(project);

switch (plan.kind) {
case "full-stack":

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think we need to code flow to start separating here based on fullstack / static.
inside deploytoDEplymentsApi we should check if there is a user worker to also deploy and decide internally what to add to the createDeployment call, but the bottom line is that we sdhould have a single call to createDeployment in the code, it's jsut the paramters to it that changes based on what we have to deploy

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and done — there is now one flow and one createDeployment() call site.

core/site/full-stack.ts and core/site/static-site.ts are gone, replaced by core/site/deployment.ts with a single deployToDeployments({projectRoot, outputDir, gitHash, ...}). It checks for a worker itself, and that only changes what it sends:

const worker = await resolveWorkerBuild(projectRoot, progress);   // null = no worker
const assetsDir = worker ? worker.assetsDir : outputDir;
const assets = assetsDir ? await buildAssetManifest(assetsDir, appId) : NO_ASSETS;

const created = await createDeployment({
  git_hash: gitHash,
  config: worker?.config,          // presence is what selects the storage target
  asset_manifest: assets.manifest,
});

Two more forks collapsed on the way, both for the same reason — they were us deciding something the server had already decided:

  • Upload: uploadDeploymentAssets(created.assetUploads, assets, …) dispatches on the asset_uploads discriminant and returns the completion token when that arm has one. It also owns the "Found N static assets (M new)" progress, since counting what's owed is per-arm. The two assetUploads.type !== "cf"/"s3" guards each flow used to raise are deleted: with one dispatch there is no wrong arm to reject.
  • Finalize: one finalizeDeployment(deploymentId, sessionId, payload), where payload is {modules, completionJwt} or {indexHtml}. The remaining if is inside api.ts building the multipart form — that difference is the wire protocol (a worker completes with its modules, a static build with the index.html sentinel), not a flow choice, and the bytes on both arms are unchanged.

The command is down to one call: planAppDeploy() now returns deployment | tarball | none (the two deployments kinds merged), so site deploy has a 3-arm switch with a single deployToDeploymentsApi(), and its runDeployTask wrapper is inlined now that there's one caller. A worker build stays ungated and needs no site.outputDirectory.

Net −23 lines. static_site_deployments.spec.ts already asserted both parameter shapes of that one call — expect(body).not.toHaveProperty("config") on the static arm, body.config.main on the worker arm — so the contract you described is locked in by tests. Full suite: 732 passed, all 296 deploy + core tests green, typecheck/lint/knip clean.


Generated by Claude Code

claude and others added 4 commits August 31, 2026 07:59
Review feedback on #584.

A worker is not a different kind of deploy, so the code no longer forks on
one. `deployToDeployments()` checks for a worker itself and that changes only
what it sends: the worker's config on the single create call (which is what
makes the server answer with the cf arm) and its modules at finalize. The
parallel full-stack.ts / static-site.ts flows are gone, and with them the two
create call sites, the two finalize entry points and the arm-mismatch guards
each flow needed to reject the other's answer.

Downstream now follows the server's answer rather than a decision of ours:
uploadDeploymentAssets() dispatches on the asset_uploads discriminant and owns
the asset progress; finalizeDeployment() takes whichever payload completes the
deployment. The only place the two shapes are still spelled out is the finalize
form in api.ts, where the protocol itself differs.

User-facing copy says "site" again, as it did before this branch: a site is
whatever we deploy, worker or no worker, so the prompt, spinner, success line
and errors no longer say "full-stack app". The command description, the
no-config hints and the deploy labels are back to main's wording; the confirm
prompt drops the output directory only when there is none to name. Errors from
the wrangler and module paths lost "full-stack" too.

Transport plan is now deployment | tarball | none, since the deployments arms
merged. A worker build stays ungated and needs no site.outputDirectory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants