Skip to content

feat(arcade-cli): deploy Cloudflare Python (Pyodide) workers (PLT-2154)#883

Closed
pmdroid wants to merge 1 commit into
mainfrom
worktree-cf-deploy-cli
Closed

feat(arcade-cli): deploy Cloudflare Python (Pyodide) workers (PLT-2154)#883
pmdroid wants to merge 1 commit into
mainfrom
worktree-cf-deploy-cli

Conversation

@pmdroid

@pmdroid pmdroid commented Jun 23, 2026

Copy link
Copy Markdown
Member

Adds the client side of Cloudflare Python (Pyodide) worker deployment. Tracked by PLT-2154.

What's here

A new --runtime python path on arcade deploy:

  • Packages the worker directory as a zip (create_zip_archive) instead of tar.gz. Entries are stored relative to the project root (no top-level dir), so a --entrypoint src/worker.py resolves inside the archive. The engine detects a Python worker by the zip container and uploads each file as its own Worker module.
  • Sends host=cloudflare + runtime=python on CreateDeploymentRequest, with the bundle entrypoint set to the .py main module.
  • Skips local validation. A Pyodide worker.py (from workers import WorkerEntrypoint) can't run under plain CPython, so the usual "start the server and hit /worker/health" step would always fail. --runtime python therefore requires --server-name/--server-version, like --skip-validate.

The default (--runtime auto) is unchanged: tar.gz + local validation + the existing Porter path. host/runtime are sent only via model_dump(exclude_none=True), so the default payload is byte-for-byte identical.

# From a Cloudflare Python worker dir (after `pywrangler sync` vendors python_modules/):
arcade deploy --runtime python -e src/worker.py --server-name my-worker --server-version 1.0.0

Why no engine change here

The engine's JSON /deployments create path already routes by host/runtime and detects Python from the bundle's .py entrypoint (PLT-2153), so the CLI only needs to produce the right request + zip.

Testing

ruff format/ruff check/mypy clean; libs/tests/cli/deploy/test_deploy.py passes (30 tests). New tests cover the zip archive (relative paths, exclusions, zip magic), the request model (host/runtime omitted by default, included for Cloudflare), and the end-to-end deploy_server_logic Python path (zips, skips validation, sends host=cloudflare/runtime=python with the .py entrypoint). Bumped arcade-mcp to 1.16.0.

Out of scope / follow-ups

  • Auto-detecting Cloudflare from a wrangler.jsonc (explicit --runtime python for now).
  • Vendoring python_modules (the user runs pywrangler sync first; the CLI zips what's present).
  • A real end-to-end deploy through a live engine + Cloudflare account.

🐕 Written by Kyoto, an AI agent, on Pascal's behalf —


Note

Medium Risk
New deploy routing and packaging path affects engine integration; default deploy behavior is preserved via exclude_none, but misconfigured Cloudflare deploys could fail at runtime without local validation catching issues.

Overview
Adds arcade deploy --runtime python for Cloudflare Python (Pyodide) workers, alongside the unchanged default auto path (tar.gz + local validation).

For python, the CLI builds a zip with flat paths (via new create_zip_archive), skips local health/metadata validation, and on create sends host=cloudflare and runtime=python using model_dump(exclude_none=True) so default deploy payloads stay the same. Tar.gz packaging now shares exclusion logic through _is_excluded_archive_path.

main.py requires --server-name / --server-version when using --runtime python (same as --skip-validate) and treats secrets auto as skip in that case. Tests cover zip packaging, request fields, and the end-to-end Cloudflare deploy path; arcade-mcp is bumped to 1.16.0.

Reviewed by Cursor Bugbot for commit b11820b. Bugbot is set up for automated code reviews on this repo. Configure here.

Add a --runtime python path to `arcade deploy` that ships a Cloudflare Python
worker to the engine. When set, the CLI packages the worker directory as a zip
(create_zip_archive, paths relative to the project root so a .py entrypoint
resolves), sends CreateDeploymentRequest with host=cloudflare + runtime=python
and the .py entrypoint, and skips local CPython validation (a Pyodide worker
can't run there) — so --server-name/--server-version are required.

The default (--runtime auto) keeps the tar.gz + validate + Porter behavior
byte-for-byte (host/runtime sent only via model_dump(exclude_none=True)). Pairs
with the engine side (PLT-2153), whose JSON /deployments path already routes by
host/runtime and detects Python from the bundle entrypoint.
@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.04878% with 9 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
libs/arcade-cli/arcade_cli/deploy.py 86.48% 5 Missing ⚠️
libs/arcade-cli/arcade_cli/main.py 0.00% 4 Missing ⚠️
Files with missing lines Coverage Δ
libs/arcade-cli/arcade_cli/main.py 32.22% <0.00%> (-0.22%) ⬇️
libs/arcade-cli/arcade_cli/deploy.py 59.81% <86.48%> (+12.79%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@pmdroid pmdroid closed this Jun 23, 2026
@pmdroid pmdroid deleted the worktree-cf-deploy-cli branch June 23, 2026 20:56
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.

1 participant