From 466725d46958468dc8dc3a81cc859365ddce9ce0 Mon Sep 17 00:00:00 2001
From: Lucendio <dev@lucend.io>
Date: Sun, 4 Apr 2021 02:39:42 +0200
Subject: [PATCH] Remove dependency installation & rework build example

* removed hack folder and with it all code to install deps
* reworked `make build` to show more explicitly what needs to be done when
  producing an artifact
* bumped node version dep to v14 (to make jest work again)
* adjusted readme
* suppress console output when running jest client tests
---
 .gitignore                                    |   3 +
 Makefile                                      |  89 ++++------
 README.md                                     |  57 ++-----
 app/client/src/App.test.js                    |  26 +--
 .../server/dev.mongod.conf                    |   0
 hack/Makefile                                 | 152 ------------------
 hack/versions/mongodb.256.sums                |   2 -
 hack/versions/nodejs.256.sums                 |   2 -
 8 files changed, 66 insertions(+), 265 deletions(-)
 rename hack/local.mongod.conf => app/server/dev.mongod.conf (100%)
 delete mode 100644 hack/Makefile
 delete mode 100644 hack/versions/mongodb.256.sums
 delete mode 100644 hack/versions/nodejs.256.sums

diff --git a/.gitignore b/.gitignore
index a103539..4a7cd41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
 .local
+
+# macos
+.DS_Store
diff --git a/Makefile b/Makefile
index 27134b4..3154eea 100644
--- a/Makefile
+++ b/Makefile
@@ -4,27 +4,19 @@ SHELL = /usr/bin/env bash -eo pipefail
 
 
 MKFILE_DIR = $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
-LOCAL_DIR = $(abspath $(MKFILE_DIR)/.local)
+LOCAL_DIR := $(abspath $(MKFILE_DIR)/.local)
 
 
-DATA_DIR = $(LOCAL_DIR)/data
-LOG_DIR = $(LOCAL_DIR)/logs
+DATA_DIR := $(LOCAL_DIR)/data
+LOG_DIR  := $(LOCAL_DIR)/logs
+TEMP_DIR := $(LOCAL_DIR)/temp
 
 
 APP_NODE_MODULE_DIRS = $(foreach dir, client server, $(subst %,$(dir),$(MKFILE_DIR)/app/%/node_modules))
 
 
-# NOTE: make sure to use binaries installed via ./hack/Makefile if exist
-export PATH := $(LOCAL_DIR)/bin:$(PATH)
-
-
-
-
-default: all
-
-all: install build
-
 
+default: install build
 
 
 .PHONY: install
@@ -40,21 +32,29 @@ $(LOCAL_DIR)/%/:
 
 .PHONY: clean
 clean:
-	for nodeModulesDir in $(APP_NODE_MODULE_DIRS); do \
-		rm -rf "$${nodeModulesDir}"; \
-	done
+	rm -rf \
+		$(APP_NODE_MODULE_DIRS) \
+		$(TEMP_DIR) \
+		$(LOCAL_DIR)/dist
 
 
 
 .PHONY: build
-build: CLIENT_BUILD_PATH ?= $(MKFILE_DIR)/app/server/src/public
-build: SERVER_PUBLIC_URL ?= http://localhost:3000
+build: SERVER_PUBLIC_URL ?= http://127.0.0.1:3001
+build: APP_BUILD_PATH ?= $(TEMP_DIR)
 build:
-	rm -rf $(CLIENT_BUILD_PATH)
+	rm -rf $(APP_BUILD_PATH)
+
+	cp -r $(MKFILE_DIR)/app/server/src $(APP_BUILD_PATH)
+	cp $(MKFILE_DIR)/app/server/package* $(APP_BUILD_PATH)/
+	cd $(APP_BUILD_PATH) \
+	&& \
+		npm install --prod --no-audit --no-fund \
+		&& rm -rf ./package*
 	cd $(MKFILE_DIR)/app/client \
 	&& \
 		PUBLIC_URL=$(SERVER_PUBLIC_URL) \
-		BUILD_PATH=$(CLIENT_BUILD_PATH) \
+		BUILD_PATH=$(APP_BUILD_PATH)/public \
 		node ./scripts/build.js
 
 
@@ -81,27 +81,32 @@ dev-test-client:
 
 
 .PHONY: dev-start-db
