This recipe is for the repo that deploys Cloudbox. It proves the deployed Cloudbox instance can still boot a runner, execute a repo task, verify it, and return an artifact.

1. Add the workflow

Create .github/workflows/cloudbox-smoke.yml:

name: cloudbox-smoke

on:
  workflow_dispatch:
  schedule:
    - cron: "17 9 * * *"

jobs:
  smoke:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Run Cloudbox smoke test
        run: node scripts/proof-ci-smoke.mjs
        env:
          CLOUDBOX_E2E_URL: https://YOUR-CLOUDBOX.workers.dev
          CLOUDBOX_API_TOKEN: ${{ secrets.CLOUDBOX_API_TOKEN }}

      - name: Upload proof
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: cloudbox-ci-smoke
          path: artifacts/CI_SMOKE.md

2. Add the secret

In GitHub:

Repo → Settings → Secrets and variables → Actions → New repository secret

Add:

CLOUDBOX_API_TOKEN=<the token configured on your Cloudbox Worker>

3. Add the smoke script

If you are using this Cloudbox repo, the script already exists:

scripts/proof-ci-smoke.mjs

If you are copying the pattern into another repo, add this file:

#!/usr/bin/env node
import { mkdirSync, writeFileSync } from "node:fs";

const url = process.env.CLOUDBOX_E2E_URL;
const token = process.env.CLOUDBOX_API_TOKEN;
const out = "artifacts/CI_SMOKE.md";
const repo = process.env.CLOUDBOX_CI_REPO ?? "https://github.com/acoyfellow/cloudbox";
const nonce = `ci-smoke-${Date.now()}`;

if (!url) throw new Error("CLOUDBOX_E2E_URL is required");
if (!token) throw new Error("CLOUDBOX_API_TOKEN is required");

const response = await fetch(`${url}/api/runs`, {
  method: "POST",
  headers: {
    "content-type": "application/json",
    authorization: `Bearer ${token}`,
  },
  body: JSON.stringify({
    repo,
    commands: [`echo ${nonce} > CI_SMOKE.md`],
    verify: ["test -f CI_SMOKE.md"],
    artifact: "CI_SMOKE.md",
    timeoutMs: 30_000,
  }),
});

const body = await response.json();
const ready = body.runnerReceipts?.some((r) => r.type === "runner.container.ready");
const verified = body.receipts?.some((r) => r.type === "verify" && r.code === 0);
const artifactMatched = body.artifact?.content === `${nonce}\n`;
const ok = response.ok && body.ok === true && ready && verified && artifactMatched;

mkdirSync("artifacts", { recursive: true });
writeFileSync(out, `# Cloudbox CI Smoke\n\nStatus: ${ok ? "pass" : "fail"}\n\n- URL: ${url}\n- Repo: ${repo}\n- Artifact matched: ${artifactMatched}\n- Verify receipt: ${verified ? "pass" : "missing"}\n- Runner ready: ${ready ? "yes" : "missing"}\n\n## Response\n\n\`\`\`json\n${JSON.stringify(body, null, 2)}\n\`\`\`\n`);

if (!ok) process.exit(1);
console.log(`CI_SMOKE_PASS ${out}`);

4. Run it manually

From the GitHub Actions tab, choose:

cloudbox-smoke → Run workflow

A passing run uploads:

cloudbox-ci-smoke / CI_SMOKE.md

What the smoke test proves

It checks more than HTTP 200:

  • Cloudbox accepted the run.
  • The runner Container became ready.
  • The command wrote a nonce into CI_SMOKE.md.
  • Verification passed.
  • The returned artifact contains the same nonce.

That means the deployed Worker, runner Durable Object, Container, and artifact path are connected end to end.