mirror of
https://github.com/teableio/teable
synced 2024-11-21 23:04:16 +00:00
9b4f9eabad
* feat: upgrade Node, add Redis caching & WebSocket via redis-pubsub * fix: optimize `X-Request-Id` generation rules * ci: add db-migrate image build and push --------- Co-authored-by: pengap <penganpingprivte@gmail.com>
302 lines
12 KiB
Makefile
302 lines
12 KiB
Makefile
SHELL := /usr/bin/env bash
|
|
|
|
# define standard colors
|
|
ifneq (,$(findstring xterm,${TERM}))
|
|
BLACK := $(shell tput -Txterm setaf 0)
|
|
RED := $(shell tput -Txterm setaf 1)
|
|
GREEN := $(shell tput -Txterm setaf 2)
|
|
YELLOW := $(shell tput -Txterm setaf 3)
|
|
LIGHTPURPLE := $(shell tput -Txterm setaf 4)
|
|
PURPLE := $(shell tput -Txterm setaf 5)
|
|
BLUE := $(shell tput -Txterm setaf 6)
|
|
WHITE := $(shell tput -Txterm setaf 7)
|
|
RESET := $(shell tput -Txterm sgr0)
|
|
else
|
|
BLACK := ""
|
|
RED := ""
|
|
GREEN := ""
|
|
YELLOW := ""
|
|
LIGHTPURPLE := ""
|
|
PURPLE := ""
|
|
BLUE := ""
|
|
WHITE := ""
|
|
RESET := ""
|
|
endif
|
|
|
|
ENV_PATH ?= apps/nextjs-app
|
|
|
|
DOCKER_COMPOSE ?= docker compose
|
|
|
|
DOCKER_COMPOSE_ENV_FILE := $(wildcard ./dockers/.env)
|
|
COMPOSE_FILES := $(wildcard ./dockers/*.yml)
|
|
COMPOSE_FILE_ARGS := --env-file $(DOCKER_COMPOSE_ENV_FILE) $(foreach yml,$(COMPOSE_FILES),-f $(yml))
|
|
|
|
NETWORK_MODE ?= teablenet
|
|
CI_JOB_ID ?= 0
|
|
CI ?= 0
|
|
|
|
# Timeout used to await services to become healthy
|
|
TIMEOUT ?= 300
|
|
|
|
SCRATCH ?= /tmp
|
|
|
|
UNAME_S := $(shell uname -s)
|
|
|
|
# prisma database url defaults
|
|
SQLITE_PRISMA_DATABASE_URL ?= file:../../db/main.db
|
|
# set param statement_cache_size=1 to avoid query error `ERROR: cached plan must not change result type` after alter column type (modify field type)
|
|
POSTGES_PRISMA_DATABASE_URL ?= postgresql://teable:teable@127.0.0.1:5432/teable?schema=public\&statement_cache_size=1
|
|
|
|
# If the first make argument is "start", "stop"...
|
|
ifeq (docker.start,$(firstword $(MAKECMDGOALS)))
|
|
SERVICE_TARGET = true
|
|
else ifeq (docker.stop,$(firstword $(MAKECMDGOALS)))
|
|
SERVICE_TARGET = true
|
|
else ifeq (docker.restart,$(firstword $(MAKECMDGOALS)))
|
|
SERVICE_TARGET = true
|
|
else ifeq (docker.up,$(firstword $(MAKECMDGOALS)))
|
|
SERVICE_TARGET = true
|
|
else ifeq (docker.build,$(firstword $(MAKECMDGOALS)))
|
|
SERVICE_TARGET = true
|
|
else ifeq (build-nocache,$(firstword $(MAKECMDGOALS)))
|
|
SERVICE_TARGET = true
|
|
else ifeq (docker.await,$(firstword $(MAKECMDGOALS)))
|
|
SERVICE_TARGET = true
|
|
else ifeq (docker.run,$(firstword $(MAKECMDGOALS)))
|
|
RUN_TARGET = true
|
|
else ifeq (docker.integration,$(firstword $(MAKECMDGOALS)))
|
|
INTEGRATION_TARGET = true
|
|
endif
|
|
|
|
ifdef SERVICE_TARGET
|
|
# .. then use the rest as arguments for the make target
|
|
SERVICE := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
|
|
# ...and turn them into do-nothing targets
|
|
$(eval $(SERVICE):;@:)
|
|
else ifdef RUN_TARGET
|
|
# Isolate second argument as service, the rest is arguments for run command
|
|
SERVICE := $(wordlist 2, 2, $(MAKECMDGOALS))
|
|
SERVICE_ARGS := $(wordlist 3, $(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
|
|
else ifdef INTEGRATION_TARGET
|
|
# Isolate second argument as integration module, the rest as arguments
|
|
INTEGRATION_MODULE := $(wordlist 2, 2, $(MAKECMDGOALS))
|
|
$(eval $(INTEGRATION_MODULE):;@:)
|
|
INTEGRATION_ARGS := $(wordlist 3, $(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
|
|
$(eval $(INTEGRATION_ARGS):;@:)
|
|
endif
|
|
|
|
#
|
|
# Never use the network=host mode when running CI jobs, and add extra
|
|
# distinguishing identifiers to the network name and container names to
|
|
# prevent collisions with jobs from the same project running at the same
|
|
# time.
|
|
#
|
|
ifneq ($(CI_JOB_ID),)
|
|
NETWORK_MODE := teablenet-$(CI_JOB_ID)
|
|
endif
|
|
|
|
ifeq ($(CI),0)
|
|
export NODE_ENV = development
|
|
endif
|
|
|
|
|
|
ifeq ($(UNAME_S),Linux)
|
|
DOCKER_GID ?= $(shell getent group docker | cut -d: -f 3)
|
|
else ifeq ($(UNAME_S),Darwin)
|
|
DOCKER_GID ?= $(shell id -g)
|
|
else
|
|
$(error Sorry, '${UNAME_S}' is not supported yet)
|
|
endif
|
|
|
|
|
|
DOCKER_COMPOSE_ARGS := DOCKER_UID=$(shell id -u) \
|
|
DOCKER_GID=$(DOCKER_GID) \
|
|
NETWORK_MODE=$(NETWORK_MODE)
|
|
|
|
|
|
define print_db_mode_options
|
|
@echo -e "\nSelect a database to start.\n"
|
|
@echo -e "1)sqlite Lightweight embedded, ideal for mobile and embedded systems, simple, resource-efficient, easy integration (default database)"
|
|
@echo -e "2)postges(pg) Powerful and scalable, suitable for complex enterprise needs, highly customizable, rich community support\n"
|
|
endef
|
|
|
|
define print_db_push_options
|
|
@echo -e "The 'db pull' command connects to your database and adds Prisma models to your Prisma schema that reflect the current database schema.\n"
|
|
@echo -e "1) sqlite"
|
|
@echo -e "2) postges(pg)\n"
|
|
endef
|
|
|
|
.PHONY: db-mode sqlite.mode postgres.mode gen-prisma-schema gen-sqlite-prisma-schema gen-postgres-prisma-schema
|
|
.DEFAULT_GOAL := help
|
|
|
|
docker.create.network:
|
|
ifneq ($(NETWORK_MODE),host)
|
|
@docker network inspect $(NETWORK_MODE) &> /dev/null || ([ $$? -ne 0 ] && docker network create $(NETWORK_MODE))
|
|
$(info ${GREEN}network $(NETWORK_MODE) create success${RESET})
|
|
endif
|
|
|
|
docker.rm.network:
|
|
ifneq ($(NETWORK_MODE),host)
|
|
@docker network inspect $(NETWORK_MODE) &> /dev/null && ([ $$? -eq 0 ] && docker network rm $(NETWORK_MODE)) || true
|
|
$(warning ${GREEN}network $(NETWORK_MODE) removed${RESET})
|
|
endif
|
|
|
|
docker.build:
|
|
$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) build --parallel --progress=plain $(SERVICE)
|
|
|
|
docker.run: docker.create.network
|
|
$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) run -T --no-deps --rm $(SERVICE) $(SERVICE_ARGS)
|
|
|
|
docker.up: docker.create.network
|
|
@$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) up --no-recreate -d $(SERVICE)
|
|
|
|
docker.down: docker.rm.network
|
|
$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) down
|
|
|
|
docker.start:
|
|
$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) start $(SERVICE)
|
|
|
|
docker.stop:
|
|
$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) stop $(SERVICE)
|
|
|
|
docker.restart:
|
|
make docker.stop $(SERVICE)
|
|
make docker.start $(SERVICE)
|
|
|
|
TIME := 0
|
|
docker.await: ## max timeout of 300
|
|
@time=$(TIME); \
|
|
for i in $(SERVICE); do \
|
|
current_service=$$($(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) ps -q $${i}); \
|
|
if [ -z "$${current_service}" ]; then \
|
|
continue; \
|
|
fi; \
|
|
service_has_health=$$(docker inspect -f '{{.State.Health.Status}}' $${current_service}); \
|
|
if [ -z "$${service_has_health}" ]; then \
|
|
continue; \
|
|
fi; \
|
|
while [ "$$(docker inspect -f '{{.State.Health.Status}}' $${current_service})" != "healthy" ] ; do \
|
|
sleep 1; \
|
|
time=$$(expr $$time + 1); \
|
|
if [ $${time} -gt $(TIMEOUT) ]; then \
|
|
echo "${YELLOW}Timeout reached waiting for $${i} to become healthy${RESET}"; \
|
|
docker logs $${i}; \
|
|
exit 1; \
|
|
fi; \
|
|
done; \
|
|
echo "${GREEN}Service $${i} is healthy${RESET}"; \
|
|
done
|
|
|
|
docker.status:
|
|
$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) ps
|
|
|
|
docker.images:
|
|
$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) images
|
|
|
|
sqlite.integration.test:
|
|
@export PRISMA_DATABASE_URL='file:../../db/main.db'; \
|
|
make sqlite.mode; \
|
|
pnpm -F "./packages/**" run build; \
|
|
pnpm g:test-e2e
|
|
|
|
postgres.integration.test: docker.create.network
|
|
@TEST_PG_CONTAINER_NAME=teable-postgres-$(CI_JOB_ID); \
|
|
docker rm -fv $$TEST_PG_CONTAINER_NAME | true; \
|
|
$(DOCKER_COMPOSE_ARGS) $(DOCKER_COMPOSE) $(COMPOSE_FILE_ARGS) run -p 25432:5432 -d -T --no-deps --rm --name $$TEST_PG_CONTAINER_NAME teable-postgres; \
|
|
chmod +x scripts/wait-for; \
|
|
scripts/wait-for 127.0.0.1:25432 --timeout=15 -- echo 'pg database started successfully' && \
|
|
export PRISMA_DATABASE_URL=postgresql://teable:teable@127.0.0.1:25432/e2e_test_teable?schema=public\&statement_cache_size=1 && \
|
|
make postgres.mode && \
|
|
pnpm -F "./packages/**" run build && \
|
|
pnpm g:test-e2e && \
|
|
docker rm -fv $$TEST_PG_CONTAINER_NAME
|
|
|
|
gen-sqlite-prisma-schema:
|
|
@cd ./packages/db-main-prisma; \
|
|
echo '{ "PRISMA_PROVIDER": "sqlite" }' | pnpm mustache - ./prisma/template.prisma > ./prisma/sqlite/schema.prisma
|
|
@echo 'generate【 prisma/sqlite/schema.prisma 】success.'
|
|
|
|
gen-postgres-prisma-schema:
|
|
@cd ./packages/db-main-prisma; \
|
|
echo '{ "PRISMA_PROVIDER": "postgres" }' | pnpm mustache - ./prisma/template.prisma > ./prisma/postgres/schema.prisma
|
|
@echo 'generate【 prisma/postgres/schema.prisma 】success.'
|
|
|
|
gen-prisma-schema: gen-sqlite-prisma-schema gen-postgres-prisma-schema ## Generate 'schema.prisma' files for all versions of the system
|
|
|
|
sqlite-db.push: ## db.push by sqlite
|
|
@cd ./packages/db-main-prisma; \
|
|
pnpm prisma-db-push --schema ./prisma/sqlite/schema.prisma
|
|
|
|
postgres-db.push: ## db.push by postgres
|
|
@cd ./packages/db-main-prisma; \
|
|
pnpm prisma-db-push --schema ./prisma/postgres/schema.prisma
|
|
|
|
db.push: ## connects to your database and adds Prisma models to your Prisma schema that reflect the current database schema.
|
|
$(print_db_push_options)
|
|
@read -p "Enter a command: " command; \
|
|
if [ "$$command" = "1" ] || [ "$$command" = "sqlite" ]; then \
|
|
make gen-sqlite-prisma-schema; \
|
|
make sqlite-db.push; \
|
|
elif [ "$$command" = "2" ] || [ "$$command" = "postges" ] || [ "$$command" = "pg" ]; then \
|
|
make gen-postgres-prisma-schema; \
|
|
make postgres-db.push; \
|
|
else echo "Unknown command."; fi
|
|
|
|
sqlite-db-migration:
|
|
@_MIGRATION_NAME=$(if $(_MIGRATION_NAME),$(_MIGRATION_NAME),`read -p "Enter name of the migration (sqlite): " migration_name; echo $$migration_name`); \
|
|
make gen-sqlite-prisma-schema; \
|
|
PRISMA_DATABASE_URL=file:../../db/.shadow/main.db \
|
|
pnpm -F @teable/db-main-prisma prisma-migrate dev --schema ./prisma/sqlite/schema.prisma --name $$_MIGRATION_NAME
|
|
|
|
postgres-db-migration:
|
|
@_MIGRATION_NAME=$(if $(_MIGRATION_NAME),$(_MIGRATION_NAME),`read -p "Enter name of the migration (postgres): " migration_name; echo $$migration_name`); \
|
|
make gen-postgres-prisma-schema; \
|
|
PRISMA_DATABASE_URL=postgresql://teable:teable@127.0.0.1:5432/teable?schema=shadow \
|
|
pnpm -F @teable/db-main-prisma prisma-migrate dev --schema ./prisma/postgres/schema.prisma --name $$_MIGRATION_NAME
|
|
|
|
db-migration: ## Reruns the existing migration history in the shadow database in order to detect schema drift (edited or deleted migration file, or a manual changes to the database schema)
|
|
@read -p "Enter name of the migration: " migration_name; \
|
|
make sqlite-db-migration _MIGRATION_NAME=$$migration_name; \
|
|
make postgres-db-migration _MIGRATION_NAME=$$migration_name
|
|
|
|
sqlite.mode: ## sqlite.mode
|
|
@cd ./packages/db-main-prisma; \
|
|
pnpm prisma-generate --schema ./prisma/sqlite/schema.prisma; \
|
|
pnpm prisma-migrate deploy --schema ./prisma/sqlite/schema.prisma
|
|
|
|
postgres.mode: ## postgres.mode
|
|
@cd ./packages/db-main-prisma; \
|
|
pnpm prisma-generate --schema ./prisma/postgres/schema.prisma; \
|
|
pnpm prisma-migrate deploy --schema ./prisma/postgres/schema.prisma
|
|
|
|
# Override environment variable files based on variables
|
|
RUN_DB_MODE ?= sqlite
|
|
FILE_ENV_PATHS = $(ENV_PATH)/.env.development* $(ENV_PATH)/.env.test*
|
|
switch.prisma.env:
|
|
ifeq ($(CI)-$(RUN_DB_MODE),0-sqlite)
|
|
@for file in $(FILE_ENV_PATHS); do \
|
|
sed -i '' 's~^PRISMA_DATABASE_URL=.*~PRISMA_DATABASE_URL=$(SQLITE_PRISMA_DATABASE_URL)~' $$file; \
|
|
done
|
|
else ifeq ($(CI)-$(RUN_DB_MODE),0-postges)
|
|
@for file in $(FILE_ENV_PATHS); do \
|
|
sed -i '' 's~^PRISMA_DATABASE_URL=.*~PRISMA_DATABASE_URL=$(POSTGES_PRISMA_DATABASE_URL)~' $$file; \
|
|
done
|
|
endif
|
|
|
|
switch-db-mode: ## Switch Database environment
|
|
$(print_db_mode_options)
|
|
@read -p "Enter a command: " command; \
|
|
if [ "$$command" = "1" ] || [ "$$command" = "sqlite" ]; then \
|
|
make switch.prisma.env RUN_DB_MODE=sqlite; \
|
|
make sqlite.mode; \
|
|
elif [ "$$command" = "2" ] || [ "$$command" = "postges" ] || [ "$$command" = "pg" ]; then \
|
|
make switch.prisma.env RUN_DB_MODE=postges; \
|
|
make docker.up teable-postgres; \
|
|
make docker.await teable-postgres; \
|
|
make postgres.mode; \
|
|
else \
|
|
echo "Unknown command."; fi
|
|
|
|
help: ## show this help
|
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|