# Development How to work on interpres. ## Prerequisites - Go 1.27.1, the version the `go` directive in `go.mod` declares. - [just](https://github.com/casey/just) for the recipes. - The `toml-test` binary on `PATH` for the compliance recipe, installed with `go install github.com/toml-lang/toml-test/v2/cmd/toml-test@v2.2.0`. The module has no third-party dependencies, so there is nothing else to fetch. ## Setup ```sh git clone https://sourcedock.dev/petrbalvin/interpres.git cd interpres just build just test ``` ## Recipes Every recipe in the project's justfile, and what it does. Taken from the file itself, so the names and the list match it exactly; `just` with no arguments prints the same list. | Recipe | What it does | |---|---| | `just gates` | the definition of done: build, format check, vet, the test suite with the coverage floor, and the race detector | | `just build` | compiles `./cmd/interpres-decode` into `bin/interpres-decode` | | `just test` | the suite with no cache, then the coverage floor of 80 percent from `coverage.out` | | `just race` | the same suite under the race detector | | `just unit ./... TestName` | a fast scoped run for iterating; the second argument is a `-run` pattern, `.*` by default | | `just fuzz FuzzParse . 30s` | time-boxed fuzzing of one target in exactly one package; `go test -fuzz` rejects `./...`; never a gate | | `just bench` | benchmarks, `-benchmem -count=5`, on an idle machine only | | `just fmt` | `gofmt -w .`, format in place | | `just fmt-check` | `gofmt -l .`, zero diff | | `just vet` | `go vet ./...` and `go fix -diff ./...` | | `just run` | `go run ./cmd/interpres-decode`, reads TOML from stdin | | `just dev` | the same run, for iterating | | `just example` | `go run ./examples/basic`, the usage tour | | `just toml-test` | builds the adapter and runs the official toml-test compliance suite against it | | `just coverage-html` | `just test`, then `go tool cover -html` into `coverage.html` | | `just install` | builds, then copies the binary into `~/.local/bin` (`BINDIR` overrides) | | `just uninstall` | removes the installed binary | | `just clean` | removes `bin/` and `coverage.out` | ## Running a single test ```sh just unit ./... TestParseMultilineString go test -run 'TestRejectsSpecInvalid/table_over_array' ./... go test ./cmd/interpres-decode/ ``` Add `-v` for the sub-test names, and `-race` when the change touches concurrency. `-count=1` defeats the test cache when a result looks stale. ## Coverage ```sh just test go tool cover -func=coverage.out just coverage-html ``` `just test` prints the total itself and fails below 80 percent, which is the same floor CI enforces. The profile is `coverage.out`; the HTML map is `coverage.html`. Both are ignored by git. ## Benchmarks ```sh just bench ``` Benchmark on an idle machine, and compare only runs made in one process against each other. The recipe sweeps `./...` five times with `-benchmem`. The binding measurement method, and what counts as a result, is in [docs/BENCHMARKING.md](BENCHMARKING.md). ## Debugging the build ```sh go build -gcflags='-m' ./... # inlining decisions go build -gcflags='-S' ./... # what the compiler generated ``` ## Continuous integration Workflows live in `.gitea/workflows/` and run on the project's own runners. They are written by hand rather than through `just`, but they enforce the same set of gates, so a green `just gates` locally is the fastest way to a green pipeline. | Workflow | Trigger | What it does | |---|---|---| | `test.yml` | push or pull request to `development` | format check, vet, modernisation, build, the test suite with the 80 percent coverage floor, then the toml-test compliance suite | | `race.yml` | `workflow_dispatch`, by hand | the suite under the race detector; the same race gate `just gates` runs locally | | `release.yml` | a `v*` tag | tag validation, then format, vet, modernisation, build and the test suite with the coverage floor, then the Gitea release from the CHANGELOG section. No race detector: race never runs on a push path, and the local `just gates` raced the tree before the tag was cut | ## Releases Releases are cut by merging `development` into `main` and tagging `vX.Y.Z`. The tag drives the release workflow: it validates the tag, runs the static gates and the test suite with the coverage floor, extracts the matching `## [X.Y.Z]` section from `CHANGELOG.md`, and publishes the release with that section as its body. A library ships no binaries, so the release carries the notes and nothing else.