-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathMakefile
More file actions
330 lines (284 loc) · 12.6 KB
/
Copy pathMakefile
File metadata and controls
330 lines (284 loc) · 12.6 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
.PHONY: proto-clean proto-build proto-docker proto nodetest docker-compose-up down cloudsql up-and-down up-and-down-oidc sqlite expire-local-trials proto-copy-to-node proto-stub server runner-install runner-register runner-start runner-stop runner-status runner-service-install runner-service-start runner-service-stop runner-service-status github-runner license-keygen license-issue
# load .env
# https://lithic.tech/blog/2020-05/makefile-dot-env
ifneq (,$(wildcard ./.env))
include .env
endif
UNAME := $(shell uname -m)
DOCKER_TTY := $(shell if [ -t 0 ] && [ -t 1 ]; then echo -it; fi)
RUNNER_DIR ?= $(HOME)/actions-runner
RUNNER_URL ?= https://github.com/dekart-xyz/dekart
RUNNER_LABELS ?= self-hosted,laptop-build
RUNNER_NAME ?= $(shell hostname)-dekart-laptop
GITHUB_RUNNER_TOKEN ?= $(RUNNER_TOKEN)
RUNNER_VERSION ?= 2.328.0
PSQL ?= psql
LOCAL_DEV_POSTGRES_HOST ?= $(or $(DEKART_POSTGRES_HOST),localhost)
LOCAL_DEV_POSTGRES_PORT ?= $(or $(DEKART_POSTGRES_PORT),5432)
LOCAL_DEV_POSTGRES_USER ?= $(or $(DEKART_POSTGRES_USER),postgres)
LOCAL_DEV_POSTGRES_PASSWORD ?= $(DEKART_POSTGRES_PASSWORD)
LOCAL_DEV_POSTGRES_DB ?= $(or $(DEKART_POSTGRES_DB),dekart)
proto-clean:
rm -rf ./src/proto/*.go
rm -rf ./src/proto/*.js
rm -rf ./src/proto/*.ts
rm -rf ./proto/*.go
rm -rf ./proto/*.js
rm -rf ./proto/*.ts
rm -rf ./node_modules/dekart-proto
proto-build: proto-clean #to run inside docker
protoc --experimental_allow_proto3_optional --proto_path=./proto --js_out=import_style=commonjs,binary:./proto $$(find proto -type f -name "*.proto")
protoc --experimental_allow_proto3_optional --proto_path=./proto --ts_out=service=grpc-web:./proto $$(find proto -type f -name "*.proto")
protoc --experimental_allow_proto3_optional --go_out=./src $$(find proto -type f -name "*.proto")
protoc --experimental_allow_proto3_optional --go-grpc_out=./src $$(find proto -type f -name "*.proto")
proto-docker: # build docker container for building protos
ifeq ($(UNAME),arm64)
docker buildx build --load -t dekart-proto -f ./proto/Dockerfile --build-arg PLATFORM=aarch_64 .
else
docker buildx build --load -t dekart-proto -f ./proto/Dockerfile .
endif
proto-copy-to-node:
rm -rf ./node_modules/dekart-proto
rm -rf ./node_modules/.vite
mkdir -p ./node_modules/dekart-proto
cp -r ./proto/* ./node_modules/dekart-proto/
proto: proto-stub proto-copy-to-node
proto-stub: proto-docker # build proto stubs
docker run $(DOCKER_TTY) --rm \
-v $$(pwd):/home/root/dekart \
dekart-proto \
make proto-build
nodetest:
docker buildx build --platform=linux/amd64 -f ./Dockerfile --target nodetest .
gotest:
docker buildx build -f ./Dockerfile --target gotest .
e2e: bq athena snowflake
snowpark-build:
docker buildx build --platform linux/amd64 --tag ${SNOWPARK_IMAGE_NAME} --build-arg DEKART_MAPBOX_TOKEN=${DEKART_MAPBOX_TOKEN} -f ./Dockerfile . --load
snowpark-run: snowpark-build
docker run -it --rm \
-p 8082:8080 \
-v $$(pwd)/backup-volume:/dekart/backup-volume \
-e DEKART_MAPBOX_TOKEN=${DEKART_MAPBOX_TOKEN} \
-e DEKART_STORAGE=SNOWFLAKE \
-e DEKART_DATASOURCE=SNOWFLAKE \
-e DEKART_SNOWFLAKE_ACCOUNT_ID=${DEKART_SNOWFLAKE_ACCOUNT_ID} \
-e DEKART_SNOWFLAKE_USER=${DEKART_SNOWFLAKE_USER} \
-e DEKART_SNOWFLAKE_PASSWORD=${DEKART_SNOWFLAKE_PASSWORD} \
-e DEKART_LOG_DEBUG=1 \
-e DEKART_CORS_ORIGIN=null \
-e DEKART_STREAM_TIMEOUT=10 \
-e DEKART_SQLITE_DB_PATH=./dekart.db \
-e DEKART_SNOWFLAKE_STAGE=DEKART_DEV.PUBLIC.DEKART_DEV \
-e DEKART_BACKUP_FREQUENCY_MIN=5 \
${SNOWPARK_IMAGE_NAME}
snowpark-tag:
docker tag ${SNOWPARK_IMAGE_NAME} ${SNOWPARK_REPO_URL}/${SNOWPARK_IMAGE_NAME}
snowpark-docker-login:
docker login ${SNOWPARK_REPO_URL} -u ${DEKART_SNOWFLAKE_USER} -p ${DEKART_SNOWFLAKE_PASSWORD}
snowpark-docker-push:
docker push ${SNOWPARK_REPO_URL}/${SNOWPARK_IMAGE_NAME}
snowpark-spec:
snowsql -c ${SNOWSQL_CONNECTION} -q "PUT file://$(shell pwd)/snowpark/service.yaml @dekart_app.napp.app_stage overwrite=true auto_compress=false"
snowsql -c ${SNOWSQL_CONNECTION} -q "PUT file://$(shell pwd)/snowpark/setup.sql @dekart_app.napp.app_stage overwrite=true auto_compress=false"
snowsql -c ${SNOWSQL_CONNECTION} -q "PUT file://$(shell pwd)/snowpark/manifest.yml @dekart_app.napp.app_stage overwrite=true auto_compress=false"
snowsql -c ${SNOWSQL_CONNECTION} -q "PUT file://$(shell pwd)/snowpark/readme.md @dekart_app.napp.app_stage overwrite=true auto_compress=false"
snowpark-patch:
snowsql -c ${SNOWSQL_CONNECTION} -q "alter application package dekart_app_pkg ADD PATCH FOR VERSION v1 using @dekart_app.napp.app_stage;"
snowpark: snowpark-build snowpark-tag snowpark-docker-push snowpark-spec snowpark-patch
docker-test:
docker buildx build --tag ${DEKART_DOCKER_E2E_TAG} -o type=image -f ./Dockerfile --target e2etest .
docker run -it --rm \
-v ${GOOGLE_APPLICATION_CREDENTIALS}:${GOOGLE_APPLICATION_CREDENTIALS} \
-v $$(pwd)/cypress/videos:/dekart/cypress/videos/ \
-v $$(pwd)/cypress/screenshots:/dekart/cypress/screenshots/ \
-p 3000:3000 \
--env-file .env.snowflake-sqlite \
-e DEKART_PORT=3000 \
-e CYPRESS_CI=1 \
-e TEST_SPEC=/dekart/cypress/e2e/snowflake/happyPath.cy.js \
-e DEKART_SQLITE_DB_PATH=/dekart/dekart.db \
-e DEKART_STATIC_FILES=./build \
${DEKART_DOCKER_E2E_TAG}
docker: # build docker for local use
docker buildx build --tag ${DEKART_DOCKER_DEV_TAG} -o type=image --platform=linux/amd64 -f ./Dockerfile .
up-and-down:
@set -e; \
cleanup() { docker compose --env-file .env --profile local down --volumes --remove-orphans; }; \
docker compose --env-file .env --profile local up db db-tls adminer & pid=$$!; \
trap 'kill $$pid 2>/dev/null || true; cleanup; exit 0' INT TERM; \
wait $$pid || true; \
cleanup
up-and-down-oidc:
docker compose --env-file .env.oidc --profile oidc up db adminer keycloak oauth2-proxy; docker compose --env-file .env.oidc --profile oidc down --volumes
cloud:
docker compose --env-file .env.cloud --profile cloud up; docker compose --profile cloud down --volumes
up:
docker compose --env-file .env --profile local up
down:
docker compose --env-file .env --profile local down --volumes
cloudsql:
docker compose --env-file .env --profile cloudsql up
sqlite:
docker-compose --env-file .env --profile sqlite up
expire-local-trials:
@case "$(LOCAL_DEV_POSTGRES_HOST)" in localhost|127.0.0.1|"") ;; *) echo "Refusing to expire trials on non-local Postgres host: $(LOCAL_DEV_POSTGRES_HOST)"; exit 1 ;; esac
@PGPASSWORD="$(LOCAL_DEV_POSTGRES_PASSWORD)" "$(PSQL)" \
-h "$(LOCAL_DEV_POSTGRES_HOST)" \
-p "$(LOCAL_DEV_POSTGRES_PORT)" \
-U "$(LOCAL_DEV_POSTGRES_USER)" \
-d "$(LOCAL_DEV_POSTGRES_DB)" \
-v ON_ERROR_STOP=1 \
-Atc "WITH updated AS (UPDATE subscription_log SET trial_ends_at = NOW() - INTERVAL '1 minute' WHERE plan_type = 6 RETURNING 1) SELECT count(*) || ' trial subscription rows expired' FROM updated;"
define run_server
@echo "Releasing local dev port 8080..."; \
pids="$$(lsof -tiTCP:8080 -sTCP:LISTEN)"; \
if [ -n "$$pids" ]; then \
kill -9 $$pids; \
echo "Force-stopped listeners: $$pids"; \
else \
echo "No listeners on 8080"; \
fi; \
set -a; \
. $(1); \
set +a; \
go run ./src/server/main.go
endef
# Rule for the default .env file or custom env file passed as argument
# Usage: make server -> uses .env
# make server .env.cloud -> uses .env.cloud
server:
$(call run_server,$(or $(filter-out server,$(MAKECMDGOALS)),.env))
client:
@echo "Releasing local dev port 3000..."; \
pids="$$(lsof -tiTCP:3000 -sTCP:LISTEN)"; \
if [ -n "$$pids" ]; then \
kill -9 $$pids; \
echo "Force-stopped listeners: $$pids"; \
else \
echo "No listeners on 3000"; \
fi; \
npm start
# Dummy target to prevent Make from trying to build .env files as targets
# This pattern rule makes .env* targets as no-ops that are always "up to date"
.env%:
@:
npm:
npm i --legacy-peer-deps
prerelease:
npm version prerelease --preid=rc
preminor:
npm version preminor --preid=rc
premajor:
npm version premajor --preid=rc
prepatch:
npm version prepatch --preid=rc
version:
npm version $(MAKECMDGOALS)
minor: version
patch: version
patch: version
test:
go test -v -count=1 ./src/server/**/
# License key helpers (offline JWT license keys).
#
# Generates an RSA keypair used to sign license tokens:
# - Private key MUST be kept secret (never commit).
# - Public key can be embedded in the binary for verification.
# Prefer existing ./keys directory if present, otherwise default to ./license-keys.
LICENSE_KEYS_DIR ?= $(if $(wildcard ./keys),./keys,./license-keys)
LICENSE_PRIVATE_KEY ?= $(LICENSE_KEYS_DIR)/license-private.pem
LICENSE_PUBLIC_KEY ?= $(LICENSE_KEYS_DIR)/license-public.pem
license-keygen:
@set -e; \
mkdir -p "$(LICENSE_KEYS_DIR)"; \
if [ -f "$(LICENSE_PRIVATE_KEY)" ] || [ -f "$(LICENSE_PUBLIC_KEY)" ]; then \
echo "Refusing to overwrite existing key(s)."; \
echo "Delete them manually if you really want to re-generate:"; \
echo " rm -f \"$(LICENSE_PRIVATE_KEY)\" \"$(LICENSE_PUBLIC_KEY)\""; \
exit 1; \
fi; \
openssl genrsa -out "$(LICENSE_PRIVATE_KEY)" 2048; \
openssl rsa -in "$(LICENSE_PRIVATE_KEY)" -pubout -out "$(LICENSE_PUBLIC_KEY)"; \
echo "Generated:"; \
echo " $(LICENSE_PRIVATE_KEY) (KEEP SECRET; do not commit)"; \
echo " $(LICENSE_PUBLIC_KEY) (public; can be embedded/committed)"
# Issue a license token (prints DEKART_LICENSE_KEY=...).
# Usage:
# make license-issue EMAIL=me@company.com
# make license-issue EMAIL=me@company.com DAYS=14
# make license-issue EMAIL=me@company.com EXPIRE_FROM_NOW_SECONDS=3600
# make license-issue EMAIL=me@company.com EXPIRE_FROM_NOW_SECONDS=-3600
EMAIL ?=
DAYS ?= 0
EXPIRE_FROM_NOW_SECONDS ?=
license-issue:
@test -n "$(EMAIL)" || (echo "EMAIL is required. Example: make license-issue EMAIL=me@company.com"; exit 1)
@test -f "$(LICENSE_PRIVATE_KEY)" || (echo "Missing private key: $(LICENSE_PRIVATE_KEY). Run: make license-keygen"; exit 1)
@go run ./scripts/license-issue.go --email "$(EMAIL)" --private-key "$(LICENSE_PRIVATE_KEY)" \
$(if $(filter-out 0,$(DAYS)),--days "$(DAYS)",) \
$(if $(strip $(EXPIRE_FROM_NOW_SECONDS)),--expire-from-now-seconds "$(EXPIRE_FROM_NOW_SECONDS)",)
# GitHub self-hosted runner helpers (local laptop runner).
# Usage:
# make runner-register # installs runner if needed, then registers
# make runner-start
# make runner-service-install
# make runner-service-start
runner-install:
@if [ -x "$(RUNNER_DIR)/config.sh" ]; then \
echo "Runner already installed at $(RUNNER_DIR)"; \
exit 0; \
fi
@set -e; \
OS=$$(uname -s); \
ARCH=$$(uname -m); \
case "$$OS" in \
Darwin) OS_TAG="osx" ;; \
Linux) OS_TAG="linux" ;; \
*) echo "Unsupported OS: $$OS"; exit 1 ;; \
esac; \
case "$$ARCH" in \
x86_64|amd64) ARCH_TAG="x64" ;; \
arm64|aarch64) ARCH_TAG="arm64" ;; \
*) echo "Unsupported architecture: $$ARCH"; exit 1 ;; \
esac; \
PKG="actions-runner-$${OS_TAG}-$${ARCH_TAG}-$(RUNNER_VERSION).tar.gz"; \
URL="https://github.com/actions/runner/releases/download/v$(RUNNER_VERSION)/$$PKG"; \
echo "Installing GitHub runner $(RUNNER_VERSION) from $$URL"; \
mkdir -p "$(RUNNER_DIR)"; \
cd "$(RUNNER_DIR)"; \
curl -fL "$$URL" -o "$$PKG"; \
tar xzf "$$PKG"; \
rm -f "$$PKG"; \
test -x "$(RUNNER_DIR)/config.sh" || (echo "Runner install failed"; exit 1); \
echo "Runner installed in $(RUNNER_DIR)"
runner-register: runner-install
@test -n "$(GITHUB_RUNNER_TOKEN)" || (echo "GITHUB_RUNNER_TOKEN (or RUNNER_TOKEN) is required. Add it to .env or pass on command line."; exit 1)
@cd "$(RUNNER_DIR)" && ./config.sh \
--url "$(RUNNER_URL)" \
--token "$(GITHUB_RUNNER_TOKEN)" \
--labels "$(RUNNER_LABELS)" \
--name "$(RUNNER_NAME)" \
--unattended \
--replace
runner-start:
@test -x "$(RUNNER_DIR)/run.sh" || (echo "Missing $(RUNNER_DIR)/run.sh. Install and register runner first."; exit 1)
cd "$(RUNNER_DIR)" && ./run.sh
runner-stop:
@pkill -f "$(RUNNER_DIR)/bin/Runner.Listener" || true
runner-status:
@pgrep -af "$(RUNNER_DIR)/bin/Runner.Listener" || echo "Runner is not running."
runner-service-install:
@test -x "$(RUNNER_DIR)/svc.sh" || (echo "Missing $(RUNNER_DIR)/svc.sh. Install actions runner first."; exit 1)
cd "$(RUNNER_DIR)" && sudo ./svc.sh install
runner-service-start:
@test -x "$(RUNNER_DIR)/svc.sh" || (echo "Missing $(RUNNER_DIR)/svc.sh. Install actions runner first."; exit 1)
cd "$(RUNNER_DIR)" && sudo ./svc.sh start
runner-service-stop:
@test -x "$(RUNNER_DIR)/svc.sh" || (echo "Missing $(RUNNER_DIR)/svc.sh. Install actions runner first."; exit 1)
cd "$(RUNNER_DIR)" && sudo ./svc.sh stop
runner-service-status:
@test -x "$(RUNNER_DIR)/svc.sh" || (echo "Missing $(RUNNER_DIR)/svc.sh. Install actions runner first."; exit 1)
cd "$(RUNNER_DIR)" && sudo ./svc.sh status
# Simplified foreground runner command (keeps terminal open with live logs).
github-runner: runner-start