{"id":50699602,"url":"https://github.com/sha1n/testrig","last_synced_at":"2026-06-09T08:32:47.251Z","repository":{"id":358207237,"uuid":"1237764616","full_name":"sha1n/testrig","owner":"sha1n","description":"Go library for orchestrating multi-service test environments — parallel container lifecycle, property aggregation, and config injection for integration tests.","archived":false,"fork":false,"pushed_at":"2026-05-28T05:54:39.000Z","size":474,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-28T06:07:56.392Z","etag":null,"topics":["docker","go","golang","integration-testing","oidc","postgres","test-environment","test-infrastructure","testcontainers","testing","wiremock"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sha1n.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-13T13:41:16.000Z","updated_at":"2026-05-28T04:52:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sha1n/testrig","commit_stats":null,"previous_names":["sha1n/testrig"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/sha1n/testrig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha1n%2Ftestrig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha1n%2Ftestrig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha1n%2Ftestrig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha1n%2Ftestrig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sha1n","download_url":"https://codeload.github.com/sha1n/testrig/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha1n%2Ftestrig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34098932,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","go","golang","integration-testing","oidc","postgres","test-environment","test-infrastructure","testcontainers","testing","wiremock"],"created_at":"2026-06-09T08:32:47.139Z","updated_at":"2026-06-09T08:32:47.240Z","avatar_url":"https://github.com/sha1n.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# testrig\n\nA Go library for orchestrating multi-service test environments. Built on\n[testcontainers-go](https://golang.testcontainers.org/), `testrig` adds\nparallel lifecycle management and property aggregation across\nservices so an integration test can declare *what* it needs and let the\nframework handle bringing it up, wiring it into the application's config,\nand tearing it down.\n\n\u003e **Status:** pre-1.0, API not yet stable. Module path: `github.com/sha1n/testrig`.\n\n## Install\n\nThe engine and each pre-built service are independently versioned Go modules.\nAdd only what you need:\n\n```sh\n# Engine — required. Stdlib + golang.org/x/sync only.\ngo get github.com/sha1n/testrig@v0.0.0-prototype.1\n\n# Pre-built services (each pulls its own deps; pick what you use):\ngo get github.com/sha1n/testrig/services/postgres@v0.0.0-prototype.1\ngo get github.com/sha1n/testrig/services/wiremock@v0.0.0-prototype.1\ngo get github.com/sha1n/testrig/services/oidc@v0.0.0-prototype.1\n```\n\nWhile the API is still iterating, the only published tags are\n`v0.0.0-prototype.*` prereleases. **Pin explicitly** rather than using\n`@latest`: today `@latest` resolves to the highest prerelease, but the\nmoment a non-prerelease tag (e.g. `v0.1.0`) is published, `@latest`\nwill silently switch to it and skip all prereleases — possibly across\nbreaking changes while pre-1.0.\n\nThe `examples/` and `tools/` modules are repository-internal (demo apps and\nthe pinned `golangci-lint` for `make lint` respectively); they are not\nintended to be imported by external projects and have no published tags.\n\n## Why\n\nTests that need a real Postgres, a stubbed HTTP backend, or a handful of\ncollaborating services typically end up with hand-rolled `TestMain` scaffolding:\nspin up containers, aggregate host/port/credentials into the app's config,\ntear everything down on exit. `testrig` factors that scaffolding into an\n`Env` orchestrator that brings services up in parallel, gathers their published\nproperties, and tears them down on rollback or test exit.\n\n## Quickstart\n\n```go\nimport (\n    \"context\"\n    \"testing\"\n\n    \"github.com/sha1n/testrig\"\n    \"github.com/sha1n/testrig/services/postgres\"\n    \"github.com/stretchr/testify/require\"\n)\n\nfunc TestSomething(t *testing.T) {\n    // Publish the DSN directly under the application's expected config key.\n    pg := postgres.New(\"pg\").\n        WithDatabase(\"appdb\").\n        WithDSNPropertyName(\"DATABASE_URL\")\n\n    env := testrig.New(\"test\").With(pg)\n    props, err := env.Start(context.Background())\n    require.NoError(t, err)\n    t.Cleanup(func() { _ = env.Stop(context.Background()) })\n\n    // Properties are ready to merge into your app's config loader.\n    dsn := props[\"DATABASE_URL\"]\n    _ = dsn\n\n    // Or use the typed accessor on the service.\n    db, err := pg.DB(context.Background())\n    require.NoError(t, err)\n    defer db.Close()\n\n    // ... run your test against db / dsn\n}\n```\n\n## Features\n\n- **Parallel start, parallel stop.** All services start concurrently;\n  rollback on failure stops only those whose Start succeeded.\n- **Property aggregation.** Services publish a `Properties` map (host, port,\n  credentials, DSNs); `env.Properties()` returns a stable snapshot for the\n  test to read.\n- **App-aligned property keys.** Each pre-built service supports\n  `WithXxxPropertyName(...)` so its outputs land directly under the\n  application's expected config keys — no bridging step in the test.\n- **Pluggable injection.** Pass `env.Properties()` to viper, koanf, or any\n  `map[string]string`-shaped config; or use `SetEnvVars(t, props)` for\n  libraries that read only from `os.Getenv`.\n- **Opt-in startup ordering.** Use `testrig.NewStages(a).Then(b, c)` and\n  `env.WithStages(...)` when you need explicit ordering between groups\n  of services.\n- **Pre-built services.** `postgres`, `wiremock`, and\n  `oidc` ship as ready-to-use implementations (the first two\n  testcontainers-backed; OIDC is a non-dockerized in-process issuer).\n  New services are a single `Service` interface implementation away\n  (3 methods: `Name`, `Start`, `Stop`).\n\n## Pre-built services\n\nEach pre-built service is a separate Go module. `go get github.com/sha1n/testrig`\npulls only the engine; testcontainers, pgx, JWT, and other heavy deps come in\nonly when you import a service.\n\nEach service has its own README with a quickstart, full configuration\nreference, and a \"Gaps and workarounds\" section.\n\n| Service | Import | Notes |\n|---|---|---|\n| [PostgreSQL](services/postgres/README.md) | `github.com/sha1n/testrig/services/postgres` | testcontainers-backed; exposes `DSN()` and `DB(ctx)` once started; all property keys customizable. |\n| [WireMock](services/wiremock/README.md) | `github.com/sha1n/testrig/services/wiremock` | testcontainers-backed; exposes `URL()` and `Client()`; URL property key customizable. |\n| [OIDC](services/oidc/README.md) | `github.com/sha1n/testrig/services/oidc` | non-dockerized, Auth0-style OIDC issuer; supports `authorization_code` (with PKCE S256), `client_credentials`, and `refresh_token` grants; serves discovery, JWKS, `/authorize`, `/token`, `/userinfo`. |\n\n## Examples\n\nTwo parallel example apps demonstrating testrig with different config\nlibraries. Each is a small, well-structured Go server with:\n\n- `main.go` — thin entry point\n- `config/` — typed config loader (Viper or koanf — the only divergent piece)\n- `testenv/` — testrig wiring used by both `main` and the tests\n- `server/server_test.go` — integration tests sharing one env via `TestMain`\n\nThe HTTP server itself and the custom schema-seed `api.Service` are\nshared between the two examples in `examples/internal/sampleapp` and\n`examples/internal/seed` — they have no config-library opinion. The seed\npackage is the canonical demo of how to write your own\n**non-dockerized `api.Service`** and order it after a dependency via\n`WithStages`.\n\n| Example | Config library |\n|---|---|\n| [`examples/viper-app`](examples/viper-app/) | [Viper](https://github.com/spf13/viper) |\n| [`examples/koanf-app`](examples/koanf-app/) | [koanf](https://github.com/knadh/koanf) |\n\n## Spec\n\nThe full public-API and runtime-semantics specification lives at\n[`docs/SPEC.md`](docs/SPEC.md).\n\n## Repository layout\n\nThis repo is a Go multi-module workspace. Each module is independently\nversioned and published, so consumers download only the dependencies they\nactually use.\n\n```\n.                              github.com/sha1n/testrig            (engine; stdlib + golang.org/x/sync)\nservices/oidc/                 github.com/sha1n/testrig/services/oidc\nservices/postgres/             github.com/sha1n/testrig/services/postgres\nservices/wiremock/             github.com/sha1n/testrig/services/wiremock\nexamples/                      github.com/sha1n/testrig/examples   (not published)\ntools/                         github.com/sha1n/testrig/tools      (not published; pins golangci-lint)\ngo.work                        ties all of the above together for local development\n```\n\nEach sub-module imports the engine via `github.com/sha1n/testrig`, and\neach sub-module `go.mod` carries a `require github.com/sha1n/testrig\n\u003cengine version\u003e` plus a `replace github.com/sha1n/testrig =\u003e ..`.\nThe replace lets local builds work before any engine version is\npublished; it has no effect on external consumers (Go ignores `replace`\ndirectives in dependency modules). `go.work` ties all modules together\nfor editor and tool support.\n\n### Tagging and releases\n\nEach module is versioned independently using the standard Go sub-module\ntag scheme:\n\n| Module | Tag prefix | Example |\n|---|---|---|\n| root | (none) | `v0.1.0` |\n| `services/oidc` | `services/oidc/` | `services/oidc/v0.1.0` |\n| `services/postgres` | `services/postgres/` | `services/postgres/v0.1.0` |\n| `services/wiremock` | `services/wiremock/` | `services/wiremock/v0.1.0` |\n\nRelease order: tag the engine first, then bump each sub-module's\n`require github.com/sha1n/testrig` to the engine's new version, commit,\nthen tag the sub-modules. The `replace` line stays in place — it's\ninert for consumers and keeps local development working.\n\n## Build\n\n```\nmake check           # format + lint + test across every module (default)\nmake test            # tests only (every module)\nmake lint            # go vet + golangci-lint across every module; fails on issues\nmake build-examples  # build example binaries into bin/\nmake go-get          # workspace sync across every module\n```\n\n`make lint` invokes `golangci-lint` via Go's `tool` directive — the version is\npinned in `tools/go.mod`, so contributors don't need to install it separately\nand CI runs the same version.\n\nRequires Go 1.25 or later. Tests require Docker (testcontainers).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsha1n%2Ftestrig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsha1n%2Ftestrig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsha1n%2Ftestrig/lists"}