442 lines
15 KiB
Makefile
442 lines
15 KiB
Makefile
|
|
export SHELL=bash
|
|
|
|
# MAKE=make -f Makefile-loggingsymbols
|
|
# MAKE=make -d
|
|
|
|
# System information
|
|
export CPU_CORES = $(shell cat /proc/cpuinfo | grep '^processor' | wc -l)
|
|
|
|
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 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 IN_CONTAINER ?= false
|
|
export IN_CI ?= false
|
|
export CONTAINER_FILE
|
|
export CONTAINER_IDENT
|
|
export CF_PREFIX
|
|
export DEVELOP
|
|
export CONTAINER_ATTACHED
|
|
export CONTAINER_INIT
|
|
export CONTAINER_CLEANUP
|
|
export PROJECT_DIR=/fradrive
|
|
|
|
export SERVICE
|
|
export SERVICE_VARIANT ?= $(SERVICE)
|
|
export JOB
|
|
export IMAGE
|
|
export SET_IMAGE
|
|
export ENTRYPOINT
|
|
export EXEC_OPTS
|
|
|
|
export STACK_CORES = $(shell echo $(($(CPU_CORES)/2)))
|
|
export BASE_PORTS
|
|
export UNIWORXDB_OPTS ?= -cf
|
|
export PROD ?= false
|
|
export SRC
|
|
|
|
ifneq ($(PROD),true)
|
|
export --DEVELOPMENT=--flag uniworx:dev
|
|
endif
|
|
|
|
export DATE := $(shell date +'%Y-%m-%dT%H-%M-%S')
|
|
|
|
export CURR_DEV = $(shell cat develop/.current 2>/dev/null)
|
|
export SET_DEVELOP = $(eval DEVELOP=develop/$$(CURR_DEV))
|
|
export NEW_DEVELOP = $(eval DEVELOP=develop/$$(DATE))
|
|
|
|
|
|
.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:
|
|
rm -rf develop
|
|
-rm -rf node_modules .npm .cache assets/icons assets/favicons static well-known config/manifest.json frontend/src/env.sass
|
|
-rm -rf .stack-work .stack-work.lock
|
|
-rm -rf bin .Dockerfile develop
|
|
-$(CONTAINER_COMMAND) container prune --force
|
|
.PHONY: clean-images
|
|
# HELP: stop all running containers and clean all images from local repositories
|
|
clean-images:
|
|
rm -rf develop
|
|
sleep 5
|
|
-$(CONTAINER_COMMAND) system prune --all --force --volumes
|
|
-$(CONTAINER_COMMAND) image prune --all --force
|
|
-$(CONTAINER_COMMAND) volume 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 reset --force
|
|
|
|
.PHONY: release
|
|
# HELP: create, commit and push a new release
|
|
# TODO: only release when build and tests are passing!!!
|
|
release:
|
|
VERSION=`./utils/version.pl -changelog CHANGELOG.md -v` ; \
|
|
git add CHANGELOG.md ; \
|
|
git commit -m "chore(release): $${VERSION}" ; \
|
|
git push ; \
|
|
git tag $${VERSION} ; \
|
|
git push origin $${VERSION}
|
|
|
|
.PHONY: compile
|
|
# HELP: perform full compilation (frontend and backend)
|
|
compile:
|
|
$(MAKE) compile-frontend
|
|
$(MAKE) compile-backend
|
|
|
|
.PHONY: start
|
|
# HELP: start complete development environment with a fresh test database
|
|
start:
|
|
$(MAKE) start-postgres
|
|
$(MAKE) start-memcached
|
|
$(MAKE) start-minio
|
|
$(MAKE) start-maildev
|
|
$(MAKE) compile-frontend
|
|
$(MAKE) compile-uniworxdb
|
|
$(MAKE) start-backend
|
|
|
|
.PHONY: %-backend
|
|
%-backend: SERVICE=backend
|
|
%-backend: SERVICE_VARIANT=backend
|
|
%-backend: IMAGE=localhost/fradrive/backend
|
|
%-backend: BASE_PORTS = "DEV_PORT_HTTP=3000" "DEV_PORT_HTTPS=3443"
|
|
|
|
.PHONY: %-uniworxdb
|
|
%-uniworxdb: SERVICE=backend
|
|
%-uniworxdb: SERVICE_VARIANT=uniworxdb
|
|
%-uniworxdb: IMAGE=localhost/fradrive/backend
|
|
|
|
.PHONY: %-ghci
|
|
%-ghci: SERVICE=backend
|
|
%-ghci: SERVICE_VARIANT=ghci
|
|
%-ghci: IMAGE=localhost/fradrive/backend
|
|
|
|
.PHONY: %-hoogle
|
|
%-hoogle: SERVICE=backend
|
|
%-hoogle: SERVICE_VARIANT=hoogle
|
|
%-hoogle: BASE_PORTS = "HOOGLE_PORT=8081"
|
|
%-hoogle: IMAGE=localhost/fradrive/backend
|
|
--start-hoogle:
|
|
HOOGLE_PORT=`cat $(CONTAINER_FILE) | grep 'HOOGLE_PORT=' | sed 's/HOOGLE_PORT=//'` ; \
|
|
stack $(STACK_CORES) hoogle -- server --local --port $${HOOGLE_PORT}
|
|
|
|
.PHONY: %-frontend
|
|
%-frontend: SERVICE=frontend
|
|
%-frontend: SERVICE_VARIANT=frontend
|
|
%-frontend: IMAGE=localhost/fradrive/frontend
|
|
|
|
.PHONY: %-postgres
|
|
%-postgres: SERVICE=postgres
|
|
%-postgres: SERVICE_VARIANT=postgres
|
|
%-postgres: BASE_PORTS = "PGPORT=5432"
|
|
%-postgres: SET_IMAGE=localhost/fradrive/postgres
|
|
|
|
.PHONY: %-memcached
|
|
%-memcached: SERVICE=memcached
|
|
%-memcached: SERVICE_VARIANT=memcached
|
|
%-memcached: SET_IMAGE=$$(MEMCACHED_IMAGE) --port=`cat $$(CONTAINER_FILE) | grep 'MEMCACHED_PORT=' | sed 's/MEMCACHED_PORT=//'`
|
|
%-memcached: BASE_PORTS = "MEMCACHED_PORT=11211"
|
|
|
|
.PHONY: %-maildev
|
|
%-maildev: SERVICE=maildev
|
|
%-maildev: SERVICE_VARIANT=maildev
|
|
%-maildev: SET_IMAGE=$$(MAILDEV_IMAGE) --port=`cat $$(CONTAINER_FILE) | grep 'MAILDEV_PORT=' | sed 's/MAILDEV_PORT=//'`
|
|
%-maildev: BASE_PORTS = "MAILDEV_PORT=1025"
|
|
|
|
.PHONY: %-release
|
|
%-release: PROD=true
|
|
%-release: SERVICE=fradrive
|
|
%-release: SERVICE_VARIANT=fradrive
|
|
%-release: IMAGE=localhost/fradrive/fradrive
|
|
|
|
.PHONY: %-minio
|
|
%-minio: SERVICE=minio
|
|
%-minio: SERVICE_VARIANT=minio
|
|
%-minio: SET_IMAGE=$$(MINIO_IMAGE) -- server `mktemp` --address=:`cat $$(CONTAINER_FILE) | grep 'UPLOAD_S3_PORT=' | sed 's/UPLOAD_S3_PORT=//'`
|
|
%-minio: BASE_PORTS = "UPLOAD_S3_PORT=9000"
|
|
|
|
.PHONY: start-%
|
|
start-%: JOB=start
|
|
start-%: CF_PREFIX = start-
|
|
start-%: CONTAINER_ATTACHED = false
|
|
start-%: --act ;
|
|
|
|
.PHONY: compile-%
|
|
compile-%: JOB=compile
|
|
compile-%: CF_PREFIX = compile-
|
|
compile-%: CONTAINER_ATTACHED = true
|
|
compile-%: --act ;
|
|
|
|
.PHONY: dependencies-%
|
|
dependencies-%: JOB=dependencies
|
|
dependencies-%: CF_PREFIX = dependencies-
|
|
dependencies-%: CONTAINER_ATTACHED = true
|
|
dependencies-%: --act ;
|
|
|
|
.PHONY: test-%
|
|
test-%: JOB=test
|
|
test-%: CF_PREFIX = test-
|
|
test-%: CONTAINER_ATTACHED = true
|
|
test-%: --act ;
|
|
|
|
.PHONY: lint-%
|
|
lint-%: JOB=lint
|
|
lint-%: CF_PREFIX = lint-
|
|
lint-%: CONTAINER_ATTACHED = true
|
|
lint-%: --act ;
|
|
|
|
.PHONY: shell-%
|
|
# HELP(shell-$SERVICE): launch (bash) shell inside a new $SERVICE container
|
|
shell-%: JOB=shell
|
|
shell-%: CF_PREFIX=shell-
|
|
shell-%: CONTAINER_ATTACHED=true
|
|
shell-%: --act ;
|
|
.PHONY: ghci
|
|
# HELP(ghci): launch new backend instance and enter interactive ghci shell
|
|
ghci: shell-ghci;
|
|
|
|
--act: --develop_containerized;
|
|
|
|
--develop_%: PORTS = $(foreach PORT,$(BASE_PORTS),$(shell utils/next_free_port.pl $(PORT)))
|
|
--develop_%: --ensure-develop
|
|
DEVELOP=develop/`cat develop/.current` ; \
|
|
CONTAINER_IDENT=$(CF_PREFIX)$(SERVICE_VARIANT) ; \
|
|
CONTAINER_FILE=$${DEVELOP}/$${CONTAINER_IDENT} ; \
|
|
if [[ -e $${CONTAINER_FILE} ]]; then \
|
|
>&2 echo "Another $* service is already running! Use \"make new-develop\" to start a new develop instance despite currently running services." ; \
|
|
exit 1 ; \
|
|
fi ; \
|
|
echo "$(PORTS)" | sed 's/ /\n/g' > $${CONTAINER_FILE} ; \
|
|
$(MAKE) -- --$* CONTAINER_FILE=$${CONTAINER_FILE} CONTAINER_IDENT=$${CONTAINER_IDENT} JOB=$(JOB)
|
|
|
|
.PHONY: rebuild-%
|
|
# HELP(rebuild-{backend,frontend,database,memcached,minio}): force-rebuild a given container image
|
|
rebuild-%:
|
|
$(MAKE) -- --image-build SERVICE=$* NO_CACHE=--no-cache
|
|
--image-build:
|
|
ifeq "$(IMAGE)" "localhost/fradrive/$(SERVICE)"
|
|
rm -f .Dockerfile
|
|
ln -s docker/$(SERVICE)/Dockerfile .Dockerfile
|
|
PROJECT_DIR=/fradrive; \
|
|
if [ "$(IN_CONTAINER)" == "false" ] ; then \
|
|
$(CONTAINER_COMMAND) build $(NO_CACHE) \
|
|
-v $(PWD):$${PROJECT_DIR}:rw \
|
|
--build-arg PROJECT_DIR=$${PROJECT_DIR} \
|
|
--env IN_CONTAINER=true \
|
|
--env JOB=$(JOB) \
|
|
--tag fradrive/$(SERVICE) \
|
|
--file $(PWD)/.Dockerfile ; \
|
|
fi
|
|
else
|
|
:
|
|
endif
|
|
|
|
--containerized: --image-build
|
|
DEVELOP=`cat develop/.current` ; \
|
|
./utils/watchcontainerrun.sh "$(CONTAINER_COMMAND)" "$(CONTAINER_FILE)" "$(CONTAINER_INIT)" "$(CONTAINER_CLEANUP)" & \
|
|
CONTAINER_NAME=fradrive.$(CURR_DEV).$(CONTAINER_IDENT) ; \
|
|
if ! [ -z "$(SET_IMAGE)" ] ; \
|
|
then \
|
|
IMAGE="$(SET_IMAGE)" ; \
|
|
else \
|
|
IMAGE=$(IMAGE) ; \
|
|
MAKECALL="make -- --$(JOB)-$(SERVICE_VARIANT) IN_CONTAINER=true" ; \
|
|
fi ; \
|
|
CONTAINER_ID=`$(CONTAINER_BGRUN) \
|
|
-v $(PWD):$(PROJECT_DIR):rw \
|
|
--env IN_CONTAINER=true \
|
|
--env CONTAINER_FILE=$(CONTAINER_FILE) \
|
|
--env CONTAINER_NAME=$${CONTAINER_NAME} \
|
|
--env JOB=$(JOB) \
|
|
--env SRC=$(SRC) \
|
|
--name $${CONTAINER_NAME} \
|
|
$${IMAGE} \
|
|
$${MAKECALL} \
|
|
` ; \
|
|
printf "CONTAINER_ID=$${CONTAINER_ID}" >> "$(CONTAINER_FILE)" ; \
|
|
if [[ "true" == "$(CONTAINER_ATTACHED)" ]] ; then \
|
|
$(CONTAINER_COMMAND) attach $${CONTAINER_ID} || : ; \
|
|
fi
|
|
|
|
# For Reverse Proxy Problem see: https://groups.google.com/g/yesodweb/c/2EO53kSOuy0/m/Lw6tq2VYat4J
|
|
# HELP(start-backend): start development instance
|
|
--start-backend: --dependencies-backend
|
|
export YESOD_IP_FROM_HEADER=true; \
|
|
export DEV_PORT_HTTP=`cat $(CONTAINER_FILE) | grep 'DEV_PORT_HTTP=' | sed 's/DEV_PORT_HTTP=//'`; \
|
|
export DEV_PORT_HTTPS=`cat $(CONTAINER_FILE) | grep 'DEV_PORT_HTTPS=' | sed 's/DEV_PORT_HTTPS=//'`; \
|
|
export HOST=127.0.0.1 ; \
|
|
export PORT=$${PORT:-$${DEV_PORT_HTTP}} ; \
|
|
export DETAILED_LOGGING=$${DETAILED_LOGGING:-true} ; \
|
|
export LOG_ALL=$${LOG_ALL:-false} ; \
|
|
export LOGLEVEL=$${LOGLEVEL:-info} ; \
|
|
export DUMMY_LOGIN=$${DUMMY_LOGIN:-true} ; \
|
|
export SERVER_SESSION_ACID_FALLBACK=$${SERVER_SESSION_ACID_FALLBACK:-true} ; \
|
|
export SERVER_SESSION_COOKIES_SECURE=$${SERVER_SESSION_COOKIES_SECURE:-false} ; \
|
|
export COOKIES_SECURE=$${COOKIES_SECURE:-false} ; \
|
|
export ALLOW_DEPRECATED=$${ALLOW_DEPRECATED:-true} ; \
|
|
export ENCRYPT_ERRORS=$${ENCRYPT_ERRORS:-false} ; \
|
|
export RIBBON=$${RIBBON:-$${HOST:-localhost}} ; \
|
|
export APPROOT=$${APPROOT:-http://localhost:$${DEV_PORT_HTTP}} ; \
|
|
export AVSPASS=$${AVSPASS:-nopasswordset} ; \
|
|
stack $(STACK_CORES) exec --local-bin-path $$(pwd)/bin --copy-bins -- yesod devel -p "$${DEV_PORT_HTTP}" -q "$${DEV_PORT_HTTPS}"
|
|
# HELP(compile-backend): compile backend binaries
|
|
--compile-backend: --dependencies-backend
|
|
stack build $(STACK_CORES) --fast --profile --library-profiling --executable-profiling --flag uniworx:-library-only $(--DEVELOPMENT) --local-bin-path $$(pwd)/bin --copy-bins
|
|
# HELP(dependencies-backend): (re-)build backend dependencies
|
|
--dependencies-backend: #uniworx.cabal
|
|
chown -R `id -un`:`id -gn` "$(PROJECT_DIR)"; \
|
|
stack install hpack; stack install yesod-bin; \
|
|
stack build -j2 --only-dependencies
|
|
# HELP(lint-backend): lint backend
|
|
--lint-backend:
|
|
stack build $(STACK_CORES) --test --fast --flag uniworx:library-only $(--DEVELOPMENT) uniworx:test:hlint
|
|
# HELP(test-backend): test backend
|
|
--test-backend:
|
|
stack build $(STACK_CORES) --test --coverage --fast --flag uniworx:library-only $(--DEVELOPMENT)
|
|
# uniworx.cabal:
|
|
# stack exec -- hpack --force
|
|
|
|
# HELP(compile-frontend): compile frontend assets
|
|
--compile-frontend: --dependencies-frontend
|
|
npm run build
|
|
--start-frontend: --compile-frontend;
|
|
--dependencies-frontend: node_modules assets esbuild.config.mjs frontend/src/env.sass;
|
|
node_modules: package.json package-lock.json
|
|
npm install --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
|
|
frontend/src/env.sass:
|
|
echo "\$$path: '$${PROJECT_DIR}'" > frontend/src/env.sass
|
|
static: --dependencies-frontend
|
|
npm run build
|
|
well-known: static;
|
|
--lint-frontend: --compile-frontend
|
|
npm run lint
|
|
--test-frontend: --compile-frontend
|
|
npm run test
|
|
|
|
# HELP(compile-uniworxdb): clear and fill database. requires running postgres instance (use "make start-postgres" to start one)
|
|
# TODO (db-m-$MIGRATION-backend): apply migration (see src/Model/Migration/Definition.hs for list of available migrations)
|
|
--compile-uniworxdb: --compile-backend
|
|
SERVER_SESSION_ACID_FALLBACK=${SERVER_SESSION_ACID_FALLBACK:-true} ; \
|
|
AVSPASS=${AVSPASS:-nopasswordset} ; \
|
|
./bin/uniworxdb $(UNIWORXDB_OPTS)
|
|
|
|
# HELP(shell-ghci): enter ghci shell. Use "make ghci SRC=<MODULE_FILE.hs>" to load specific source modules."
|
|
--shell-ghci:
|
|
stack ghci -- $(SRC)
|
|
# --main-is uniworx:exe:uniworx
|
|
|
|
# HELP(shell-{backend,frontend,memcached,minio,postgres}): enter (bash) shell inside a new container of a given service
|
|
--shell-%:
|
|
/bin/bash
|
|
|
|
# HELP(start-minio): start minio service
|
|
|
|
.PHONY: status
|
|
# HELP: print develop status: running containers, used ports
|
|
status:
|
|
@./utils/develop-status.pl -a
|
|
|
|
.PHONY: log-%
|
|
# HELP(log-$(JOB)-$(SERVICE)): inspect output of a given service. The service must be currently running 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=develop/`cat develop/.current` ; \
|
|
SEARCH_FILE="$${DEVELOP}/$*" ; \
|
|
if [[ ! -e "$${SEARCH_FILE}" ]] ; then \
|
|
SEARCH_FILE="$${DEVELOP}/.exited.$*" ; \
|
|
fi ; \
|
|
if [[ -e "$${SEARCH_FILE}" ]] ; then \
|
|
$(CONTAINER_COMMAND) logs --follow `cat "$${SEARCH_FILE}" | grep CONTAINER_ID= | sed 's/^CONTAINER_ID=//'` ; \
|
|
else \
|
|
>&2 echo "Cannot show log: No develop file found for '$*'" ; \
|
|
exit 1 ; \
|
|
fi
|
|
|
|
.PHONY: enter
|
|
# HELP: launch (bash) shell inside a currently running container. Use ./enter shell wrapper for more convenient usage, possibly with tab-completion in the future
|
|
enter: --ensure-develop
|
|
$(MAKE) -- --enter
|
|
|
|
.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: --ensure-develop
|
|
$(MAKE) -- --enter CONTAINER_FILE=develop/`cat develop/.current`/start-postgres
|
|
|
|
--enter:
|
|
CONTAINER_ID=`cat $(CONTAINER_FILE) | grep 'CONTAINER_ID=' | sed 's/CONTAINER_ID=//'` ; \
|
|
$(CONTAINER_COMMAND) exec -it $(EXEC_OPTS) $${CONTAINER_ID} $(if $(ENTRYPOINT),$(ENTRYPOINT),/bin/bash)
|
|
|
|
.PHONY: stop
|
|
# HELP: stop all currently running develop instances
|
|
stop:
|
|
rm -rf develop
|
|
.PHONY: stop-%
|
|
# HELP(stop-SERVICE): stop all currently running develop instances of a given service (i.e. backend,frontend,uniworxdb,hoogle,postgres,...)
|
|
# HELP(stop-JOB): stop all currently running develop instances of a given job (i.e. compile,start,test,lint)
|
|
stop-compile: CF_PREFIX=compile-
|
|
stop-start: CF_PREFIX=start-
|
|
stop-test: CF_PREFIX=test-
|
|
stop-lint: CF_PREFIX=lint-
|
|
stop-%: --stop;
|
|
--stop:
|
|
$(SET_DEVELOP)
|
|
ifdef CF_PREFIX
|
|
rm -rf $(DEVELOP)/$(CF_PREFIX)*
|
|
endif
|
|
ifdef SERVICE_VARIANT
|
|
rm -rf $(DEVELOP)/*-$(SERVICE_VARIANT)
|
|
endif
|
|
|
|
.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
|
|
--ensure-develop:
|
|
if ! [[ -e develop ]]; then \
|
|
$(MAKE) new-develop; \
|
|
fi
|
|
$(MAKE) develop/.current
|
|
$(SET_DEVELOP)
|
|
.PHONY: develop/.current
|
|
develop/.current:
|
|
ls -1 develop | tail -n1 > develop/.current
|
|
|
|
.PHONY: --%
|
|
.SUFFIXES: # Delete all default suffixes
|