Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Build the runner from the repository root:
docker build -t turbo-playground-runner -f website/playground-runner/Dockerfile .
```

Run it with the hardening flags or deploy it with the Fly config documented in
Run it with the hardening flags documented in
[`playground-runner/README.md`](playground-runner/README.md), then configure the
website runtime in Vercel:

Expand All @@ -79,6 +79,9 @@ missing.
If those variables are absent, `/api/playground/run` returns an explicit
unavailable response and the page shows the local CLI command instead.

The hosted runner is not deployed today. It was shut down on 2026-10-29, so
production returns that unavailable response.

## Content Ownership

When compiler, CLI, release, or packaging behavior changes, update the matching website pages in `website/src/app/**` in the same cycle or record the doc gap in `.omx/product-cycles/open-tasks.md`.
27 changes: 9 additions & 18 deletions website/playground-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,16 @@ From the repository root:
docker build -t turbo-playground-runner -f website/playground-runner/Dockerfile .
```

## Deploy on Fly.io
## Deployment Status

The repo includes `fly.toml` for the public runner. Create the app once, set a
random bearer token as a Fly secret, deploy from the repository root, then point
Vercel at the deployed `/run` URL with the same token.
The hosted runner is not deployed. It was shut down on 2026-10-29, and this
repo no longer ships a deploy config for it. With no runner configured,
`https://turbolang.dev/api/playground/run` returns the "not configured" 503
response and `/play` shows the local CLI command instead.

```bash
flyctl apps create turbolang-playground-runner --org zvn-dev

TOKEN="$(openssl rand -hex 32)"
flyctl secrets set \
--app turbolang-playground-runner \
TURBO_PLAYGROUND_RUNNER_TOKEN="$TOKEN"

flyctl deploy --config website/playground-runner/fly.toml
```

After deployment, configure the website runtime:
To host it again, run the image in an isolated container with the flags shown
under Run Locally, give it a random bearer token, then point the website at its
`/run` URL with the same token:

```bash
cd website
Expand All @@ -42,8 +34,7 @@ vercel env add TURBO_PLAYGROUND_RUNNER_URL preview
vercel env add TURBO_PLAYGROUND_RUNNER_TOKEN preview
```

Use `https://turbolang-playground-runner.fly.dev/run` for
`TURBO_PLAYGROUND_RUNNER_URL`. After Vercel redeploys, smoke the public site:
After Vercel redeploys, smoke the public site:

```bash
cd website
Expand Down
39 changes: 0 additions & 39 deletions website/playground-runner/fly.toml

This file was deleted.

2 changes: 1 addition & 1 deletion website/playground-smoke-utils.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@
// runtime resources with an unbounded compute loop. On the deployed container it
// must be contained — killed by the prlimit CPU cap or the wall-clock watchdog —
// never returning a successful run. This is the first non-mock exercise of the
// prlimit path, so it validates on the Fly deploy rather than in local/CI (which
// prlimit path, so it validates on a deployed runner rather than in local/CI (which
// have no prlimit and rely on the wall timeout alone).
export async function assertResourceAbuseContained(fetcher, runUrl, options = {}) {
const label = options.label ?? "playground";
const source =
"fn main() { let mut x = 0\n while x >= 0 { x = x + 1 } print(x) }";
const { response, body } = await postRunSource(fetcher, runUrl, source, options);

Check warning on line 58 in website/playground-smoke-utils.mjs

View workflow job for this annotation

GitHub Actions / Website lint + build

'response' is assigned a value but never used
if (body?.success === true) {
throw new Error(`${label} resource-limit smoke check failed: abusive program returned success`);
}
Expand Down
13 changes: 0 additions & 13 deletions website/tests/bl14-playground-runner.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,12 @@ function readRawHttpResponse(port, requestText, timeoutMs = 750) {
test("standalone playground runner artifacts exist and stay container-oriented", () => {
assert.equal(existsSync(join(root, "playground-runner/runner.mjs")), true);
assert.equal(existsSync(join(root, "playground-runner/Dockerfile")), true);
assert.equal(existsSync(join(root, "playground-runner/fly.toml")), true);
assert.equal(existsSync(join(root, "playground-runner/README.md")), true);
assert.equal(existsSync(join(root, "playground-runner/smoke.mjs")), true);

const packageJson = JSON.parse(read("package.json"));
const runner = read("playground-runner/runner.mjs");
const dockerfile = read("playground-runner/Dockerfile");
const flyConfig = read("playground-runner/fly.toml");
const readme = read("playground-runner/README.md");
const ciWorkflow = read("../.github/workflows/ci.yml");

Expand All @@ -113,20 +111,9 @@ test("standalone playground runner artifacts exist and stay container-oriented",
assert.match(dockerfile, /HEALTHCHECK/);
assert.match(dockerfile, /\/healthz/);
assert.doesNotMatch(dockerfile, /\b(curl|wget)\b/);
assert.match(flyConfig, /app = "turbolang-playground-runner"/);
// Path is relative to fly.toml's own directory (fixed in 9a1195e for fly deploy)
assert.match(flyConfig, /dockerfile = "Dockerfile"/);
assert.match(flyConfig, /TURBO_PLAYGROUND_RUNNER_ALLOW_UNSAFE_HOST = "1"/);
assert.match(flyConfig, /internal_port = 8787/);
assert.match(flyConfig, /auto_stop_machines = "off"/);
assert.match(flyConfig, /auto_start_machines = true/);
assert.match(flyConfig, /min_machines_running = 1/);
assert.match(flyConfig, /path = "\/healthz"/);
assert.match(flyConfig, /memory_mb = 256/);
assert.match(readme, /--read-only/);
assert.match(readme, /--cap-drop=ALL/);
assert.match(readme, /-e TURBO_PLAYGROUND_RUNNER_ALLOW_UNSAFE_HOST=1/);
assert.match(readme, /flyctl deploy --config website\/playground-runner\/fly\.toml/);
assert.match(readme, /TURBO_PLAYGROUND_RUNNER_URL/);
assert.match(ciWorkflow, /name: Playground runner image/);
assert.match(ciWorkflow, /docker build -t turbo-playground-runner:ci -f website\/playground-runner\/Dockerfile \./);
Expand Down
Loading