feat: v0.3 core CI (M8) — .gitflare/ci.yml jobs on Cloudflare Sandboxes#5
Merged
Conversation
- ci.yml format: jobs/needs/run steps (multi-line via new block-scalar support in yaml.ts), per-job env + timeout_minutes; parse-time cycle and unknown-needs validation, Kahn topological order - CiDO: detached runs (202 + pending-work), one sandbox per run cloned from the Artifacts mirror with env-scoped git auth (token never in argv/.git/config/stderr; all output scrubbed), streamed live logs over hibernatable WS, alarm watchdog, cancel, push-storm supersede - deploy jobs delegate to DeployDO (mode "ci", strict at-sha ref-aware clone) keeping one deploy history + cross-format rollback; CI-built worker entries ship via entryOverrides instead of stale committed files - fail-closed: committed ci.yml with CI disabled blocks ungated deploy.yml - GitHub commit statuses (legacy Status API, soft-fail), runs UI at /r/:name/ci, /control/ci/* endpoints - CLI: gitflare ci enable/disable/run/list/cancel; containers block with public docker.io/cloudflare/sandbox image (no local Docker), migrations v3/v4 unconditional, symmetric CONTROL_SECRET reuse - 51 new unit tests (107 total) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ifact gating) Adversarial review of the M8 diff surfaced 18 confirmed issues; this fixes 14 and documents the rest as known limitations (PLAN §12): - watchdog/pipeline verdict race: finalizedRunIds fence prevents a lagging coroutine from resurrecting a run the watchdog failed; watchdog no longer clears a concurrent cancel - fallback alarm armed in begin() so pre-deadline eviction can't zombie a run - ARTIFACTS.get moved into the try + last-resort commit status (no vanished push) - webhook skips tag/non-branch refs (were minting failed runs + red statuses) - artifact handover gated on the deploy job's whole run-job needs closure succeeding (was shipping a failed build's output) - missing-SANDBOX path fails closed honestly (dead deploy.yml fallback removed) - delegated-deploy response mapping extracted to a tested pure fn — skipped never reads as green - remote-URL allowlist rejects shell metacharacters - duplicate webhook deliveries de-duped by branch+sha - dashboard cancel gated behind Access (open on public mirrors before); CLI cancel stays CONTROL_SECRET-gated - CONTROL_SECRET always (re)written on enable; config persisted once the Worker is live (was strandable cross-machine / on partial enable) +8 tests (delegation shapes, needs-closure, tightened remote validation); 115 total. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ry-run wrangler deploy --dry-run flagged instance_type 'standard' as renamed to 'standard-1'. Default + allowed list updated to the numbered tiers. The dry-run also validated both TOML variants (CI-provisioned and default) parse and resolve RepoDO/DeployDO/CiDO/Sandbox exports — including migration v4 with an unbound Sandbox class, clearing that live-validation TODO. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…enable error Live run confirmed: the worker script uploads fine, but the container rollout returns Forbidden without BOTH the Cloudchamber:Edit and Containers:Edit account token permissions (Containers:Edit alone is insufficient — cf workers-sdk#12483). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…jection
Live run: Cloudflare's container application namespace rejects consecutive
dashes, but wrangler derives the app name as `${workerName}-sandbox` and the
worker name carries `--` from the owner--repo Artifacts convention. Emit an
explicit collapsed name in the [[containers]] block.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…proxy) Live run: webhook sync 500'd with 'Git remote "[object JsRpcProperty]" uses an unrecognized transport protocol'. On the current Artifacts beta, property access on the binding (artifactsRepo.remote) returns a lazy RPC proxy that stringifies to [object JsRpcProperty]; only RPC methods (createToken) resolve. Thread the REPO_MAP remote string (already used by every browse path) through RepoDO/git.push instead. Pre-existing since M1; M4's validation exercised the one-shot import path, not the git.push webhook sync. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two issues from the live run: - The push webhook awaited the full in-worker sync before responding, blowing past GitHub's 10s delivery timeout on any real repo (504 + redeliveries). Now respond 202 immediately and run sync + CI/deploy dispatch in waitUntil; sync errors surface via RepoDO/dashboard, not GitHub's delivery UI. - CI commit-status postback soft-failed silently on an expired GITHUB_TOKEN. Keep the soft-fail, but log why it didn't post so it's diagnosable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What
Ships the M8 slice of v0.3 (Generic CI) from PLAN.md §4: a
.gitflare/ci.ymlworkflow format withjobs/needs/run:steps, executed on Cloudflare Sandboxes running on the user's own account. Deploy jobs gate on test jobs and ship what CI just built rather than the stale committed file. Live logs, cancel, run history, and GitHub commit-status postback are all in.How it works
src/ci/workflow.tsreuses the existing hand-rolled YAML subset (extended with|/|-block scalars for multi-linerun:) and the sharedcloudflare/deploystep validator.needsgets parse-time unknown/cycle validation + Kahn topo order; per-jobenv+timeout_minutes.CiDO(bindingCI, migration v3).POST /runanswers 202 and the pipeline runs as detached DO work under an alarm watchdog. One sandbox per run, cloned from the Artifacts mirror with env-scoped git auth (the read token never lands in argv,.git/config, or stderr; every log line is scrubbed). Jobs run in topo order with streamed, line-buffered logs over a hibernatable WebSocket.DeployDO(mode: "ci", strict at-sha ref-aware clone) so deploy history + rollback stay in one place across both workflow formats. Worker entries built in the sandbox are handed over viaentryOverrides(gated on the deploy job's wholeneedsclosure of run jobs succeeding).gitflare ci enable/disable/run/list/cancel. Enable provisions a[[containers]]block using the publicdocker.io/cloudflare/sandboximage (no local Docker), default instance typestandard-1. Migrations v3+v4 are emitted unconditionally so cross-machine redeploys never miss an applied tag;CI_ENABLEDgates behavior while the container config stays provisioned acrossdisable.gitflare/ci), soft-fail (GitHub being down is the whole point).Quality
pnpm -r test), typecheck clean, worker bundle 1.57 MB / 354 KB gzip.wrangler deploy --dry-run: both the CI-provisioned and default TOML variants parse and resolve all four DO class exports, including migration v4 with an unbound Sandbox class.Not in this PR (rest of v0.3, tracked in PLAN §12 M8 notes)
R2 build cache, Browser Run for E2E, the GitHub Actions importer, Pages build-artifact handover,
runtime: worker(Dynamic Workers can't run npm), per-job container images (containers pin the image at deploy time). And the standing caveat: needs one live run against a real Workers Paid account to confirm the Containers provisioning path + Sandbox exec/gitCheckout wire behavior.🤖 Generated with Claude Code