Provision declared infrastructure and run conformance packs

You will make a project declare the infrastructure its tests need, have putnami test provision it automatically, and certify the project against a shared conformance pack with one committed line — no per-project database wiring, no hardcoded connections.

The idea: your project declares what it needs (a Postgres datasource), and the toolchain provisions it. Locally, putnami test starts a throwaway container and injects a binding; in CI, it consumes the binding your pipeline already supplies. Your tests never probe for a server or hardcode a port. On top of that, a conformance pack lets you certify a whole family of behaviors (transactions, health probes, …) against the provisioned infrastructure with a single opt-in line.

Steps

1) Declare the infrastructure your tests need

Add infra/requirements.json at the project root, listing the datasources your tests use:

{
  "$schema": "https://putnami.dev/schemas/putnami-infra.json",
  "protocolVersion": 1,
  "databases": [
    {
      "name": "default",
      "engine": "postgres",
      "schemas": ["public"]
    }
  ]
}

That is the whole contract. The requirement travels with the project through its dependency graph, so a library that declares a datasource pulls the requirement into every workload that depends on it.

2) Let putnami test provision it

Run your tests normally:

putnami test

putnami test reads the declared requirements and resolves an infrastructure policy before running anything:

mode when behavior
auto local default provisions a throwaway Postgres container (needs Docker), injects a DATABASE_TEST_BINDINGS binding, tears it down after
require CI default never provisions — consumes the DATABASE_TEST_BINDINGS your pipeline injects, and fails loudly if none is present
skip opt out injects nothing; tests gated on the binding skip

Override the policy with the --infra flag or the test.infra config key (flag wins):

putnami test --infra require   # consume an external binding, fail if absent
putnami test --infra skip       # never provision
putnami test --infra-down       # tear down any leftover provisioned containers

An externally set DATABASE_TEST_BINDINGS always wins: when the variable is present, putnami test injects nothing and your binding flows through untouched.

Because the binding is provisioned from your declared requirements, your tests must consume it through the framework's datasource resolution rather than a hardcoded connection — a provisioned binding wins, and your committed test config is the fallback:

// Resolve the datasource through the framework. A provisioned binding wins;
// conf/.env.test.yaml is the fallback. No hardcoded host/port in the test.
import { database } from '@putnami/database';

const sql = await database('default');
await sql`SELECT 1`;

3) Opt into a conformance pack (one line)

A conformance pack is a shared, cross-language test corpus a framework ships so every adopter certifies the same behavior against its own provisioned infrastructure. Opt in with a single committed line in a test file.

TypeScript — certify the transaction / concurrency corpus:

// test/conformance.test.ts
import { registerConformanceTests } from '@putnami/database/conformance';

registerConformanceTests();

Go — the same corpus, same manifest, from the sibling runner:

// conformance_test.go
package myapp_test

import (
	"testing"

	"go.putnami.dev/database/conformance"
)

func TestTransactionConformance(t *testing.T) {
	conformance.Run(t)
}

Both runners provision through the same DATABASE_TEST_BINDINGS path from step 2, so the pack runs live against the auto-provisioned database and skips cleanly when no binding is present. Health-probe packs follow the same shape (registerHealthConformanceTests() in TypeScript; the Go health runner in go.putnami.dev/app/conformance).

4) Understand the pack-manifest convention

A framework advertises a pack with a committed conformance/pack.json next to its runner:

{
  "id": "putnami.transaction.conformance",
  "corpus": "manifest.json",
  "capabilityKinds": ["datasource"],
  "languages": ["go", "typescript"]
}
field meaning
id stable pack identity
capabilityKinds the capability kinds the pack certifies (e.g. datasource, health)
languages languages with an exported runner
corpus optional path to a committed corpus fixture; omit when the corpus is a runtime artifact

When a pack is reachable through your project's dependency graph and its capabilityKinds intersect the kinds your project declares in schema/capabilities.json, putnami test prints a one-line advisory naming the pack:

Test infrastructure:
  [test_infra.conformance_advisory] project my-app: capability kind "datasource" has an available conformance pack "putnami.transaction.conformance" with no opt-in; add a one-line conformance.Run(t) / registerConformanceTests() to certify it

The advisory is purely informational — it never fails a build and it disappears the moment you add the opt-in line from step 3. A project with no matching pack, or no capability manifest, gets no advisory and pays no cost.

You now have a project that declares its own infrastructure, provisions it automatically under putnami test, and certifies its behavior against a shared conformance pack — with no per-project database plumbing and no hardcoded connections.