Make

Make#

###############################################################################
# Developer Documentation
###############################################################################
define DEVELOPER_DOCUMENTATION
====
Make
====
The Makefile at ``./Makefile`` is the exclusive tool for building targets within
the metacrud2 monorepository. Any contributions to this repository should include
the appropriate Makefile targets for building the software using existing 
conventions as found throughout. Refer to the Zen of Python for justification. 
The sections of the Makefile are as described below.

Developer Documentation
=======================
Documentation for the Makefile should be written within the top of the ``./Makefile``
in valid ReStructuredText format in order that it can be extracted and used within
the documentation site. This is to maintain documentation within the code whenever
possible to make documentation maintenance easier.

User Documentation
==================
The user documentation will always describe the available commands and targets within
the Makefile. It is important that this section be updated with any new 
commands or changes to existing commands since this is the primary source of 
truth for how to use the Makefile to the typical user.

Default
=======
The first command found within the Makefile is automatically run if no command is
provided. By providing the first target as 'default', this is explicit. 
Simply running ``make`` will be the same as running ``make default``. This will
always execute the ``make help`` command.

Help
====
The ``make help`` command produces the user documentation.

Configuration
=============
The configuration section will contain variables and other configuration data
used within the Makefile. All variables should be intuitively and consistently 
named.

Error Checking
==============
The error checking section will contain the commands used to verify the 
environment is ready for building the software. This should include verifying
the Python version, Make version, Docker version, and that the Docker daemon is 
running, as well as check for required versions of each.

Targets/Dependencies
====================
The targets/dependencies section will enumerate the targets and dependencies for
building the software. Make is designed to monitor dependencies for changes and 
accelerate the build process by only rebuilding what has changed. By defining the
targets entirely within this section, each with its corresponding dependencies, 
compilation can be structured in this section for intuitive readability.

Utilities
=========
Utilities such as clean commands are contained within the utilities section.

Additional Resources
====================
Refer to https://makefiletutorial.com for additional documentation.

endef
export DEVELOPER_DOCUMENTATION

###############################################################################
# User Documentation
###############################################################################
define USER_DOCUMENTATION
Setup/Configuration
===================
make devenv		    # Build and run the development environment Docker container
make connect_devenv	# Connect to the development environment Docker container

Valid Targets
=============
make docs
	# Make documentation site (and publish to localhost:82)
make home
	# Make production and development versions of home web application (and publish to localhost:81)
make database.systems.exact.engineering
	# Make the database container for metacrud2
make metacrud2.systems.exact.engineering
	# Make the metacrud2 container(Refer to ./src/docker/metacrud2/var/metacrud2/_log.txt for feedback)

Utilities
=========
make cleanAll		# Clean directories and Docker
make cleanDirs		# Clean directories only
make cleanDocker	# Clean Docker only

endef
export USER_DOCUMENTATION

###############################################################################
# Default
###############################################################################
# Explicitly defines the default action as the first action found to produce
# the user documentation if no commands/targets are provided. This will always
# execute the ``make help`` command.
.PHONY: default
default: help

###############################################################################
# Help
###############################################################################
# ``make help`` command produces the user documentation.
.PHONY: help
help:
	@echo "$$USER_DOCUMENTATION"

###############################################################################
# Configuration
###############################################################################
NAME = metacrud
VERSION = 2.0.1
CURRENT_GIT_BRANCH:=$(shell git rev-parse --abbrev-ref HEAD)

# Start date/time
START_TIME:=$(shell echo $$(date +%s))
END_TIME=$$(date +%s)

# Paths
HERE=$(shell pwd)
SRC_DIR:=$(HERE)/src
BUILD_DIR:=$(HERE)/build
DIST_DIR:=$(HERE)/dist

# User Context
USER=$(shell whoami)
UID=$(shell id -u)
GID=$(shell id -g)

###############################################################################
# Error Checking
###############################################################################
# Required commands and versions
REQUIRED_COMMANDS := python3 make
REQUIRED_PYTHON := 3.11
REQUIRED_MAKE := 3.8
REQUIRED_DOCKER := 20.10
MAKE := make

# Define PYTHON variable if not already set
PYTHON ?= python3

