Run tests against real services
Replace mocks with a real Postgres and Redis for the duration of a test run.
Recipes: PostgreSQL, Redis
Mocks drift, and Testcontainers needs Docker, which cloud sandboxes and CI runners often lack. briq gives a test run real services for a few cents and tears them down after.
Recipe outputs are private addresses that only briqs of your team can reach, so the tests run in a briq too, in the same stack as the services.
From an agent
Run the integration tests against a real Postgres and Redis instead of the mocks.
The agent starts the postgres and redis recipes and a runner in the same stack, runs the tests
there with the outputs as env, destroys the stack's briqs, and can tell you what the run cost.
Run in briq
briq_run({ recipe: "postgres", stack: "ci" })
briq_run({ recipe: "redis", stack: "ci" })
briq_run({ image: "node:22", stack: "ci", cmd: ["sleep", "infinity"],
env: { DATABASE_URL: { secret: "DATABASE_URL", value: "<from postgres>" },
REDIS_URL: "<from redis>" } })
briq_files_put({ briq: "bq_…", path: "/app.tgz", contentBase64: "…" })
briq_exec({ briq: "bq_…", cmd: ["sh", "-c", "tar xzf /app.tgz -C / && cd /app && npm ci && npm test"], timeoutMs: 600000 })DATABASE_URL holds a password, so it goes in as a secret: plain env values show in status and on
the dashboard. briq_exec shows the first 32 KB of output: send long output to a file and read it
with briq_files_get.
From CI
The same calls over REST. sleep: "30m" puts everything to sleep 30 minutes
after the job last used it, even if the job dies before its cleanup step. A sleeping briq is not
billed, but its disk counts toward the plan's allowance until it is destroyed.
api() { local p=$1; shift; curl -sf "https://api.briq.cloud/v1$p" \
-H "Authorization: Bearer $BRIQ_API_KEY" -H "Content-Type: application/json" "$@"; }
DB=$(api /briqs -d '{ "recipe": "postgres", "stack": "ci", "sleep": "30m" }')
CACHE=$(api /briqs -d '{ "recipe": "redis", "stack": "ci", "sleep": "30m" }')
RUNNER=$(api /briqs -d "$(jq -n --argjson db "$DB" --argjson c "$CACHE" '{ stack: "ci", spec: {
name: "runner", image: "node:22", cmd: ["sleep", "infinity"], sleep: "30m",
env: { DATABASE_URL: { secret: "DATABASE_URL", value: $db.outputs.DATABASE_URL },
REDIS_URL: $c.outputs.REDIS_URL } } }')")
ID=$(jq -r '.briqs[0].id' <<<"$RUNNER")
git archive HEAD | gzip | base64 | jq -Rs '{ path: "/app.tgz", contentBase64: . }' \
| api "/briqs/$ID/files" -d @- >/dev/null
api "/briqs/$ID/exec" -d '{ "timeoutMs": 600000, "cmd": ["sh", "-c",
"mkdir -p /app && tar xzf /app.tgz -C /app && cd /app && npm ci && npm test"] }' \
| tee result.json | jq -r .stdout
STATUS=$(jq .exitCode result.json)
for id in $(jq -r '.briqs[].id' <<<"$DB $CACHE $RUNNER"); do api "/briqs/$id" -X DELETE >/dev/null; done
exit "$STATUS"Uploads are capped at 1 MB a file; for a repo, have the runner git clone it instead.
nano is enough for Redis and most test databases.