Files

103 lines
3.7 KiB
Makefile
Raw Permalink Normal View History

# nfs.
#
# The recipes follow the project standard set: everything below the variable
# block is identical in every repository.
binary := "nfsd"
package := "./cmd/nfsd"
client := "./cmd/nfs"
# What the test and bench recipes sweep. Scoped to the logic packages: the
# thin cmd/nfsd and cmd/nfs count as zero coverage and would drag the floor
# below 80 percent on their own. The protocol logic lives under internal/.
packages := "./internal/..."
# The memory fence for the test recipes: a cgroup ceiling with swap off, so a
# runaway run dies as a failed run and never eats the machine. 4G is the
# default; raise it only with a reason recorded here.
memlimit := "4G"
bindir := env_var_or_default("BINDIR", env_var("HOME") / ".local" / "bin")
default:
@just --list
# Compile both binaries. Zero errors, zero warnings; -trimpath and -buildvcs make the binaries place-independent and version-stamped.
build:
CGO_ENABLED=0 go build -trimpath -buildvcs=true -ldflags "-s -w" -o bin/nfsd {{package}}
CGO_ENABLED=0 go build -trimpath -buildvcs=true -ldflags "-s -w" -o bin/nfs {{client}}
# The test gate: the suite, no cache, the coverage floor, under the memory fence.
test:
#!/usr/bin/env perl
my @fence = (q{systemd-run}, q{--user}, q{--scope},
q{-p}, q{MemoryMax={{memlimit}}}, q{-p}, q{MemorySwapMax=0});
system(@fence, q{go}, q{test}, q{-count=1}, q{-timeout}, q{10m},
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;
exit($total < 80 ? 1 : 0);
# The same suite under the race detector. The expensive one, still fenced.
race:
systemd-run --user --scope -p MemoryMax={{memlimit}} -p MemorySwapMax=0 go test -race -count=1 -timeout 10m {{packages}}
# Fast scoped run for iterating. This is the one that runs after every edit.
unit pkgs=packages run=".*":
systemd-run --user --scope -p MemoryMax={{memlimit}} -p MemorySwapMax=0 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":
systemd-run --user --scope -p MemoryMax={{memlimit}} -p MemorySwapMax=0 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/nfsd "{{bindir}}/nfsd"
install -m 755 bin/nfs "{{bindir}}/nfs"
# Remove the installed binary.
uninstall:
rm -f "{{bindir}}/nfsd" "{{bindir}}/nfs"
# 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}}