Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
252 lines (215 loc) · 8.62 KB
/
Copy pathMakefile
File metadata and controls
252 lines (215 loc) · 8.62 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
249
250
251
252
# Slopscale Makefile
# Modern Makefile following best practices
# Version calculation
VERSION ?= $(shell git describe --always --tags --dirty)
# Build configuration
GOOS ?= $(shell uname | tr '[:upper:]' '[:lower:]')
# SQLite is mattn/go-sqlite3, compiled from C by cgo with the flags in
# sqlite.cflags (hardening and performance defines). Every go invocation
# below inherits them; a build without them logs a warning at startup.
export CGO_ENABLED := 1
export CGO_CFLAGS := $(shell grep -v '^\#' sqlite.cflags | tr '\n' ' ')
ifeq ($(filter $(GOOS), openbsd netbsd solaris plan9), )
PIE_FLAGS = -buildmode=pie
endif
# Tool availability check with nix warning
define check_tool
@command -v $(1) >/dev/null 2>&1 || { \
echo "Warning: $(1) not found. Run 'nix develop' to ensure all dependencies are available."; \
exit 1; \
}
endef
# Source file collections using shell find for better performance
GO_SOURCES := $(shell find . -name '*.go' -not -path './gen/*' -not -path './vendor/*')
MARKUP_SOURCES := $(shell find . \( -name '*.md' -o -name '*.yaml' -o -name '*.yml' -o -name '*.ts' -o -name '*.js' -o -name '*.html' -o -name '*.css' -o -name '*.scss' -o -name '*.sass' \) -not -path './gen/*' -not -path './vendor/*' -not -path './node_modules/*' -not -path './web/*' -not -path './docs/*' -not -path './.claude/*')
# oxfmt is pinned in web/bun.lock and formats the repo's markup and config
# files as well as the console (see .oxfmtrc.json for the root scope).
OXFMT := web/node_modules/.bin/oxfmt
WEB_SOURCES := $(shell find web -type f -not -path 'web/node_modules/*' -not -path 'web/codegen/node_modules/*' -not -path 'web/dist/*' -not -path 'web/public/tsconnect/*')
# Default target
.PHONY: all
all: lint test build
# Dependency checking
.PHONY: check-deps
check-deps:
$(call check_tool,go)
$(call check_tool,golangci-lint)
.PHONY: check-web-deps
check-web-deps:
$(call check_tool,bun)
# Build targets
.PHONY: build
build: check-deps $(GO_SOURCES) go.mod go.sum
@echo "Building slopscale..."
go build $(PIE_FLAGS) -trimpath -ldflags "-s -w -X main.version=$(VERSION)" -o slopscale ./cmd/slopscale
# Admin console. The React app in web/ is built by bun and embedded into
# the binary by web/embed.go, so `make web` must run before `make build`
# for the console to ship; without it the server serves a placeholder at
# /admin/. Runtime dependencies are pinned by web/bun.lock.
.PHONY: web-deps
web-deps: check-web-deps web/package.json web/bun.lock
@echo "Installing console dependencies..."
cd web && bun install --frozen-lockfile
# The console's SSH terminal runs Tailscale's in-browser client, compiled
# from tailscale.com/cmd/tsconnect/wasm by cmd/tsconnect-build into
# web/public/tsconnect (gitignored): the raw wasm for the Vite dev
# server, the gzipped one for the embedded server, wasm_exec.js and a
# manifest. Only the gzipped file ships in the binary, so make web
# removes the raw one from dist; web/embed.go serves .wasm from .wasm.gz.
.PHONY: wasm
wasm: check-deps
@echo "Building the in-browser Tailscale client..."
go run ./cmd/tsconnect-build
.PHONY: web
web: web-deps wasm $(WEB_SOURCES)
@echo "Building admin console..."
cd web && bun run build
rm -f web/dist/tsconnect/*.wasm
# Regenerate the console's API types from the served OpenAPI document. The
# spec is committed under gen/openapi so the TypeScript output is
# reproducible without a Go toolchain.
.PHONY: web-generate
web-generate: web-deps
@echo "Generating console API types..."
go run ./cmd/gen-openapi -out gen/openapi/v1.yaml
cd web && bun run generate && bun run fmt
.PHONY: lint-web
lint-web: web-deps
@echo "Checking admin console..."
cd web && bun run typecheck && bun run lint && bun run fmt:check
.PHONY: fmt-web
fmt-web: web-deps
@echo "Formatting admin console..."
cd web && bun run fmt && bun run lint:fix
.PHONY: test-web
test-web: web-deps
@echo "Running console tests..."
cd web && bun run test
.PHONY: docs-deps
docs-deps:
cd docs && bun install --frozen-lockfile --silent
.PHONY: docs
docs: docs-deps
@echo "Building documentation..."
cd docs && bun run build && bun run validate && bun run audit
.PHONY: docs-dev
docs-dev: docs-deps
cd docs && bun run dev
# End-to-end: builds the console, starts a real server through cmd/dev
# with its mock identity provider, and signs in through a browser.
.PHONY: test-e2e
test-e2e: web-deps
@echo "Running console end-to-end tests..."
cd web && bun run e2e
# Test targets
.PHONY: test
test: check-deps $(GO_SOURCES) go.mod go.sum
@echo "Running Go tests..."
go test -race -short -timeout 30m ./...
# Formatting targets
.PHONY: fmt
fmt: fmt-go fmt-markup fmt-web
.PHONY: fmt-go
fmt-go: check-deps $(GO_SOURCES)
@echo "Formatting Go code..."
go fix ./...
golangci-lint fmt
golangci-lint run --fix
.PHONY: fmt-markup
fmt-markup: web-deps $(MARKUP_SOURCES)
@echo "Formatting markup and config files..."
$(OXFMT) --config .oxfmtrc.json .
# Linting targets. `lint` is the full gate: every golangci-lint linter and
# formatter (see .golangci.yaml), go vet, a tidy/verified module graph, and a
# vulnerability scan of the dependency tree.
.PHONY: lint
lint: lint-go lint-mod lint-vuln lint-web lint-markup
.PHONY: lint-markup
lint-markup: web-deps $(MARKUP_SOURCES)
@echo "Checking markup and config formatting..."
$(OXFMT) --config .oxfmtrc.json --check .
.PHONY: lint-go
lint-go: check-deps $(GO_SOURCES) go.mod go.sum
@echo "Linting Go code..."
golangci-lint run --timeout 10m
go vet -tags integration ./...
.PHONY: lint-mod
lint-mod: go.mod go.sum
@echo "Checking module graph..."
go mod tidy -diff
go mod verify
.PHONY: lint-vuln
lint-vuln: go.mod go.sum
@echo "Scanning dependencies for known vulnerabilities..."
go tool govulncheck ./...
# Code generation
.PHONY: generate
generate: check-deps
@echo "Generating code..."
go generate ./...
$(MAKE) client
$(MAKE) web-generate
# Emit the OpenAPI spec on demand. The server serves it live at /openapi.yaml;
# this is for external consumers or inspection and is not committed.
.PHONY: openapi
openapi:
@echo "Emitting OpenAPI spec from code..."
go run ./cmd/gen-openapi
# Generate the strongly-typed Go HTTP clients (v1 and v2) from the served
# OpenAPI 3.1 documents using oapi-codegen. Pinned so the committed clients
# are reproducible.
.PHONY: client
client:
@echo "Generating API clients..."
@tmp=$$(mktemp -t slopscale-openapi-3.1.XXXXXX.yaml); \
go run ./cmd/gen-openapi -out "$$tmp" && \
go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.8.0 \
-generate types,client -package clientv1 -o gen/client/v1/client.gen.go "$$tmp" && \
go run ./cmd/gen-openapi -api v2 -out "$$tmp" && \
go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.8.0 \
-generate types,client -package clientv2 -o gen/client/v2/client.gen.go "$$tmp"; \
status=$$?; rm -f "$$tmp"; exit $$status
# Clean targets
.PHONY: clean
clean:
rm -rf slopscale gen/client web/dist/assets web/dist/index.html
# Development workflow
.PHONY: dev
dev: fmt lint test build
# Start a local slopscale dev server (use mts to add nodes)
.PHONY: dev-server
dev-server:
go run ./cmd/dev
# Help target
.PHONY: help
help:
@echo "Slopscale Development Makefile"
@echo ""
@echo "Main targets:"
@echo " all - Run lint, test, and build (default)"
@echo " build - Build slopscale binary"
@echo " test - Run Go tests"
@echo " fmt - Format all code (Go, docs, markup)"
@echo " lint - Lint all code (golangci-lint, vet, mod tidy, govulncheck)"
@echo " generate - Generate code (go generate + client + web-generate)"
@echo " dev - Full development workflow (fmt + lint + test + build)"
@echo " clean - Clean build artifacts"
@echo ""
@echo "Specific targets:"
@echo " fmt-go - Format Go code only"
@echo " fmt-markup - Format markup and config files only (oxfmt)"
@echo " lint-go - Lint Go code only"
@echo " web - Build the admin console into web/dist (embedded by build)"
@echo " wasm - Build the in-browser Tailscale client for the console's SSH terminal"
@echo " web-generate - Regenerate the console's API types from the OpenAPI spec"
@echo " lint-web - Typecheck, lint and format-check the admin console"
@echo " docs - Build the documentation site and validate its links"
@echo " docs-dev - Serve the documentation with hot reload"
@echo " test-web - Run the admin console's browser tests"
@echo " test-e2e - Sign in to a real server through the browser (mock identity provider)"
@echo ""
@echo "Dependencies:"
@echo " check-deps - Verify required tools are available"
@echo ""
@echo "Note: If not running in a nix shell, ensure dependencies are available:"
@echo " nix develop"