Skip to content

Commit 78919e8

Browse files
author
Mark Saroufim
committed
Add CLAUDE.md and update test_bot.md documentation
- Add CLAUDE.md with ruff linting instructions and codebase overview - Point Problem Configuration section to gpu-mode/reference-kernels - Add update-problems command examples to test_bot.md
1 parent 7e37b09 commit 78919e8

2 files changed

Lines changed: 364 additions & 0 deletions

File tree

‎CLAUDE.md‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Kernelbot Development Guide
2+
3+
## Linting
4+
5+
Always run ruff before committing:
6+
7+
```bash
8+
uv run ruff check . --exclude examples/ --line-length 120 --fix
9+
```
10+
11+
To check without auto-fixing:
12+
13+
```bash
14+
uv run ruff check . --exclude examples/ --line-length 120
15+
```
16+
17+
## Testing
18+
19+
Run tests with pytest:
20+
21+
```bash
22+
uv run pytest tests/ -v
23+
```
24+
25+
## Local Development
26+
27+
See `SKILLS/test_bot.md` for local testing setup instructions.
28+
29+
## Architecture
30+
31+
### Problem Configuration
32+
33+
Problems are defined in the [gpu-mode/reference-kernels](https://github.com/gpu-mode/reference-kernels) repository. See that repo for examples of problem structure and `task.yml` format.
34+
35+
### Leaderboard Creation
36+
37+
- **Dev leaderboards** (via API): Created from a single problem directory. GPUs must be specified in the problem's `task.yml`. The leaderboard name is auto-derived as `{directory}-dev`.
38+
39+
- **Competition leaderboards** (via Discord admin_cog): Created from a competition YAML file that references multiple problems with their deadlines and GPU configurations.

‎SKILLS/test_bot.md‎

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
# Local Testing Guide for Kernelbot + Popcorn CLI
2+
3+
This document describes how to set up and test the kernelbot API and popcorn-cli admin flow locally.
4+
5+
## Prerequisites
6+
7+
### 1. PostgreSQL Setup
8+
9+
Install and start PostgreSQL:
10+
11+
```bash
12+
# Install PostgreSQL 14 via Homebrew
13+
brew install postgresql@14
14+
15+
# Start the service
16+
brew services start postgresql@14
17+
18+
# If brew services fails, start directly:
19+
/opt/homebrew/opt/postgresql@14/bin/pg_ctl -D /opt/homebrew/var/postgresql@14 start
20+
```
21+
22+
Create the kernelbot database:
23+
24+
```bash
25+
# Replace YOUR_USERNAME with your system username
26+
psql -U YOUR_USERNAME -d postgres -c "CREATE DATABASE kernelbot;"
27+
```
28+
29+
### 2. Environment Variables
30+
31+
Create a `.env` file in the kernelbot root directory:
32+
33+
```bash
34+
# Required for API startup
35+
GITHUB_TOKEN=placeholder_github_token
36+
GITHUB_REPO=owner/kernelbot
37+
38+
# Local PostgreSQL database (replace YOUR_USERNAME with your system username)
39+
DATABASE_URL=postgresql://YOUR_USERNAME@localhost:5432/kernelbot
40+
DISABLE_SSL=true
41+
42+
# Admin token for local testing
43+
ADMIN_TOKEN=your_secure_token_here
44+
45+
# Problem directory (absolute path to examples folder)
46+
PROBLEM_DEV_DIR=/path/to/kernelbot/examples
47+
```
48+
49+
### 3. Database Migrations
50+
51+
Run yoyo migrations to set up the schema:
52+
53+
```bash
54+
cd /path/to/kernelbot
55+
# Replace YOUR_USERNAME with your system username
56+
uv run yoyo apply --database "postgresql://YOUR_USERNAME@localhost:5432/kernelbot" src/migrations/ --batch
57+
```
58+
59+
If migrations fail due to partial application, mark them as applied:
60+
61+
```bash
62+
# Replace YOUR_USERNAME with your system username
63+
uv run yoyo mark --all --database "postgresql://YOUR_USERNAME@localhost:5432/kernelbot" src/migrations/ --batch
64+
```
65+
66+
## Running Tests
67+
68+
### Unit Tests (pytest)
69+
70+
Run the admin API tests:
71+
72+
```bash
73+
cd /path/to/kernelbot
74+
uv run pytest tests/test_admin_api.py -v
75+
```
76+
77+
Run all tests:
78+
79+
```bash
80+
uv run pytest tests/ -v
81+
```
82+
83+
### Integration Tests with Docker
84+
85+
The test suite uses docker-compose for database setup:
86+
87+
```bash
88+
uv run pytest tests/ -v
89+
```
90+
91+
This automatically starts a test database container.
92+
93+
## Starting the API
94+
95+
### API-Only Mode (No Discord)
96+
97+
Start the API server without requiring Discord credentials:
98+
99+
```bash
100+
cd /path/to/kernelbot/src/kernelbot
101+
uv run python main.py --api-only
102+
```
103+
104+
The API will be available at `http://localhost:8000`.
105+
106+
### Verify API is Running
107+
108+
```bash
109+
curl http://localhost:8000/leaderboards
110+
# Should return: []
111+
```
112+
113+
## Testing Admin Commands
114+
115+
### Using curl
116+
117+
```bash
118+
# Set your admin token
119+
TOKEN="your_secure_token_here"
120+
121+
# Start accepting jobs
122+
curl -X POST http://localhost:8000/admin/start -H "Authorization: Bearer $TOKEN"
123+
124+
# Get stats
125+
curl http://localhost:8000/admin/stats -H "Authorization: Bearer $TOKEN"
126+
127+
# Stop accepting jobs
128+
curl -X POST http://localhost:8000/admin/stop -H "Authorization: Bearer $TOKEN"
129+
```
130+
131+
### Using Popcorn CLI
132+
133+
First, build the CLI:
134+
135+
```bash
136+
cd /path/to/popcorn-cli
137+
cargo build
138+
```
139+
140+
Then run admin commands:
141+
142+
```bash
143+
# Set environment variables
144+
export POPCORN_API_URL=http://127.0.0.1:8000
145+
export POPCORN_ADMIN_TOKEN=your_secure_token_here
146+
147+
# IMPORTANT: If you have HTTP proxy set, bypass it for local testing
148+
unset HTTP_PROXY HTTPS_PROXY
149+
150+
# Admin commands
151+
./target/debug/popcorn-cli admin start
152+
./target/debug/popcorn-cli admin stats
153+
./target/debug/popcorn-cli admin stop
154+
./target/debug/popcorn-cli admin get-submission 123
155+
./target/debug/popcorn-cli admin delete-submission 123
156+
./target/debug/popcorn-cli admin create-leaderboard identity_py
157+
./target/debug/popcorn-cli admin delete-leaderboard identity_py-dev
158+
159+
# Update problems from reference-kernels repo (mirrors Discord /admin update-problems)
160+
./target/debug/popcorn-cli admin update-problems --problem-set nvidia
161+
./target/debug/popcorn-cli admin update-problems --problem-set pmpp_v2 --force
162+
./target/debug/popcorn-cli admin update-problems # Updates all problem sets
163+
```
164+
165+
## End-to-End CLI Testing
166+
167+
Full workflow to test the admin CLI:
168+
169+
```bash
170+
# 1. Start the API server (in kernelbot repo)
171+
cd /path/to/kernelbot/src/kernelbot
172+
ADMIN_TOKEN=test_token PROBLEM_DEV_DIR=/path/to/kernelbot/examples uv run python main.py --api-only
173+
174+
# 2. In another terminal, set up CLI environment
175+
cd /path/to/popcorn-cli
176+
cargo build
177+
unset HTTP_PROXY HTTPS_PROXY
178+
export POPCORN_API_URL=http://127.0.0.1:8000
179+
export POPCORN_ADMIN_TOKEN=test_token
180+
181+
# 3. Test admin commands
182+
./target/debug/popcorn-cli admin start
183+
./target/debug/popcorn-cli admin stats
184+
185+
# 4. Create and delete a leaderboard (name auto-derived as "{directory}-dev")
186+
./target/debug/popcorn-cli admin create-leaderboard identity_py
187+
curl -s http://127.0.0.1:8000/leaderboards | jq '.[].name'
188+
./target/debug/popcorn-cli admin delete-leaderboard identity_py-dev
189+
```
190+
191+
## Troubleshooting
192+
193+
### "Connection refused" errors
194+
195+
1. Check if API is running: `lsof -i :8000`
196+
2. Make sure you're using `127.0.0.1` instead of `localhost` (IPv6 issues)
197+
3. Check for HTTP proxy: `echo $HTTP_PROXY` - if set, unset it for local testing
198+
199+
### "folly::AsyncSocketException" errors
200+
201+
This indicates an HTTP proxy is intercepting requests. Fix:
202+
203+
```bash
204+
unset HTTP_PROXY HTTPS_PROXY
205+
export NO_PROXY=127.0.0.1,localhost
206+
```
207+
208+
### Database connection errors
209+
210+
1. Check PostgreSQL is running: `brew services list | grep postgres`
211+
2. Verify DATABASE_URL in .env matches your setup
212+
3. Check database exists: `psql -U YOUR_USERNAME -d kernelbot -c "SELECT 1;"`
213+
214+
### "DISCORD_TOKEN not found" error
215+
216+
Make sure you're using `--api-only` flag when starting the server.
217+
218+
### Admin token errors
219+
220+
- 401 "Missing Authorization header": Token not being sent
221+
- 401 "Invalid admin token": Token doesn't match ADMIN_TOKEN in .env
222+
- 500 "ADMIN_TOKEN not configured": Set ADMIN_TOKEN in .env
223+
224+
## Architecture Notes
225+
226+
### API-Only Mode
227+
228+
The `--api-only` flag allows running the FastAPI server without Discord:
229+
- Skips Discord token validation
230+
- Creates backend without Discord bot initialization
231+
- All admin endpoints work via HTTP API
232+
233+
### Admin Authentication
234+
235+
Admin endpoints require:
236+
- Header: `Authorization: Bearer <ADMIN_TOKEN>`
237+
- Token is read from ADMIN_TOKEN environment variable
238+
239+
### CLI Admin Commands
240+
241+
The popcorn-cli admin commands use:
242+
- `POPCORN_API_URL`: API endpoint (default: production Heroku)
243+
- `POPCORN_ADMIN_TOKEN`: Bearer token for admin endpoints
244+
245+
## Testing Against Production (Heroku)
246+
247+
### Prerequisites
248+
249+
1. Get the production admin token from Heroku config vars:
250+
```bash
251+
heroku config:get ADMIN_TOKEN -a discord-cluster-manager
252+
```
253+
254+
2. Or set it in Heroku if not already configured:
255+
```bash
256+
heroku config:set ADMIN_TOKEN=your_secure_production_token -a discord-cluster-manager
257+
```
258+
259+
3. If migrating from LOCAL_ADMIN_TOKEN:
260+
```bash
261+
heroku config:set ADMIN_TOKEN=$(heroku config:get LOCAL_ADMIN_TOKEN -a discord-cluster-manager) -a discord-cluster-manager
262+
heroku config:unset LOCAL_ADMIN_TOKEN -a discord-cluster-manager
263+
```
264+
265+
### Using CLI with Production
266+
267+
```bash
268+
# Build CLI
269+
cd /path/to/popcorn-cli
270+
cargo build --release
271+
272+
# Use production API (default URL)
273+
export POPCORN_ADMIN_TOKEN=<production_token_from_heroku>
274+
275+
# Admin commands will hit production
276+
./target/release/popcorn-cli admin stats
277+
./target/release/popcorn-cli admin start
278+
./target/release/popcorn-cli admin stop
279+
```
280+
281+
### Using curl with Production
282+
283+
```bash
284+
PROD_URL="https://discord-cluster-manager-1f6c4782e60a.herokuapp.com"
285+
PROD_TOKEN="<production_token_from_heroku>"
286+
287+
# Get stats
288+
curl "$PROD_URL/admin/stats" -H "Authorization: Bearer $PROD_TOKEN"
289+
290+
# Start/stop job acceptance
291+
curl -X POST "$PROD_URL/admin/start" -H "Authorization: Bearer $PROD_TOKEN"
292+
curl -X POST "$PROD_URL/admin/stop" -H "Authorization: Bearer $PROD_TOKEN"
293+
```
294+
295+
### Checking Heroku Logs
296+
297+
```bash
298+
# View recent logs
299+
heroku logs --tail -a discord-cluster-manager
300+
301+
# Filter for admin actions
302+
heroku logs -a discord-cluster-manager | grep admin
303+
```
304+
305+
### Production Environment Variables
306+
307+
Required Heroku config vars for full functionality:
308+
- `DISCORD_TOKEN`: Discord bot token
309+
- `GITHUB_TOKEN`: GitHub API token
310+
- `GITHUB_REPO`: GitHub repository (e.g., `org/kernelbot`)
311+
- `DATABASE_URL`: PostgreSQL connection string (auto-set by Heroku Postgres)
312+
- `ADMIN_TOKEN`: Admin API authentication token
313+
- `MODAL_TOKEN_ID` / `MODAL_TOKEN_SECRET`: Modal credentials for GPU runs
314+
315+
View all config vars:
316+
```bash
317+
heroku config -a discord-cluster-manager
318+
```
319+
320+
### Safety Notes for Production
321+
322+
- Always test changes locally first before deploying to production
323+
- Admin commands affect live users - use `admin stop` carefully
324+
- Check stats before and after operations to verify expected behavior
325+
- Monitor Heroku logs when testing production changes

0 commit comments

Comments
 (0)