Skip to main content

run-roachtest

Run a single CockroachDB roachtest end-to-end: pick local vs. user's GCE worker, launch detached on worker via tmux + `roachstress.sh` with long-poll done-notification and tail. Use whenever user asks to run/stress/kick off a roachtest, or just modified one and next step is running it. Single test + single iteration only; nightly loops belong elsewhere.

Jump to install

Source facts

Repository
cockroachdb/cockroach
Last source activity
May 12, 2026 at 13:50
Detected SKILL.md language
English
Stars
32,481
Forks
4,111

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
run-roachtest
description
Run a single CockroachDB roachtest end-to-end: pick local vs. user's GCE worker, launch detached on worker via tmux + `roachstress.sh` with long-poll done-notification and tail. Use whenever user asks to run/stress/kick off a roachtest, or just modified one and next step is running it. Single test + single iteration only; nightly loops belong elsewhere.
# run-roachtest Run a CockroachDB roachtest from end to end. The skill handles three things that are easy to get wrong: 1. **Where** to run (local vs. the user's GCE worker). 2. **How** to launch on the worker so the run survives a closed laptop lid and Claude stays informed when it finishes. 3. **How** to give the user a no-friction way to peek at progress. Requires the `roachdev worker` CLI configured (provisions and addresses the user's GCE worker without a name argument). ## When to use this skill - The user says "run X", "kick off X", "stress X", "try X on the worker", "run this test", etc., where X is a roachtest. - The user just wrote or modified a roachtest and the next move is to run it. Do NOT use this skill for: - Multi-test sweeps or nightly-style loops (different shape — wrap many invocations). - Builds/unit tests (use `./dev test`). - Investigating an existing failed roachtest run (use the teamcity / engflow-artifacts skills). ## Step 1 — Decide local vs. remote Pick local or remote as follows. **The user's wording is the strongest signal.** Honor it directly: | Phrase | Action | |--------|--------| | "locally", "on this machine", "on my mac" | local | | "on the worker", "on the agent", "remotely", "on gceworker", "on the gce worker" | remote | | Otherwise | inspect the test (below) | When wording is silent, read the test source under `pkg/cmd/roachtest/tests/` and consider: - **Linux-only mechanics** — `cgroups`, `iptables`, disk stalls, `dmsetup`, network namespaces, sysctls. → remote. - **Heavy clusters** — anything provisioning more than a couple of nodes, or specifying high `spec.CPU(...)`. Local mac will choke. → remote. - **Local-mode bypass** — many heavy tests check `c.IsLocal()` and short-circuit to a smoke test. If present, local IS viable; warn the user it will be a smoke test rather than the real thing. - **Toy/acceptance tests** — `acceptance/*` and similarly named tests are usually fine locally. If after looking at the test you still cannot tell, ask the user. A 30-second clarification beats a 2-hour run on the wrong machine. ## Step 2a — Local run Use `roachstress.sh -l` from the repo root. It builds locally and runs in-process: ```bash bash pkg/cmd/roachtest/roachstress.sh -c 1 -u -l '<test-name>' ``` Tee to a log so output is inspectable mid-run. Run as a background Bash task (`run_in_background: true`). No tmux needed — local runs inherit the user's session. That's it for local. The rest of the skill is the remote workflow. ## Step 2b — Remote run on the user's GCE worker `roachdev worker ssh` (and the other `roachdev worker` subcommands) default to the current user's worker when no name is given — e.g. `roachdev worker ssh -- 'hostname'` returns the user's worker hostname. **Always omit the worker name** so this skill works unmodified for every developer. The repo on the worker lives at `~/go/src/github.com/cockroachdb/cockroach` (standard `$GOPATH` layout that `roachdev` provisions). ### Step 2b.1 — Pre-flight Run these in parallel via SSH (single round-trip): ```bash roachdev worker ssh -- ' tmux ls 2>&1; echo ---; pgrep -af roachstress | head -10; echo ---; cd ~/go/src/github.com/cockroachdb/cockroach && git rev-parse --abbrev-ref HEAD && git rev-parse HEAD ' ``` Inspect the output: - **Worker stopped** — `roachdev worker resume` first. - **Existing tmux sessions** — note their names so the new session name does not collide. - **Running roachstress** — another agent or the user is in the middle of a test. Do NOT wipe `artifacts/` or destroy the worker. Pick a unique session/log/signal name. **Before touching the checkout (branch switch, fetch, reset), confirm those tests are past their build phase** — see Step 2b.1.5. - **Branch / SHA** — see "Getting your code on the worker" below. ### Step 2b.1.5 — Is the in-progress test past its build phase? If pre-flight showed another `roachstress` already running, **before touching the checkout** (branch switch, fetch, reset) you must confirm its build phase is done — otherwise you corrupt its build. See `references/concurrent-runs.md` for the check command, the "build is done" criteria, and the long-poll wait-for-build loop. Read it only when this case applies; the common case (no concurrent run) skips straight to Step 2b.2. ### Step 2b.2 — Getting your code on the worker If the test is unmodified upstream code (e.g. `acceptance/build-info`), just use whatever branch/SHA the worker happens to be on. `roachstress.sh` caches binaries by SHA, so reusing the existing checkout reuses cached binaries — fast startup. If the test depends on local changes: 1. Push the branch from the local worktree to the user's GitHub fork: `git push -u origin <branch>`. 2. On the worker, fetch and check out: ```bash roachdev worker ssh -- ' cd ~/go/src/github.com/cockroachdb/cockroach && git fetch origin <branch> && git checkout <branch> && git reset --hard origin/<branch> ' ``` This is safe even with other tests running, **provided Step 2b.1.5 confirmed they are past the build phase**. The new SHA gets a fresh `artifacts/<new-sha>/` directory. **Worktree fallback (rare).** If you cannot wait for the in-progress build to finish, `git worktree add ../cockroach-<branch> origin/<branch>` and run `roachstress.sh` from the worktree path. Downside: bazel cache contention slows both builds, and the worktree needs cleanup later. ### Step 2b.3 — Launch in detached tmux Pick three unique names so concurrent runs do not collide: | Slot | Suggested form | |------|----------------| | tmux session | `rt-<short-test-name>` | | log file | `~/rt-<short-test-name>.log` | | wait-for signal | `rt-<short-test-name>-done` | For example: `rt-build-info`, `~/rt-build-info.log`, `rt-build-info-done`. Launch: ```bash roachdev worker ssh -- "tmux new-session -d -s <SESSION> \"cd <REPO> && bash pkg/cmd/roachtest/roachstress.sh -c 1 -u <TEST> 2>&1 | tee <LOG>; echo EXIT=\\\$? >> <LOG>; tmux wait-for -S <SIGNAL>\"" ``` Why this exact form: - `tmux new-session -d` detaches immediately — SSH returns, the run keeps going. Closing the laptop is fine. - `bash pkg/cmd/roachtest/roachstress.sh` from the repo root: the script demands its own working directory. - `-u`: build the full `cockroach` binary with the DB Console UI baked in (instead of `cockroach-short`). This makes the cluster's admin UI available — useful when you want to hand the user a clickable http://...:26258 link for live debugging. Adds ~1-2 min to the first build per SHA; cached afterward. - `2>&1 | tee <LOG>`: captures stdout + stderr into a single inspectable file. - `echo EXIT=$? >> <LOG>`: records the script's exit code so the notification can report success/failure without re-grepping. - `tmux wait-for -S <SIGNAL>`: signals a tmux semaphore as the very last thing. Step 2b.4 blocks on the matching `wait-for <SIGNAL>`. - The `\\\$?` escaping: outer SSH consumes one layer of `\`, the outer shell another — three backslashes leave one literal `\$?` for tmux to pass through to bash so the exit-code expansion happens inside tmux's window, not at SSH-time. After launch, verify the session is alive: ```bash roachdev worker ssh -- 'tmux ls | grep <SESSION>; sleep 5; tail -30 <LOG>' ``` The early log should show `roachstress.sh` locating binaries and starting the test. ### Step 2b.4 — Long-poll notification Spawn a Bash task in background that blocks on the tmux semaphore. When the run finishes, the SSH command returns, the background task completes, and Claude gets a task-completion notification. ```bash roachdev worker ssh -- 'tmux wait-for <SIGNAL> && echo SIGNAL_RECEIVED && tail -40 <LOG>' ``` Run with `run_in_background: true`. Set the Bash `timeout` to the expected max duration plus a safety margin (e.g. 6h for a long perturbation test, 10min for `acceptance/build-info`). This is **long-poll**, not poll: the worker-side `tmux wait-for` blocks indefinitely on a kernel-cheap semaphore wait. There is no periodic checking — Claude simply gets one notification at the end. When the notification arrives: - Read the task output (it ends with the last 40 log lines + EXIT code). - Summarize for the user: pass/fail, duration, and where the artifacts live (`artifacts/<sha>/<runid>/<test-name>/run_1/`). ### Step 2b.5 — Long-running tail (peek window) Spawn a second background Bash task that runs `tail -F` against the log: ```bash roachdev worker ssh -- 'tail -F <LOG>' ``` Run with `run_in_background: true` and a long timeout. This task is NOT meant to complete; it lets the user (and Claude) read live output through `BashOutput` / `/tasks` without re-SSHing each time. Tell the user the task ID so they know which background task to peek at. ## Step 3 — Reporting back Initial message after launch — keep it short: ``` Launched <test> on the worker. - tmux session: <SESSION> - log: <LOG> - notify task: <ID> (fires when run finishes) - tail task: <ID> (live log, peek anytime) ``` When the notify task fires, post a one-paragraph result: pass/fail, duration, key error if it failed, artifact path on the worker, and a suggested `roachdev worker scp` command to download anything specific the user might want. ## Pitfalls and gotchas - **Closing SSH does not stop tmux.** `tmux new-session -d` detaches before SSH returns. The run is robust to lid-close, network drop, and Claude's bash timeout. - **Concurrent runs share `artifacts/`.** Each `roachstress.sh` invocation gets its own `artifacts/<sha>/<runid>/` subdir, so collision is fine. But `rm -rf artifacts/` would nuke another agent's work — never do this without checking `pgrep -af roachstress`. - **Branch switches affect anyone building from the same checkout.** If another test is still in its build phase, switching breaks it. See Step 2b.1.5 — wait for the build to finish, then switch in place. Worktrees are a last resort. - **`./dev` vs `./pkg/cmd/roachtest/roachstress.sh`.** Always use `roachstress.sh` for roachtests — it cross-compiles `cockroach`, `workload`, and `roachtest` for the cluster's arch and caches by SHA. `./dev test` is for unit tests and will not produce the right binaries. ## Artifact paths After a successful run, artifacts live at: ``` ~/go/src/github.com/cockroachdb/cockroach/artifacts/<sha>/<runid>/<test-name>/run_1/ ``` Useful files inside `run_1/`: - `test.log` — main test log; start here when debugging. - `<N>.perf/stats.json` — workload per-second tick data (node `<N>` is the workload node, usually the highest-numbered). - `<N>.perf/phases.json` — perturbation baseline / perturbation / recovery boundaries (RFC3339Nano). - `1.perf/stats.json` — aggregated ratio summary stats (perturbation tests only). - `run_*.log` — individual command logs (cockroach start, workload invocations, etc). Download with: ```bash roachdev worker scp -- ':<path-on-worker>' /local/path ``` ## Quick reference: full remote launch ```bash # 1. Pre-flight. roachdev worker ssh -- ' tmux ls; echo ---; pgrep -af roachstress; echo ---; cd ~/go/src/github.com/cockroachdb/cockroach && git rev-parse HEAD ' # 2. (If needed) push and fetch your branch. git push -u origin <branch> roachdev worker ssh -- ' cd ~/go/src/github.com/cockroachdb/cockroach && git fetch origin <branch> && git reset --hard origin/<branch> ' # 3. Launch detached. roachdev worker ssh -- "tmux new-session -d -s rt-<name> \"cd ~/go/src/github.com/cockroachdb/cockroach && bash pkg/cmd/roachtest/roachstress.sh -c 1 -u <test> 2>&1 | tee ~/rt-<name>.log; echo EXIT=\\\$? >> ~/rt-<name>.log; tmux wait-for -S rt-<name>-done\"" # 4. Notify task (run_in_background: true). roachdev worker ssh -- 'tmux wait-for rt-<name>-done && echo SIGNAL_RECEIVED && tail -40 ~/rt-<name>.log' # 5. Tail task (run_in_background: true). roachdev worker ssh -- 'tail -F ~/rt-<name>.log' ```
View on GitHub