Menshen

Deployment

There are two major types of deployment:

  • Local development environment
  • Production environment

Local deployment

We will be using Docker to spin up a local development environment.

Our dockerfile will look like this

FROM ubuntu:18.04

RUN apt-get update && apt-get install \
    # install AWS CLI
	pip install awscli \
    # install Chrome 
    apt-get install libxss1 libappindicator1 libindicator7 libnss3 \
    wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
    dpkg -i google-chrome*.deb \
    apt-get install xvfb \
    export CHROME_BINARY_PATH=`which google-chrome-stable` \
    export PATH="$PATH:/path/to/project/directory/scripts/url_to_pdf.sh" \
    # install ChromeDriver
    sCHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` \
    wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/ \
    unzip ~/chromedriver_linux64.zip -d ~/ \
    rm ~/chromedriver_linux64.zip \
    ./chromedriver --url-base=/wd/hub \
    # install mimetypes
    # install Erlang and Elixir
    wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && dpkg -i erlang-solutions_1.0_all.deb \
    apt-get update \
    apt-get install esl-erlang \
    apt-get install elixir \
    # install postgres
    apt install postgresql postgresql-contrib \
    # get latest version of menshen and run
    git clone https://kudoo@bitbucket.org/kudoocloud/menshen.git \
    mix deps.get \
    mix ecto.reset \
    mix phx.server \

    # Need to open port 4000 and 9595 for Chromedriver
    # Need to add environment variables

Production deploymnet

Our production environment will be on Unbuntu Bionic Beaver 18.04

There are two major elements for our Deployment:

  1. Make sure the Production environment has all the correct prerequisites
  2. Creating the release and deploying to production

Environment

We will be using Ansible to automate the spinning up of our Production environment. The current prerequisites for deploying Menshen are:

  1. Python
  2. AWS
  3. Chrome, xvfb & Chromedriver
  4. Mimetypes

Python3 should come preinstalled on Bionic Beaver

AWS We use AWS in order to store uploaded files into S3 buckets. We currently have 3 buckets.

  • menshen-dev
  • menshen-test
  • menshen-prod

We need to make sure that the AWS CLI is installed on the Production server because of AWS S3 https://aws.amazon.com/cli/

So you’ll need to run the following command pip install awscli

Once you’ve installed the AWS CLI, then you’ll need to configure it https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html

Basically you’ll need to run aws configure

You’ll need to fill in the following details

  • AWS access key - Justin Trollip will have this
  • AWS secret key - Justin Trollip will have this
  • Default region name - Currently this is Sydney ap-southeast-2
  • Default output format - We can use json

Installed chrome

Google Chrome isn't in the repositories - however, Chromium is.

Google Chrome is only available for 64-bit Linux. I've included directions for 64 below.

To install Google Chrome, run the following:

sudo apt-get install libxss1 libappindicator1 libindicator7
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome*.deb

If error messages pop up after running the command sudo dpkg -i google-chrome*.deb then run the command

sudo apt-get install -f

and then re-run the previous command. The error messages mentioned should include something similar to

google-chrome-stable depends on [lib-example]; however; Package [lib-example] is not installed.

This installs a needed library for Google Chrome, then downloads the latest version of Chrome to a temporary directory and installs it. Run google-chrome to start the browser.

During the installation a PPA is added to your system so that Google Chrome receives the latest updates whenever you check for system updates.

Install xvfb

sudo apt-get install xvfb

Set chrome path

  1. Set path to chrome in CHROME_BINARY_PATH system environment variable
export CHROME_BINARY_PATH=`which google-chrome-stable` # Gentoo Linux chrome binary name

export PATH="$PATH:/path/to/project/directory/scripts/url_to_pdf.sh"

Note: I need to use sh file, because otherwise Chrome binary have some problems.

I think it’s because sh file is started by #!/bin/bash comment line and therefore some things are changed.

We require Chrome and ChromeDriver and started ChromeDriver before starting menshen.

Install Chromedriver

sCHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`

wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/

unzip ~/chromedriver_linux64.zip -d ~/

rm ~/chromedriver_linux64.zip

apt install libnss3

and finally start ChromeDriver server: ./chromedriver --url-base=/wd/hub

Add chromedriver to startup script

Use systemd to do this.

Debugging Chromedriver

To debug Chromedriver try this: run iex -S mix in the menshen directory

call Hound.start_session()

This should start Chrome.

Sometimes if Chrome isn’t your default browser there can be problems.

To have PDF generation working we need 3 things on every machine:

Mimetypes

https://github.com/mbeijen/File-MimeInfo

export AWS_ACCESS_KEY_ID="get from Justin"

export AWS_SECRET_ACCESS_KEY="get from Justin"

set PORT environment variable in .bashrc file to 4000 and prepared nginx to listen on that port

Release

  1. increase version number - regarding to semantic versioning

  2. mix edeliver stop production

  3. mix edeliver build release

  4. mix edeliver deploy release to production

  5. optionally run MIX_ENV=prod mix ecto.migrate in $HOME/app_build - at production server

  6. mix edeliver start production

Migrations
Go live

Environment variables

Deploying latest Menshen version

Testing

Generating data

Run iex -S mix and type: Fixture.company(). It will automatically create Company with all of its requirements.

Then you will be able to query it in GraphQL.

Fixture (aliased Menshen.Fixture) is created for tests only, so it can insert all valid data including: Fixture.user(%{is_root: true}) :

Menshen schema

Both Company and Customer have unique value of trader_id, because Trader is created automatically for them when they are created, so for example:

Customer id#1 trader_id#2 company_id#1

Customer id#2 trader_id#3 company_id#1

Company  id#2 trader_id#4

Customer id#3 trader_id#5 company_id#2```

Invoice stores `buyer_trader_id` from `Customer.trader_id` and `seller_trader_id` from `Company.trader_id`.