2026-08-19 14:31:00 +02:00
# interpres.
#
2026-09-22 21:45:25 +02:00
# Everything below the variable block is the standard recipe set, identical in
# every repository; project values live in the variable block only.
2026-08-19 14:31:00 +02:00
binary := "interpres-decode"
package := "./cmd/interpres-decode"
# What the test and bench recipes sweep. Scope this to the logic packages when a thin
# cmd/ drags the coverage floor down, for example "./internal/... ./pkg/...". Never name
# a directory the project does not have: a pattern that matches nothing is a setup
# failure, not an empty run.
packages := "./..."
bindir := env_var_or_default( "BINDIR" , env_var( "HOME" ) / ".local" / "bin" )
default :
@just --list
# Compile. Zero errors, zero warnings.
build :
CGO_ENABLED = 0 go build -ldflags "-s -w" -o bin/{{ binary}} {{ package}}
# The test gate: the suite, no cache, the coverage floor.
test :
#!/usr/bin/env perl
system( q{ go} , q{ test} , q{ -count= 1} , q{ -timeout} , q{ 30m} ,
q{ -coverprofile} , q{ coverage.out} , qw({{ packages}})) == 0
or die qq{ the test suite failed\n } ;
open( my $c , q{ -| } , q{ go} , q{ tool} , q{ cover} , q{ -func= coverage.out}) or die qq{ cover: $! } ;
my $total ;
while ( my $l = <$c >) { $total = $1 if $l = ~ m{ ^total:\s +\S +\s +([ 0-9.] +) %} }
close( $c ) ;
die qq{ no total line in coverage.out\n } unless defined $total ;
printf qq{ Total coverage: %s%%\n } , $total ;
2026-09-22 21:15:07 +02:00
exit( $total < 80 ? 1 : 0) ;
2026-08-19 14:31:00 +02:00
# The same suite under the race detector. The expensive one.
race :
go test -race -count= 1 -timeout 30m {{ packages}}
# Fast scoped run for iterating. This is the one that runs after every edit.
unit pkgs=packages run=".*" :
go test {{ pkgs}} -run '{{run}}'
# Time-boxed fuzz of one target in one package. The package is required; never a gate.
fuzz target pkg fuzztime="60s" :
go test -run '^$' -fuzz '{{target}}' -fuzztime={{ fuzztime}} {{ pkg}}
# Benchmarks. On an idle machine only.
bench pkgs=packages :
go test -run '^$' -bench= . -benchmem -count= 5 {{ pkgs}}
# Format in place.
fmt :
gofmt -w .
# Zero diff. Prints nothing when everything is formatted.
fmt-check :
#!/usr/bin/env perl
open( my $g , q{ -| } , q{ gofmt} , q{ -l} , q{ .}) or die qq{ gofmt: $! } ;
my @bad = <$g >;
close( $g ) ;
print @bad;
exit( @bad ? 1 : 0) ;
# Both static gates: go vet and go fix -diff.
vet :
go vet ./...
go fix -diff ./...
# The definition of done, in one command. Once per task, never per edit.
gates : build fmt -check vet test race
# Build artefacts only, not the installed binary.
clean :
rm -rf bin/ coverage.out
# Build, then copy the binary into bindir.
install : build
install -d "{{bindir}}"
install -m 755 bin/{{ binary}} "{{bindir}}/{{binary}}"
# Remove the installed binary.
uninstall :
rm -f "{{bindir}}/{{binary}}"
# Run the program. The flag is there because `go run` does not stamp the build otherwise.
run :
go run -buildvcs= true {{ package}}
# Run with watch or hot reload, where the project has one.
dev :
go run -buildvcs= true {{ package}}
2026-09-19 11:38:19 +02:00
# Runs the official toml-test compliance suite in both directions, decoder and encoder, against the built adapter; toml-test must be on PATH (go install github.com/toml-lang/toml-test/v2/cmd/toml-test@v2.2.0); not standard because no canonical recipe covers a domain compliance suite.
2026-08-19 14:31:00 +02:00
toml-test : build
2026-09-22 21:15:07 +02:00
toml-test test -decoder= bin/interpres-decode -encoder= 'bin/interpres-decode --encode' -toml= 1.1
2026-08-19 14:31:00 +02:00
# Coverage report as an HTML map from the gate's profile; not standard because the gate needs only the numeric floor, and a browser artefact is exploration, not a gate.
coverage-html : test
go tool cover -html= coverage.out -o coverage.html
2026-09-22 21:28:30 +02:00
# Cross-compile smoke: the library and the command build for the foreign architectures and the browser and edge runtimes; not a gate, it is a hand-run convenience and runs std-lib only.
2026-09-22 01:03:27 +02:00
cross :
GOARCH = arm64 go build ./...
GOARCH = loong64 go build ./...
GOARCH = riscv64 go build ./...
2026-09-22 01:26:48 +02:00
GOOS = js GOARCH = wasm go build ./...
GOOS = wasip1 GOARCH = wasm go build ./...
2026-09-22 01:03:27 +02:00
GOARCH = arm64 CGO_ENABLED = 0 go build -o /dev/null {{ package}}
GOARCH = loong64 CGO_ENABLED = 0 go build -o /dev/null {{ package}}
GOARCH = riscv64 CGO_ENABLED = 0 go build -o /dev/null {{ package}}
2026-08-19 14:31:00 +02:00
# Runs the example program under examples/basic; not standard because `run` runs the adapter, and an example is documentation, not the product.
example :
go run ./examples/basic
2026-09-22 01:26:48 +02:00
2026-09-22 21:45:25 +02:00
# The release pre-flight, in one command: the branch, a clean tree, a sync with origin, the gates, and a CHANGELOG section ready to release. Not a gate, it is the checklist before a release may even be discussed.
2026-09-22 01:26:48 +02:00
release-check version :
#!/usr/bin/env perl
2026-09-22 21:48:00 +02:00
# The version arrives through the recipe interpolation: just does not hand
# positional arguments to a shebang script's @ARGV.
2026-09-22 21:49:05 +02:00
my $version = "{{version}}" ;
2026-09-22 01:26:48 +02:00
$version = ~ m{ \A v?\d +\.\d +\.\d +\z } or die qq{ usage: just release-check X.Y.Z\n } ;
my $branch = qx{ git rev-parse --abbrev-ref HEAD} ;
chomp $branch ;
$branch eq q{ development} or die qq{ release-check: on '$branch' , cut releases from development\n } ;
my $dirty = qx{ git status --porcelain} ;
$dirty eq q{} or die qq{ release-check: the working tree is dirty\n } ;
system( qw{ git fetch origin}) == 0 or die qq{ release-check: git fetch failed\n } ;
my $local = qx{ git rev-parse development} ;
my $remote = qx{ git rev-parse origin/development} ;
$local eq $remote or die qq{ release-check: development is out of sync with origin\n } ;
my $changelog = do { open( my $fh , q{ <} , q{ CHANGELOG.md}) or die qq{ release-check: cannot read CHANGELOG.md: $! \n } ; local $/; <$fh > } ;
$changelog = ~ m{ ## \[development\]\n\n### \w+} or die qq{release-check: the [development] section of CHANGELOG.md is missing or empty\n};
print qq{ branch, tree, sync and changelog verified; running the gates\n } ;
system( qw{ just gates}) == 0 or die qq{ release-check: the gates failed\n } ;
print qq{ release-check: ready to release $version \n } ;
2026-09-22 01:31:37 +02:00
print qq{ after tagging, verify the /v2 module resolves through the proxy:\n } ;
print qq{ cd \$ ( mktemp -d) && go mod init t && GOPRIVATE = GOPROXY = https://proxy.golang.org go get sourcedock.dev/petrbalvin/interpres/v2\@ $version \n } ;
2026-09-22 01:26:48 +02:00
# Compares the toml-test counts the documentation names with the live suite run; not standard, it exists because a corpus change used to be corrected by hand.
docs-drift :
perl scripts/docs-drift.pl