Files
interpres/docs/DEVELOPMENT.md
T
petrbalvin 18f1cd51e9
Test / test (push) Successful in 1m42s
build: upgrade the compliance suite to toml-test v2.2.0
Assisted-by: GLM 5.3 Flash
2026-09-17 21:30:41 +02:00

109 lines
4.2 KiB
Markdown

# 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`.
## 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 | the same gates plus the race detector, then the Gitea release from the CHANGELOG section |
## 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 full gate set
including the race detector, 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.