From 60442ce103c70110b8509eef24f5d13e872b0802 Mon Sep 17 00:00:00 2001 From: sneak Date: Mon, 10 Aug 2026 13:46:25 +0000 Subject: [PATCH 1/2] build: add a make build target, drop README's raw go build (closes #19) The executable builds to build/rogue. All generated artifacts go under build/, which .gitignore covers as a whole; a target writing outside it can commit its output. build is in neither check nor test: check stays fmt-check lint test and still writes nothing into the working tree. README's "Building and running" block and the run examples use ./build/rogue, and no raw go invocation is left in the file. Verified: make build writes build/rogue and git status stays clean; GOFLAGS=-count=1 make check green in 34s with the lint layer executing (21.9s, "0 issues.", not CACHED) and the suite running for real (cmd/rogue 1.027s, game 3.450s), git status clean afterwards. --- .dockerignore | 4 ++++ .gitignore | 1 + Makefile | 22 +++++++++++++++++----- README.md | 18 +++++++++--------- TODO.md | 10 ++++++++++ 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/.dockerignore b/.dockerignore index 4f59329..52f67c3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,3 +2,7 @@ # excluding a self-contained Go source here drops it from the lint silently. # Never exclude Go sources, go.mod/go.sum or .golangci.yml. .git + +# Generated artifacts only; `make build` puts a multi-megabyte binary here +# and it would otherwise be shipped into the build context. +/build/ diff --git a/.gitignore b/.gitignore index 2b846e1..25aaccd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.log *.out *.test +/build/ /rogue diff --git a/Makefile b/Makefile index 3bd0b22..784d9bd 100644 --- a/Makefile +++ b/Makefile @@ -6,15 +6,27 @@ # around the Go toolchain and prettier so `make fmt` / `make check` behave # the same as in sneak's other repos. -GO_PKGS := ./... -MD_FILES := $(shell git ls-files '*.md') -PRETTIER := prettier --tab-width 4 --prose-wrap always +GO_PKGS := ./... +MD_FILES := $(shell git ls-files '*.md') +PRETTIER := prettier --tab-width 4 --prose-wrap always -.PHONY: check fmt fmt-check lint test +# Every generated artifact goes here, and the whole directory is +# git-ignored. Targets that write outside it can commit their output. +BUILD_DIR := build +BIN := $(BUILD_DIR)/rogue -# Format, lint, and test — the full local pre-commit gate. +.PHONY: build check fmt fmt-check lint test + +# Format, lint, and test — the full local pre-commit gate. Keep this list +# to targets that write nothing into the working tree. check: fmt-check lint test +# Build the executable into $(BUILD_DIR). `go build -o` does not create the +# parent directory. +build: + @mkdir -p $(BUILD_DIR) + go build -o $(BIN) ./cmd/rogue + # Format Go and Markdown in place. fmt: gofmt -w . diff --git a/README.md b/README.md index 691dc81..2c22419 100644 --- a/README.md +++ b/README.md @@ -21,19 +21,19 @@ original program structure and the design of this port. Requires Go 1.25 or later and a terminal at least 80x24. ```bash -go build ./cmd/rogue -./rogue +make build +./build/rogue ``` ```bash # Restore a saved game -./rogue ~/rogue.save +./build/rogue ~/rogue.save # View high scores -./rogue -s +./build/rogue -s # Test the death screen (demo mode) -./rogue -d +./build/rogue -d ``` ## In-game commands @@ -57,7 +57,7 @@ Press `?` in game for the full list. export ROGUEOPTS="name=YourName,terse,jump,fruit=mango" # Wizard (debug) mode, with a reproducible dungeon -ROGUE_WIZARD=1 SEED=12345 ./rogue +ROGUE_WIZARD=1 SEED=12345 ./build/rogue ``` The scoreboard is kept in `~/.rogue.scores`. Save files are Go gob snapshots @@ -80,9 +80,9 @@ For development, the `Makefile` wraps the toolchain: `make fmt` (gofmt + prettier), `make lint` (`script/lint`, which runs golangci-lint inside the pinned container built from `Dockerfile.lint` — it is never installed on the host, so docker is required), `make test` (the suite, under the race detector -with coverage and a timeout), and `make check` (all three). Use the targets -rather than invoking `go test` directly — they carry the flags the project -relies on. +with coverage and a timeout), `make check` (all three), and `make build` (the +executable, into the git-ignored `build/`). Use the targets rather than the +toolchain directly — they carry the flags the project relies on. ## License diff --git a/TODO.md b/TODO.md index 7c2e24c..d67db14 100644 --- a/TODO.md +++ b/TODO.md @@ -35,6 +35,16 @@ is finished. # Completed Steps +- 2026-08-10 `make build` added (https://git.eeqj.de/sneak/rgoue/issues/19). The + executable is built to `build/rogue`; `README.md` no longer contains a raw + `go` invocation anywhere. `build` is in neither `check` nor `test` — + `make check` stays `fmt-check lint test` and still writes nothing into the + working tree. + + Generated artifacts now all live under `build/`, which `.gitignore` covers + as a whole. Anything written outside it is committable, so a target that + puts its output elsewhere reintroduces the stray-artifact problem. + - 2026-08-10 Linting moved into a container (https://git.eeqj.de/sneak/rgoue/issues/41). `golangci-lint` is no longer invoked on the host anywhere in the repo: `Dockerfile.lint` pins -- 2.49.1 From e3ab4aba8bebca0503315ccbce4f69a7e2dae08b Mon Sep 17 00:00:00 2001 From: sneak Date: Mon, 10 Aug 2026 13:48:52 +0000 Subject: [PATCH 2/2] build: add a make cover target for per-function coverage (closes #17) make cover writes build/coverage.out and prints the per-function report; make cover-html renders the same profile to build/coverage.html. The per-package percentage make test prints cannot say which function is untested. Both write files, so neither is in check, and neither may be added to it: check must not modify the working tree. Their output lands under the already-ignored build/. Verified: make cover printed per-function lines and a 62.6% total, make cover-html wrote build/coverage.html, and git status stayed clean. GOFLAGS=-count=1 make check green in 24s with the lint layer executing (12.0s, "0 issues.", not CACHED) and the suite running for real (cmd/rogue 1.037s, game 3.410s); check is still fmt-check lint test and git status is clean afterwards. --- Makefile | 17 ++++++++++++++++- README.md | 6 ++++-- TODO.md | 10 ++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 784d9bd..fbdcc93 100644 --- a/Makefile +++ b/Makefile @@ -14,8 +14,10 @@ PRETTIER := prettier --tab-width 4 --prose-wrap always # git-ignored. Targets that write outside it can commit their output. BUILD_DIR := build BIN := $(BUILD_DIR)/rogue +COVERPROF := $(BUILD_DIR)/coverage.out +COVERHTML := $(BUILD_DIR)/coverage.html -.PHONY: build check fmt fmt-check lint test +.PHONY: build check cover cover-html fmt fmt-check lint test # Format, lint, and test — the full local pre-commit gate. Keep this list # to targets that write nothing into the working tree. @@ -27,6 +29,19 @@ build: @mkdir -p $(BUILD_DIR) go build -o $(BIN) ./cmd/rogue +# Per-function coverage, for finding which functions are untested. The +# percentage `make test` prints is a per-package total and cannot answer +# that. Writes files, so it stays out of `check`. +cover: + @mkdir -p $(BUILD_DIR) + go test -timeout 30s -coverprofile=$(COVERPROF) $(GO_PKGS) + go tool cover -func=$(COVERPROF) + +# Render the same profile as annotated source. +cover-html: cover + go tool cover -html=$(COVERPROF) -o $(COVERHTML) + @echo "wrote $(COVERHTML)" + # Format Go and Markdown in place. fmt: gofmt -w . diff --git a/README.md b/README.md index 2c22419..b7b5ece 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,10 @@ For development, the `Makefile` wraps the toolchain: `make fmt` (gofmt + prettier), `make lint` (`script/lint`, which runs golangci-lint inside the pinned container built from `Dockerfile.lint` — it is never installed on the host, so docker is required), `make test` (the suite, under the race detector -with coverage and a timeout), `make check` (all three), and `make build` (the -executable, into the git-ignored `build/`). Use the targets rather than the +with coverage and a timeout), `make check` (all three), `make build` (the +executable), and `make cover` / `make cover-html` (per-function coverage, and +the same profile as annotated source at `build/coverage.html`). Everything they +generate lands in the git-ignored `build/`. Use the targets rather than the toolchain directly — they carry the flags the project relies on. ## License diff --git a/TODO.md b/TODO.md index d67db14..7d2bc01 100644 --- a/TODO.md +++ b/TODO.md @@ -35,6 +35,16 @@ is finished. # Completed Steps +- 2026-08-10 `make cover` added (https://git.eeqj.de/sneak/rgoue/issues/17). + `make cover` writes `build/coverage.out` and prints the per-function report; + `make cover-html` renders the same profile to `build/coverage.html`. The + per-package percentage `make test` prints cannot say _which_ function is + untested, which is how the coverage gaps closed so far had to be found — by + grepping test files for identifiers. + + Neither target is in `check`, and neither may be added to it: both write + files, and `make check` must not modify the working tree. + - 2026-08-10 `make build` added (https://git.eeqj.de/sneak/rgoue/issues/19). The executable is built to `build/rogue`; `README.md` no longer contains a raw `go` invocation anywhere. `build` is in neither `check` nor `test` — -- 2.49.1