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-%: --%-containerized-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-containerized-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: echo "FS:$(FRADRIVE_SERVICE) SV:$(SERVICE_VARIANT) DE:$(DEVELOP) CF:$(CONTAINER_FILE)" @: ifeq "$(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 ifeq "$(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 #ifeq "$(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 #ifeq "$(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-%: --checkvarsset docker/database/initdb.sh docker/database/pg_hba.conf docker/database/postgresql.conf docker/database/schema.sql --image-build $(MAKE) -- --imagerun-$* else --containerized-%: --checkvarsset $(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 # runs --% in the container. Targets meant to be called manually cannot be run in the container via this target. If that is ever needed split this target into two targets, one for manually one for automatic (one may use the other) so that not at every usage a '---' has to be after containerized --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 FRADRIVE_SERVICE=$(FRADRIVE_SERVICE) --env SERVICE_VARIANT=$(SERVICE_VARIANT) --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 FRADRIVE_SERVICE=$(FRADRIVE_SERVICE) --env SERVICE_VARIANT=$(SERVICE_VARIANT) --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