-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMakefile
More file actions
205 lines (173 loc) · 8.32 KB
/
Makefile
File metadata and controls
205 lines (173 loc) · 8.32 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
-include .env
export POSTHOG_KEY
.PHONY: dev-daemon dev-tui dev-gui build build-daemon build-cli test lint proto clean install-tools \
build-daemon-arm64 build-daemon-amd64 build-cli-arm64 build-cli-amd64 build-universal sync-version package-gui \
install install-all uninstall
# Binary names
DAEMON_BINARY=watchfired
CLI_BINARY=watchfire
# Build directories
BUILD_DIR=build
CMD_DIR=cmd
# Go parameters
GOCMD=go
GOBUILD=$(GOCMD) build
GOTEST=$(GOCMD) test
GOGET=$(GOCMD) get
GOMOD=$(GOCMD) mod
# Version info from version.json
VERSION := $(shell python3 -c "import json; print(json.load(open('version.json'))['version'])")
CODENAME := $(shell python3 -c "import json; print(json.load(open('version.json'))['codename'])")
COMMIT := $(shell git rev-parse --short HEAD)
BUILD_DATE := $(shell date -u +%Y-%m-%d)
# Ldflags for version injection
LDFLAGS := -X github.com/watchfire-io/watchfire/internal/buildinfo.Version=$(VERSION) \
-X github.com/watchfire-io/watchfire/internal/buildinfo.Codename=$(CODENAME) \
-X github.com/watchfire-io/watchfire/internal/buildinfo.CommitHash=$(COMMIT) \
-X github.com/watchfire-io/watchfire/internal/buildinfo.BuildDate=$(BUILD_DATE) \
-X github.com/watchfire-io/watchfire/internal/buildinfo.PostHogKey=$(POSTHOG_KEY)
# Development with hot reload
dev-daemon:
@echo "Starting daemon with hot reload..."
air -c .air.toml
# Build and run TUI
dev-tui: build-cli
./$(BUILD_DIR)/$(CLI_BINARY)
# Run Electron dev mode
dev-gui:
cd gui && npm run dev
# Build all Go binaries (native arch)
build: build-daemon build-cli
build-daemon build-daemon-dev:
@mkdir -p $(BUILD_DIR)
CGO_ENABLED=1 $(GOBUILD) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(DAEMON_BINARY) ./$(CMD_DIR)/watchfired
build-cli:
@mkdir -p $(BUILD_DIR)
$(GOBUILD) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(CLI_BINARY) ./$(CMD_DIR)/watchfire
# Architecture-specific builds
build-daemon-arm64:
@mkdir -p $(BUILD_DIR)
CGO_ENABLED=1 GOARCH=arm64 $(GOBUILD) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(DAEMON_BINARY)-arm64 ./$(CMD_DIR)/watchfired
build-daemon-amd64:
@mkdir -p $(BUILD_DIR)
CGO_ENABLED=1 GOARCH=amd64 $(GOBUILD) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(DAEMON_BINARY)-amd64 ./$(CMD_DIR)/watchfired
build-cli-arm64:
@mkdir -p $(BUILD_DIR)
GOARCH=arm64 $(GOBUILD) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(CLI_BINARY)-arm64 ./$(CMD_DIR)/watchfire
build-cli-amd64:
@mkdir -p $(BUILD_DIR)
GOARCH=amd64 $(GOBUILD) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(CLI_BINARY)-amd64 ./$(CMD_DIR)/watchfire
# Universal (fat) binaries via lipo — for release packaging
build-universal: build-daemon-arm64 build-daemon-amd64 build-cli-arm64 build-cli-amd64
@echo "Creating universal binaries..."
lipo -create -output $(BUILD_DIR)/$(DAEMON_BINARY) $(BUILD_DIR)/$(DAEMON_BINARY)-arm64 $(BUILD_DIR)/$(DAEMON_BINARY)-amd64
lipo -create -output $(BUILD_DIR)/$(CLI_BINARY) $(BUILD_DIR)/$(CLI_BINARY)-arm64 $(BUILD_DIR)/$(CLI_BINARY)-amd64
@echo "Universal binaries created."
lipo -info $(BUILD_DIR)/$(DAEMON_BINARY)
lipo -info $(BUILD_DIR)/$(CLI_BINARY)
@# Create x64 aliases for electron-builder ${arch} substitution
cp $(BUILD_DIR)/$(DAEMON_BINARY)-amd64 $(BUILD_DIR)/$(DAEMON_BINARY)-x64
cp $(BUILD_DIR)/$(CLI_BINARY)-amd64 $(BUILD_DIR)/$(CLI_BINARY)-x64
# Sync version.json → gui/package.json
sync-version:
@echo "Syncing version to gui/package.json..."
jq --arg v "$(VERSION)" '.version = $$v' gui/package.json > gui/package.json.tmp && mv gui/package.json.tmp gui/package.json
# Run tests
test:
$(GOTEST) -v -race ./...
# Run linter
lint:
golangci-lint run ./...
# Generate protobuf code
proto:
@echo "Generating protobuf code..."
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
proto/watchfire.proto
# Build GUI (Electron)
build-gui:
cd gui && npm run build
# Package GUI as distributable (builds universal Go binaries first)
package-gui: sync-version build-universal build-gui
cd gui && npm run package
# Clean build artifacts
clean:
rm -rf $(BUILD_DIR)
rm -rf tmp
rm -rf gui/out gui/dist gui/node_modules/.cache
# Install development tools
install-tools:
@echo "Installing development tools..."
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install github.com/air-verse/air@latest
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
@echo "Tools installed successfully"
# Tidy dependencies
tidy:
$(GOMOD) tidy
# Run daemon in foreground (no hot reload)
run-daemon: build-daemon
./$(BUILD_DIR)/$(DAEMON_BINARY) --foreground
# Run CLI
run-cli: build-cli
./$(BUILD_DIR)/$(CLI_BINARY)
# Install locally — builds native binaries and copies to /usr/local/bin
# Simulates what the GUI installer does on first launch.
# Usage:
# make install — build with version.json and install
# make install VERSION=0.0.1 — override version (useful for testing updates)
install: build
@# Stop daemon if running (replacing binary while daemon runs causes issues on macOS)
@if pgrep -x watchfired >/dev/null 2>&1; then \
echo "Stopping running daemon..."; \
pkill -TERM watchfired 2>/dev/null; \
sleep 1; \
fi
@echo "Installing watchfire v$(VERSION) to /usr/local/bin..."
@cp $(BUILD_DIR)/$(CLI_BINARY) /usr/local/bin/$(CLI_BINARY) 2>/dev/null || \
sudo cp $(BUILD_DIR)/$(CLI_BINARY) /usr/local/bin/$(CLI_BINARY)
@cp $(BUILD_DIR)/$(DAEMON_BINARY) /usr/local/bin/$(DAEMON_BINARY) 2>/dev/null || \
sudo cp $(BUILD_DIR)/$(DAEMON_BINARY) /usr/local/bin/$(DAEMON_BINARY)
@# Remove quarantine flags that macOS may carry over from previous installs
@xattr -dr com.apple.quarantine /usr/local/bin/$(CLI_BINARY) 2>/dev/null || \
sudo xattr -dr com.apple.quarantine /usr/local/bin/$(CLI_BINARY) 2>/dev/null || true
@xattr -dr com.apple.quarantine /usr/local/bin/$(DAEMON_BINARY) 2>/dev/null || \
sudo xattr -dr com.apple.quarantine /usr/local/bin/$(DAEMON_BINARY) 2>/dev/null || true
@# Re-sign binaries after copy (macOS Gatekeeper may kill unsigned binaries in /usr/local/bin)
@codesign --sign - --force /usr/local/bin/$(CLI_BINARY) 2>/dev/null || \
sudo codesign --sign - --force /usr/local/bin/$(CLI_BINARY)
@codesign --sign - --force /usr/local/bin/$(DAEMON_BINARY) 2>/dev/null || \
sudo codesign --sign - --force /usr/local/bin/$(DAEMON_BINARY)
@echo "Installed:"
@$(BUILD_DIR)/$(CLI_BINARY) version
@$(BUILD_DIR)/$(DAEMON_BINARY) version
# Install everything — CLI, daemon, and GUI app
# Builds native Go binaries + packages the Electron app, then installs all.
install-all: install install-gui
# Build and install GUI app to /Applications (native arch only)
NATIVE_ARCH := $(shell uname -m | sed 's/x86_64/x64/')
install-gui: sync-version build build-gui
@# Create arch-suffixed copies that electron-builder's ${arch} substitution expects
@cp $(BUILD_DIR)/$(DAEMON_BINARY) $(BUILD_DIR)/$(DAEMON_BINARY)-$(NATIVE_ARCH)
@cp $(BUILD_DIR)/$(CLI_BINARY) $(BUILD_DIR)/$(CLI_BINARY)-$(NATIVE_ARCH)
@# Generate local config with native arch only (avoids universal build needing cross-compiled binaries)
@sed 's/arch: \[universal\]/arch: [$(NATIVE_ARCH)]/' gui/electron-builder.yml > gui/electron-builder.local.yml
@echo "Packaging Watchfire.app ($(NATIVE_ARCH)) for local install..."
cd gui && npx electron-builder --config electron-builder.local.yml --publish never --mac -c.mac.notarize=false
@rm -f gui/electron-builder.local.yml
@echo "Installing Watchfire.app to /Applications..."
@APP_DIR=$$(ls -d gui/dist/mac-$(NATIVE_ARCH)/Watchfire.app 2>/dev/null | head -1); \
if [ -z "$$APP_DIR" ]; then echo "Error: Watchfire.app not found in gui/dist/"; exit 1; fi; \
rm -rf /Applications/Watchfire.app 2>/dev/null || sudo rm -rf /Applications/Watchfire.app; \
cp -R "$$APP_DIR" /Applications/Watchfire.app 2>/dev/null || \
sudo cp -R "$$APP_DIR" /Applications/Watchfire.app
@xattr -dr com.apple.quarantine /Applications/Watchfire.app 2>/dev/null || true
@echo "Watchfire.app installed to /Applications"
# Remove installed binaries and app
uninstall:
@echo "Removing watchfire from /usr/local/bin..."
@rm -f /usr/local/bin/$(CLI_BINARY) 2>/dev/null || sudo rm -f /usr/local/bin/$(CLI_BINARY)
@rm -f /usr/local/bin/$(DAEMON_BINARY) 2>/dev/null || sudo rm -f /usr/local/bin/$(DAEMON_BINARY)
@rm -rf /Applications/Watchfire.app 2>/dev/null || sudo rm -rf /Applications/Watchfire.app
@echo "Uninstalled."