-dev-start-db: | $(LOG_DIR)/ $(DATA_DIR)/
-	mkdir -p $(DATA_DIR)/db
-	mongod --config $(MKFILE_DIR)/hack/local.mongod.conf
+dev-start-db: $(LOG_DIR)/ $(DATA_DIR)/ $(DATA_DIR)/db/
+	mongod --config $(MKFILE_DIR)/app/server/dev.mongod.conf
 
 
 .PHONY: dev-start-app
-dev-start-app: build
+dev-start-app:
+	cd $(MKFILE_DIR)/app/client \
+	&& \
+		PUBLIC_URL=$(SERVER_PUBLIC_URL) \
+		BUILD_PATH=$(MKFILE_DIR)/app/server/src/public \
+		node ./scripts/build.js
 	cd $(MKFILE_DIR)/app/server \
 	&& npm run start:dev
 
 
 
 .PHONY: run
+run: BUILD_PATH = $(LOCAL_DIR)/dist
 run: PUBLIC_URL = http://localhost
-run: SERVER_PORT = 3001
+run: SERVER_PORT = 3000
 run: DB_HOST = localhost
 run: DB_PORT = 27017
-run: | $(DATA_DIR)/ $(LOG_DIR)/
-	mkdir -p $(DATA_DIR)/db
-
-	make build SERVER_PUBLIC_URL=$(PUBLIC_URL):$(SERVER_PORT)
+run: $(DATA_DIR)/ $(LOG_DIR)/ $(DATA_DIR)/db/
+	make build \
+		APP_BUILD_PATH=$(BUILD_PATH) \
+		SERVER_PUBLIC_URL=$(PUBLIC_URL):$(SERVER_PORT)
 
 	(exec mongod \
 		--port $(DB_PORT) \
@@ -113,31 +118,7 @@ run: | $(DATA_DIR)/ $(LOG_DIR)/
 	(PORT=$(SERVER_PORT) \
 	MONGODB_URL=mongodb://$(DB_HOST):$(DB_PORT)/todo-app \
 	JWT_SECRET=myjwtsecret \
-	exec node $(MKFILE_DIR)/app/server/src/index.js \
+	exec node $(BUILD_PATH)/index.js \
 	) & PIDS[2]=$$!; \
 	\
 	for PID in $${PIDS[*]}; do wait $${PID}; done;
-
-
-
-
-.PHONY: deps
-deps:
-	NODEJS_VERSION=12.21.0  \
-	NPM_VERSION=6.14.11     \
-	MONGODB_VERSION=4.2.12  \
-		make -C $(MKFILE_DIR)/hack \
-		install
-	@echo ''
-	@echo 'In order to use the installed dependencies, the $$PATH variable must be adjusted.'
-	@echo 'Run:'
-	@echo ''
-	@echo '  export PATH=$$(pwd)/.local/bin:$${PATH}'
-	@echo ''
-
-
-.PHONY: nuke
-nuke:
-	cd $(MKFILE_DIR)/hack \
-		&& make clean
-	make clean
diff --git a/README.md b/README.md
index d6e3d69..8b04bc0 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ Additionally, it documents various invocations that may help you adapting this a
 **_Please note, that the `Makefile` is only meant to showcase steps that are usually needed to be taken in order to
 automate the deployment lifecycle of such an application and code base.
 It is NOT recommended to invoke `make` targets from the CI/CD, but rather to utilize platform-specific interfaces 
-(e.g. `Jenkinsfile`, `.travis.yml`, etc.), which may then invoke commands shown in the `make` target or in the `scripts`
+(e.g. `.gitlab-ci.yml`, `Jenkinsfile`, etc.), which may then invoke commands shown in the `make` target or in the `scripts`
  section of one of the `package.json` files._**
 
 
@@ -26,39 +26,16 @@ It is NOT recommended to invoke `make` targets from the CI/CD, but rather to uti
 
 The following software must be installed and available in your `${PATH}`:
 
-* `node` ([NodeJS](https://nodejs.org/en/download)) 
-* `npm` ([npm](https://www.npmjs.com/get-npm))
-* `mongod` ([MongoDB](https://docs.mongodb.com/manual/installation/))
+* `node` ([NodeJS](https://nodejs.org/en/download)): latest v14
+* `npm` ([npm](https://www.npmjs.com/get-npm)): latest v6
+* `mongod` ([MongoDB](https://docs.mongodb.com/manual/installation/)): latest v4.2
 
-*NOTE: [required versions](https://github.com/lucendio/lecture-devops-app/blob/master/hack/Makefile#L18-L20)*
-
-
-#### Option 1
+*NOTE: the application in this repository has not been tested with versions newer than that*
 
 Choose for yourself how you want to install these dependencies. Perhaps you can use the package manager
 available on your operating system, or maybe you prefer using container images. 
 
 
-#### Option 2
-
-Install all executables via `Makefile` into this project structure.
-
-a) from the root directory:
-```sh
-make deps
-```
-
-b) from the `./hack` folder:
-```sh
-$(cd ./hack && make install)
-```
-
-__Don't forget to add the new folder (`./.local/bin` ) to your `${PATH}` variable in your shell environment:__ 
-```sh
-export PATH=$(pwd)/.local/bin:${PATH}
-```
-
-
 ### Commands
 
 The following commands are available from the root directory:
@@ -71,13 +48,15 @@ The following commands are available from the root directory:
 
 #### `make build`
 
-* builds the client code
-* copies it over into the server
+1. copies server source into some empty location
+2. copies dependency manifest (`package*`) into the same location right next to the server source
+3. installs server dependencies
+4. builds client code (requires client dependencies to be installed already) and puts it next to the server source into   
 
 
 #### `make test`
 
-*NOTE: requires a MongoDB service to already run (see `MONGODB_URL` in target on where it's assumed to be running)*
+*NOTE: requires a MongoDB service already ro be running (see `MONGODB_URL` in target on where it's assumed to be running)*
 
 * runs client & server tests in [CI mode](https://jestjs.io/docs/en/cli.html#--ci) (exits regardless of the test outcome; closed tty)
 
@@ -101,8 +80,8 @@ The following commands are available from the root directory:
 *NOTE (1): only demonstrates a use case during local development and are not meant to run in any other context (e.g. automation)*
 *NOTE (2): it might be desired to first start a database service (e.g. `make dev-start-db`)*
 
-* builds client (see `make build`) 
-* starts server in development mode and with development configuration
+* builds client
+* starts server in development mode with development configuration
 
 
 #### `make run`
@@ -119,14 +98,4 @@ The following commands are available from the root directory:
 #### `make clean`
 
 * removes all `node_modules` dependencies that have been installed locally via `npm`
-
-
-#### `make deps`
-
-* installs the software prerequisites as prebuild binaries locally in `.local/bin`
-
-
-#### `make nuke`
-
-* removes all `npm` dependencies (see `make clean`)
-* throws away `.local` folder and thus all software prerequisites that were installed within it
+* removes other temporarily created folder in `.local` 
diff --git a/app/client/src/App.test.js b/app/client/src/App.test.js
index 9170134..af56110 100644
--- a/app/client/src/App.test.js
+++ b/app/client/src/App.test.js
@@ -2,13 +2,17 @@ import React from 'react';
 import { render, waitForElement, fireEvent } from '@testing-library/react';
 import App from './App';
 
+// NOTE: suppress virtual console output
+console.error = ()=>{};
+
+
 test.skip('renders header title "ToDo App"', () => {
   const { getByText } = render(<App />);
   const linkElement = getByText(/ToDo App/i);
   expect(linkElement).toBeInTheDocument();
 });
 
-test('renders a header title', () => {
+test('renders a header container', () => {
   const { container } = render(<App />);
   const header = container.querySelector('.header-main')
   expect(header).toHaveTextContent(/.+/);
@@ -16,18 +20,18 @@ test('renders a header title', () => {
 
 test('renders a login form', async () => {
   const { getByText } = render(<App />);
-  await waitForElement(() => getByText(/Sign in/i))
-  await waitForElement(() => getByText(/Email/i))
-  await waitForElement(() => getByText(/Password/i))
-  await waitForElement(() => getByText(/Login/i))
+  await waitForElement(() => getByText(/Sign in/i));
+  await waitForElement(() => getByText(/Email/i));
+  await waitForElement(() => getByText(/Password/i));
+  await waitForElement(() => getByText(/Login/i));
 });
 
 test('renders registration form when register button clicked', async () => {
   const { getByText } = render(<App />);
-  await waitForElement(() => getByText(/Signup/i))
-  fireEvent.click(getByText('Signup'))
-  await waitForElement(() => getByText(/Your name/i))
-  await waitForElement(() => getByText(/Your email/i))
-  await waitForElement(() => getByText(/Your password/i))
-  await waitForElement(() => getByText(/Create User/i))
+  await waitForElement(() => getByText(/Signup/i));
+  fireEvent.click(getByText('Signup'));
+  await waitForElement(() => getByText(/Your name/i));
+  await waitForElement(() => getByText(/Your email/i));
+  await waitForElement(() => getByText(/Your password/i));
+  await waitForElement(() => getByText(/Create User/i));
 });
diff --git a/hack/local.mongod.conf b/app/server/dev.mongod.conf
similarity index 100%
rename from hack/local.mongod.conf
rename to app/server/dev.mongod.conf
diff --git a/hack/Makefile b/hack/Makefile
deleted file mode 100644
index 53a4944..0000000
--- a/hack/Makefile
+++ /dev/null
@@ -1,152 +0,0 @@
-.DEFAULT_GOAL := default
-SHELL = /usr/bin/env bash -eo pipefail
-
-
-
-MKFILE_DIR = $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
-PLATFORM := $(shell if echo $$OSTYPE | grep -q darwin; then echo darwin; else echo linux; fi)
-LOCAL_DIR = $(abspath $(MKFILE_DIR)/../.local)
-
-
-BIN_DIR = $(LOCAL_DIR)/bin
-LIB_DIR = $(LOCAL_DIR)/lib
-TEMP_DIR = $(LOCAL_DIR)/tmp
-
-
-
-# next LTS: 14.13.0
-NODEJS_VERSION ?= 12.21.0
-NPM_VERSION ?= 6.14.11
-MONGODB_VERSION ?= 4.2.12
-
-REACT_APP_VERSION = 3.4.1
-
-
-
-NODEJS_URL = https://nodejs.org/dist/v$(NODEJS_VERSION)/node-v$(NODEJS_VERSION)-$(PLATFORM)-x64.tar.gz
-NODEJS_ARTIFACT = $(TEMP_DIR)/node-v$(NODEJS_VERSION)-$(PLATFORM)-x64.tar.gz
-NODEJS_ARCHIVE = $(patsubst %.tar.gz,%,$(notdir $(NODEJS_ARTIFACT)))
-NODEJS_BIN = $(BIN_DIR)/node
-NPM_BIN = $(BIN_DIR)/npm
-NODEJS_SHA256 ?= $(shell cat $(MKFILE_DIR)/versions/nodejs.256.sums | grep v$(NODEJS_VERSION)-$(PLATFORM)-x64 | awk '{ print $$ 1 }')
-
-
-ifeq ($(PLATFORM), darwin)
-MONGODB_URL = https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-$(MONGODB_VERSION).tgz
-else ifeq ($(PLATFORM), linux)
-# NOTE: hard-coded Debian version. Others can be found here: https://www.mongodb.com/download-center/community
-MONGODB_URL = https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-debian10-$(MONGODB_VERSION).tgz
-else
-	fail 'Unknown platform. No condition met'
-endif
-MONGODB_ARTIFACT = $(TEMP_DIR)/mongodb-$(PLATFORM)-$(MONGODB_VERSION).tar.gz
-MONGODB_ARCHIVE = $(patsubst %.tar.gz,%,$(notdir $(MONGODB_ARTIFACT)))
-MONGODB_BIN = $(BIN_DIR)/mongod
-MONGODB_SHA256 ?= $(shell cat $(MKFILE_DIR)/versions/mongodb.256.sums | grep $(PLATFORM)-x86_64-$(MONGODB_VERSION) | awk '{ print $$ 1 }')
-
-
-
-
-default: all
-
-all: install
-
-
-
-.PHONY: install
-install: node npm mongod
-
-
-$(LOCAL_DIR)/%/:
-	mkdir -p $(@)
-
-
-.PHONY: clean
-clean:
-	rm -rf \
-		$(LOCAL_DIR)
-
-
-
-.PHONY: node
-node: $(NODEJS_BIN)
-$(NODEJS_BIN): | $(NODEJS_ARTIFACT) $(BIN_DIR)/
-	@ [ $$(openssl dgst -sha256 "$(NODEJS_ARTIFACT)" | awk '{ print $$ 2 }') == $(NODEJS_SHA256) ] || ( echo "Invalid SHA256." && rm $(NODEJS_ARTIFACT) && exit 1 )
-	tar \
-		--extract \
-		--verbose \
-		--strip-components 2 \
-		--directory "$(BIN_DIR)" \
-		--file "$(NODEJS_ARTIFACT)" \
-		$(NODEJS_ARCHIVE)/bin/node
-	chmod +x "$@"
-
-$(NODEJS_ARTIFACT): | $(TEMP_DIR)/
-	curl \
-		--silent --show-error \
-		--location \
-		$(NODEJS_URL) \
-		> $(NODEJS_ARTIFACT)
-
-
-.PHONY: npm
-npm: $(NPM_BIN)
-npm: export PATH := $(BIN_DIR):$(PATH)
-$(NPM_BIN): | $(NODEJS_BIN)
-	mkdir -p $(LIB_DIR)
-	tar \
-		--extract \
-		--verbose \
-		--strip-components 2 \
-		--directory "$(LIB_DIR)" \
-		--file "$(NODEJS_ARTIFACT)" \
-		$(NODEJS_ARCHIVE)/lib/node_modules
-	chmod +x $(LIB_DIR)/node_modules/npm/bin/npm-cli.js
-	ln -s $(LIB_DIR)/node_modules/npm/bin/npm-cli.js $(NPM_BIN)
-	npm install -g npm@$(NPM_VERSION)
-
-
-.PHONY: mongod
-mongod: $(MONGODB_BIN)
-$(MONGODB_BIN): | $(MONGODB_ARTIFACT) $(BIN_DIR)/
-	@ [ $$(openssl dgst -sha256 "$(MONGODB_ARTIFACT)" | awk '{ print $$ 2 }') == $(MONGODB_SHA256) ] || ( echo "Invalid SHA256." && rm $(MONGODB_ARTIFACT) && exit 1 )
-	mkdir -p $(TEMP_DIR)/$(MONGODB_ARCHIVE)
-	tar \
-		--extract \
-		--verbose \
-		--strip-components 2 \
-		--directory "$(TEMP_DIR)/$(MONGODB_ARCHIVE)" \
-		--file "$(MONGODB_ARTIFACT)"
-	mv $(TEMP_DIR)/$(MONGODB_ARCHIVE)/mongod "$@"
-	chmod +x "$@"
-	rm -rf $(TEMP_DIR)/$(MONGODB_ARCHIVE)
-
-$(MONGODB_ARTIFACT): | $(TEMP_DIR)/
-	curl \
-		--silent --show-error \
-		--location \
-		$(MONGODB_URL) \
-		> $(MONGODB_ARTIFACT)
-
-
-
-
-.PHONY: update-react-app-template
-update-react-app-template: export PATH := $(BIN_DIR):$(PATH)
-update-react-app-template:
-	rm -rf $(TEMP_DIR)/npm-project-scope
-	mkdir -p $(TEMP_DIR)/npm-project-scope
-	cd $(TEMP_DIR)/npm-project-scope \
-		&& npm install --save-dev react-scripts@$(REACT_APP_VERSION) \
-		&& npm init react-app $(TEMP_DIR)/npm-project-scope/cra
-	cp \
-		$(TEMP_DIR)/npm-project-scope/cra/src/* \
-		$(MKFILE_DIR)/../app/client/src/
-	cp \
-		$(TEMP_DIR)/npm-project-scope/cra/public/* \
-		$(MKFILE_DIR)/../app/client/public/
-	cp \
-		$(TEMP_DIR)/npm-project-scope/cra/package.json \
-		$(MKFILE_DIR)/../app/client/
-	rm -rf \
-		$(MKFILE_DIR)/../app/client/src/logo.svg
diff --git a/hack/versions/mongodb.256.sums b/hack/versions/mongodb.256.sums
deleted file mode 100644
index 8800f19..0000000
--- a/hack/versions/mongodb.256.sums
+++ /dev/null
@@ -1,2 +0,0 @@
-36e7355b133a15c12e2fb5e8fefef354a99ffa048906cd855d639064f0f795b6 mongodb-linux-x86_64-4.2.12.tgz
-06adf7b23ad3a3d97ae688d9001221c6cb263392ef74f3e265129b9b77b0a2e2 mongodb-darwin-x86_64-4.2.12.tgz
diff --git a/hack/versions/nodejs.256.sums b/hack/versions/nodejs.256.sums
deleted file mode 100644
index bd622da..0000000
--- a/hack/versions/nodejs.256.sums
+++ /dev/null
@@ -1,2 +0,0 @@
-ab121de3c472d76ec425480b0594e43109ee607bd57c3d5314bdb65fa816bf1c node-v12.21.0-linux-x64.tar.gz
-4d0b5d07d41a16909fdeb41c3158c27bcdccf16231cccf76d5eb6835e2076e90 node-v12.21.0-darwin-x64.tar.gz
-- 
GitLab