-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
267 lines (233 loc) · 12.4 KB
/
Copy pathMakefile
File metadata and controls
267 lines (233 loc) · 12.4 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
.PHONY: all build build-cli build-controller build-controller-linux build-plugins build-plugin-proxmox build-plugin-k3s build-plugin-cloudflare build-plugin-k8s build-plugin-k3s-agent build-plugin-k3s-agent-linux install clean test test-e2e fmt lint modernize modernize-check generate ui ui-install ui-clean codesign-setup
# Binary names
CLI_BINARY=openctl
CONTROLLER_BINARY=openctl-controller
PLUGIN_PROXMOX_BINARY=openctl-proxmox
PLUGIN_K3S_BINARY=openctl-k3s
PLUGIN_K3S_AGENT_BINARY=openctl-k3s-agent
# Build directories
BUILD_DIR=bin
PROXMOX_PLUGIN_DIR=plugins/proxmox
K3S_PLUGIN_DIR=plugins/k3s
K8S_PLUGIN_DIR=plugins/k8s
UI_DIR=ui
UI_OUT=internal/controller/server/uiassets/dist
# Go settings.
#
# LDFLAGS injects git SHA + build time into the controller binary
# (server.GitCommit / server.BuildTime), surfaced by Ping so the UI and
# CLI can confirm which build is running without guessing from
# behavior. Falls back to "dev" when git or date aren't available
# (fresh checkout without commits, unusual PATHs) so the build never
# fails on the injection.
GIT_COMMIT := $(shell git rev-parse --short=12 HEAD 2>/dev/null || echo dev)
BUILD_TIME := $(shell date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo dev)
LDFLAGS := -s -w \
-X github.com/openctl/openctl/internal/controller/server.GitCommit=$(GIT_COMMIT) \
-X github.com/openctl/openctl/internal/controller/server.BuildTime=$(BUILD_TIME)
GOFLAGS=-ldflags="$(LDFLAGS)"
export GOWORK=off
# macOS code signing.
#
# `go build` emits an ad-hoc Mach-O whose cdhash changes every build, so
# per-app firewalls (LuLu, Little Snitch) treat each rebuild as a new app
# and silently re-block it — surfacing as `connect: no route to host`
# reaching Proxmox. Signing each build with ONE persistent self-signed
# identity gives every rebuild the same designated requirement, so a
# firewall rule approved once keeps applying. One-time setup:
#
# make codesign-setup # or: scripts/macos-codesign-setup.sh
#
# codesign_binary is a no-op off macOS or when the identity isn't
# installed (see scripts/codesign-macos.sh), so CI and unconfigured devs
# build normally. $(call codesign_binary,<path>,<bundle-id>)
CODESIGN_IDENTITY ?= openctl-dev
codesign_binary = @CODESIGN_IDENTITY=$(CODESIGN_IDENTITY) sh scripts/codesign-macos.sh "$(1)" "$(2)"
all: build
build: build-cli build-controller build-plugins
build-cli:
@echo "Building openctl CLI..."
@mkdir -p $(BUILD_DIR)
go build $(GOFLAGS) -o $(BUILD_DIR)/$(CLI_BINARY) ./cmd/openctl
$(call codesign_binary,$(BUILD_DIR)/$(CLI_BINARY),io.openctl.cli)
# build-controller depends on `ui` because the controller embeds
# uiassets/dist/ via //go:embed. Without rebuilding, the browser bundle
# stays stuck on whatever was last built — a common footgun where Go
# code changes ship but UI code changes don't. If you specifically want
# to skip the UI (CI without npm, or rapid Go-only iteration), invoke
# `go build ./cmd/openctl-controller` directly.
build-controller: ui
@echo "Building openctl-controller..."
@mkdir -p $(BUILD_DIR)
go build $(GOFLAGS) -o $(BUILD_DIR)/$(CONTROLLER_BINARY) ./cmd/openctl-controller
$(call codesign_binary,$(BUILD_DIR)/$(CONTROLLER_BINARY),io.openctl.controller)
build-plugins: build-plugin-proxmox build-plugin-k3s build-plugin-cloudflare build-plugin-k8s
# The k8s plugin (Helm-SDK workload provider) is a separate module.
build-plugin-k8s:
@echo "Building k8s plugin..."
@mkdir -p $(BUILD_DIR)
cd $(K8S_PLUGIN_DIR) && go build $(GOFLAGS) -o ../../$(BUILD_DIR)/openctl-k8s ./cmd/openctl-k8s
$(call codesign_binary,$(BUILD_DIR)/openctl-k8s,io.openctl.plugin.k8s)
# The cloudflare plugin lives in the root module (stdlib-only), so it builds
# straight from ./plugins/cloudflare — no separate module / `cd` needed.
build-plugin-cloudflare:
@echo "Building cloudflare plugin..."
@mkdir -p $(BUILD_DIR)
go build $(GOFLAGS) -o $(BUILD_DIR)/openctl-cloudflare ./plugins/cloudflare
$(call codesign_binary,$(BUILD_DIR)/openctl-cloudflare,io.openctl.plugin.cloudflare)
build-plugin-proxmox:
@echo "Building openctl-proxmox plugin..."
@mkdir -p $(BUILD_DIR)
cd $(PROXMOX_PLUGIN_DIR) && go build $(GOFLAGS) -o ../../$(BUILD_DIR)/$(PLUGIN_PROXMOX_BINARY) ./cmd/openctl-proxmox
$(call codesign_binary,$(BUILD_DIR)/$(PLUGIN_PROXMOX_BINARY),io.openctl.plugin.proxmox)
build-plugin-k3s:
@echo "Building openctl-k3s plugin..."
@mkdir -p $(BUILD_DIR)
cd $(K3S_PLUGIN_DIR) && go build $(GOFLAGS) -o ../../$(BUILD_DIR)/$(PLUGIN_K3S_BINARY) ./cmd/openctl-k3s
$(call codesign_binary,$(BUILD_DIR)/$(PLUGIN_K3S_BINARY),io.openctl.plugin.k3s)
# Build the k3s agent for the host platform (for local dev/testing).
build-plugin-k3s-agent:
@echo "Building openctl-k3s-agent (native)..."
@mkdir -p $(BUILD_DIR)
cd $(K3S_PLUGIN_DIR) && go build $(GOFLAGS) -o ../../$(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY) ./cmd/openctl-k3s-agent
$(call codesign_binary,$(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY),io.openctl.k3s-agent)
# Cross-compile the k3s agent for all Linux architectures we deploy to.
# These are Linux ELF binaries — NOT Mach-O — so they are deliberately not
# codesigned (codesign only operates on Mach-O; they run on remote nodes,
# not this Mac, so no local firewall cares).
# These artifacts get uploaded to k3s nodes during cluster create.
build-plugin-k3s-agent-linux:
@echo "Building openctl-k3s-agent for linux/amd64, linux/arm64, linux/arm..."
@mkdir -p $(BUILD_DIR)
cd $(K3S_PLUGIN_DIR) && GOOS=linux GOARCH=amd64 go build $(GOFLAGS) -o ../../$(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-amd64 ./cmd/openctl-k3s-agent
cd $(K3S_PLUGIN_DIR) && GOOS=linux GOARCH=arm64 go build $(GOFLAGS) -o ../../$(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-arm64 ./cmd/openctl-k3s-agent
cd $(K3S_PLUGIN_DIR) && GOOS=linux GOARCH=arm GOARM=7 go build $(GOFLAGS) -o ../../$(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-armv7 ./cmd/openctl-k3s-agent
# Cross-compile the controller for Linux (the run-anywhere daemon target and
# the payload for `openctl-controller install --target ssh://`). Pure-Go
# SQLite (modernc.org/sqlite) means CGO_ENABLED=0 yields a static ELF binary —
# no cross C toolchain needed. Depends on `ui` because the controller
# //go:embeds the built UI assets. Not codesigned (ELF, not Mach-O).
build-controller-linux: ui
@echo "Building openctl-controller for linux/amd64, linux/arm64..."
@mkdir -p $(BUILD_DIR)
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(GOFLAGS) -o $(BUILD_DIR)/$(CONTROLLER_BINARY)-linux-amd64 ./cmd/openctl-controller
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build $(GOFLAGS) -o $(BUILD_DIR)/$(CONTROLLER_BINARY)-linux-arm64 ./cmd/openctl-controller
install: build build-plugin-k3s-agent-linux
@echo "Installing binaries..."
@mkdir -p $(HOME)/.openctl/plugins/k3s-agents
cp $(BUILD_DIR)/$(CLI_BINARY) $(GOBIN)/ 2>/dev/null || cp $(BUILD_DIR)/$(CLI_BINARY) /usr/local/bin/
cp $(BUILD_DIR)/$(CONTROLLER_BINARY) $(GOBIN)/ 2>/dev/null || cp $(BUILD_DIR)/$(CONTROLLER_BINARY) /usr/local/bin/
cp $(BUILD_DIR)/$(PLUGIN_PROXMOX_BINARY) $(HOME)/.openctl/plugins/
cp $(BUILD_DIR)/$(PLUGIN_K3S_BINARY) $(HOME)/.openctl/plugins/
cp $(BUILD_DIR)/openctl-cloudflare $(HOME)/.openctl/plugins/
cp $(BUILD_DIR)/openctl-k8s $(HOME)/.openctl/plugins/
cp $(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-amd64 $(HOME)/.openctl/plugins/k3s-agents/
cp $(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-arm64 $(HOME)/.openctl/plugins/k3s-agents/
cp $(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-armv7 $(HOME)/.openctl/plugins/k3s-agents/
install-cli: build-cli
cp $(BUILD_DIR)/$(CLI_BINARY) $(GOBIN)/ 2>/dev/null || cp $(BUILD_DIR)/$(CLI_BINARY) /usr/local/bin/
install-plugins: build-plugins build-plugin-k3s-agent-linux
@mkdir -p $(HOME)/.openctl/plugins/k3s-agents
cp $(BUILD_DIR)/$(PLUGIN_PROXMOX_BINARY) $(HOME)/.openctl/plugins/
cp $(BUILD_DIR)/$(PLUGIN_K3S_BINARY) $(HOME)/.openctl/plugins/
cp $(BUILD_DIR)/openctl-cloudflare $(HOME)/.openctl/plugins/
cp $(BUILD_DIR)/openctl-k8s $(HOME)/.openctl/plugins/
cp $(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-amd64 $(HOME)/.openctl/plugins/k3s-agents/
cp $(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-arm64 $(HOME)/.openctl/plugins/k3s-agents/
cp $(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-armv7 $(HOME)/.openctl/plugins/k3s-agents/
install-plugin-proxmox: build-plugin-proxmox
@mkdir -p $(HOME)/.openctl/plugins
cp $(BUILD_DIR)/$(PLUGIN_PROXMOX_BINARY) $(HOME)/.openctl/plugins/
install-plugin-k3s: build-plugin-k3s build-plugin-k3s-agent-linux
@mkdir -p $(HOME)/.openctl/plugins/k3s-agents
cp $(BUILD_DIR)/$(PLUGIN_K3S_BINARY) $(HOME)/.openctl/plugins/
cp $(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-amd64 $(HOME)/.openctl/plugins/k3s-agents/
cp $(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-arm64 $(HOME)/.openctl/plugins/k3s-agents/
cp $(BUILD_DIR)/$(PLUGIN_K3S_AGENT_BINARY)-linux-armv7 $(HOME)/.openctl/plugins/k3s-agents/
clean: ui-clean
@echo "Cleaning..."
rm -rf $(BUILD_DIR)
# One-time: create the persistent self-signed code-signing identity so
# rebuilt binaries keep a stable identity and per-app firewalls stop
# re-blocking them. Safe to re-run. See scripts/macos-codesign-setup.sh.
codesign-setup:
@CODESIGN_IDENTITY=$(CODESIGN_IDENTITY) sh scripts/macos-codesign-setup.sh
# Build the browser UI (Vite + Svelte). Output goes directly into the
# controller's embed.FS root ($(UI_OUT)) so a subsequent `make build` bakes
# it into the binary. ui-install runs `npm ci` against committed
# package-lock.json — keep it separate from ui so iterative builds don't
# re-resolve deps on every invocation.
ui-install:
@echo "Installing UI dependencies..."
cd $(UI_DIR) && npm install
ui: ui-install
@echo "Building UI ($(UI_DIR) -> $(UI_OUT))..."
cd $(UI_DIR) && npm run build
@# Vite's emptyOutDir wipes the .gitkeep marker we use to keep the
@# dist/ directory present in git for fresh checkouts; restore it so
@# `go:embed all:uiassets/dist` keeps working after `make clean` etc.
@touch $(UI_OUT)/.gitkeep
ui-clean:
@echo "Cleaning UI build output..."
@# Use find rather than rm -rf $(UI_OUT) so we don't blow away the
@# directory itself (embed.FS needs it to exist) or the .gitkeep.
@find $(UI_OUT) -mindepth 1 ! -name .gitkeep -delete 2>/dev/null || true
@rm -rf $(UI_DIR)/node_modules
test:
go test ./...
cd $(PROXMOX_PLUGIN_DIR) && go test ./...
cd $(K3S_PLUGIN_DIR) && go test ./...
cd $(K8S_PLUGIN_DIR) && go test ./...
test-e2e: build-cli
go test -v ./test/e2e/...
fmt:
go fmt ./...
cd $(PROXMOX_PLUGIN_DIR) && go fmt ./...
cd $(K3S_PLUGIN_DIR) && go fmt ./...
lint:
golangci-lint run ./...
cd $(PROXMOX_PLUGIN_DIR) && golangci-lint run --config=../../.golangci.yml ./...
cd $(K3S_PLUGIN_DIR) && golangci-lint run --config=../../.golangci.yml ./...
# Download dependencies
deps:
go mod download
go mod tidy
cd $(PROXMOX_PLUGIN_DIR) && go mod download && go mod tidy
cd $(K3S_PLUGIN_DIR) && go mod download && go mod tidy
cd $(K8S_PLUGIN_DIR) && go mod download && go mod tidy
# Regenerate gRPC bindings from .proto files. Requires protoc + the Go
# plugins (see DEVELOPMENT.md for install instructions). The generated
# files are committed so building the project doesn't require protoc.
generate:
@echo "Regenerating gRPC + gateway bindings..."
@GW1=$$(go env GOMODCACHE)/github.com/grpc-ecosystem/grpc-gateway@v1.16.0/third_party/googleapis; \
test -d "$$GW1" || (echo "missing $$GW1 — run: go mod download github.com/grpc-ecosystem/grpc-gateway" && exit 1); \
protoc \
--proto_path=pkg/api/v1 \
--proto_path=$$GW1 \
--go_out=pkg/api/v1 --go_opt=paths=source_relative \
--go-grpc_out=pkg/api/v1 --go-grpc_opt=paths=source_relative \
--grpc-gateway_out=pkg/api/v1 --grpc-gateway_opt=paths=source_relative \
pkg/api/v1/api.proto
# Modernize code using latest Go idioms
modernize:
@echo "Installing modernize tool..."
@go install golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest
@echo "Running modernize on root module..."
modernize -fix ./...
@echo "Running modernize on proxmox plugin..."
cd $(PROXMOX_PLUGIN_DIR) && modernize -fix ./...
@echo "Running modernize on k3s plugin..."
cd $(K3S_PLUGIN_DIR) && modernize -fix ./...
@echo "Running modernize on k8s plugin..."
cd $(K8S_PLUGIN_DIR) && modernize -fix ./...
@echo "Done! Review changes with 'git diff'"
# Check for modernize suggestions without applying fixes
modernize-check:
@go install golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest
@echo "Checking root module..."
@modernize ./... || true
@echo "Checking proxmox plugin..."
@cd $(PROXMOX_PLUGIN_DIR) && modernize ./... || true
@echo "Checking k3s plugin..."
@cd $(K3S_PLUGIN_DIR) && modernize ./... || true