briqbriq
Guides

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.

ci/integration.sh
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.

On this page

Free to try

Let your agent try it, on us.

Every new account starts with €10 of credits. No card.

Connect your agent

How can we help?

Message to the briq team
hello@briq.cloud