fradrive/Makefile
2024-11-01 07:05:29 +01:00

506 lines
17 KiB
Makefile

include .gnumake/*.Mak
SHELL=bash
# MAKE=make -d
export CONTAINER_COMMAND ?= podman
export CONTAINER_BGRUN ?= $(CONTAINER_COMMAND) run -dit --network=host --replace
export CONTAINER_FGRUN ?= $(CONTAINER_COMMAND) run -it --network=host --replace
#export CONTAINER_NAME ?= $(FRADRIVE_SERVICE)
export ENTRYPOINT
export IN_CONTAINER ?= false
export IN_CI ?= false
export SINGLETON
export WATCH
export UNIWORXDB_OPTS ?= -cf
export CONTAINER_ID
export FRADRIVE_SERVICE
export SERVICE_VARIANT
export DEV_PORT_HTTP
export DEV_PORT_HTTPS
export HOOGLE_PORT
export IMAGE_REGISTRY = docker.io
export MEMCACHED_IMAGE = $(IMAGE_REGISTRY)/memcached:latest
export MINIO_IMAGE = $(IMAGE_REGISTRY)/minio/minio:latest
export MAILDEV_IMAGE = $(IMAGE_REGISTRY)/maildev/maildev:latest # TODO: needs different port than 1025 to avoid conflicts
export DEVELOP
export CONTAINER_FILE
export CONTAINER_FILE_CONTENT
export LOGSIZE ?= 1024
export PROD ?= false
ifneq ($(PROD),true)
export --DEVELOPMENT=--flag uniworx:dev
endif
# HELP HEADER START
# To see the definition of all available targets, take a look into the Makefile.
# Targets starting with '--' are not meant to be directly called.
# If you want to do so anyway please use 'make -- --target' to avoid '--target' being treated as option to 'make'.
#
#
# Targets meant to be used by humans are:
# HELP HEADER END
###########################
##### GENERAL TARGETS #####
.PHONY: help
# HELP: print out this help message
help:
@if [ -z "$$(which perl 2>/dev/null)" ] ; then \
$(CONTAINER_FGRUN) .:/mnt 'debian:12.5' '/mnt/utils/makehelp.pl' '/mnt/Makefile' ; \
else \
utils/makehelp.pl Makefile ; \
fi
.PHONY: clean
# HELP: stop all running containers and remove all compilation results in the directory (but leave images including dependencies unharmed)
clean:
$(MAKE) stop
-rm -rf node_modules .npm .cache assets/icons assets/favicons static well-known config/manifest.json
-rm -rf .stack-work .stack-work-run .stack-work-test .stack-work-doc .stack-work.lock
-rm -rf bin .Dockerfile develop
-$(CONTAINER_COMMAND) container prune --force
.PHONY: clean-all
# HELP: like clean but with full container, image, and volume prune
clean-all: clean
-rm -rf .stack
-$(CONTAINER_COMMAND) system prune --all --force --volumes
-$(CONTAINER_COMMAND) image prune --all --force
-$(CONTAINER_COMMAND) volume prune --force
.PHONY: release
# HELP: create, commit and push a new release
release:
./.gitlab-ci/version.pl -changelog CHANGELOG.md
git add CHANGELOG.md
VERSION=`.gitlab-ci/version.pl`
git tag $${VERSION}
git commit -m "chore(release): $${VERSION}"
git push
.PHONY: %-shell
# HELP: launch shell (bash) inside a currently running container
%-shell: --%-shell;
--shell:
$(CONTAINER_COMMAND) exec -it $(EXEC_OPTS) fradrive.$(CURR_DEV).$* $(if $(ENTRYPOINT),$(ENTRYPOINT),/bin/bash)
compile-%: --%-compile;
##### GENERAL TARGETS #####
###########################
##############################################
##### SERVICE DEPENDENCIES AND VARIABLES #####
--frontend-%: FRADRIVE_SERVICE=frontend
--frontend-%: SERVICE_VARIANT=frontend
--frontend-%: SINGLETON = false
--frontend-%: WATCH = false
--frontend-%:
# TODO --containerized-% is not yet working; comment this in again as soon as it does
# $(MAKE) -- --containerized-static --containerized-well-known
$(MAKE) -- --$*
--backend-%: FRADRIVE_SERVICE=backend
--backend-%: SERVICE_VARIANT=backend
--backend-%: BASE_PORTS = "DEV_PORT_HTTP=3000" "DEV_PORT_HTTPS=3443"
--backend-%: SINGLETON = false
--backend-%:
$(MAKE) -- --frontend-compile
$(MAKE) -- --$*
--hoogle-%: FRADRIVE_SERVICE=backend
--hoogle-%: SERVICE_VARIANT=hoogle
--hoogle-%: BASE_PORTS = "HOOGLE_PORT=8081"
--hoogle-%: SINGLETON = true
--hoogle-%:
$(MAKE) -- --$*
# --uniworxdb was --db in old versions
--uniworxdb-%: FRADRIVE_SERVICE=backend
--uniworxdb-%: SERVICE_VARIANT=uniworxdb
--uniworxdb-%:
$(MAKE) -- --$*
--minio-%: FRADRIVE_SERVICE=minio
--minio-%: SERVICE_VARIANT=minio
--minio-%:
$(MAKE) -- --$*
--memcached-%: FRADRIVE_SERVICE=memcached
--memcached-%: SERVICE_VARIANT=memcached
--memcached-%:
$(MAKE) -- --$*
# --postgres was --database in old versions
--postgres-%: BASE_PORTS = "PGPORT=5432"
--postgres-%: SINGLETON = true
--postgres-%:
$(MAKE) -- --$*
##### SERVICE DEPENDENCIES AND VARIABLES #####
##############################################
############################################
##### UNIFIED FRONTEND/BACKEND TARGETS #####
.PHONY: start
# HELP: start database services, frontend and backend
start: start-database start-memcached start-minio start-frontend start-backend;
.PHONY: compile
# HELP: compile frontend and backend
compile:
$(MAKE) compile-frontend
$(MAKE) compile-backend
--compile-%: --checkvarsset --develop --%
.PHONY: lint
# HELP: lint frontend and backend
lint: lint-frontend lint-backend;
.PHONY: test
# HELP: test frontend, backend, and check internationalization
test: start-database test-frontend test-backend i18n-check;
##### UNIFIED FRONTEND/BACKEND TARGETS #####
############################################
--checkvarsset:
@:
ifndef ($(FRADRIVE_SERVICE))
>&2 echo "Variable FRADRIVE_SERVICE is not set; this hints to an internal error in the Makefile unless you have manually requested a '--'-target"
exit 1
endif
ifndef ($(SERVICE_VARIANT))
>&2 echo "Variable SERVICE_VARIANT is not set; this hints to an internal error in the Makefile unless you have manually requested a '--'-target"
exit 1
endif
ifndef ($(DEVELOP))
>&2 echo "Variable DEVELOP is not set; this hints to an internal error in the Makefile unless you have manually requested a '--'-target"
exit 1
endif
ifndef ($(CONTAINER_FILE))
>&2 echo "Variable CONTAINER_FILE is not set; this hints to an internal error in the Makefile unless you have manually requested a '--'-target"
exit 1
endif
############################
##### FRONTEND TARGETS #####
#--frontend-%: --image-build --containerized---%-frontend;
#--%-frontend: --containerized-static-frontend --containerized-well-known-frontend
#--frontend-start: static
# npm run start
ifeq ($(SERVICE_VARIANT), frontend)
--start: --checkvarsset
npm run start
# HELP(compile-frontend): compile frontend
--compile: static well-known --checkvarsset;
# HELP(lint-frontend): lint frontend
--lint: eslint.config.js --checkvarsset
npx -- eslint frontend/src $(FIX)
@echo Hooray! There are no hints.
# HELP(test-frontend): test frontend
--test: karma.conf.cjs --checkvarsset
@echo Karma frontend tests are currently broken after npm update and have therefor been temporarily disabled.
# npx -- karma start --conf karma.conf.cjs $(WATCH)
endif
node_modules: package.json package-lock.json
npm ci --cache .npm --prefer-offline
package-lock.json: package.json
npm install --cache .npm --prefer-offline
assets: assets/favicons assets/icons;
assets/favicons:
./utils/faviconize.pl assets/favicon.svg long assets/favicons
assets/icons: node_modules assets/icons-src/fontawesome.json
./utils/renamer.pl node_modules/@fortawesome/fontawesome-free/svgs/solid assets/icons-src/fontawesome.json assets/icons/fradrive
./utils/renamer.pl node_modules/@fortawesome/fontawesome-free/svgs/regular assets/icons-src/fontawesome.json assets/icons/fradrive
cp assets/icons-src/*.svg assets/icons/fradrive
static: node_modules assets esbuild.config.mjs
npm run build
well-known: static;
##### FRONTEND TARGETS #####
############################
###########################
##### BACKEND TARGETS #####
ifeq ($(SERVICE_VARIANT), backend)
--start: --checkvarsset
DEV_PORT_HTTP=`cat $(CONTAINER_FILE) | grep 'DEV_PORT_HTTP=' | sed 's/DEV_PORT_HTTP=//'`; \
DEV_PORT_HTTPS=`cat $(CONTAINER_FILE) | grep 'DEV_PORT_HTTPS=' | sed 's/DEV_PORT_HTTPS=//'`; \
stack --work-dir=.stack-work-run $(--DEVELOPMENT) exec -- yesod devel -p "$${DEV_PORT_HTTP}" -q "$${DEV_PORT_HTTPS}"
endif
ifeq ($(SERVICE_VARIANT), hoogle)
--start:
HOOGLE_PORT=`cat $(CONTAINER_FILE) | grep 'HOOGLE_PORT=' | sed 's/HOOGLE_PORT=//'` ; \
echo "${HOOGLE_PORT}" ; \
stack --work-dir=.stack-work-doc hoogle -- server --local --port $${HOOGLE_PORT}
endif
# HELP(compile-backend): compile backend
ifeq ($(SERVICE_VARIANT), backend)
--compile: --checkvarsset
stack build --fast --profile --library-profiling --executable-profiling --flag uniworx:-library-only $(--DEVELOPMENT) --local-bin-path $$(pwd)/bin
# HELP(lint-backend): lint backend
--lint: --checkvarsset
stack build --test --fast --work-dir=.stack-work-test --flag uniworx:library-only $(--DEVELOPMENT) uniworx:test:hlint
# HELP(test-backend): test backend
--test: --checkvarsset
stack build --test --coverage --fast --work-dir=.stack-work-test --flag uniworx:library-only $(--DEVELOPMENT)
endif
# HELP(uniworxdb): clear and fill database. requires running postgres
uniworxdb: --frontend-compile --backend-imagebuild-containerized-uniworxdb-start;
# TODO (db-m-$MIGRATION-backend): apply migration (see src/Model/Migration/Definition.hs for list of available migrations)
ifeq ($(SERVICE_VARIANT), uniworxdb)
--start: .stack
SERVER_SESSION_ACID_FALLBACK=${SERVER_SESSION_ACID_FALLBACK:-true} ; \
AVSPASS=${AVSPASS:-nopasswordset} ; \
stack $(--DEVELOPMENT) exec uniworxdb -- $(UNIWORXDB_OPTS)
endif
.PHONY: .stack
.stack:
if [ "$(IN_CONTAINER)" == "true" ] ; then \
$(MAKE) -- --.stack ; \
else \
$(MAKE) -- --image-run---.stack ; \
fi
--.stack: stack.yaml stack.yaml.lock package.yaml
stack build --fast --only-dependencies
##### BACKEND TARGETS #####
###########################
############################
##### DATABASE TARGETS #####
ifeq ($(SERVICE_VARIANT), postgres)
--containerized-%: docker/database/initdb.sh docker/database/pg_hba.conf docker/database/postgresql.conf docker/database/schema.sql --image-build
$(MAKE) -- --imagerun-$*
else
--containerized-%:
$(MAKE) -- --imagerun-$*
endif
.PHONY: psql
# HELP: enter psql (postgresql) cli inside a currently running database container
psql: ENTRYPOINT=/usr/bin/psql -d uniworx
psql: EXEC_OPTS=--user postgres
psql: --database-shell;
##### DATABASE TARGETS #####
############################
#############################
##### CONTAINER TARGETS #####
#--containerized-%-frontend: FRADRIVE_SERVICE=frontend
#--containerized-%-frontend: SERVICE_VARIANT=frontend
#--containerized-%-frontend: --image-build
# $(MAKE) -- --image-run-$*-frontend
#
#--containerized-%-backend: FRADRIVE_SERVICE=backend
#--containerized-%-backend: SERVICE_VARIANT?=backend
#--containerized-%-backend: --image-build
# $(MAKE) -- --image-run-$*-backend
#--containerized-%-hoogle: FRADRIVE_SERVICE=backend
#--containerized-%-hoogle: SERVICE_VARIANT=hoogle
#--containerized-%-hoogle: --image-build
# $(MAKE) -- --image-run-$*-hoogle-backend
# --containerized-%-minio: FRADRIVE_SERVICE=minio
# --containerized-%-minio: --image-build
# $(MAKE) -- --image-run-$*-minio
ifeq ($(SERVICE_VARIANT), minio)
--containerized-start:
UPLOAD_S3_PORT=`cat $(CONTAINER_FILE) | grep 'UPLOAD_S3_PORT=' | sed 's/UPLOAD_S3_PORT=//'`; \
MINIO_DIR=`mktemp` ; \
./utils/watchcontainerrun.sh "$(CONTAINER_COMMAND)" "$(CONTAINER_FILE)" "" "rm -rf $${MINIO_DIR}" & \
CONTAINER_ID=`$(CONTAINER_BGRUN) --name fradrive.$(CURR_DEV).minio $(MINIO_IMAGE) -- server $${MINIO_DIR} --address=:$${UPLOAD_S3_PORT}` ; \
printf "CONTAINER_ID=$${CONTAINER_ID}\nUPLOAD_S3_PORT=$${UPLOAD_S3_PORT}\nMINIO_DIR=$${MINIO_DIR}" >> $(CONTAINER_FILE)
endif
# --containerized-%-memcached: FRADRIVE_SERVICE=memcached
# --containerized-%-memcached: --image-build
# $(MAKE) -- --image-run-$*-memcached
ifeq ($(SERVICE_VARIANT), memcached)
--containerized-start:
MEMCACHED_PORT=`cat $(CONTAINER_FILE) | grep 'MEMCACHED_PORT=' | sed 's/MEMCACHED_PORT=//'`; \
./utils/watchcontainerrun.sh "$(CONTAINER_COMMAND)" "$(CONTAINER_FILE)" & \
CONTAINER_ID=`$(CONTAINER_BGRUN) --name fradrive.$(CURR_DEV).memcached $(MEMCACHED_IMAGE) --port=$${MEMCACHED_PORT}` ; \
printf "CONTAINER_ID=$${CONTAINER_ID}\nMEMCACHED_PORT=$${MEMCACHED_PORT}" >> $(CONTAINER_FILE)
endif
.PHONY: image-rebuild
# HELP(image-rebuild-{backend,frontend,database,memcached,minio}): force-rebuild the stated docker image
image-rebuild-%:
$(MAKE) -- --image-build FRADRIVE_SERVICE=$* NO_CACHE=--no-cache
--image-build:
rm -f .Dockerfile
ln -s docker/$(FRADRIVE_SERVICE)/Dockerfile .Dockerfile
MOUNT_DIR=/mnt/fradrive; \
PROJECT_DIR=/mnt/fradrive; \
if [ "$(IN_CI)" == "true" ] ; then \
PROJECT_DIR=/fradrive; \
fi; \
if [ "$(IN_CONTAINER)" == "false" ] ; then \
$(CONTAINER_COMMAND) build $(NO_CACHE) -v $(PWD):$${MOUNT_DIR} --env IN_CONTAINER=true --build-arg MOUNT_DIR=$${MOUNT_DIR} --build-arg PROJECT_DIR=$${PROJECT_DIR} --tag fradrive/$(FRADRIVE_SERVICE) --file $(PWD)/.Dockerfile ; \
fi
--imagerun-%: --checkvarsset docker/$(FRADRIVE_SERVICE)/Dockerfile
MOUNT_DIR=/mnt/fradrive; \
if [ "$(IN_CONTAINER)" == "true" ] ; then \
$(MAKE) -- $* ; \
else \
if [ -z "$(CONTAINER_FILE)" ] ; then \
$(CONTAINER_FGRUN) -v $(PWD):$${MOUNT_DIR} --env IN_CONTAINER=true --env FRADRIVE_MAKE_TARGET=$* --env CONTAINER_FILE=$(CONTAINER_FILE) --env CONTAINER_FILE_CONTENT=$(CONTAINER_FILE_CONTENT) --env WATCH=$(WATCH) --name fradrive.$(CURR_DEV).$(SERVICE_VARIANT) localhost/fradrive/$(FRADRIVE_SERVICE) ; \
else \
./utils/watchcontainerrun.sh "$(CONTAINER_COMMAND)" "$(CONTAINER_FILE)" & \
CONTAINER_ID=`$(CONTAINER_BGRUN) -v $(PWD):$${MOUNT_DIR} --env IN_CONTAINER=true --env FRADRIVE_MAKE_TARGET=$* --env CONTAINER_FILE=$(CONTAINER_FILE) --env CONTAINER_FILE_CONTENT=$(CONTAINER_FILE_CONTENT) --env WATCH=$(WATCH) --name fradrive.$(CURR_DEV).$(SERVICE_VARIANT) localhost/fradrive/$(FRADRIVE_SERVICE)` ; \
echo "CONTAINER_ID=$${CONTAINER_ID}" >> "$(CONTAINER_FILE)"; \
fi \
fi
# HELP(start-database): start postgres server
# HELP(start-memcached): start memcached server
# HELP(start-minio): start minio server
# HELP(start-backend): serve yesod development site
# HELP(start-frontend): start frontend watcher. Watches frontend source files for changes and recompiles on change. (TODO: watcher functionality currently broken!)
# HELP(start-hoogle): serve local hoogle instance
start-%: FRADRIVE_SERVICE = %
start-%: PORTS = $(foreach PORT,$(BASE_PORTS),$(shell utils/next_free_port.pl $(PORT)))
start-%: --develop
echo "$*"
echo "$(DATE)"
echo "DEV $(DEVELOP)"
if [[ "$(SINGLETON)" = "true" ]]; then \
CONTAINER_FILE=$(DEVELOP)/$* ; \
if [[ -e $${CONTAINER_FILE} ]]; then \
>&2 echo "Another $* service is already running! Use \"make new-develop\" or \"make start\" to start a new develop instance despite currently running services." ; \
exit 1 ; \
fi \
else \
DEVDIR=$(DEVELOP)/$*; \
I=`ls $${DEVDIR} | sort -n | tail -n1`; \
echo "$${I}"; \
CONTAINER_FILE=$${DEVDIR}-$$(($${I}+1)); \
fi ; \
echo "$(PORTS)" | sed 's/ /\n/g' > $${CONTAINER_FILE} ; \
$(MAKE) -- --containerized---start-$* CONTAINER_FILE=$${CONTAINER_FILE}
.PHONY: stop
# HELP: stop all currently running develop instances
stop:
rm -rf develop
.PHONY: stop-%
# HELP(stop-{database,memcached,minio,backend,frontend,hoogle}): stop all currently running develop instances of a given type
stop-%:
$(SET_DEVELOP)
rm -rf $(DEVELOP)/$*
stop-container-by-file:
rm $(CONTAINER_FILE)
stop-container-by-id:
$(CONTAINER_COMMAND) stop $(CONTAINER_ID)
# CONTAINER_ID=`grep 'CONTAINER_ID=' $(CONTAINER_FILE) | sed 's/CONTAINER_ID=//'` ; \
# $(MAKE) stop-container-by-id CONTAINER_ID=$${CONTAINER_ID}
.PHONY: status
# HELP: print develop status: running containers, used ports
status:
@./utils/develop-status.pl
.PHONY: log-%
# HELP(log-{database,memcached,minio,backend,frontend,hoogle}): inspect output of a given (currently running) service. When a service supports multiple running instances in one develop (i.e. backend), you need to specify the exact instance by its associated file (e.g. backend-1, backend-2, etc.), please check the contents of the develop/ directory for a list of running instances.
log-%: --develop
$(CONTAINER_COMMAND) logs --follow --tail=$(LOGSIZE) `cat $(DEVELOP)/$* | grep CONTAINER_ID= | sed 's/^CONTAINER_ID=//'`
##### CONTAINER TARGETS #####
#############################
# TODO: move targets below to better location
DATE := $(shell date +'%Y-%m-%dT%H-%M-%S')
CURR_DEV = $(shell ls -1 develop | tail -n1)
SET_DEVELOP = $(eval DEVELOP=develop/$$(CURR_DEV))
NEW_DEVELOP = $(eval DEVELOP=develop/$$(DATE))
.PHONY: new-develop
# HELP: instantiate new development bundle, i.e. create new directory under develop/
new-develop:
$(NEW_DEVELOP)
mkdir -p $(DEVELOP)
$(MAKE) develop/.current
.PHONY: switch-develop
# HELP: switch current develop instance to DEVELOP=...
switch-develop:
if ! [ -e develop/$(DEVELOP) ]; then \
echo "Specified develop $(DEVELOP) does not exist! Not switching." ; \
exit 1 ; \
fi ; \
echo "$(DEVELOP)" > develop/.current
.PHONY: --develop
--develop:
if ! [[ -e develop ]]; then \
$(MAKE) new-develop; \
fi
$(SET_DEVELOP)
$(MAKE) develop/.current
.PHONY: develop/.current
develop/.current:
$(SET_DEVELOP)
echo "$(DEVELOP)" > develop/.current
# Some convenience aliases:
.PHONY: hoogle
# HELP: alias for start-hoogle
hoogle: start-hoogle;
.PHONY: i18n-check
# HELP: check internationalization
i18n-check: --image-run---i18n-check
--i18n-check:
./missing-translations.sh
@echo No missing translations.
%.lock:
[ -e $@ ] || touch $@
flock -en $@ true
.PHONY: --%
.SUFFIXES: # Delete all default suffixes