Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
248 lines (222 loc) · 10.3 KB
/
Copy pathMakefile
File metadata and controls
248 lines (222 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
BINARY := ploy
BUILD_DIR := dist
COVERAGE_FILE := $(BUILD_DIR)/coverage.out
HTML_COVERAGE_FILE := $(BUILD_DIR)/coverage.html
REQUIRED_GO_TOOLCHAIN := go1.26.9
VERSION_FILE := VERSION
VERSION ?= $(shell tr -d '[:space:]' < $(VERSION_FILE) 2>/dev/null || echo "")
PLOY_SIGN_BINARIES ?= 0
PLOY_BUILD_PLATFORMS ?= linux/amd64
ROADMAP_VERIFY_PHASES ?=
# Version stamping
GIT_COMMIT := $(shell git rev-parse --short=12 HEAD 2>/dev/null || echo unknown)
BUILD_DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
LDV := github.com/iw2rmb/ploy/internal/version
LDFLAGS := -X $(LDV).Version=$(VERSION) -X $(LDV).Commit=$(GIT_COMMIT) -X $(LDV).BuiltAt=$(BUILD_DATE)
.PHONY: verify-version
verify-version:
@if [ -z "$(VERSION)" ]; then \
echo "error: VERSION is empty; set VERSION env var or populate $(VERSION_FILE)"; \
exit 1; \
fi
@if ! echo "$(VERSION)" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z][0-9A-Za-z.-]*)?$$'; then \
echo "error: VERSION='$(VERSION)' is not semver (expected vX.Y.Z or vX.Y.Z-prerelease)"; \
exit 1; \
fi
.PHONY: verify-go-toolchain
verify-go-toolchain: ## Fail fast when local Go toolchain is not pinned version
@toolchain="$$(go env GOVERSION 2>/dev/null || true)"; \
if [ -z "$$toolchain" ]; then \
echo "error: unable to detect Go toolchain (go env GOVERSION failed)"; \
exit 1; \
fi; \
if [ "$$toolchain" != "$(REQUIRED_GO_TOOLCHAIN)" ]; then \
echo "error: Go toolchain $$toolchain detected; require $(REQUIRED_GO_TOOLCHAIN)"; \
echo "hint: run 'GOTOOLCHAIN=$(REQUIRED_GO_TOOLCHAIN) make <target>'"; \
exit 1; \
fi
.PHONY: build
build: verify-go-toolchain verify-version ## Build the CLI/server/node binaries
@mkdir -p $(BUILD_DIR)
GOFLAGS= go build -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY) ./cmd/ploy
@if [ -d ./cmd/ployd ]; then \
go build -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/ployd ./cmd/ployd; \
first_arch=""; \
for platform in $$(printf '%s' "$(PLOY_BUILD_PLATFORMS)" | tr ',' ' '); do \
goos="$${platform%%/*}"; \
goarch="$${platform##*/}"; \
if [ "$$goos" != "linux" ]; then \
echo "error: unsupported GOOS '$$goos' in PLOY_BUILD_PLATFORMS='$(PLOY_BUILD_PLATFORMS)'; only linux is supported"; \
exit 1; \
fi; \
case "$$goarch" in \
amd64|arm64|arm) ;; \
*) echo "error: unsupported GOARCH '$$goarch' in PLOY_BUILD_PLATFORMS='$(PLOY_BUILD_PLATFORMS)'"; exit 1 ;; \
esac; \
if [ -z "$$first_arch" ]; then first_arch="$$goarch"; fi; \
CGO_ENABLED=0 GOOS="$$goos" GOARCH="$$goarch" go build -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/ployd-linux-$$goarch ./cmd/ployd; \
done; \
if [ -n "$$first_arch" ] && [ -f "$(BUILD_DIR)/ployd-linux-$$first_arch" ]; then \
cp "$(BUILD_DIR)/ployd-linux-$$first_arch" "$(BUILD_DIR)/ployd-linux"; \
fi; \
fi
@if [ -d ./cmd/ployd-node ]; then \
go build -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/ployd-node ./cmd/ployd-node; \
first_arch=""; \
for platform in $$(printf '%s' "$(PLOY_BUILD_PLATFORMS)" | tr ',' ' '); do \
goos="$${platform%%/*}"; \
goarch="$${platform##*/}"; \
if [ "$$goos" != "linux" ]; then \
echo "error: unsupported GOOS '$$goos' in PLOY_BUILD_PLATFORMS='$(PLOY_BUILD_PLATFORMS)'; only linux is supported"; \
exit 1; \
fi; \
case "$$goarch" in \
amd64|arm64|arm) ;; \
*) echo "error: unsupported GOARCH '$$goarch' in PLOY_BUILD_PLATFORMS='$(PLOY_BUILD_PLATFORMS)'"; exit 1 ;; \
esac; \
if [ -z "$$first_arch" ]; then first_arch="$$goarch"; fi; \
CGO_ENABLED=0 GOOS="$$goos" GOARCH="$$goarch" go build -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/ployd-node-linux-$$goarch ./cmd/ployd-node; \
done; \
if [ -n "$$first_arch" ] && [ -f "$(BUILD_DIR)/ployd-node-linux-$$first_arch" ]; then \
cp "$(BUILD_DIR)/ployd-node-linux-$$first_arch" "$(BUILD_DIR)/ployd-node-linux"; \
fi; \
fi
@case "$(PLOY_SIGN_BINARIES)" in \
1|true|TRUE|yes|YES|on|ON) $(MAKE) sign-binaries VERSION="$(VERSION)" ;; \
*) ;; \
esac
.PHONY: sign-binaries
sign-binaries: verify-version ## Sign dist binaries with cosign (keyless or key-based)
@if ! command -v cosign >/dev/null 2>&1; then \
echo "error: cosign not found; install cosign or set PLOY_SIGN_BINARIES=0"; \
exit 1; \
fi
@mkdir -p $(BUILD_DIR)/signatures
@for bin in "$(BUILD_DIR)/ploy" "$(BUILD_DIR)/ployd" "$(BUILD_DIR)/ployd-linux" "$(BUILD_DIR)/ployd-node" "$(BUILD_DIR)/ployd-node-linux" $(BUILD_DIR)/ployd-linux-* $(BUILD_DIR)/ployd-node-linux-*; do \
if [ ! -f "$$bin" ]; then \
continue; \
fi; \
base="$$(basename "$$bin")"; \
prefix="$(BUILD_DIR)/signatures/$${base}-$(VERSION)"; \
if command -v sha256sum >/dev/null 2>&1; then \
sha256sum "$$bin" > "$${prefix}.sha256"; \
else \
shasum -a 256 "$$bin" > "$${prefix}.sha256"; \
fi; \
COSIGN_YES=true cosign sign-blob --yes \
--output-signature "$${prefix}.sig" \
--output-certificate "$${prefix}.pem" \
"$$bin"; \
done
.PHONY: fmt
fmt: ## Format Go source files
gofmt -w $(shell find . -name '*.go' -not -path './dist/*')
.PHONY: lint-md
lint-md: ## Lint Markdown documentation with markdownlint
npx --yes markdownlint --config .markdownlint.yaml $(shell git ls-files '*.md')
.PHONY: test
test: verify-go-toolchain ## Run unit tests (fast path)
@TMP=$$(mktemp -d 2>/dev/null || mktemp -d -t ploytest); \
PLOY_CONFIG_HOME="$$TMP" go test ./internal/... ./cmd/...; \
rc=$$?; rm -rf "$$TMP"; exit $$rc
.PHONY: test-race
test-race: verify-go-toolchain ## Run all unit tests with race detector
@TMP=$$(mktemp -d 2>/dev/null || mktemp -d -t ploytest); \
PLOY_CONFIG_HOME="$$TMP" go test -race -cover ./...; \
rc=$$?; rm -rf "$$TMP"; exit $$rc
.PHONY: test-coverage
test-coverage: $(COVERAGE_FILE) ## Run unit tests and generate coverage report (statement coverage)
@echo "\n=== Coverage Summary (statement) ==="
@go tool cover -func=$(COVERAGE_FILE) | grep '^total:'
.PHONY: FORCE
FORCE:
$(COVERAGE_FILE): verify-go-toolchain FORCE
@mkdir -p $(BUILD_DIR)
@TMP=$$(mktemp -d 2>/dev/null || mktemp -d -t ploytest); \
PLOY_CONFIG_HOME="$$TMP" go test -coverpkg=./... -coverprofile=$(COVERAGE_FILE) -covermode=atomic ./internal/... ./cmd/...; \
rc=$$?; rm -rf "$$TMP"; exit $$rc
.PHONY: coverage
coverage: test-coverage ## Alias for test-coverage
.PHONY: coverage-html
coverage-html: $(COVERAGE_FILE) ## Generate HTML coverage report (statement coverage)
@mkdir -p $(BUILD_DIR)
@go tool cover -html=$(COVERAGE_FILE) -o $(HTML_COVERAGE_FILE)
@echo "Wrote $(HTML_COVERAGE_FILE)"
.PHONY: coverage-open
coverage-open: coverage-html ## Open HTML coverage report (macOS)
@open $(HTML_COVERAGE_FILE)
.PHONY: coverage-all
coverage-all: verify-go-toolchain ## Generate coverage for all packages (may include integration tests)
@mkdir -p $(BUILD_DIR)
@TMP=$$(mktemp -d 2>/dev/null || mktemp -d -t ploytest); \
PLOY_CONFIG_HOME="$$TMP" go test -coverpkg=./... -coverprofile=$(COVERAGE_FILE) -covermode=atomic ./...; \
rc=$$?; rm -rf "$$TMP"; exit $$rc
.PHONY: vet
vet: verify-go-toolchain ## Run go vet
go vet ./...
.PHONY: lint
lint: ## Run golangci-lint
@if command -v golangci-lint >/dev/null 2>&1; then \
golangci-lint run ./...; \
else \
echo "golangci-lint not installed. Install from https://golangci-lint.run/usage/install/"; \
exit 1; \
fi
.PHONY: staticcheck
staticcheck: verify-go-toolchain ## Run staticcheck
go run honnef.co/go/tools/cmd/staticcheck@v0.6.1 -checks=all,-SA1019,-ST1003,-ST1000,-U1000 ./...
.PHONY: redundancy-check
redundancy-check: ## Check for LOC and duplication regressions in hotspot packages
@bash scripts/redundancy-check.sh
.PHONY: roadmap-verify
roadmap-verify: ## Verify targeted roadmap phases are done and have closed gaps/evidence checks
@if [ -z "$(strip $(ROADMAP_VERIFY_PHASES))" ]; then \
echo "roadmap verification skipped: ROADMAP_VERIFY_PHASES is empty"; \
exit 0; \
else \
tools/roadmap/verify_done.sh $(ROADMAP_VERIFY_PHASES); \
fi
.PHONY: ci-check
ci-check: fmt vet staticcheck test test-coverage redundancy-check ## Run core CI checks locally
@echo "\n=== All CI checks passed ==="
.PHONY: pre-commit-install
pre-commit-install: ## Install pre-commit hooks
@if command -v pre-commit >/dev/null 2>&1; then \
pre-commit install; \
echo "Pre-commit hooks installed successfully"; \
else \
echo "pre-commit not installed. Install from https://pre-commit.com/"; \
exit 1; \
fi
.PHONY: experiment-role-sep
experiment-role-sep: verify-go-toolchain ## Run role-separated TDD experiment (stub fails, impl passes)
@echo "[Phase A] Expect failing HT under stub build" && \
go test -tags "experiment experiment_stub" ./tests/guards ./tests/experiments/role_sep -run '^TestHT_' || true ; \
echo "[Phase B] Expect passing HT under impl build" && \
go test -tags "experiment experiment_impl" ./tests/guards ./tests/experiments/role_sep -run '^TestHT_' -cover
.PHONY: clean
clean: ## Remove build artifacts
rm -rf $(BUILD_DIR)
.PHONY: help
help: ## Show available targets
@echo "Targets:"
@echo " make build # Build the CLI and server binaries"
@echo " make sign-binaries # Sign dist binaries with cosign"
@echo " make verify-version # Enforce semver VERSION (vX.Y.Z)"
@echo " make verify-go-toolchain # Enforce pinned local Go toolchain ($(REQUIRED_GO_TOOLCHAIN))"
@echo " make fmt # Run gofmt over Go source"
@echo " make test # Run unit tests"
@echo " make test-race # Run tests with race detector"
@echo " make test-coverage # Run unit tests and generate coverage report (statement coverage)"
@echo " make coverage # Alias for test-coverage"
@echo " make coverage-html # Generate HTML coverage report"
@echo " make coverage-open # Open HTML coverage report (macOS)"
@echo " make coverage-all # Generate coverage for all packages (may include integration tests)"
@echo " make vet # Run go vet"
@echo " make lint # Run golangci-lint"
@echo " make staticcheck # Run staticcheck"
@echo " make redundancy-check # Check LOC and duplication guardrails in hotspot packages"
@echo " make roadmap-verify # Verify done roadmap phases have closed gaps and completed evidence checks"
@echo " make ci-check # Run core CI checks locally"
@echo " make pre-commit-install # Install pre-commit hooks"
@echo " make clean # Remove build artifacts"