From 3d5d3f8f833e573dde06072ab0c6b46875ab4ad8 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 16:13:21 +0000 Subject: [PATCH] Add test-env setup script and skill for Claude Code cloud sessions Add an on-demand setup script (scripts/setup-test-env.sh) plus a companion skill that prepare an ephemeral Linux container (e.g. a Claude Code cloud session) for running the test suite: - install sentry-devenv via the official bash installer - run `uv sync` (builds the venv and compiles the rust_snuba extension) - start the Docker daemon if needed - bring up devservices (clickhouse, redis, kafka) This is a standalone script rather than a session-start hook so the multi-minute cost is only paid when tests are actually needed. Lower the clickhouse `nofile` ulimit in devservices/config.yml to soft 1024 / hard 4096 so the container can start in environments without CAP_SYS_RESOURCE (the previous 262144 cannot be applied there). Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01CutWwsFwLDtczduJzjvF8Y --- .claude/skills/setup-test-env/SKILL.md | 65 ++++++++++++++++ devservices/config.yml | 4 +- scripts/setup-test-env.sh | 101 +++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 .claude/skills/setup-test-env/SKILL.md create mode 100755 scripts/setup-test-env.sh diff --git a/.claude/skills/setup-test-env/SKILL.md b/.claude/skills/setup-test-env/SKILL.md new file mode 100644 index 00000000000..db2d9b14dc8 --- /dev/null +++ b/.claude/skills/setup-test-env/SKILL.md @@ -0,0 +1,65 @@ +--- +name: setup-test-env +description: Set up the Snuba dev/test environment in a Claude Code cloud session so the test suite can run. Use when the user wants to run tests, install devenv/devservices, start clickhouse/redis/kafka, or otherwise prepare an ephemeral Linux container for development. Installs sentry-devenv, builds the Python venv and the rust_snuba native extension, starts Docker, and brings up devservices. +--- + +# Set up the Snuba test environment + +Use this skill to make tests runnable in an ephemeral Linux container (such as a +Claude Code cloud session), where nothing is installed and the Docker daemon is +not running. + +## How to run it + +Run the setup script from the repo root: + +```bash +bash scripts/setup-test-env.sh +``` + +It is idempotent, so it is safe to re-run. It takes several minutes on a cold +container (`uv sync` builds the rust extension, and the clickhouse/redis/kafka +images have to be pulled), and is much faster afterwards because the container +state is cached. + +The script: + +1. Installs `sentry-devenv` via the official bash installer + (`~/.local/share/sentry-devenv/bin/devenv`). +2. Runs `uv sync --frozen --active`, which creates `.venv` **and** compiles the + native `rust_snuba` extension into it (no separate `maturin develop` needed). + `devservices` is a dev dependency, so it lands at `.venv/bin/devservices`. +3. Starts the Docker daemon (`sudo dockerd`) if it isn't already running. +4. Runs `.venv/bin/devservices up` to start clickhouse, redis and kafka. + +## Running tests after setup + +Run pytest **from inside the `tests/` directory**: + +```bash +(cd tests && SNUBA_SETTINGS=test ../.venv/bin/pytest -m "not ci_only") +``` + +Why from inside `tests/`: invoking pytest from the repo root loads +`test_distributed_migrations/conftest.py`, whose `pytest_configure` connects to a +multi-node clickhouse host (`clickhouse-query`) that devservices does not provide +in single-node mode, causing an `INTERNALERROR` before any test runs. Running +from within `tests/` avoids loading that sibling conftest. + +For rust tests, source the rust env vars first: + +```bash +. scripts/rust-envvars && (cd rust_snuba && cargo test --workspace) +``` + +## Notes / gotchas + +- `devenv` refuses to run as root and `devenv sync` is Homebrew-based, so in the + cloud container the functional setup path is `uv sync` + `devservices`, not + `devenv sync`. The global `devenv` install is included only for parity with + local laptop setups. +- The clickhouse container's `nofile` ulimit in `devservices/config.yml` is set + to a value (soft 1024 / hard 4096) that fits inside the container's capability + set; the production-style 262144 cannot be applied without `CAP_SYS_RESOURCE`. +- If `devservices up` reports clickhouse is unhealthy, check + `docker ps` / `docker logs snuba-clickhouse-1`. diff --git a/devservices/config.yml b/devservices/config.yml index 642088c9357..e5113b50e31 100644 --- a/devservices/config.yml +++ b/devservices/config.yml @@ -50,8 +50,8 @@ services: image: ghcr.io/getsentry/image-mirror-altinity-clickhouse-server:25.3.8.10041.altinitystable ulimits: nofile: - soft: 262144 - hard: 262144 + soft: 1024 + hard: 4096 ports: - 127.0.0.1:9000:9000 - 127.0.0.1:9009:9009 diff --git a/scripts/setup-test-env.sh b/scripts/setup-test-env.sh new file mode 100755 index 00000000000..1dc78070e9b --- /dev/null +++ b/scripts/setup-test-env.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# Set up a Snuba dev/test environment in an ephemeral Linux container +# (e.g. a Claude Code cloud session) so that the test suite can run. +# +# This is intentionally a standalone, on-demand script (not a session-start +# hook): `uv sync` plus pulling the service images takes several minutes, so we +# only want to pay that cost when we actually need to run tests. +# +# What it does (all steps are idempotent and safe to re-run): +# 1. Install sentry-devenv (via the official bash installer). +# 2. Build the Python virtualenv AND the native rust_snuba extension +# (`uv sync` compiles rust_snuba into the venv, so no separate +# `maturin develop` step is needed). +# 3. Make sure the Docker daemon is running. +# 4. Bring up the service dependencies via devservices (clickhouse, redis, +# kafka). +# +# Usage: bash scripts/setup-test-env.sh + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO_ROOT" + +log() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; } + +# --------------------------------------------------------------------------- +# 1. Install sentry-devenv (global, into ~/.local/share/sentry-devenv/bin). +# devservices itself is installed by `uv sync` below (it is a dev +# dependency and ends up at .venv/bin/devservices). +# --------------------------------------------------------------------------- +DEVENV_BIN="$HOME/.local/share/sentry-devenv/bin" +if [ -x "$DEVENV_BIN/devenv" ]; then + log "sentry-devenv already installed ($DEVENV_BIN/devenv)" +else + log "Installing sentry-devenv" + installer="$(mktemp -t install-devenv.XXXX.sh)" + curl -fsSL https://raw.githubusercontent.com/getsentry/devenv/main/install-devenv.sh -o "$installer" + # The installer only runs when invoked as a file literally named + # `install-devenv.sh`, so rename before executing. + mv "$installer" "$(dirname "$installer")/install-devenv.sh" + installer="$(dirname "$installer")/install-devenv.sh" + chmod +x "$installer" + # CI=1 makes the installer non-interactive; /dev/null 2>&1; then + echo "Docker daemon already running." +else + echo "Starting dockerd ..." + sudo dockerd >/tmp/dockerd.log 2>&1 & + for _ in $(seq 1 30); do + if docker info >/dev/null 2>&1; then break; fi + sleep 1 + done + if ! docker info >/dev/null 2>&1; then + echo "ERROR: Docker daemon did not become ready. Last log lines:" >&2 + tail -n 20 /tmp/dockerd.log >&2 || true + exit 1 + fi + echo "Docker daemon is up." +fi + +# --------------------------------------------------------------------------- +# 4. Bring up the service dependencies (clickhouse, redis, kafka). +# --------------------------------------------------------------------------- +log "Starting devservices (clickhouse, redis, kafka)" +.venv/bin/devservices up + +# --------------------------------------------------------------------------- +# Done. +# --------------------------------------------------------------------------- +log "Environment ready. To run tests:" +cat <<'EOF' + export PATH="$PWD/.venv/bin:$PATH" + + # Run pytest from inside the tests/ directory. Invoking it from the repo + # root loads test_distributed_migrations/conftest.py, whose pytest_configure + # connects to a multi-node clickhouse ("clickhouse-query") that devservices + # does not provide in single-node mode. + (cd tests && SNUBA_SETTINGS=test ../.venv/bin/pytest -m "not ci_only") + + # For rust tests you also need the rust env vars: + # . scripts/rust-envvars && (cd rust_snuba && cargo test --workspace) +EOF