Concepts
Parallel & Sequence
Run the same workflow across multiple containers simultaneously, or chain sandboxes where each step sees the previous result.
parallel
Run the same set of operations across multiple containers at the same time.
await workflow(client)
.parallel(
[
{ image: "node:20", resources: { cpu: "500m", memory: "512Mi" } },
{ image: "node:22", resources: { cpu: "500m", memory: "512Mi" } },
{ image: "node:24", resources: { cpu: "500m", memory: "512Mi" } },
],
(sb) => sb.exec("npm test"),
)
.pipe(process.stdout);All configs receive the same fn callback. The sandboxes run concurrently — stdout from all of them is merged in the result. Each sandbox is its own isolated container.
Cross-version matrix testing
const nodeVersions = ["18", "20", "22"];
await workflow(client)
.parallel(
nodeVersions.map((v) => ({
image: `node:${v}`,
resources: { cpu: "500m", memory: "512Mi" },
})),
(sb) => {
sb.exec("npm ci");
sb.exec("npm test");
},
)
.pipe(process.stdout);sequence
Chain sandboxes one after another. Each step's callback receives the previous step's WorkflowResult as prev.
await workflow(client)
.sequence([
{
image: "node:22",
resources: { cpu: "1", memory: "1Gi" },
name: "build",
run: (sb) => {
sb.exec("npm ci");
sb.exec("npm run build");
sb.exec("tar -czf /tmp/dist.tar.gz dist/");
sb.readFile("/tmp/dist.tar.gz", "artifact");
},
},
{
image: "ubuntu:22.04",
resources: { cpu: "500m", memory: "512Mi" },
name: "deploy",
run: (sb, prev) => {
// prev.vars.artifact is the tarball from the build step
sb.exec("./deploy.sh");
},
},
])
.pipe(process.stdout);SequenceStep
interface SequenceStep {
image: string | { uri: string; auth?: { username: string; password: string } };
resources: { cpu: string; memory: string; gpu?: string };
env?: Record<string, string>;
timeout?: number;
name?: string;
run: (sb: SandboxBuilder, prev?: WorkflowResult) => void;
}prev is undefined for the first step.
Combining parallel and sequence
.parallel() and .sequence() are both methods on WorkflowBuilder and can be chained:
await workflow(client)
.sandbox(opts, (sb) => sb.exec("npm ci")) // setup
.parallel(matrix, (sb) => sb.exec("npm test")) // test across versions
.pipe(process.stdout);Each call adds a stage. Stages run in the order they are added.