@blopai/ingest
v0.1.2
Published
Universal test-result ingestion client for Blop Cloud. Emits CloudEvents (qa.run.started/step.finished/finished.v1) and uploads artifacts from any test runner — blop CLI, vitest, pytest, Go, or any framework that emits JUnit XML.
Maintainers
Readme
@blopai/ingest
Universal test-result ingestion client for Blop Cloud.
Emits CloudEvents (qa.run.started.v1,
qa.run.step.finished.v1, qa.run.finished.v1) and uploads artifacts via
presigned URLs to the Blop platform — from any test runner.
Adapters
- blop CLI — built-in (the
@blopai/clipackage uses this internally). - Vitest —
@blopai/ingest/vitestreporter (see Vitest integration). - Any framework via JUnit XML —
blop-ingest upload --junit report.xmlworks with pytest, Go, RSpec, PHPUnit, Jest, Mocha, Gradle, .NET, and more (see Any framework via JUnit).
Install
pnpm add -D @blopai/ingestQuick start (Vitest)
// vitest.config.ts
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
reporters: ["default", "@blopai/ingest/vitest"],
},
});# .github/workflows/test.yml
- run: pnpm test
env:
BLOP_INGEST_URL: ${{ vars.BLOP_INGEST_URL }}
BLOP_INGEST_SECRET: ${{ secrets.BLOP_INGEST_SECRET }}
BLOP_PROJECT_ID: ${{ vars.BLOP_PROJECT_ID }}Quick start (any framework via JUnit XML)
pytest --junitxml=report.xml
npx @blopai/ingest upload --junit report.xmlEnvironment variables
| Variable | Required | Role |
|----------|----------|------|
| BLOP_INGEST_URL | yes | Platform ingest endpoint |
| BLOP_INGEST_SECRET | yes | Per-project ingest secret |
| BLOP_PROJECT_ID | yes | Project id |
| BLOP_RUN_ID | no | Run id (auto-generated if unset) |
| BLOP_TRIGGER | no | Trigger source (ci | manual | schedule | healer_verify) |
Programmatic API
import { createIngestClient } from "@blopai/ingest";
const client = createIngestClient();
if (client) {
await client.emitStarted();
await client.emitFinished({
status: "failed",
counts: { passed: 3, failed: 2, skipped: 1 },
durationMs: 5000,
topFailures: [{ test_file: "tests/auth.test.ts", message: "login failed" }],
});
}When config is missing, createIngestClient() returns null — callers
should treat upload as skipped, not an error.
License
MIT
