Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh

Commit

A deploy that changes the runner's image or its container settings rolls every idle sandbox over at once (--containers-rollout=immediate), where Cloudflare's default rollout went in steps over wall-clock time and, with deploys often half an hour apart, never reached every sandbox: jobs kept starting on old images and old machine sizes. A change to the container settings alone, such as the instance type, now rolls out too; before, an unchanged image meant --containers-rollout none and the new settings were never applied. Busy sandboxes still get rollout_active_grace_period to finish.

syntaqxcommitted Parentf7e146cBrowse files
4 files+31−60/4 viewed
+2−4
6666 } from "./deploy/image.mjs";
6767 import { decide, git, planJson, pool, table } from "./deploy/plan.mjs";
6868 import { reportDeployment } from "./deploy/report.mjs";
69−import { ROOT, byStage, codeStages, findWranglerConfigs, npmCiArgs, npmWorkspace, pick, problems, resolvedStack, waves } from "./deploy/stack.mjs";
69+import { ROOT, byStage, codeStages, containersRollout, findWranglerConfigs, npmCiArgs, npmWorkspace, pick, problems, resolvedStack, waves } from "./deploy/stack.mjs";
7070 import { withDeployWindow } from "./deploy/status-window.mjs";
7171
7272 const USAGE = "usage: node scripts/deploy.mjs plan|deploy|build|migrate|manifest|doctor|install|build-base|image [--all] [--only a,b] [--skip a,b] [--force] [--rollback] [--concurrency N] [--stage S] [--json]";
361361 // Wrangler is given the image by reference, so it builds nothing.
362362 const image = await runnerImage(unit, { dryRun, docker, rebuildImage, rebuildBase }, out);
363363 args.push("--config", writeDeployConfig(unit, image.ref));
364− // Nothing the image is built from changed: the running sandboxes
365− // keep going, and new ones start from the same image.
366− if (!rebuildImage && !rebuildBase && !decision.image) args.push("--containers-rollout", "none");
364+ args.push("--containers-rollout", containersRollout(unit, decision, { rebuildImage, rebuildBase }));
367365 result.note = image.note;
368366 }
369367 // Tried again after a wait when Cloudflare, not what is deployed, is
+10−0
4949 findWranglerConfigs,
5050 loadStack,
5151 npmCiArgs,
52+ containersRollout,
5253 npmWorkspace,
5354 outsideImports,
5455 parseJsonc,
860861 assert.equal(retryableDeploy("✘ [ERROR] Processing wrangler.jsonc configuration:\n - \"main\" is not a valid path"), false);
861862 assert.equal(retryableDeploy("fetch failed: ECONNRESET"), true);
862863 });
864+
865+test("sandboxes roll over at once when their image or container settings changed, and not otherwise", () => {
866+ const unit = { id: "runner", path: "services/runner" };
867+ assert.equal(containersRollout(unit, { image: true, files: [] }), "immediate");
868+ assert.equal(containersRollout(unit, { image: false, files: ["services/runner/wrangler.jsonc"] }), "immediate");
869+ assert.equal(containersRollout(unit, { image: false, files: ["services/runner/src/egress.ts"] }), "none");
870+ assert.equal(containersRollout(unit, { image: false, files: ["services/runnerx/wrangler.jsonc"] }), "none");
871+ assert.equal(containersRollout(unit, { image: false, files: [] }, { rebuildImage: true }), "immediate");
872+});
+15−0
486486 }
487487
488488 /**
489+ * How a unit with a Containers image rolls its sandboxes over: `immediate`
490+ * when what they run changed (the image, or the container settings in its
491+ * wrangler.jsonc, such as the instance type), else `none`. Cloudflare's
492+ * default rollout goes in steps over wall-clock time, so with deploys
493+ * often apart a new version never reached every sandbox; `immediate`
494+ * replaces the idle ones at once, and `rollout_active_grace_period` still
495+ * keeps a sandbox in the middle of a job from being stopped.
496+ */
497+export function containersRollout(unit, decision, { rebuildImage = false, rebuildBase = false } = {}) {
498+ const config = (file) => file.startsWith(`${unit.path}/`) && /wrangler\.jsonc?$/.test(file);
499+ const changed = rebuildImage || rebuildBase || decision.image || (decision.files ?? []).some(config);
500+ return changed ? "immediate" : "none";
501+}
502+
503+/**
489504 * npm ci of only what the units need: Wrangler alone for Rust workers,
490505 * and each npm-built unit's workspace with the packages it uses. A CI job
491506 * that deploys three Rust workers does not install the site's toolchain.
+4−2
2525 // hosted label), and all other work: 2 vCPU, 8 GiB, 16 GB.
2626 "instance_type": "standard-3",
2727 "max_instances": 20,
28− // A deploy replaces sandboxes. Ones that are busy are given this
29− // long, in seconds, to finish first, so shipping g1t does not
28+ // A deploy that changes the image or these settings replaces every
29+ // idle sandbox at once (scripts/deploy.mjs passes
30+ // --containers-rollout=immediate). Ones that are busy are given
31+ // this long, in seconds, to finish first, so shipping g1t does not
3032 // kill work in the middle.
3133 "rollout_active_grace_period": 7200
3234 },

Comments

Sign in to comment.