From cf79f0de0adccbd8812ed23a3d0a013cd5af7ff8 Mon Sep 17 00:00:00 2001 From: Nabarun Gogoi Date: Tue, 18 Apr 2023 18:25:58 +0530 Subject: [PATCH] Package mobymask-v2 stack web-apps similar to laconic-console app (#310) * Build MobyMask web-app at container build step * Fix web-app start script to use env variables in config * Replace variables in built web-app files * Use published mobymask-ui package from gitea * Use published react-peer/test-app from gitea * Remove local gitea publish TODO --- .../compose/docker-compose-mobymask-app.yml | 11 ++-- .../compose/docker-compose-peer-test-app.yml | 9 ++- .../mobymask-app-config.json | 7 --- .../watcher-mobymask-v2/mobymask-app-start.sh | 17 +++--- .../watcher-mobymask-v2/test-app-start.sh | 10 +--- .../cerc-mobymask-ui/Dockerfile | 59 ++++++++++++++++--- .../cerc-mobymask-ui/apply-webapp-config.sh | 42 +++++++++++++ .../container-build/cerc-mobymask-ui/build.sh | 5 +- .../cerc-mobymask-ui/start-serving-app.sh | 9 +++ .../cerc-react-peer/Dockerfile | 30 +++++++--- .../cerc-react-peer/apply-webapp-config.sh | 42 +++++++++++++ .../container-build/cerc-react-peer/build.sh | 5 +- .../cerc-react-peer/start-serving-app.sh | 9 +++ .../fixturenet-laconic-loaded/README.md | 2 +- app/data/stacks/mobymask-v2/README.md | 4 +- app/data/stacks/mobymask-v2/web-apps.md | 6 +- 16 files changed, 210 insertions(+), 57 deletions(-) delete mode 100644 app/data/config/watcher-mobymask-v2/mobymask-app-config.json create mode 100755 app/data/container-build/cerc-mobymask-ui/apply-webapp-config.sh create mode 100755 app/data/container-build/cerc-mobymask-ui/start-serving-app.sh create mode 100755 app/data/container-build/cerc-react-peer/apply-webapp-config.sh create mode 100755 app/data/container-build/cerc-react-peer/start-serving-app.sh diff --git a/app/data/compose/docker-compose-mobymask-app.yml b/app/data/compose/docker-compose-mobymask-app.yml index df14d7db..6df48130 100644 --- a/app/data/compose/docker-compose-mobymask-app.yml +++ b/app/data/compose/docker-compose-mobymask-app.yml @@ -3,6 +3,7 @@ version: '3.2' services: # Builds and serves the MobyMask react-app mobymask-app: + restart: unless-stopped image: cerc/mobymask-ui:local env_file: - ../config/watcher-mobymask-v2/mobymask-params.env @@ -12,6 +13,7 @@ services: CERC_DEPLOYED_CONTRACT: ${CERC_DEPLOYED_CONTRACT} CERC_APP_WATCHER_URL: ${CERC_APP_WATCHER_URL} CERC_RELAY_NODES: ${CERC_RELAY_NODES} + working_dir: /scripts # Waits for watcher server to be up before app build # Required when running with watcher stack to get deployed contract address command: @@ -19,15 +21,14 @@ services: - -c - ./wait-for-it.sh -h ${CERC_WATCHER_HOST:-$${DEFAULT_CERC_WATCHER_HOST}} -p ${CERC_WATCHER_PORT:-$${DEFAULT_CERC_WATCHER_PORT}} -s -t 0 -- ./mobymask-app-start.sh volumes: - - ../config/wait-for-it.sh:/app/wait-for-it.sh - - ../config/watcher-mobymask-v2/mobymask-app-config.json:/app/src/mobymask-app-config.json - - ../config/watcher-mobymask-v2/mobymask-app-start.sh:/app/mobymask-app-start.sh + - ../config/wait-for-it.sh:/scripts/wait-for-it.sh + - ../config/watcher-mobymask-v2/mobymask-app-start.sh:/scripts/mobymask-app-start.sh - peers_ids:/peers - mobymask_deployment:/server ports: - - "0.0.0.0:3002:3000" + - "0.0.0.0:3002:80" healthcheck: - test: ["CMD", "nc", "-v", "localhost", "3000"] + test: ["CMD", "nc", "-v", "localhost", "80"] interval: 20s timeout: 5s retries: 15 diff --git a/app/data/compose/docker-compose-peer-test-app.yml b/app/data/compose/docker-compose-peer-test-app.yml index 7d1b89d6..0a8d1c65 100644 --- a/app/data/compose/docker-compose-peer-test-app.yml +++ b/app/data/compose/docker-compose-peer-test-app.yml @@ -4,7 +4,7 @@ services: peer-test-app: # Builds and serves the peer-test react-app image: cerc/react-peer:local - working_dir: /app/packages/test-app + working_dir: /scripts env_file: - ../config/watcher-mobymask-v2/mobymask-params.env environment: @@ -12,13 +12,12 @@ services: CERC_RELAY_NODES: ${CERC_RELAY_NODES} command: ["sh", "./test-app-start.sh"] volumes: - - ../config/watcher-mobymask-v2/test-app-config.json:/app/packages/test-app/src/test-app-config.json - - ../config/watcher-mobymask-v2/test-app-start.sh:/app/packages/test-app/test-app-start.sh + - ../config/watcher-mobymask-v2/test-app-start.sh:/scripts/test-app-start.sh - peers_ids:/peers ports: - - "0.0.0.0:3003:3000" + - "0.0.0.0:3003:80" healthcheck: - test: ["CMD", "nc", "-v", "localhost", "3000"] + test: ["CMD", "nc", "-v", "localhost", "80"] interval: 20s timeout: 5s retries: 15 diff --git a/app/data/config/watcher-mobymask-v2/mobymask-app-config.json b/app/data/config/watcher-mobymask-v2/mobymask-app-config.json deleted file mode 100644 index ed913b51..00000000 --- a/app/data/config/watcher-mobymask-v2/mobymask-app-config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "MobyMask", - "relayNodes": [], - "peer": { - "enableDebugInfo": true - } -} diff --git a/app/data/config/watcher-mobymask-v2/mobymask-app-start.sh b/app/data/config/watcher-mobymask-v2/mobymask-app-start.sh index c494ed5c..0437d22d 100755 --- a/app/data/config/watcher-mobymask-v2/mobymask-app-start.sh +++ b/app/data/config/watcher-mobymask-v2/mobymask-app-start.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash set -e if [ -n "$CERC_SCRIPT_DEBUG" ]; then set -x @@ -28,13 +28,10 @@ else echo "Taking deployed contract details from env" fi -# Export config values in a json file -jq --arg address "$CERC_DEPLOYED_CONTRACT" \ - --argjson chainId "$CERC_CHAIN_ID" \ - --argjson relayNodes "$CERC_RELAY_NODES" \ - '.address = $address | .chainId = $chainId | .relayNodes = $relayNodes' \ - /app/src/mobymask-app-config.json > /app/src/config.json +# Use yq to create config.yml with environment variables +yq -n ".address = env(CERC_DEPLOYED_CONTRACT)" > /config/config.yml +yq ".watcherUrl = env(CERC_APP_WATCHER_URL)" -i /config/config.yml +yq ".chainId = env(CERC_CHAIN_ID)" -i /config/config.yml +yq ".relayNodes = strenv(CERC_RELAY_NODES)" -i /config/config.yml -REACT_APP_WATCHER_URI="$CERC_APP_WATCHER_URL/graphql" npm run build - -serve -s build +/scripts/start-serving-app.sh diff --git a/app/data/config/watcher-mobymask-v2/test-app-start.sh b/app/data/config/watcher-mobymask-v2/test-app-start.sh index ef7aa539..42e4397d 100755 --- a/app/data/config/watcher-mobymask-v2/test-app-start.sh +++ b/app/data/config/watcher-mobymask-v2/test-app-start.sh @@ -14,11 +14,7 @@ fi echo "Using CERC_RELAY_NODES $CERC_RELAY_NODES" -# Set relay nodes in config using CERC_RELAY_NODES -jq --argjson relayNodes "$CERC_RELAY_NODES" \ - '.relayNodes = $relayNodes' \ - ./src/test-app-config.json > ./src/config.json +# Use yq to create config.yml with environment variables +yq -n ".relayNodes = strenv(CERC_RELAY_NODES)" > /config/config.yml -yarn build - -serve -s build +/scripts/start-serving-app.sh diff --git a/app/data/container-build/cerc-mobymask-ui/Dockerfile b/app/data/container-build/cerc-mobymask-ui/Dockerfile index c04b001d..3f04ec45 100644 --- a/app/data/container-build/cerc-mobymask-ui/Dockerfile +++ b/app/data/container-build/cerc-mobymask-ui/Dockerfile @@ -1,14 +1,57 @@ -FROM node:18.15.0-alpine3.16 +# Originally from: https://github.com/devcontainers/images/blob/main/src/javascript-node/.devcontainer/Dockerfile +# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster +ARG VARIANT=16-bullseye +FROM node:${VARIANT} -RUN apk --update --no-cache add make git jq bash +ARG USERNAME=node +ARG NPM_GLOBAL=/usr/local/share/npm-global -WORKDIR /app +# This container pulls npm package from a registry configured via env var +ARG CERC_NPM_REGISTRY_URL -COPY . . +# Add NPM global to PATH. +ENV PATH=${NPM_GLOBAL}/bin:${PATH} +# Prevents npm from printing version warnings +ENV NPM_CONFIG_UPDATE_NOTIFIER=false -RUN npm install -g serve +RUN \ + # Configure global npm install location, use group to adapt to UID/GID changes + if ! cat /etc/group | grep -e "^npm:" > /dev/null 2>&1; then groupadd -r npm; fi \ + && usermod -a -G npm ${USERNAME} \ + && umask 0002 \ + && mkdir -p ${NPM_GLOBAL} \ + && touch /usr/local/etc/npmrc \ + && chown ${USERNAME}:npm ${NPM_GLOBAL} /usr/local/etc/npmrc \ + && chmod g+s ${NPM_GLOBAL} \ + && npm config -g set prefix ${NPM_GLOBAL} \ + && su ${USERNAME} -c "npm config -g set prefix ${NPM_GLOBAL}" \ + # Install eslint + && su ${USERNAME} -c "umask 0002 && npm install -g eslint" \ + && npm cache clean --force > /dev/null 2>&1 -RUN echo "Building mobymask-ui" && \ - npm install +# Install additional OS packages. +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends jq bash -WORKDIR /app +# We do this to get a yq binary from the published container, for the correct architecture we're building here +COPY --from=docker.io/mikefarah/yq:latest /usr/bin/yq /usr/local/bin/yq + +RUN mkdir -p /scripts +COPY ./apply-webapp-config.sh /scripts +COPY ./start-serving-app.sh /scripts + +# Configure the local npm registry +RUN npm config set @cerc-io:registry ${CERC_NPM_REGISTRY_URL} + +RUN mkdir -p /config + +# Install simple web server for now (use nginx perhaps later) +RUN yarn global add http-server + +# Globally install the payload web app package +RUN yarn global add @cerc-io/mobymask-ui + +# Expose port for http +EXPOSE 80 + +CMD ["/scripts/start-serving-app.sh"] diff --git a/app/data/container-build/cerc-mobymask-ui/apply-webapp-config.sh b/app/data/container-build/cerc-mobymask-ui/apply-webapp-config.sh new file mode 100755 index 00000000..9f32cd23 --- /dev/null +++ b/app/data/container-build/cerc-mobymask-ui/apply-webapp-config.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi +if [[ $# -ne 3 ]]; then + echo "Illegal number of parameters" >&2 + exit 1 +fi +config_file_name=$1 +webapp_files_dir=$2 +config_prefix=$3 +if ! [[ -f ${config_file_name} ]]; then + echo "Config file ${config_file_name} does not exist" >&2 + exit 1 +fi +if ! [[ -d ${webapp_files_dir} ]]; then + echo "Webapp directory ${webapp_files_dir} does not exist" >&2 + exit 1 +fi +# First some magic using sed to translate our yaml config file into an array of key value pairs like: +# ${config_prefix}= +# sed "s/'//g" is used to remove single quote for relayNodes value +readarray -t config_kv_pair_array < <( sed -E 's/([^:]+):\s*(.*)/\1=\2/g' ${config_file_name} | sed "s/'//g" | sed "s/^/${config_prefix}_/" ) +declare -p config_kv_pair_array +# Then iterate over that kv array making the template substitution in our web app files +for kv_pair_string in "${config_kv_pair_array[@]}" +do + kv_pair=(${kv_pair_string//=/ }) + template_string_to_replace=${kv_pair[0]} + template_value_to_substitute=${kv_pair[1]} + # Run find and sed to do the substitution of one variable over all files + # See: https://stackoverflow.com/a/21479607/1701505 + echo "Substituting: ${template_string_to_replace} = ${template_value_to_substitute}" + + # TODO: Pass keys to be replaced without double quotes + if [[ "$template_string_to_replace" =~ ^${config_prefix}_(relayNodes|chainId)$ ]]; then + find ${webapp_files_dir} -type f -exec sed -i 's#"'"${template_string_to_replace}"'"#'"${template_value_to_substitute}"'#g' {} + + else + # Note: we do not escape our strings, on the expectation they do not container the '#' char. + find ${webapp_files_dir} -type f -exec sed -i 's#'${template_string_to_replace}'#'${template_value_to_substitute}'#g' {} + + fi +done diff --git a/app/data/container-build/cerc-mobymask-ui/build.sh b/app/data/container-build/cerc-mobymask-ui/build.sh index 52687093..7628ff5c 100755 --- a/app/data/container-build/cerc-mobymask-ui/build.sh +++ b/app/data/container-build/cerc-mobymask-ui/build.sh @@ -6,4 +6,7 @@ source ${CERC_CONTAINER_BASE_DIR}/build-base.sh # See: https://stackoverflow.com/a/246128/1701505 SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -docker build -t cerc/mobymask-ui:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/mobymask-ui +CERC_NPM_REGISTRY_URL="https://git.vdb.to/api/packages/cerc-io/npm/" + +docker build -t cerc/mobymask-ui:local ${build_command_args} -f ${SCRIPT_DIR}/Dockerfile \ + --build-arg CERC_NPM_REGISTRY_URL ${SCRIPT_DIR} diff --git a/app/data/container-build/cerc-mobymask-ui/start-serving-app.sh b/app/data/container-build/cerc-mobymask-ui/start-serving-app.sh new file mode 100755 index 00000000..4e0a976c --- /dev/null +++ b/app/data/container-build/cerc-mobymask-ui/start-serving-app.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +# TODO: Don't hard wire this: +webapp_files_dir=/usr/local/share/.config/yarn/global/node_modules/@cerc-io/mobymask-ui/build +/scripts/apply-webapp-config.sh /config/config.yml ${webapp_files_dir} MOBYMASK_HOSTED_CONFIG +http-server -p 80 ${webapp_files_dir} diff --git a/app/data/container-build/cerc-react-peer/Dockerfile b/app/data/container-build/cerc-react-peer/Dockerfile index fcc198f3..f60ba504 100644 --- a/app/data/container-build/cerc-react-peer/Dockerfile +++ b/app/data/container-build/cerc-react-peer/Dockerfile @@ -1,14 +1,30 @@ FROM node:18.15.0-alpine3.16 -RUN apk --update --no-cache add make git python3 jq +# This container pulls npm package from a registry configured via env var +ARG CERC_NPM_REGISTRY_URL -WORKDIR /app +RUN apk --update --no-cache add make git python3 jq bash -COPY . . +# We do this to get a yq binary from the published container, for the correct architecture we're building here +COPY --from=docker.io/mikefarah/yq:latest /usr/bin/yq /usr/local/bin/yq -RUN yarn global add serve +RUN mkdir -p /scripts +COPY ./apply-webapp-config.sh /scripts +COPY ./start-serving-app.sh /scripts -RUN echo "Building react-peer" && \ - yarn install --ignore-scripts && yarn build --ignore @cerc-io/test-app +# Configure the local npm registry +RUN npm config set @cerc-io:registry ${CERC_NPM_REGISTRY_URL} -WORKDIR /app +RUN mkdir -p /config + +# Install simple web server for now (use nginx perhaps later) +RUN yarn global add http-server + +# Globally install the payload web app package +RUN yarn global add @cerc-io/test-app + + +# Expose port for http +EXPOSE 80 + +CMD ["/scripts/start-serving-app.sh"] diff --git a/app/data/container-build/cerc-react-peer/apply-webapp-config.sh b/app/data/container-build/cerc-react-peer/apply-webapp-config.sh new file mode 100755 index 00000000..a7f0a28e --- /dev/null +++ b/app/data/container-build/cerc-react-peer/apply-webapp-config.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi +if [[ $# -ne 3 ]]; then + echo "Illegal number of parameters" >&2 + exit 1 +fi +config_file_name=$1 +webapp_files_dir=$2 +config_prefix=$3 +if ! [[ -f ${config_file_name} ]]; then + echo "Config file ${config_file_name} does not exist" >&2 + exit 1 +fi +if ! [[ -d ${webapp_files_dir} ]]; then + echo "Webapp directory ${webapp_files_dir} does not exist" >&2 + exit 1 +fi +# First some magic using sed to translate our yaml config file into an array of key value pairs like: +# ${config_prefix}= +# sed "s/'//g" is used to remove single quote for relayNodes value +readarray -t config_kv_pair_array < <( sed -E 's/([^:]+):\s*(.*)/\1=\2/g' ${config_file_name} | sed "s/'//g" | sed "s/^/${config_prefix}_/" ) +declare -p config_kv_pair_array +# Then iterate over that kv array making the template substitution in our web app files +for kv_pair_string in "${config_kv_pair_array[@]}" +do + kv_pair=(${kv_pair_string//=/ }) + template_string_to_replace=${kv_pair[0]} + template_value_to_substitute=${kv_pair[1]} + # Run find and sed to do the substitution of one variable over all files + # See: https://stackoverflow.com/a/21479607/1701505 + echo "Substituting: ${template_string_to_replace} = ${template_value_to_substitute}" + + # TODO: Pass keys to be replaced without double quotes + if [[ "$template_string_to_replace" == "${config_prefix}_relayNodes" ]]; then + find ${webapp_files_dir} -type f -exec sed -i 's#"'"${template_string_to_replace}"'"#'"${template_value_to_substitute}"'#g' {} + + else + # Note: we do not escape our strings, on the expectation they do not container the '#' char. + find ${webapp_files_dir} -type f -exec sed -i 's#'${template_string_to_replace}'#'${template_value_to_substitute}'#g' {} + + fi +done diff --git a/app/data/container-build/cerc-react-peer/build.sh b/app/data/container-build/cerc-react-peer/build.sh index 48edc4b3..7078b754 100755 --- a/app/data/container-build/cerc-react-peer/build.sh +++ b/app/data/container-build/cerc-react-peer/build.sh @@ -6,4 +6,7 @@ source ${CERC_CONTAINER_BASE_DIR}/build-base.sh # See: https://stackoverflow.com/a/246128/1701505 SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -docker build -t cerc/react-peer:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/react-peer +CERC_NPM_REGISTRY_URL="https://git.vdb.to/api/packages/cerc-io/npm/" + +docker build -t cerc/react-peer:local ${build_command_args} -f ${SCRIPT_DIR}/Dockerfile \ + --build-arg CERC_NPM_REGISTRY_URL ${SCRIPT_DIR} diff --git a/app/data/container-build/cerc-react-peer/start-serving-app.sh b/app/data/container-build/cerc-react-peer/start-serving-app.sh new file mode 100755 index 00000000..e01b91c3 --- /dev/null +++ b/app/data/container-build/cerc-react-peer/start-serving-app.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +# TODO: Don't hard wire this: +webapp_files_dir=/usr/local/share/.config/yarn/global/node_modules/@cerc-io/test-app/build +/scripts/apply-webapp-config.sh /config/config.yml ${webapp_files_dir} MOBYMASK_HOSTED_CONFIG +http-server -p 80 ${webapp_files_dir} diff --git a/app/data/stacks/fixturenet-laconic-loaded/README.md b/app/data/stacks/fixturenet-laconic-loaded/README.md index 2fc21594..b94189c2 100644 --- a/app/data/stacks/fixturenet-laconic-loaded/README.md +++ b/app/data/stacks/fixturenet-laconic-loaded/README.md @@ -14,7 +14,7 @@ $ chmod +x ./laconic-so $ export PATH=$PATH:$(pwd) # Or move laconic-so to ~/bin or your favorite on-path directory ``` ## 2. Prepare the local build environment -Note that this step needs only to be done once on a new machine. +Note that this step needs only to be done once on a new machine. Detailed instructions can be found [here](../build-support/README.md). For the impatient run these commands: ``` $ laconic-so --stack build-support build-containers --exclude cerc/builder-gerbil diff --git a/app/data/stacks/mobymask-v2/README.md b/app/data/stacks/mobymask-v2/README.md index 9dcca6c0..aaa4ac7f 100644 --- a/app/data/stacks/mobymask-v2/README.md +++ b/app/data/stacks/mobymask-v2/README.md @@ -27,11 +27,11 @@ git checkout v0.2.35 # react-peer cd ~/cerc/react-peer -git checkout v0.2.31 +git checkout v0.2.32 # mobymask-ui cd ~/cerc/mobymask-ui -git checkout laconic +git checkout v0.1.2 # MobyMask cd ~/cerc/MobyMask diff --git a/app/data/stacks/mobymask-v2/web-apps.md b/app/data/stacks/mobymask-v2/web-apps.md index 09d6834d..866f22f0 100644 --- a/app/data/stacks/mobymask-v2/web-apps.md +++ b/app/data/stacks/mobymask-v2/web-apps.md @@ -19,17 +19,17 @@ Checkout to the required versions and branches in repos: ```bash # react-peer cd ~/cerc/react-peer -git checkout v0.2.31 +git checkout v0.2.32 # mobymask-ui cd ~/cerc/mobymask-ui -git checkout laconic +git checkout v0.1.2 ``` Build the container images: ```bash -laconic-so --stack mobymask-v2 build-containers --include cerc/react-peer-v2,cerc/mobymask-ui +laconic-so --stack mobymask-v2 build-containers --include cerc/react-peer,cerc/mobymask-ui ``` This should create the required docker images in the local image registry