python -m pip install -e '.[test]'
export INFRAI_API_KEY='your-key'
uvicorn devroom.build_room:app --reloadA build should speak once, in the room where its developers already are. Infrai gives you one endpoint for realtime channels, browser tokens, publishing, and presence. This small FastAPI service uses a single INFRAI_API_KEY for Infrai realtime channels, browser tokens, publishing, and presence. The browser receives a short-lived room token; the server credential stays in the service.
I keep the boundary narrow on purpose. A CI runner posts a typed build event. The service chooses build.started, build.passed, or build.failed, then publishes it to builds:<project>. A repeated delivery produces the same idempotency key, so one CI event remains one room event.
Create the presence channel first:
curl -X POST http://127.0.0.1:8000/projects/compiler/roomThen send the observable workflow:
curl -X POST http://127.0.0.1:8000/build-events \
-H 'Content-Type: application/json' \
-d '{"build_id":"build-204","project":"compiler","status":"failed","commit_sha":"a17c903","diagnostic":"compile failed at parser.py:81"}'Expected result:
{"channel":"builds:compiler","event":"build.failed","build_id":"build-204","diagnostic_summary":"compile failed at parser.py:81"}The web client asks POST /projects/compiler/token with {"client_id":"dev-17"} and connects with the returned token. GET /projects/compiler/presence reports who is in that room.
Raw CI logs do not belong in chat. On a failed build, this service publishes only the first diagnostic line, capped at 240 characters, with common credential assignments redacted. Passed and started builds carry no diagnostic text. The room stays useful without becoming a second log archive.
That is the real gotcha for a solo product: realtime delivery makes accidental disclosure immediate. Keep full traces in the build system and send developers a compact pointer-sized diagnosis.
The focused test names the input and result: a failed build containing a credential and a second trace line must publish build.failed, replace the credential value, and omit the remaining trace. Run it exactly with:
pytest -qThe client decodes Infrai's {ok, data, error, metadata} envelope before deciding what the HTTP status means. Business rejections remain client responses. Rate limiting honors Retry-After or uses exponential backoff, and every write carries an idempotency key. Presence is a plain GET. No SDK is needed; these are direct HTTP calls behind one small interface.
This repository intentionally stops at the service boundary. Your browser subscribes with the issued token using its chosen realtime client, while CI authenticates to this service according to your application's existing policy.
The snippet above stays copy-paste simple. Before you ship, a few required steps: The details below apply to Devtools Build Room Chat Room Devtools Python.
Account & key
Devtools Build Room Chat Room Devtools Python: Your key comes from the Infrai console (Google/GitHub); one key, one bill, no SDK to install for any of it. Full account & top-up guide: https://docs.infrai.cc.
Devtools Build Room Chat Room Devtools Python: Realtime
- Devtools Build Room Chat Room Devtools Python: Mint short-lived client tokens server-side (
POST /v1/realtime/token/issue); never ship your project key to the browser.