# Get installed versions and paths
PYTHON_VERSION := $(shell $(PYTHON) -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
PYTHON_PATH := $(shell which $(PYTHON))
MAKE_VERSION := $(shell make --version | head -n 1 | cut -d ' ' -f 3)
MAKE_PATH := $(shell which make)
# DOCKER_VERSION := $(shell docker --version | cut -d ' ' -f 3 | tr -d ',v')
# DOCKER_PATH := $(shell which docker)

# Check for required commands
# $(foreach cmd,$(REQUIRED_COMMANDS),\
#     $(if $(shell command -v $(cmd)),,$(error "Command '$(cmd)' not found. Please install it.")))

# Verify Python version
# ifneq ($(shell echo "$(PYTHON_VERSION) >= $(REQUIRED_PYTHON)" | bc),1)
#     $(error "Python version $(REQUIRED_PYTHON) or higher is required, but $(PYTHON_VERSION) was found")
# endif

# # Verify Make version
# ifneq ($(shell echo "$(MAKE_VERSION) >= $(REQUIRED_MAKE)" | bc),1)
#     $(error "GNU Make version $(REQUIRED_MAKE) or higher is required, but $(MAKE_VERSION) was found")
# endif

# Verify Docker version
# DOCKER_VERSION_CHECK := $(shell echo "$(DOCKER_VERSION)" | awk -v required="$(REQUIRED_DOCKER)" '{ if ($$1 >= required) print 1; else print 0; }')
# ifneq ($(DOCKER_VERSION_CHECK),1)
#     $(error "Docker version is $(DOCKER_VERSION), but minimum required version is $(REQUIRED_DOCKER)")
# endif

# # Check if Docker daemon is running
# DOCKER_RUNNING := $(shell docker info >/dev/null 2>&1 && echo 1 || echo 0)
# ifeq ($(DOCKER_RUNNING),0)
#     $(error "Docker daemon is not running. Please start Docker and try again")
# endif

# # Store versions and paths for help output
# define ENVIRONMENT_INFO
# Environment Information:
# Python: $(PYTHON_VERSION) ($(PYTHON_PATH))
# Make: $(MAKE_VERSION) ($(MAKE_PATH))
# Docker: $(DOCKER_VERSION) ($(DOCKER_PATH))

# endef
# export ENVIRONMENT_INFO

###############################################################################
# Targets/Dependencies
###############################################################################
.PHONY: devenv
devenv:
	docker stop devenv || true
	docker rm devenv || true
	docker rmi devenv || true
	docker build -t devenv $(SRC_DIR)/docker/devenv
	docker run --detach --name devenv \
		--volume $(HERE)/:/src/metacrud2 \
		--volume $(BUILD_DIR)/var/www/engineering-exact:/var/www/engineering-exact \
		--volume $(BUILD_DIR)/var/www/engineering-exact-systems-docs:/var/www/engineering-exact-systems-docs \
		--volume $(BUILD_DIR)/var/www/com-exactcontrols:/var/www/com-exactcontrols \
		--publish 81:81 \
		--publish 82:82 \
		--publish 83:83 \
		devenv

.PHONY: connect_devenv
connect_devenv:
#	This command was temporarily added to fix a git permisssion issue when running commands in the devenv container, once a long term solution is found, this should be removed
	docker exec -t devenv git config --global --add safe.directory /src/metacrud2
	docker exec --interactive --tty devenv /bin/bash
	

.PHONY: docs.systems.exact.engineering exact.engineering
docs.systems.exact.engineering exact.engineering: $(BUILD_DIR)/docker/$@.uuid
	# Build and run the new container
	docker build -t $* $(SRC_DIR)/docker/$*
	docker run --detach --name $* \
		--volume $(HERE)/:/home/$(USER)/Repositories/metacrud2 \
		$*

	# Create stamp file with container ID
	@mkdir -p $(dir $@)
	@docker ps -q -f name=$* > $@

.PHONY: home
home: 
	cd $(HERE) && npm install
	make $(BUILD_DIR)/var/www/engineering-exact
	make $(DIST_DIR)/var/www/engineering-exact

# Development target for 'home' web application
.PHONY: $(BUILD_DIR)/var/www/engineering-exact
$(BUILD_DIR)/var/www/engineering-exact: $(shell find $(HERE)/public/apps/engineering-exact -type f)
	mkdir -p $@
	cd $(HERE) && npm run build:dev -w engineering-exact

# Production target for 'home' web application
.PHONY: $(DIST_DIR)/var/www/engineering-exact
$(DIST_DIR)/var/www/engineering-exact: $(shell find $(HERE)/public/apps/engineering-exact -type f)
	mkdir -p $@
	cd $(HERE) && npm run build:prod -w engineering-exact


.PHONY: exactcontrols
exactcontrols:
	cd $(HERE) && npm install
	make $(BUILD_DIR)/var/www/com-exactcontrols
	make $(DIST_DIR)/var/www/com-exactcontrols

# Development target for 'exactcontrols.com' web application
.PHONY: $(BUILD_DIR)/var/www/com-exactcontrols
$(BUILD_DIR)/var/www/com-exactcontrols: $(shell find $(HERE)/public/apps/com-exactcontrols -type f)
	mkdir -p $@
	cd $(HERE) && npm run build:dev -w com-exactcontrols

# Production target for 'exactcontrols.com' web application
.PHONY: $(DIST_DIR)/var/www/com-exactcontrols
$(DIST_DIR)/var/www/com-exactcontrols: $(shell find $(HERE)/public/apps/com-exactcontrols -type f)
	mkdir -p $@
	cd $(HERE) && npm run build:prod -w com-exactcontrols

# Development target for documentation site
.PHONY: docs
docs:
	make $(BUILD_DIR)/var/www/engineering-exact-systems-docs
	npx wrangler pages deploy ./build/docs/html --project-name=docs-systems-exact-engineering
	# Refer to login directions as necessary: 
	# https://developers.cloudflare.com/workers/wrangler/commands/#login

.PHONY: $(BUILD_DIR)/var/www/engineering-exact-systems-docs
$(BUILD_DIR)/var/www/engineering-exact-systems-docs: $(BUILD_DIR)/docs/html
	mkdir -p $@
	cp -r $(BUILD_DIR)/docs/html/* $@/

.PHONY: $(BUILD_DIR)/docs/html
$(BUILD_DIR)/docs/html: $(BUILD_DIR)/docs/rst
	sphinx-build -b html -d $(BUILD_DIR)/docs/doctrees $(BUILD_DIR)/docs/rst $(BUILD_DIR)/docs/html

.PHONY: $(BUILD_DIR)/docs/rst
$(BUILD_DIR)/docs/rst: $(shell find $(HERE)/docs/ -type f -regex ".*\.rst")
	mkdir -p $@
	cp -r $(HERE)/docs/* $@
	python3 $(HERE)/utilities/2_enhanceDocumentation.py $(BUILD_DIR)/docs/rst

.PHONY: api
api:
	make $(BUILD_DIR)/api/specification.json

$(BUILD_DIR)/api/specification.json: $(shell find $(HERE)/src/schema/table -type f -regex ".*\.yaml")
	python3 $(HERE)/utilities/0_compileApiSpecification.py \
		--schemas-dir $(HERE)/src/schema/table \
		--output $@ \
		--title "API Documentation" \
		--version "1.0.0" \
		--logo $(HERE)/public/img/Exact_Systems_logo_color.svg

.PHONY: database
database:
	make $(BUILD_DIR)/sql/configuration.sql

$(BUILD_DIR)/sql/configuration.sql: $(shell find $(HERE)/src/schema/table -type f -regex ".*\.yaml")
	python3 $(HERE)/utilities/1_compileSqlScripts.py \
		--schemas-dir $(HERE)/src/schema/table \
		--output $@

.PHONY: dev.exact.engineering
dev.exact.engineering:
	make $(DIST_DIR)/var/www/engineering/exact
	# Check if container is running
	# @if docker ps -q -f name=$@ >/dev/null 2>&1; then \
	# 	echo "$@ container is already running"; \
	# else \
	echo "Starting new $@ container..."; \
	docker stop $@ || true; \
	docker rm $@ || true; \
	docker rmi $@ || true; \
	docker build -t $@ $(SRC_DIR)/docker/$@; \
	docker run --detach --name $@ \
		--volume $(DIST_DIR)/var/www/engineering/exact:/var/www/engineering/exact/dev \
		$@; \

.PHONY: metacrud2.systems.exact.engineering
metacrud2.systems.exact.engineering:
	echo "Starting new $@ container..."; \
	docker stop $@ || true; \
	docker rm $@ || true; \
	docker rmi $@ || true; \
	docker build -t $@ $(SRC_DIR)/docker/$@; \
	docker run --interactive --tty --name $@ \
		--volume $(HERE)/src/metacrud2:/usr/lib/python3.11/metacrud2 \
		--volume $(HERE)/src/docker/$@/var:/var \
		$@; \

.PHONY: database.systems.exact.engineering
database.systems.exact.engineering:
	echo "Starting new $@ container..."
	docker stop $@ || true
	docker rm $@ || true
	docker rmi $@ || true
	mkdir -p $(HERE)/src/docker/$@/var/lib/postgresql/data
	docker build -t $@ $(SRC_DIR)/docker/$@
	docker run --detach --name $@ \
		--publish 5432:5432 \
		--volume $(HERE)/src/docker/$@/var/lib/postgresql/data:/var/lib/postgresql/data \
		$@


# ###############################################################################
# # SQL Schema
# ###############################################################################
# sql_schema: $(HERE)/build/schema.sql

# $(HERE)/build/schema.sql: $(shell find $(HERE)/src/schema/tables -type f -regex ".*\.json")
# 	@echo "Generating SQL schema..."
# 	python3 utilities/2_generate_sql.py --schemas-dir $(HERE)/src/schema/tables --output $@



# $(HERE)/dist/exactsystems.pdf: $(HERE)/build/pdf/latex/exactsystems.pdf
# 	@echo "Copying PDF documentation to dist directory..."
# 	cp $< $@

# ###############################################################################
# # OpenAPI Specification
# ###############################################################################

# # API specification
# apiSpecification =  $(HERE)/build/openapi.json
# apiSpecification: $(apiSpecification)
# $(apiSpecification): $(shell find $(HERE)/src/schema/tables -type f -regex ".*\.toml")
# 	@echo "Generating API specification..."
# 	@mkdir -p $(shell dirname $@)
# 	python3 utilities/1_generate_openapi.py \
# 		--schemas-dir $(HERE)/src/schema/tables \
# 		--output $@ \
# 		--title "API Documentation" \
# 		--version "1.0.0" \
# 		--logo $(HERE)/public/img/Exact_Systems_logo_color.svg

# # API documentation
# apiDocumentation = $(HERE)/dist/var/www/html/$(DOCS_PREFIX)/Operations/Technology/API/index.html
# apiDocumentation: $(apiDocumentation)
# $(apiDocumentation): $(apiSpecification)
# 	@echo "Generating API documentation site..."
# 	@mkdir -p $(shell dirname $@)
# 	redocly build-docs $(HERE)/build/openapi.json \
# 		--output $@

# ###############################################################################
# # Docker commands to stop, clean, build, and connect to any valid container
# ###############################################################################
# These are all the valid Docker containers to be ran
DOCKER_CONTAINERS := \
	devenv \
	exact.engineering \
	dev.exact.engineering \
	docs.systems.exact.engineering \
	db.systems.exact.engineering \
	metacrud2.systems.exact.engineering

# # These are verbs/actions that all Docker containers re-use
# # Start is intentionally omitted, since the command differs between containers
# COMMON_DOCKER_VERBS := \
# 	stop \
# 	clean \
# 	build \
# 	connect

# # Form an inclusive list of common Docker commands(i.e. stop_dev, clean_dev.exact.engineering)
# DOCKER_COMMANDS := $(foreach v,$(COMMON_DOCKER_VERBS),$(foreach c,$(DOCKER_CONTAINERS),$(v)_$(c)))

# Generic stop command for all Docker containers
.PHONY: stop_%
stop_%:
	@echo "Stopping container $*..."
	docker stop $* || true # $* is the container name matched by the pattern

# Generic clean command for all Docker containers
.PHONY: clean_%
clean_%: stop_%
	@echo "Cleaning container $*..."
	docker rm $* || true # $* is the container name matched by the pattern
	docker rmi $* || true # $* is the container name matched by the pattern

# # Generic dependencies for building all Docker containers
# .PHONY: build_%
# build_%: clean_%
# 	@echo "Building container $*..."
# 	docker build --tag $* \
# 		--build-arg USER=$(shell whoami) \
# 		--build-arg UID=$(shell id -u) \
# 		--build-arg GID=$(shell id -g) \
# 		$(DOCKER_DIR)/$*

# # Specific build command for docs.systems.exact.engineering
# .PHONY: build_docs.systems.exact.engineering
# build_docs.systems.exact.engineering: clean_docs.systems.exact.engineering
# 	@rm -rf $(DOCKER_DIR)/docs.systems.exact.engineering/var/*
# 	@mkdir -p $(DOCKER_DIR)/docs.systems.exact.engineering/var/www/html/engineering/exact/systems/docs	
# 	cp -r $(HERE)/dist/var/www/html/engineering/exact $(DOCKER_DIR)/docs.systems.exact.engineering/var/www/html/engineering/exact/systems/
# 	@echo "Building container docs.systems.exact.engineering..."
# 	docker build --tag docs.systems.exact.engineering \
# 		--build-arg USER=$(shell whoami) \
# 		--build-arg UID=$(shell id -u) \
# 		--build-arg GID=$(shell id -g) \
# 		$(DOCKER_DIR)/docs.systems.exact.engineering

# # Specific build command for exact.engineering
# .PHONY: build_exact.engineering
# build_exact.engineering: clean_exact.engineering
# 	@rm -rf $(DOCKER_DIR)/exact.engineering/var/*
# 	@mkdir -p $(DOCKER_DIR)/exact.engineering/var/www/html/engineering/exact	
# 	cp -r $(HERE)/dist/var/www/html/engineering/exact $(DOCKER_DIR)/exact.engineering/var/www/html/engineering/exact/
# 	@echo "Building container exact.engineering..."
# 	docker build --tag exact.engineering \
# 		--build-arg USER=$(shell whoami) \
# 		--build-arg UID=$(shell id -u) \
# 		--build-arg GID=$(shell id -g) \
# 		$(DOCKER_DIR)/exact.engineering

# # Specific run commands for specific containers
# .PHONY: run_devenv
# run_devenv: build_devenv
# 	@echo "Starting development environment(devenv)..."
# 	docker container run --detach --name devenv \
# 		--user $(shell id -u):$(shell id -g) \
# 		--volume $(HERE)/:/home/$(shell whoami)/Repositories/metacrud2 \
# 		--volume $(HERE)/public/apps/home/node_modules:\
/home/$(shell whoami)/Repositories/metacrud2/public/apps/home/node_modules \
# 		--volume $(DOCKER_DIR)/devenv/etc/rclone:/home/$(shell whoami)/.config/rclone \
# 		devenv

# .PHONY: run_dev.exact.engineering
# run_dev.exact.engineering: build_dev.exact.engineering
# 	@echo "Starting dev.exact.engineering..."
# 	docker run --detach --name dev.exact.engineering \
# 		--publish 82:80 \
# 		--volume $(DOCKER_DIR)/dev.exact.engineering/etc/nginx:/etc/nginx \
# 		--volume $(DOCKER_DIR)/dev.exact.engineering/etc/cloudflared:/etc/cloudflared \
# 		--volume $(DIST_DIR)/var/www/html:/var/www/html \
# 		dev.exact.engineering

# .PHONY: run_exact.engineering
# run_exact.engineering: build_exact.engineering
# 	@echo "Starting exact.engineering..."
# 	docker run --detach --name exact.engineering \
# 		exact.engineering

# .PHONY: run_docs.systems.exact.engineering
# run_docs.systems.exact.engineering: build_docs.systems.exact.engineering
# 	@echo "Starting documentation server(docs.systems.exact.engineering)..."
# 	docker run --detach --name docs.systems.exact.engineering \
# 		--publish 81:80 \
# 		docs.systems.exact.engineering

# .PHONY: run_db.systems.exact.engineering
# run_db.systems.exact.engineering: build_db.systems.exact.engineering
# 	@echo "Starting database server(db.systems.exact.engineering)..."
# 	mkdir -p $(DOCKER_DIR)/db.systems.exact.engineering/var/lib/postgresql/data
# 	docker run --detach --name db.systems.exact.engineering \
# 		--publish 5432:5432 \
# 		--volume $(DOCKER_DIR)/db.systems.exact.engineering/var/lib/postgresql/data:/var/lib/postgresql/data \
# 		db.systems.exact.engineering

# .PHONY: run_metacrud2.systems.exact.engineering
# run_metacrud2.systems.exact.engineering: build_metacrud2.systems.exact.engineering
# 	@echo "Starting metacrud2 server(metacrud2.systems.exact.engineering)..."
# 	docker run --interactive --tty --name metacrud2.systems.exact.engineering \
# 		--volume $(HERE)/src/metacrud2:/usr/local/lib/python3.11/dist-packages/metacrud2 \
# 		--volume $(DOCKER_DIR)/metacrud2.systems.exact.engineering/etc/metacrud2:/etc/metacrud2 \
# 		--volume $(DOCKER_DIR)/metacrud2.systems.exact.engineering/var/metacrud2:/var/metacrud2 \
# 		metacrud2.systems.exact.engineering

# # Generic connect command for all Docker containers
# .PHONY: connect_%
# connect_%:
# 	@echo "Connecting to container $*..."
# 	docker exec --interactive --tty $* bash

# ###############################################################################
# # Development Environment(devenv) Commands
# ###############################################################################

# # Development environment commands
# # Do not condense these, this format is more readable and readability counts
# .PHONY: devenv_make
# devenv_make:
# 	docker exec --interactive --tty devenv \
# 		make

# .PHONY: devenv_help
# devenv_help:
# 	docker exec --interactive --tty devenv \
# 		make help

# .PHONY: devenv_apiSpecification
# devenv_apiSpecification:
# 	docker exec --interactive --tty devenv \
# 		make apiSpecification

# .PHONY: devenv_apiDocumentation
# devenv_apiDocumentation:
# 	docker exec --interactive --tty devenv \
# 		make apiDocumentation

# .PHONY: devenv_documentationPdf
# devenv_documentationPdf:
# 	docker exec --interactive --tty devenv \
# 		make documentationPdf

# .PHONY: devenv_npminstall
# devenv_npminstall:
# 	docker exec --interactive --tty devenv \
# 		make npminstall

# .PHONY: devenv_npmbuild
# devenv_npmbuild:
# 	docker exec --interactive --tty devenv \
# 		make npmbuild

# .PHONY: devenv_npmwatch
# devenv_npmwatch:
# 	docker exec --interactive --tty devenv \
# 		make npmwatch

# .PHONY: devenv_cleanDirs
# devenv_cleanDirs:
# 	docker exec --interactive --tty devenv \
# 		make cleanDirs

###############################################################################
# Utilities
###############################################################################
.PHONY: systemInfo
systemInfo:
	@echo "$$ENVIRONMENT_INFO"

.PHONY: cleanAll
cleanAll:
	make cleanDirs
	make cleanDocker

.PHONY: cleanDocker
cleanDocker: $(foreach c,$(DOCKER_CONTAINERS),clean_$(c))

# .PHONY: cleanImages
# cleanImages: $(foreach c,$(DOCKER_CONTAINERS),clean_$(c))

# .PHONY: cleanContainers
# cleanContainers:
# 	docker rm 

.PHONY: cleanDirs
cleanDirs:
	rm -rf $(BUILD_DIR)
	rm -rf $(DIST_DIR)

# ###############################################################################
# # Locally host production containers(exact.engineering domain)
# ###############################################################################
# .PHONY: exact.engineering
# exact.engineering:
# 	@echo "Starting production domain: $@"
# 	# @if [ "$(CURRENT_BRANCH)" != "main" ]; then \
# 	# 	echo "Error: This command can only be run from the 'main' branch of the git repository."; \
# 	# 	exit 1; \
# 	# fi
# 	make clean
# 	make run_devenv
# 	# make devenv_npmbuild
# 	# make run_exact.engineering



# ###############################################################################
# # Locally host production containers(systems.exact.engineering domain)
# ###############################################################################
# .PHONY: systems.exact.engineering
# systems.exact.engineering:
# 	@echo "Starting containers for production domain(systems.exact.engineering)..."
# 	@if [ "$(CURRENT_BRANCH)" != "main" ]; then \
# 		echo "Error: This command can only be run from the 'main' branch of the git repository."; \
# 		exit 1; \
# 	fi
# 	make clean
# 	make run_devenv
# 	make devenv_documentation
# 	make devenv_apiSpecification
# 	make devenv_apiDocumentation
# 	make devenv_npmbuild
# 	make run_docs.systems.exact.engineering
# 	make run_db.systems.exact.engineering

# ###############################################################################
# # Locally host development containers(dev.exact.engineering domain)
# ###############################################################################
# .PHONY: dev.exact.engineering
# dev.exact.engineering:
# 	@echo "Starting containers for development domain(dev.exact.engineering/$(CURRENT_BRANCH))..."
# 	@if [ "$(CURRENT_BRANCH)" != "dev" ] && [[ ! "$(CURRENT_BRANCH)" =~ ^scope ]]; then \
# 		echo "Error: This command can only be run from the 'dev' branch or a branch starting with 'scope'"; \
# 		exit 1; \
# 	fi
# 	make clean
# 	make run_devenv
# 	make devenv_documentation
# 	make devenv_apiSpecification
# 	make devenv_apiDocumentation
# 	make devenv_npmbuild
# 	make run_dev.exact.engineering
# 	make devenv_npmwatch