POST /build/stream
Build with streaming progress via Server-Sent Events (SSE). This endpoint accepts the same parameters as POST /build but returns real-time progress updates instead of waiting for completion.
Request
All requests use multipart/form-data. You must provide either a source file OR a repo_url, not both.
Git Repository
curl -X POST -N https://api.kettle.build/v1/build/stream \
-F "repo_url=https://github.com/owner/repo" \
-F "ref=main"
ZIP Upload
curl -X POST -N https://api.kettle.build/v1/build/stream \
-F "source=@source.zip"
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
source | file | No* | ZIP file containing source code |
repo_url | string | No* | Git repository URL to clone |
ref | string | No | Git ref (branch, tag, or commit). Only used with repo_url |
*One of source or repo_url must be provided, but not both.
Response
The endpoint returns a stream of Server-Sent Events. Each event contains a JSON payload:
Progress Events
data: {"type": "info", "message": "Initializing build environment"}
data: {"type": "info", "message": "Detecting project type"}
data: {"type": "info", "message": "Running cargo build --release"}
data: {"type": "info", "message": "Generating provenance"}
data: {"type": "info", "message": "Creating attestation"}
Completion Event
The final event contains the complete build result:
data: {"type": "complete", "result": {"build_id": "a1b2c3d4", "status": "success", ...}}
Event Types
| Type | Description |
|---|---|
info | General progress information |
complete | Build finished, contains full result in result field |
Client Example
const formData = new FormData();
formData.append('repo_url', 'https://github.com/owner/repo');
const response = await fetch('/api/build/stream', {
method: 'POST',
body: formData,
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
const lines = text.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.slice(6));
if (data.type === 'complete') {
console.log('Build result:', data.result);
} else {
console.log(`[${data.type}] ${data.message}`);
}
}
}
}
Response Headers
Content-Type: text/event-stream
Cache-Control: no-cache
X-Accel-Buffering: no