-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
executable file
·322 lines (265 loc) · 12 KB
/
Makefile
File metadata and controls
executable file
·322 lines (265 loc) · 12 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
# ==================================================================================== #
# VARIABLES
# ==================================================================================== #
## Application
APP_NAME = indexer
BUILD_DIR = ./build
MAIN_PATH = ./cmd/indexer
DOCKER_IMAGE_NAME ?= indexer
DOCKER_FILE = deployment/Dockerfile
## Build info
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
COMMIT_HASH = $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
BUILD_TIME = $(shell date -u '+%Y-%m-%d_%H:%M:%S')
LDFLAGS = -ldflags "-X github.com/pacviewer/indexer/version.GitCommit=$(COMMIT_HASH)"
## Tools versions
GOFUMPT_VERSION = latest
GOLANGCI_LINT_VERSION = latest
SQLC_VERSION = latest
GOSEC_VERSION = latest
## Test configuration
TEST_TIMEOUT = 10m
INTEGRATION_TEST_TIMEOUT = 15m
COVERAGE_FILE = coverage.out
COVERAGE_HTML = coverage.html
## Colors for output
COLOR_RESET = \033[0m
COLOR_BOLD = \033[1m
COLOR_GREEN = \033[32m
COLOR_YELLOW = \033[33m
COLOR_BLUE = \033[34m
# ==================================================================================== #
# HELPERS
# ==================================================================================== #
.PHONY: help
help: ## Display this help message
@echo "$(COLOR_BOLD)Indexer - Makefile Commands$(COLOR_RESET)"
@echo ""
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(COLOR_GREEN)%-25s$(COLOR_RESET) %s\n", $$1, $$2}'
.PHONY: confirm
confirm: ## Prompt for confirmation
@echo -n "Are you sure? [y/N] " && read ans && [ $${ans:-N} = y ]
# ==================================================================================== #
# SETUP & INSTALLATION
# ==================================================================================== #
.PHONY: setup
setup: devtools deps init-env ## Complete development environment setup
@echo "$(COLOR_GREEN)✓ Development environment ready!$(COLOR_RESET)"
.PHONY: devtools
devtools: install-gofumpt install-golangci-lint install-mockery install-sqlc install-migrate install-gosec ## Install all development tools
@echo "$(COLOR_GREEN)✓ All dev tools installed!$(COLOR_RESET)"
.PHONY: install-gofumpt
install-gofumpt: ## Install gofumpt for code formatting
@echo "$(COLOR_BLUE)→ Installing gofumpt...$(COLOR_RESET)"
@go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION)
@echo "$(COLOR_GREEN)✓ gofumpt installed$(COLOR_RESET)"
.PHONY: install-golangci-lint
install-golangci-lint: ## Install golangci-lint for code linting
@echo "$(COLOR_BLUE)→ Installing golangci-lint...$(COLOR_RESET)"
@go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)
@echo "$(COLOR_GREEN)✓ golangci-lint installed$(COLOR_RESET)"
.PHONY: install-sqlc
install-sqlc: ## Install sqlc for SQL code generation
@echo "$(COLOR_BLUE)→ Installing sqlc...$(COLOR_RESET)"
@go install github.com/sqlc-dev/sqlc/cmd/sqlc@$(SQLC_VERSION)
@echo "$(COLOR_GREEN)✓ sqlc installed$(COLOR_RESET)"
.PHONY: install-gosec
install-gosec: ## Install gosec for security scanning
@echo "$(COLOR_BLUE)→ Installing gosec...$(COLOR_RESET)"
@go install github.com/securego/gosec/v2/cmd/gosec@$(GOSEC_VERSION)
@echo "$(COLOR_GREEN)✓ gosec installed$(COLOR_RESET)"
.PHONY: deps
deps: ## Download Go module dependencies
@echo "$(COLOR_BLUE)→ Downloading dependencies...$(COLOR_RESET)"
@go mod download
@go mod verify
@echo "$(COLOR_GREEN)✓ Dependencies downloaded$(COLOR_RESET)"
.PHONY: deps-update
deps-update: confirm ## Update Go module dependencies
@echo "$(COLOR_BLUE)→ Updating dependencies...$(COLOR_RESET)"
@go get -u ./...
@go mod tidy
@echo "$(COLOR_GREEN)✓ Dependencies updated$(COLOR_RESET)"
.PHONY: init-env
init-env: confirm ## Initialize .env file from .env.example
@if [ ! -f .env ]; then \
echo "$(COLOR_BLUE)→ Creating .env from .env.example...$(COLOR_RESET)"; \
cp .env.example .env; \
echo "$(COLOR_YELLOW)⚠ Please update .env with your configuration$(COLOR_RESET)"; \
else \
echo "$(COLOR_YELLOW)⚠ .env already exists, skipping$(COLOR_RESET)"; \
fi
# ==================================================================================== #
# CODE GENERATION
# ==================================================================================== #
.PHONY: generate
generate: sqlc
@echo "$(COLOR_GREEN)✓ All code generation complete$(COLOR_RESET)"
.PHONY: sqlc
sqlc: ## Generate code from SQL queries using sqlc
@if ! command -v sqlc >/dev/null 2>&1; then \
echo "$(COLOR_YELLOW)⚠ sqlc not found, installing...$(COLOR_RESET)"; \
$(MAKE) install-sqlc; \
fi
@echo "$(COLOR_BLUE)→ Generating SQLC code...$(COLOR_RESET)"
@sqlc generate
@echo "$(COLOR_GREEN)✓ SQLC generation complete$(COLOR_RESET)"
.PHONY: create-migration
create-migration:
@read -p "Enter migration name: " name; \
if [ -z "$$name" ]; then \
echo "$(COLOR_YELLOW)⚠ Migration name cannot be empty$(COLOR_RESET)"; \
exit 1; \
fi; \
echo "$(COLOR_BLUE)→ Creating migration: $$name...$(COLOR_RESET)"; \
migrate create -ext sql -dir internal/persistence/postgres/migrations $$name; \
echo "$(COLOR_GREEN)✓ Migration created$(COLOR_RESET)"
# ==================================================================================== #
# SECURITY & SECRETS
# ==================================================================================== #
.PHONY: generate-random-secret gosec
generate-random-secret: ## Generate a single random secret
@openssl rand -base64 32
gosec:
@echo "$(COLOR_BLUE)→ Check security in $(APP_NAME)...$(COLOR_RESET)"
@gosec -exclude-dir=internal/persistence/postgres/gen -exclude-dir=tests/mocks ./...
# ==================================================================================== #
# BUILD
# ==================================================================================== #
.PHONY: build
build: ## Build the application binary
@echo "$(COLOR_BLUE)→ Building $(APP_NAME)...$(COLOR_RESET)"
@mkdir -p $(BUILD_DIR)
@go build $(LDFLAGS) -o $(BUILD_DIR)/$(APP_NAME) $(MAIN_PATH)
@echo "$(COLOR_GREEN)✓ Build complete: $(BUILD_DIR)/$(APP_NAME)$(COLOR_RESET)"
.PHONY: build-race
build-race: ## Build with race detector enabled
@echo "$(COLOR_BLUE)→ Building $(APP_NAME) with race detector...$(COLOR_RESET)"
@mkdir -p $(BUILD_DIR)
@go build -race $(LDFLAGS) -o $(BUILD_DIR)/$(APP_NAME) $(MAIN_PATH)
@echo "$(COLOR_GREEN)✓ Build complete: $(BUILD_DIR)/$(APP_NAME)$(COLOR_RESET)"
.PHONY: build-all
build-all: clean build build-race ## Clean and build all variants
.PHONY: install
install: ## Install the binary to $GOPATH/bin
@echo "$(COLOR_BLUE)→ Installing $(APP_NAME)...$(COLOR_RESET)"
@go install $(LDFLAGS) $(MAIN_PATH)
@echo "$(COLOR_GREEN)✓ Installed to $$(go env GOPATH)/bin/$(APP_NAME)$(COLOR_RESET)"
# ==================================================================================== #
# DEVELOPMENT
# ==================================================================================== #
.PHONY: run
run: ## Run the application locally
@if [ ! -f .env ]; then \
echo "$(COLOR_YELLOW)⚠ .env file not found. Creating from .env.example...$(COLOR_RESET)"; \
cp .env.example .env; \
echo "$(COLOR_YELLOW)⚠ Please update .env with your configuration before running the application.$(COLOR_RESET)"; \
exit 1; \
fi
@echo "$(COLOR_BLUE)→ Running $(APP_NAME)...$(COLOR_RESET)"
@go run $(MAIN_PATH) start --dotenv .env
.PHONY: clean
clean: ## Remove build artifacts
@echo "$(COLOR_BLUE)→ Cleaning...$(COLOR_RESET)"
@rm -rf $(BUILD_DIR)
@rm -f $(COVERAGE_FILE) $(COVERAGE_HTML)
@go clean -cache -testcache -modcache
@echo "$(COLOR_GREEN)✓ Clean complete$(COLOR_RESET)"
# ==================================================================================== #
# TESTING
# ==================================================================================== #
.PHONY: test
test: test-unit test-integration ## Run all tests
.PHONY: test-unit
test-unit: ## Run unit tests
@echo "$(COLOR_BLUE)→ Running unit tests...$(COLOR_RESET)"
@go test -v -race -timeout=$(TEST_TIMEOUT) ./...
@echo "$(COLOR_GREEN)✓ Unit tests passed$(COLOR_RESET)"
.PHONY: test-integration
test-integration: ## Run integration tests
@echo "$(COLOR_BLUE)→ Running integration tests...$(COLOR_RESET)"
@go test -v -timeout=$(INTEGRATION_TEST_TIMEOUT) ./tests/integration/...
@echo "$(COLOR_GREEN)✓ Integration tests passed$(COLOR_RESET)"
.PHONY: test-short
test-short: ## Run only short tests
@echo "$(COLOR_BLUE)→ Running short tests...$(COLOR_RESET)"
@go test -v -short -race ./...
.PHONY: test-verbose
test-verbose: ## Run tests with verbose output
@go test -v -race -timeout=$(TEST_TIMEOUT) ./... -count=1
test-coverage: ## Run tests with coverage report
@echo "$(COLOR_BLUE)→ Running tests with coverage...$(COLOR_RESET)"
@go test ./... -coverprofile=coverage.out -coverpkg=./internal/...
@go tool cover -func=coverage.out | grep total | awk '{print "$(COLOR_GREEN)✓ Total coverage: " $$3 "$(COLOR_RESET)"}'
.PHONY: bench
bench: ## Run benchmarks
@echo "$(COLOR_BLUE)→ Running benchmarks...$(COLOR_RESET)"
@go test -bench=. -benchmem ./...
# ==================================================================================== #
# CODE QUALITY
# ==================================================================================== #
.PHONY: check
check: fmt vet lint gosec ## Run all quality checks (fmt, vet, lint, security)
@echo "$(COLOR_GREEN)✓ All quality checks passed$(COLOR_RESET)"
.PHONY: fmt
fmt: ## Format code with gofumpt
@echo "$(COLOR_BLUE)→ Formatting code...$(COLOR_RESET)"
@gofumpt -l -w .
@echo "$(COLOR_GREEN)✓ Code formatted$(COLOR_RESET)"
.PHONY: vet
vet: ## Run go vet
@echo "$(COLOR_BLUE)→ Running go vet...$(COLOR_RESET)"
@go vet ./...
@echo "$(COLOR_GREEN)✓ go vet passed$(COLOR_RESET)"
.PHONY: lint
lint: ## Run golangci-lint
@echo "$(COLOR_BLUE)→ Running linter...$(COLOR_RESET)"
@golangci-lint run --timeout=20m
@echo "$(COLOR_GREEN)✓ Linting passed$(COLOR_RESET)"
.PHONY: lint-fix
lint-fix: ## Run golangci-lint with auto-fix
@echo "$(COLOR_BLUE)→ Running linter with auto-fix...$(COLOR_RESET)"
@golangci-lint run --fix --timeout=20m
@echo "$(COLOR_GREEN)✓ Linting complete$(COLOR_RESET)"
.PHONY: tidy
tidy: ## Tidy and verify go.mod
@echo "$(COLOR_BLUE)→ Tidying go.mod...$(COLOR_RESET)"
@go mod tidy
@go mod verify
@echo "$(COLOR_GREEN)✓ go.mod tidied$(COLOR_RESET)"
# ==================================================================================== #
# DOCKER
# ==================================================================================== #
.PHONY: docker-build
docker-build: ## Build Docker image
@echo "$(COLOR_BLUE)→ Building Docker image...$(COLOR_RESET)"
@docker build -f $(DOCKER_FILE) -t $(DOCKER_IMAGE_NAME):$(VERSION) -t $(DOCKER_IMAGE_NAME):latest \
--build-arg VERSION=$(VERSION) \
--build-arg COMMIT_HASH=$(COMMIT_HASH) \
--build-arg BUILD_TIME=$(BUILD_TIME) \
.
@echo "$(COLOR_GREEN)✓ Docker image built: $(DOCKER_IMAGE_NAME):$(VERSION)$(COLOR_RESET)"
.PHONY: docker-run
docker-run: ## Run Docker container
@echo "$(COLOR_BLUE)→ Running Docker container...$(COLOR_RESET)"
@docker run --rm -p 8080:8080 --env-file .env $(DOCKER_IMAGE_NAME):latest
.PHONY: docker-compose-up
docker-compose-up: ## Start all services with docker-compose
@echo "$(COLOR_BLUE)→ Starting services...$(COLOR_RESET)"
@cd deployment && docker-compose up -d
@echo "$(COLOR_GREEN)✓ Services started$(COLOR_RESET)"
.PHONY: docker-compose-down
docker-compose-down: ## Stop all services
@echo "$(COLOR_BLUE)→ Stopping services...$(COLOR_RESET)"
@cd deployment && docker-compose down
@echo "$(COLOR_GREEN)✓ Services stopped$(COLOR_RESET)"
.PHONY: docker-compose-logs
docker-compose-logs: ## View docker-compose logs
@cd deployment && docker-compose logs -f
.PHONY: docker-clean
docker-clean: confirm ## Remove Docker images and volumes
@echo "$(COLOR_BLUE)→ Cleaning Docker resources...$(COLOR_RESET)"
@docker rmi $(DOCKER_IMAGE_NAME):$(VERSION) $(DOCKER_IMAGE_NAME):latest 2>/dev/null || true
@echo "$(COLOR_GREEN)✓ Docker cleanup complete$(COLOR_RESET)"
# Default target
.DEFAULT_GOAL := help