> For the complete documentation index, see [llms.txt](https://atomic-blend.gitbook.io/mongo2pg/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://atomic-blend.gitbook.io/mongo2pg/contributing/development.md).

# Development

## `GOWORK=off` is required

This repository sits inside the `backend/` Go workspace, but is **not listed** in `backend/go.work`. A bare `go build ./...` (or `go test`, `go vet`, …) run from here fails with:

```
directory prefix . does not contain modules listed in go.work
```

The toolchain discovers `go.work` by walking up the directory tree, so it finds `backend/go.work` even though nothing in it names this module — and then refuses to build. `Makefile` and `scripts/coverage.sh` both set `GOWORK=off` for you; set it yourself for any `go` command you run directly:

```bash
GOWORK=off go build ./...
GOWORK=off go test ./...
GOWORK=off go run ./cmd/mongo2pg --help
```

## Running the suites

```bash
make test    # unit + integration (testcontainers: a real MongoDB replica set and PostgreSQL)
make cover   # 90% statement-coverage floor on every package — see Architecture § Testing philosophy
make build   # bin/mongo2pg
make lint    # golangci-lint
```

`make test` needs Docker: the integration suite spins up real containers via [testcontainers-go](https://golang.testcontainers.org/) rather than mocking MongoDB or PostgreSQL — a mock of a driver error proves only that the mock works, which is exactly why the I/O-bound packages (the Mongo reader, the stream watcher, the PG writer, the metrics server) lean on this suite and the chaos suite below instead of unit-level mocks for their driver-error paths.

## Acceptance tests

Two suites, behind Go build tags, exercising the two ways mongo2pg actually gets deployed — see [Coverage target](/mongo2pg/contributing/architecture.md#testing-philosophy) for why coverage percentage is not the bar these are held to.

```bash
GOWORK=off go test ./test/acceptance/... -tags compose -v -timeout 30m
GOWORK=off go test ./test/acceptance/... -tags kind    -v -timeout 30m
```

**`-tags compose`** drives a real Docker Compose stack — the same one described in [Docker Compose](/mongo2pg/getting-started/getting-started/docker-compose.md) — against real data shaped like the local development database: the mixed-`_id` `tasks` collection, the `SyncTime` string/date split, and the boolean soft-deletes all live here, in one shared MongoDB database. It runs the end-to-end consistency check (`schema apply` → `run` to completion → `cutover check` must exit `0`, then an **independent** comparison — deliberately not reusing `mongo2pg verify`, so a bug in the mapper cannot mark its own work correct) and the live-sync/CDC suite (insert, update, soft-delete toggle, hard delete, `kill -9` mid-batch and restart, and re-running the full comparison afterward to catch a CDC path that diverges from the backfill path).

**`-tags kind`** deploys the Helm chart into a real [Kind](https://kind.sigs.k8s.io/) cluster, loaded from a `mongodump` of the local database **restored into one MongoDB database per service**, matching the production topology. This is the only place that can catch: the chart actually rendering and installing, RBAC genuinely permitting the ConfigMap read (a too-narrow `Role` fails only in-cluster, at startup), ConfigMap hot reload, Secret-sourced credentials, `replicas: 1` + `Recreate` holding across an upgrade, ServiceMonitor labels surviving relabeling, `GrafanaDashboard` CRs being accepted — and, critically, **cross-service references resolving across genuinely separate databases**, which the single-database Compose environment cannot exercise at all since a resolver bug that quietly reached across databases would still pass there.

Both environments are scripted and re-runnable locally; neither requires access to real production data — see `test/kind/` for the Kind cluster bootstrap scripts.

## Coverage

```bash
bash scripts/coverage.sh
```

Also sets `GOWORK=off`. Enforces the 90% statement-coverage floor per package described in [Architecture § Testing philosophy](/mongo2pg/contributing/architecture.md#testing-philosophy) — a floor against neglect, not a substitute for the mutation-testing discipline the codebase actually holds itself to.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://atomic-blend.gitbook.io/mongo2pg/contributing/development.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
