-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
464 lines (414 loc) · 17 KB
/
Copy pathMakefile
File metadata and controls
464 lines (414 loc) · 17 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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
.PHONY: help build run clean install reinstall update test test-coverage test-coverage-html test-race test-integration test-bench fmt fmt-check vet lint lint-fix setup demo quality security check-pre-commit pr prepare release
# ============================================================================
# Configuration
# ============================================================================
# Define Go packages to be used in tests
ALL_PKGS := $(shell go list ./cmd/... ./internal/... ./pkg/...)
CORE_PKGS := $(shell go list ./internal/... ./pkg/store/... ./pkg/log/... ./pkg/ui/...)
# pkg/store/local is excluded from race testing: its rotation test performs O(n²) disk
# reads (1000+ iterations × full YAML parse each) which times out under -race overhead.
RACE_PKGS := $(shell go list ./internal/... ./pkg/store \
./pkg/log/... ./pkg/ui/...)
CLI_PKGS := $(shell go list ./pkg/cli/...)
# Build flags
BUILD_FLAGS ?=
# PR Management flags
PR_ENHANCED ?= false
PR_SKIP_CHECKS ?= false
# Release Management flags
RELEASE_JOB ?= check
RELEASE_SNAPSHOT ?= true
RELEASE_CLEAN ?= true
# ============================================================================
# Reusable Functions
# ============================================================================
define log_info
@echo "ℹ️ $(1)"
endef
define log_success
@echo "✅ $(1)"
endef
define log_error
@echo "❌ $(1)"
endef
define log_warning
@echo "⚠️ $(1)"
endef
define log_section
@echo ""
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@echo "$(1)"
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@echo ""
endef
define install_tool
@command -v $(1) >/dev/null 2>&1 || ($(call log_info,Installing $(1)...) && go install $(2)@latest)
endef
define check_tool
@command -v $(1) >/dev/null 2>&1 || ($(call log_warning,$(1) not installed. Install with: $(2)) && exit 1)
endef
define build_binary
@BRANCH=$$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown'); \
VERSION="$(1)"; \
COMMIT=$$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown'); \
BUILD_DATE=$$(date -u '+%Y-%m-%dT%H:%M:%SZ'); \
$(call log_info,Building with version: $$VERSION [$$COMMIT]); \
go build $(BUILD_FLAGS) -ldflags="-X 'github.com/arc-framework/arc-cli/pkg/version.Version=$$VERSION' \
-X 'github.com/arc-framework/arc-cli/pkg/version.Commit=$$COMMIT' \
-X 'github.com/arc-framework/arc-cli/pkg/version.BuildDate=$$BUILD_DATE'" \
-o arc cmd/arc/main.go
$(call log_success,Build complete: ./arc)
@ls -lh arc
endef
# ============================================================================
# Help
# ============================================================================
# Default target
help:
$(call log_section,🚀 A.R.C. CLI - Available Commands)
@echo "📦 Build & Run:"
@echo " make build - Build the arc binary"
@echo " make build-release - Build with version info"
@echo " make run - Run without building"
@echo " make demo - Build and run"
@echo " make install - Build and install to /usr/local/bin"
@echo " make reinstall - Clean, build, and reinstall"
@echo " make update - Fresh build, remove old, install new (dev workflow)"
@echo " make clean - Remove built binary"
@echo ""
@echo " Build Flags (pass with BUILD_FLAGS):"
@echo " make build BUILD_FLAGS='-v' - Verbose build"
@echo " make update BUILD_FLAGS='-race' - Build with race detector"
@echo " make install BUILD_FLAGS='-v -race' - Verbose build with race detector"
@echo ""
@echo "🧪 Testing:"
@echo " make test - Run all tests"
@echo " make test-coverage - Run tests with coverage"
@echo " make test-coverage-html - Generate HTML coverage report"
@echo " make test-race - Run race detector"
@echo " make test-integration - Run integration tests"
@echo " make test-bench - Run benchmarks"
@echo ""
@echo "🎨 Code Quality:"
@echo " make prepare - Format, fix, and check code"
@echo " make fmt - Format all Go code"
@echo " make fmt-check - Check formatting"
@echo " make vet - Run go vet"
@echo " make lint - Run golangci-lint"
@echo " make lint-fix - Run golangci-lint with auto-fix"
@echo " make quality - Run all quality checks"
@echo " make security - Run security scans"
@echo ""
@echo "🛠️ Development:"
@echo " make setup - Setup dev environment"
@echo " make check-pre-commit - Check pre-commit installation"
@echo ""
@echo "📝 PR Management:"
@echo " make pr - Generate PR description (enhanced by default)"
@echo " make pr PR_ENHANCED=false - Generate basic PR description"
@echo " make pr PR_SKIP_CHECKS=true - Skip pre-commit checks"
@echo ""
@echo "📦 Release Management:"
@echo " make release - Check config (default)"
@echo " make release RELEASE_JOB=check - Validate .goreleaser.yaml"
@echo " make release RELEASE_JOB=test - Test build (current platform)"
@echo " make release RELEASE_JOB=build - Build all platforms"
@echo " make release RELEASE_JOB=snapshot - Full dry-run"
@echo ""
@echo "💡 Quick Start:"
@echo " make setup # One-time setup"
@echo " make demo # See it in action"
@echo ""
# ============================================================================
# Build & Run
# ============================================================================
build:
$(call log_section,🏗️ Building A.R.C.)
$(call build_binary,dev-$$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown'))
build-release:
$(call log_section,🏗️ Building Release Version)
$(call build_binary,0.0.1)
@./arc version
run:
$(call log_section,🚀 Running A.R.C. CLI)
@go run cmd/arc/main.go
demo: build
$(call log_section,🎬 Running Built Binary)
@./arc
install: build
$(call log_section,📦 Installing to System)
$(call log_info,Installing to /usr/local/bin...)
@sudo rm -f /usr/local/bin/arc
@sudo cp arc /usr/local/bin/
@sudo chmod +x /usr/local/bin/arc
$(call log_success,Installed! Run 'arc' from anywhere)
@echo ""
$(call log_info,Verifying installation...)
@which arc
@arc --version
reinstall: clean build
$(call log_section,📦 Reinstalling A.R.C.)
@sudo rm -f /usr/local/bin/arc
@sudo cp arc /usr/local/bin/
@sudo chmod +x /usr/local/bin/arc
$(call log_success,Reinstalled!)
@echo ""
@which arc
@arc --version
update:
$(call log_section,🔄 Updating A.R.C. CLI)
$(call log_info,Step 1/4: Cleaning old binary...)
@rm -f arc
$(call log_success,Old binary removed)
@echo ""
$(call log_info,Step 2/4: Removing system installation...)
@sudo rm -f /usr/local/bin/arc
$(call log_success,Old installation removed)
@echo ""
$(call log_info,Step 3/4: Building fresh binary...)
@if [ -n "$(BUILD_FLAGS)" ]; then \
echo "ℹ️ Using build flags: $(BUILD_FLAGS)"; \
fi
@BRANCH=$$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown'); \
VERSION="dev-$$BRANCH"; \
COMMIT=$$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown'); \
BUILD_DATE=$$(date -u '+%Y-%m-%dT%H:%M:%SZ'); \
go build $(BUILD_FLAGS) -ldflags="-X 'github.com/arc-framework/arc-cli/pkg/version.Version=$$VERSION' \
-X 'github.com/arc-framework/arc-cli/pkg/version.Commit=$$COMMIT' \
-X 'github.com/arc-framework/arc-cli/pkg/version.BuildDate=$$BUILD_DATE'" \
-o arc cmd/arc/main.go
$(call log_success,Build complete)
@ls -lh arc
@echo ""
$(call log_info,Step 4/4: Installing new binary...)
@sudo cp arc /usr/local/bin/
@sudo chmod +x /usr/local/bin/arc
$(call log_success,Installation complete!)
@echo ""
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@echo "🎉 A.R.C. CLI Successfully Updated!"
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@echo ""
@which arc
@arc version
@echo ""
@echo "💡 Tip: Use BUILD_FLAGS to pass custom build options"
@echo " Example: make update BUILD_FLAGS='-v -race'"
clean:
$(call log_info,Cleaning build artifacts...)
@rm -f arc
$(call log_success,Clean complete)
# ============================================================================
# Testing
# ============================================================================
test:
$(call log_section,🧪 Running Tests)
$(call log_info,Running core package tests with race detector...)
@go test -v -race $(RACE_PKGS)
$(call log_info,Running I/O packages without race detector \(O\(n²\) disk reads are too slow under -race\)...)
@go test -v ./pkg/store/local/...
$(call log_info,Running CLI tests (sequential)...)
@go test -v -p 1 $(CLI_PKGS)
$(call log_success,Tests complete)
test-coverage:
$(call log_section,🧪 Running Tests with Coverage)
$(call log_info,Running core package tests...)
@go test -v -race -coverprofile=coverage.txt -covermode=atomic $(CORE_PKGS)
$(call log_info,Running CLI tests...)
@go test -v -p 1 -coverprofile=coverage-cli.txt -covermode=atomic $(CLI_PKGS)
$(call log_info,Merging coverage profiles...)
@grep -v "mode: atomic" coverage-cli.txt >> coverage.txt
@rm coverage-cli.txt
@echo ""
@echo "📊 Coverage Summary:"
@go tool cover -func=coverage.txt | grep total
@echo ""
@total_coverage=$$(go tool cover -func=coverage.txt | grep total | awk '{print $$3}' | sed 's/%//'); \
threshold=70; \
if awk -v cov="$$total_coverage" -v the="$$threshold" 'BEGIN {exit !(cov >= the)}'; then \
$(call log_success,Coverage $$total_coverage% meets threshold $$threshold%); \
else \
$(call log_error,Coverage $$total_coverage% is below threshold $$threshold%); \
echo "Please add more tests to increase coverage."; \
exit 1; \
fi
test-coverage-html: test-coverage
$(call log_info,Generating HTML coverage report...)
@go tool cover -html=coverage.txt -o coverage.html
$(call log_success,Coverage report: coverage.html)
test-race:
$(call log_section,🏁 Running Race Detector)
$(call log_info,Testing core packages only (CLI excluded due to cobra races))
@go test -v -race $(CORE_PKGS)
$(call log_success,Race detector passed)
test-integration:
$(call log_section,🔗 Running Integration Tests)
@go test -v -tags=integration -race $(CORE_PKGS)
@go test -v -tags=integration -p 1 $(CLI_PKGS)
$(call log_success,Integration tests complete)
test-bench:
$(call log_section,⚡ Running Benchmarks)
$(call log_info,Running benchmarks on critical packages only...)
@go test -v -bench=. -benchmem -benchtime=100ms -timeout=5m \
./pkg/catalog/... \
./pkg/ui/theme/... \
./pkg/workspace/... \
./internal/preferences/...
$(call log_success,Benchmarks complete)
# ============================================================================
# Code Quality
# ============================================================================
fmt:
$(call log_section,🎨 Formatting Code)
$(call log_info,Installing/checking formatters...)
$(call install_tool,gofumpt,mvdan.cc/gofumpt)
$(call install_tool,goimports,golang.org/x/tools/cmd/goimports)
$(call log_info,Running gofumpt...)
@gofumpt -l -w .
$(call log_info,Running goimports...)
@goimports -w -local github.com/arc-framework/arc-cli .
$(call log_success,Format complete)
fmt-check:
$(call log_section,🔍 Checking Code Formatting)
$(call install_tool,gofumpt,mvdan.cc/gofumpt)
$(call install_tool,goimports,golang.org/x/tools/cmd/goimports)
$(call log_info,Checking gofumpt...)
@UNFMT=$$(gofumpt -l . 2>&1); \
if [ -n "$$UNFMT" ]; then \
$(call log_error,Files not formatted with gofumpt:); \
echo "$$UNFMT"; \
echo ""; \
echo "Run 'make fmt' to fix formatting"; \
exit 1; \
fi
$(call log_info,Checking goimports...)
@UNIMPORTED=$$(goimports -l -local github.com/arc-framework/arc-cli . 2>&1 | grep -v '^vendor/'); \
if [ -n "$$UNIMPORTED" ]; then \
$(call log_error,Files with incorrect imports:); \
echo "$$UNIMPORTED"; \
echo ""; \
echo "Run 'make fmt' to fix imports"; \
exit 1; \
fi
$(call log_success,All files properly formatted)
vet:
$(call log_section,🔍 Running Go Vet)
@go vet ./...
$(call log_success,Vet complete)
lint:
$(call log_section,🔍 Running Linter)
@golangci-lint run ./...
$(call log_success,Lint complete)
lint-fix:
$(call log_section,🔧 Running Linter with Auto-fix)
@golangci-lint run --fix ./...
$(call log_success,Lint fix complete)
quality:
$(call log_section,🎯 Running All Quality Checks)
@golangci-lint run ./...
$(call log_success,All quality checks complete)
security:
$(call log_section,🔒 Running Security Scans)
$(call log_info,Running gosec (lenient mode)...)
$(call install_tool,gosec,github.com/securego/gosec/v2/cmd/gosec)
@gosec -exclude=G304,G301,G306 -confidence=high -severity=high -quiet ./... || $(call log_success,No critical security issues)
@echo ""
$(call log_info,Checking for vulnerabilities in dependencies...)
@go list -json -deps ./... | command -v nancy >/dev/null 2>&1 && nancy sleuth || $(call log_info,Install nancy: go install github.com/sonatype-nexus-community/nancy@latest)
$(call log_success,Security scans complete)
prepare: fmt lint-fix vet
$(call log_success,Code prepared successfully!)
# ============================================================================
# Development Setup
# ============================================================================
check-pre-commit:
$(call check_tool,pre-commit,pip install pre-commit)
$(call log_success,pre-commit is installed)
setup:
$(call log_section,🛠️ Setting Up Development Environment)
@./scripts/setup-dev.sh
@echo ""
$(call log_info,Installing pre-commit hooks (optional)...)
@if command -v pre-commit >/dev/null 2>&1; then \
pre-commit install --install-hooks; \
pre-commit install --hook-type commit-msg; \
$(call log_success,Pre-commit hooks installed); \
else \
$(call log_info,pre-commit not found. Install with: pip install pre-commit); \
fi
@echo ""
$(call log_success,Development environment ready!)
@echo ""
@echo "Recommended tools:"
@echo " - golangci-lint: brew install golangci-lint"
@echo " - pre-commit: pip install pre-commit"
# ============================================================================
# PR Management
# ============================================================================
pr:
$(call log_section,📝 Generating PR Description)
ifeq ($(PR_SKIP_CHECKS),false)
$(call log_info,Running pre-commit checks...)
@$(MAKE) prepare
@echo ""
endif
ifeq ($(PR_ENHANCED),true)
$(call log_info,Generating enhanced PR description...)
@./scripts/generate-pr-description.sh --enhanced || ./scripts/generate-pr-description.sh
else
$(call log_info,Generating PR description...)
@./scripts/generate-pr-description.sh
endif
$(call log_success,PR description generated!)
@echo ""
@echo "💡 Tips:"
@echo " - Use PR_ENHANCED=true for detailed analysis"
@echo " - Use PR_SKIP_CHECKS=true to skip pre-commit checks"
# ============================================================================
# Release Management
# ============================================================================
release:
$(call log_section,📦 Release Management - $(RELEASE_JOB))
ifeq ($(RELEASE_JOB),check)
$(call log_info,Validating GoReleaser configuration...)
@goreleaser check
$(call log_success,Configuration is valid!)
else ifeq ($(RELEASE_JOB),test)
$(call log_info,Testing build for current platform...)
ifeq ($(RELEASE_SNAPSHOT),true)
@goreleaser build --snapshot $(if $(filter true,$(RELEASE_CLEAN)),--clean,) --single-target
else
@goreleaser build $(if $(filter true,$(RELEASE_CLEAN)),--clean,) --single-target
endif
$(call log_success,Test build complete! Check ./dist/)
else ifeq ($(RELEASE_JOB),build)
$(call log_info,Building for all platforms...)
ifeq ($(RELEASE_SNAPSHOT),true)
@goreleaser build --snapshot $(if $(filter true,$(RELEASE_CLEAN)),--clean,)
else
@goreleaser build $(if $(filter true,$(RELEASE_CLEAN)),--clean,)
endif
$(call log_success,Multi-platform build complete! Check ./dist/)
else ifeq ($(RELEASE_JOB),snapshot)
$(call log_info,Running full release dry-run...)
@goreleaser release --snapshot $(if $(filter true,$(RELEASE_CLEAN)),--clean,) --skip=publish
$(call log_success,Snapshot release complete! Check ./dist/)
@echo ""
@echo "📝 To create a real release:"
@echo " 1. git tag -a v1.0.0 -m 'Release v1.0.0'"
@echo " 2. git push origin v1.0.0"
@echo " 3. GitHub Actions will create the release"
else
$(call log_error,Unknown RELEASE_JOB: $(RELEASE_JOB))
@echo ""
@echo "Available jobs:"
@echo " check - Validate .goreleaser.yaml"
@echo " test - Test build (current platform)"
@echo " build - Build all platforms"
@echo " snapshot - Full release dry-run"
@echo ""
@echo "Flags:"
@echo " RELEASE_SNAPSHOT=true/false (default: true)"
@echo " RELEASE_CLEAN=true/false (default: true)"
@exit 1
endif