From 108e077742e430e0c92d251e380fd79fd5fb8882 Mon Sep 17 00:00:00 2001
From: Sebastien Dubois <seb@dsebastien.net>
Date: Mon, 23 Apr 2018 17:40:26 +0200
Subject: [PATCH] feat(build): added release and publish support. Closes #54.
 Closes #24. Closes #27

---
 .gitignore               |   2 +
 .release-it.json         |  47 +++++++++++
 .travis.yml              |   9 +-
 CHANGELOG.md             |  29 +++++++
 CONTRIBUTING.md          |  12 +--
 README.md                |   3 +
 RELEASE.md               |  57 +++++++++++++
 build-functions.sh       |  48 -----------
 build.sh                 |  39 ++++++---
 modules.txt              |   3 +
 package.json             |  21 +++--
 release-publish.sh       | 178 +++++++++++++++++++++++++++++++++++++++
 scripts/ci/print-logs.sh |  17 ++++
 util-functions.sh        |  49 +++++++++++
 14 files changed, 432 insertions(+), 82 deletions(-)
 create mode 100644 .release-it.json
 create mode 100644 CHANGELOG.md
 create mode 100644 RELEASE.md
 create mode 100644 modules.txt
 create mode 100644 release-publish.sh
 create mode 100644 scripts/ci/print-logs.sh
 create mode 100644 util-functions.sh

diff --git a/.gitignore b/.gitignore
index bbc8386bda..5e54de49b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,8 @@ dist/
 dist/
 .tmp/
 /.tmp/
+tmp/
+
 
 # Reports directory
 reports/
diff --git a/.release-it.json b/.release-it.json
new file mode 100644
index 0000000000..2313cf40ab
--- /dev/null
+++ b/.release-it.json
@@ -0,0 +1,47 @@
+{
+	"non-interactive": false,
+	"dry-run": false,
+	"verbose": false,
+	"force": false,
+	"pkgFiles": ["package.json"],
+	"increment": "patch",
+	"buildCommand": false,
+	"safeBump": true,
+	"beforeChangelogCommand": false,
+	"requireCleanWorkingDir": true,
+	"requireUpstream": true,
+	"src": {
+		"commit": true,
+		"commitMessage": "chore(release): release %s",
+		"commitArgs": "",
+		"tag": true,
+		"tagName": "%s",
+		"tagAnnotation": "%s",
+		"push": true,
+		"pushArgs": "",
+		"pushRepo": null,
+		"beforeStartCommand": false,
+		"afterReleaseCommand": false
+	},
+	"npm": {
+		"publish": false
+	},
+	"github": {
+		"release": true,
+		"releaseName": "Release %s",
+		"draft": false,
+		"tokenRef": "GITHUB_TOKEN",
+		"assets": null,
+		"host": null
+	},
+	"prompt": {
+		"src": {
+			"status": false,
+			"commit": true,
+			"tag": true,
+			"push": true,
+			"release": true,
+			"publish": true
+		}
+	}
+}
diff --git a/.travis.yml b/.travis.yml
index d5ac196a57..858f8db791 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,14 +1,18 @@
 language: node_js
 node_js:
-  - "6"
   - "8"
+  - "6"
+
 dist: trusty
 sudo: false # better for performance
 
 before_install:
   - export TZ=Europe/Brussels
+  # TODO remove this variable as it's probably not needed (defined by travis by default?): https://docs.travis-ci.com/user/environment-variables/
   - TRAVIS=1 # used by build.sh
   - npm i -g npm@5.8.0
+  # This ensures that we are authenticated without requiring to have an actual .npmrc file within the project
+  - 'echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc'
 
 install:
   # Create file & folder for Travis logs
@@ -42,5 +46,8 @@ cache:
 script:
   - npm run lint:all
   - npm run test:ci:all
+  - npm run release:publish
+  - bash ./scripts/ci/print-logs.sh
+
 after_success:
   - npm run test:ci:coveralls:stark-core
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000..e7e0eb3f74
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,29 @@
+<a name="10.0.0-alpha.1"></a>
+# 10.0.0-alpha.1 (2018-03-29)
+
+
+### Bug Fixes
+
+* **build:** fixed issue with prettier config name with webpack plugin and added new scripts at root ([51be4f6](https://github.com/nationalbankbelgium/stark/commit/51be4f6))
+* **http:** fix unit tests. Enhance http demo in Starter ([#268](https://github.com/nationalbankbelgium/stark/issues/268)) ([6d609b8](https://github.com/nationalbankbelgium/stark/commit/6d609b8)), closes [#68](https://github.com/nationalbankbelgium/stark/issues/68) [#68](https://github.com/nationalbankbelgium/stark/issues/68) [#84](https://github.com/nationalbankbelgium/stark/issues/84) [#93](https://github.com/nationalbankbelgium/stark/issues/93) [angular/zone.js#1015](https://github.com/angular/zone.js/issues/1015) [#96](https://github.com/nationalbankbelgium/stark/issues/96)
+* **lazy-loading:** Remove PreloadAllModules preloading strategy from routing coneiguration to make lazy-loaded modules to be actually lazy loaded :) ([9634dac](https://github.com/nationalbankbelgium/stark/commit/9634dac))
+* **lazy-loading:** Remove PreloadAllModules preloading strategy from routing coneiguration tz makz lazz-loaded modules to be actually lazy loaded :) ([80d09ce](https://github.com/nationalbankbelgium/stark/commit/80d09ce))
+* **linting:** clean stark-build/tslint.json. Remove obsolete options for 'ban' rule ([86ed26c](https://github.com/nationalbankbelgium/stark/commit/86ed26c))
+* **linting:** fix some TS linting issues ([8d5d6a8](https://github.com/nationalbankbelgium/stark/commit/8d5d6a8))
+
+
+### Features
+
+* **build:** added .gitattributes. Closes [#144](https://github.com/nationalbankbelgium/stark/issues/144). ([b4c3ef2](https://github.com/nationalbankbelgium/stark/commit/b4c3ef2))
+* **build:** added support for building a subset of the packages ([55ec4c1](https://github.com/nationalbankbelgium/stark/commit/55ec4c1))
+* **http:** create StarkHttp module. Fixed imports. Implemented small demo in Starter [[#96](https://github.com/nationalbankbelgium/stark/issues/96)] ([201edb8](https://github.com/nationalbankbelgium/stark/commit/201edb8))
+* **http:** implement Stark Http in stark-core (unit tests to be completed) [[#96](https://github.com/nationalbankbelgium/stark/issues/96)] ([579c59b](https://github.com/nationalbankbelgium/stark/commit/579c59b))
+* **http:** implement Stark Http in stark-core (unit tests to be completed) [[#96](https://github.com/nationalbankbelgium/stark/issues/96)] ([719d92d](https://github.com/nationalbankbelgium/stark/commit/719d92d))
+* **polyfills:** Update polyfills.browser.ts with the relevant polyfills needed only for IE11 and some special features from Angular. Add needed npm dependencies for those polyfils ([2b6a160](https://github.com/nationalbankbelgium/stark/commit/2b6a160))
+* **routing:** adapt CSP style-src directive to allow inline styles from UI Router visualizer ([8a1a8fa](https://github.com/nationalbankbelgium/stark/commit/8a1a8fa))
+* **routing:** add UI Router visualizer. Adapt CSP img-src directive to allow png images from UI Router visualizer ([3bc995b](https://github.com/nationalbankbelgium/stark/commit/3bc995b))
+* **routing:** replace Angular Router by UI Router ([24b70d4](https://github.com/nationalbankbelgium/stark/commit/24b70d4))
+* **stark-testing:** create separate stark-testing package and use it in all stark packages and starter ([#267](https://github.com/nationalbankbelgium/stark/issues/267)) ([204dc35](https://github.com/nationalbankbelgium/stark/commit/204dc35)), closes [#68](https://github.com/nationalbankbelgium/stark/issues/68) [#68](https://github.com/nationalbankbelgium/stark/issues/68) [#84](https://github.com/nationalbankbelgium/stark/issues/84) [#93](https://github.com/nationalbankbelgium/stark/issues/93) [angular/zone.js#1015](https://github.com/angular/zone.js/issues/1015)
+
+
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 780789713c..f8ba0e2d76 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -256,17 +256,7 @@ If you want to clean up completely the installed node_modules and reinstall late
 * execute the `clean:modules:all` npm script to clean up every modules files in your project; for example: `npm run clean:modules:all`
 
 ## Releasing a version
-* commit all changes to include in the release
-* edit the version in package.json
-  * respect semver
-* update CHANGELOG.MD
-* commit
-* git tag <version>
-* git push --tags
-* draft the release on GitHub (add description, etc)
-* npm publish
-
-TODO: review/complete; see #31
+See [this page](/RELEASE.md)
 
 ## <a name="commit"></a> Commit Message Guidelines
 We have precise rules over how our git commit messages can be formatted. This leads to **more readable messages** that are easy to follow when looking through the **project history**.
diff --git a/README.md b/README.md
index 0ff63f8d93..95cc92ebc3 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,9 @@ TODO add links to developer guide sections
 ### Contributing
 Please follow our [contribution guidelines](/CONTRIBUTING.md)
 
+### Releasing Stark
+See [this page](/RELEASE.md)
+
 ## Authors
 
 ### Sebastien Dubois
diff --git a/RELEASE.md b/RELEASE.md
new file mode 100644
index 0000000000..bb2d3d39ce
--- /dev/null
+++ b/RELEASE.md
@@ -0,0 +1,57 @@
+# Releasing Stark
+
+## Pre-reqs
+### Local
+On your local machine, you must configure the `GITHUB_TOKEN` environment variable.
+It will be used by release-it to push to and create the release page on GitHub (cfr release:prepare section below).
+
+### Travis
+On Travis, the following should be configured:
+* NPM_TOKEN environment variable
+  * if 2FA is enabled for the account the only auth-only level can be used: https://docs.npmjs.com/getting-started/using-two-factor-authentication#levels-of-authentication
+  * that variable MUST NEVER be logged/exposed. If exposed then the token MUST be revoked and the account password changed ASAP
+
+## Changelog
+First of all: *Never* edit CHANGELOG.md manually!
+
+The changelog will be updated automatically as part of the release process and based on the commit log using conventional-changelog (https://github.com/conventional-changelog)
+We use the Angular format for our changelog and for it to work properly, please make sure to respect our commit conventions (see CONTRIBUTING guide).
+
+## Creating a release
+Make sure that:
+* all changes have merged into master
+* everything is up to date locally
+* everything is clean locally
+* execute `npm run release`
+
+Enjoy the show.
+
+## Publishing the release on npm
+Once you have pushed the tag, Travis will handle things from there
+
+## What happens once a release is triggered
+
+### release
+* first we make sure that there are no local changes (if there are we stop right there)
+* then we execute release-it: https://github.com/webpro/release-it which
+  * bumps the version in the root package.json automatically (determines the bump type to use depending on the commit message logs)
+    * that version number will be used as basis in the build to adapt all other package.json files
+  * generates/updates the CHANGELOG.md file using: conventional-changelog: https://github.com/conventional-changelog
+  * commits both package.json and CHANGELOG.md
+  * creates a new git tag and pushes it
+  * creates a github release page and makes it final
+
+After this, the release is tagged and visible on github
+
+### publish
+Once the tag is pushed to GitHub, Travis picks it up and initiates a build.
+Travis executes builds, tests, then executes `npm run release:publish`.
+
+That script makes some checks then, if all succeed it publishes the different packages on npm.
+Checks that are performed:
+* node version: should be "8"
+* NPM_TOKEN environment variable should be defined
+* TRAVIS_REPO_SLUG should be "NationalBankBelgium/stark"
+* TRAVIS_TAG should be defined and not empty (this is the case when Travis builds for a tag) 
+
+Other details can be found here: https://github.com/NationalBankBelgium/stark/issues/54
diff --git a/build-functions.sh b/build-functions.sh
index 35988789ce..5434d19f9e 100644
--- a/build-functions.sh
+++ b/build-functions.sh
@@ -1,53 +1,5 @@
 #!/usr/bin/env bash
 
-# Three-Fingered Claw technique :)
-# Reference: https://stackoverflow.com/questions/1378274/in-a-bash-script-how-can-i-exit-the-entire-script-if-a-certain-condition-occurs
-yell() { echo "$0: $*" >&2; }
-die() { yell "$*"; exit 111; }
-try() { "$@" || die "cannot $*"; }
-
-#######################################
-# Echo the passed message if verbose mode is enabled
-# Arguments:
-#   param1 - message to log if verbose mode is enabled
-#   param2 - depth: spaces to add before the string
-#######################################
-logDebug() {
-  if [[ ${VERBOSE} == true ]] || [[ ${TRACE} == true ]]; then
-    logInfo "$@"
-  fi
-}
-
-#######################################
-# Echo the passed message if trace mode is enabled
-# Arguments:
-#   param1 - message to log if trace mode is enabled
-#   param2 - depth: spaces to add before the string
-#######################################
-logTrace() {
-  if [[ ${TRACE} == true ]]; then
-    logInfo "$@"
-  fi
-}
-
-#######################################
-# Echo the passed message
-# Arguments:
-#   param1 - message to log if verbose mode is enabled
-#   param2 - (optional) depth: spaces to add before the string (defaults to 0)
-#######################################
-#log() {
-#  local message=${1:-NO MESSAGE TO LOG GIVEN TO log function (this is probably a mistake)}
-#  local numSpaces=${2:-0}
-#  printf "%${numSpaces}s$message\n"
-#}
-logInfo() {
-  local message="${1:-NO MESSAGE TO LOG GIVEN TO log function (this is probably a mistake)}"
-  local numSpaces="${2:-0}"
-  printf -v spacing '%*s' "$numSpaces"
-  printf "${spacing}%s\n" "$message"
-}
-
 #######################################
 # Verifies a directory isn't in the ignored list
 # Arguments:
diff --git a/build.sh b/build.sh
index 47b649473a..6239edb0bd 100644
--- a/build.sh
+++ b/build.sh
@@ -13,6 +13,7 @@ readonly currentDir=$(cd $(dirname $0); pwd)
 export NODE_PATH=${NODE_PATH:-}:${currentDir}/node_modules
 
 source ${currentDir}/scripts/ci/_travis-fold.sh
+source ${currentDir}/util-functions.sh
 source ${currentDir}/build-functions.sh
 
 cd ${currentDir}
@@ -27,12 +28,15 @@ TSC_PACKAGES=()
 # Packages that should not be compiled at all
 NODE_PACKAGES=(stark-build stark-testing)
 
-ALL_PACKAGES=(stark-build stark-testing stark-core)
+# We read from a file because the list is also shared with release-publish.sh
+# Not using readarray because it does not handle \r\n
+OLD_IFS=$IFS # save old IFS value
+IFS=$'\r\n' GLOBIGNORE='*' command eval 'ALL_PACKAGES=($(cat ./modules.txt))'
+IFS=$OLD_IFS # restore IFS
 
 BUILD_ALL=true
 BUNDLE=true
 VERSION_PREFIX=$(node -p "require('./package.json').version")
-VERSION_SUFFIX="-$(git log --oneline -1 | awk '{print $1}')" # last commit id
 COMPILE_SOURCE=true
 TYPECHECK_ALL=true
 
@@ -41,13 +45,6 @@ TRAVIS=${TRAVIS:-}
 VERBOSE=false
 TRACE=false
 
-PROJECT_ROOT_DIR=`pwd`
-logTrace "PROJECT_ROOT_DIR: ${PROJECT_ROOT_DIR}" 1
-ROOT_DIR=${PROJECT_ROOT_DIR}/packages
-logTrace "ROOT_DIR: ${ROOT_DIR}" 1
-ROOT_OUT_DIR=${PROJECT_ROOT_DIR}/dist/packages
-logTrace "ROOT_OUT_DIR: ${ROOT_OUT_DIR}" 1
-
 for ARG in "$@"; do
   case "$ARG" in
     --quick-bundle=*)
@@ -60,7 +57,6 @@ for ARG in "$@"; do
       
       # parse to identify the packages to build
       PACKAGES_STR=${ARG#--packages=}
-      PACKAGES_STR=${ARG#--packages=}
       PACKAGES_STR="${PACKAGES_STR//,/ }" # replace , by ' '
       PACKAGES_STR="${PACKAGES_STR//;/ }" # replace ; by ' '
       PACKAGES_STR="${PACKAGES_STR// /_}" # replace all spaces by '_'
@@ -113,9 +109,6 @@ for ARG in "$@"; do
     --bundle=*)
       BUNDLE=( "${ARG#--bundle=}" )
       ;;
-    --publish)
-      VERSION_SUFFIX=""
-      ;;
     --compile=*)
       COMPILE_SOURCE=${ARG#--compile=}
       ;;
@@ -139,6 +132,26 @@ for ARG in "$@"; do
   esac
 done
 
+PROJECT_ROOT_DIR=`pwd`
+logTrace "PROJECT_ROOT_DIR: ${PROJECT_ROOT_DIR}" 1
+ROOT_DIR=${PROJECT_ROOT_DIR}/packages
+logTrace "ROOT_DIR: ${ROOT_DIR}" 1
+ROOT_OUT_DIR=${PROJECT_ROOT_DIR}/dist/packages
+logTrace "ROOT_OUT_DIR: ${ROOT_OUT_DIR}" 1
+
+# Making sure the variable exists
+if [[ -z ${TRAVIS_TAG+x} ]]; then
+  TRAVIS_TAG=""
+fi
+
+if [[ ${TRAVIS_TAG} == "" ]]; then
+  logTrace "Setting the version suffix to the latest commit hash" 1
+  VERSION_SUFFIX="-$(git log --oneline -1 | awk '{print $1}')" # last commit id
+else
+  logTrace "Build executed for a tag. Not using a version suffix!" 1
+  VERSION_SUFFIX="" # last commit id
+fi
+
 VERSION="${VERSION_PREFIX}${VERSION_SUFFIX}"
 
 logInfo "============================================="
diff --git a/modules.txt b/modules.txt
new file mode 100644
index 0000000000..ec07e407b0
--- /dev/null
+++ b/modules.txt
@@ -0,0 +1,3 @@
+stark-build
+stark-testing
+stark-core
diff --git a/package.json b/package.json
index 81937b6f72..4156d7dce6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "stark-srcs",
-  "version": "10.0.0-alpha.0",
+  "version": "10.0.0-alpha.1",
   "private": true,
   "description": "Stark - a framework for Angular apps",
   "author": "Stark Team <sebastien.dubois@nbb.be>",
@@ -26,6 +26,7 @@
     "husky": "0.14.3",
     "lint-staged": "7.0.4",
     "prettier": "1.12.1",
+    "release-it": "7.2.1",
     "rollup": "0.58.1",
     "rollup-plugin-commonjs": "9.1.0",
     "rollup-plugin-node-resolve": "3.3.0",
@@ -38,19 +39,11 @@
     "uglify-es": "3.3.9"
   },
   "scripts": {
-    "precommit": "lint-staged",
-    "prettier-check": "prettier **/*.{css,js,json,pcss,scss,ts} --write",
-    "stylelint-check": "stylelint-config-prettier-check",
-    "tsc": "tsc",
-    "ngc": "ngc",
     "build": "bash ./build.sh",
     "build:trace": "npm run build -- --trace",
     "build:stark-build": "npm run build -- --packages=stark-build",
     "build:stark-core": "npm run build -- --packages=stark-core",
     "build:stark-testing": "npm run build -- --packages=stark-testing",
-    "preupdate:starter": "npm run clean:starter",
-    "update:starter": "cd starter && npm install && cd ..",
-    "starter": "cd starter && npm start && cd ..",
     "clean": "rimraf ./dist",
     "clean:all": "npm run clean && npm run clean:stark-build && npm run clean:stark-core && npm run clean:stark-testing && npm run clean:starter",
     "clean:stark-build": "cd packages/stark-build && npm run clean && cd ../..",
@@ -63,6 +56,9 @@
     "clean:modules:stark-core": "cd packages/stark-core && npm run clean:modules && cd ../..",
     "clean:modules:stark-testing": "cd packages/stark-testing && npm run clean:modules dist && cd ../..",
     "clean:modules:starter": "cd starter && npm run clean:modules dist && cd ..",
+    "preupdate:starter": "npm run clean:starter",
+    "update:starter": "cd starter && npm install && cd ..",
+    "starter": "cd starter && npm start && cd ..",
     "lint": "tslint --config tslint.json --project ./tsconfig.json --format codeFrame",
     "lint:stark-core": "cd packages/stark-core && npm run lint && cd ../..",
     "lint:starter": "cd starter && npm run lint && cd ..",
@@ -77,6 +73,12 @@
     "install:ci:stark-testing": "cd packages/stark-testing && npm ci && cd ../..",
     "install:ci:starter": "cd starter && npm ci && cd ..",
     "install:travis:all": "npm run install:stark-build && npm run install:stark-testing && npm run install:stark-core && npm run build:trace && npm run update:starter",
+    "ngc": "ngc",
+    "precommit": "lint-staged",
+    "prettier-check": "prettier **/*.{css,js,json,pcss,scss,ts} --write",
+    "release": "release-it",
+    "release:publish": "bash ./release-publish.sh --trace",
+    "stylelint-check": "stylelint-config-prettier-check",
     "test:stark-core": "cd packages/stark-core && npm run test-fast && cd ../..",
     "test:starter": "cd starter && npm run test-fast && cd ../..",
     "test:all": "npm run test:stark-core && npm run test:starter",
@@ -84,6 +86,7 @@
     "test:ci:starter": "cd starter && npm run test-fast:ci && cd ../..",
     "test:ci:all": "npm run test:ci:stark-core && npm run test:ci:starter",
     "test:ci:coveralls:stark-core": "cd packages/stark-core && cat ./reports/coverage/packages/lcov.info | ../stark-testing/node_modules/coveralls/bin/coveralls.js",
+    "tsc": "tsc",
     "tslint": "tslint",
     "tslint-check": "tslint-config-prettier-check ./tslint.json"
   },
diff --git a/release-publish.sh b/release-publish.sh
new file mode 100644
index 0000000000..1b975e72fc
--- /dev/null
+++ b/release-publish.sh
@@ -0,0 +1,178 @@
+#!/usr/bin/env bash
+
+# TODO
+#===================
+# provide a clean way to define/check the "current" version of node (i.e., the one we should execute the publish under/for)
+# provide support for publishing only a subset of the packages (same --packages logic as in build.sh)
+# provide support for publishing locally in addition to travis
+
+set -u -e -o pipefail
+
+VERBOSE=false
+TRACE=false
+DRY_RUN=false
+
+# We read from a file because the list is also shared with build.sh
+# Not using readarray because it does not handle \r\n
+OLD_IFS=$IFS # save old IFS value
+IFS=$'\r\n' GLOBIGNORE='*' command eval 'ALL_PACKAGES=($(cat ./modules.txt))'
+IFS=$OLD_IFS # restore IFS
+
+EXPECTED_REPO_SLUG="NationalBankBelgium/stark"
+EXPECTED_NODE_VERSION="8"
+
+#----------------------------------------------
+# Uncomment block below to test locally
+#----------------------------------------------
+#LOGS_DIR=./.tmp/stark/logs
+#mkdir -p ${LOGS_DIR}
+#touch ${LOGS_DIR}/build-perf.log
+#NPM_TOKEN="dummy"
+#TRAVIS=1
+#TRAVIS_REPO_SLUG="NationalBankBelgium/stark"
+#TRAVIS_NODE_VERSION="8"
+
+# For normal builds:
+#TRAVIS_EVENT_TYPE="pull_request"
+#TRAVIS_TAG="fooBar"
+
+# For nightly builds:
+#TRAVIS_EVENT_TYPE="cron"
+#----------------------------------------------
+
+NIGHTLY_BUILD=false
+
+readonly currentDir=$(cd $(dirname $0); pwd)
+
+source ${currentDir}/scripts/ci/_travis-fold.sh
+source ${currentDir}/util-functions.sh
+
+cd ${currentDir}
+
+logInfo "============================================="
+logInfo "Stark release publish @ npm"
+
+for ARG in "$@"; do
+  case "$ARG" in
+    --dry-run)
+      logInfo "============================================="
+      logInfo "Dry run enabled!"
+      DRY_RUN=true
+      ;;
+    --verbose)
+      logInfo "============================================="
+      logInfo "Verbose mode enabled!"
+      VERBOSE=true
+      ;;
+    --trace)
+      logInfo "============================================="
+      logInfo "Trace mode enabled!"
+      TRACE=true
+      ;;
+    --nightly)
+      logInfo "============================================="
+      logInfo "Nightly build!"
+      NIGHTLY_BUILD=true
+      ;;
+    *)
+      echo "Unknown option $ARG."
+      exit 1
+      ;;
+  esac
+done
+logInfo "============================================="
+
+PROJECT_ROOT_DIR=`pwd`
+logTrace "PROJECT_ROOT_DIR: ${PROJECT_ROOT_DIR}" 1
+ROOT_PACKAGES_DIR=${PROJECT_ROOT_DIR}/dist/packages-dist
+logTrace "ROOT_PACKAGES_DIR: ${ROOT_PACKAGES_DIR}" 1
+
+travisFoldStart "publish checks" "no-xtrace"
+
+if [[ ${TRAVIS:-} ]]; then
+  logInfo "Publishing from Travis";
+  logInfo "============================================="
+  
+  # If the previous commands in the `script` section of .travis.yaml failed, then abort.
+  # The variable is not set in early stages of the build, so we default to 0 there.
+  # https://docs.travis-ci.com/user/environment-variables/
+  if [[ ${TRAVIS_TEST_RESULT=0} == 1 ]]; then
+    exit 1;
+  fi
+  
+  # Don't even try if not running against the official repo
+  # We don't want release to run outside of our own little world
+  if [[ ${TRAVIS_REPO_SLUG} != ${EXPECTED_REPO_SLUG} ]]; then
+    logInfo "Skipping release because this is not the main repository.";
+    exit 0;
+  fi
+  
+  # Ensuring that this is the execution for Node x
+  # Without this check, we would publish a release for each node version we test under! :)
+  if [[ ${TRAVIS_NODE_VERSION} != ${EXPECTED_NODE_VERSION} ]]; then
+    logInfo "Skipping release because this is not the expected version of node: ${TRAVIS_NODE_VERSION}"
+    exit 0;
+  fi
+  
+  logInfo "Verifying if this build has been triggered for a tag" 
+  # Making sure the variable does exist.. 
+  if [[ -z ${TRAVIS_TAG+x} ]]; then
+    TRAVIS_TAG=""
+  fi
+  
+  if [[ ${TRAVIS_EVENT_TYPE} == "cron" ]]; then
+    logTrace "Nightly build initiated by Travis cron job" 1
+    NIGHTLY_BUILD=true
+  elif [[ ${TRAVIS_TAG} == "" ]]; then
+      logTrace "Not publishing because this is not a build triggered for a tag" 1
+      exit 0;
+  else
+    logInfo "This build has been triggered for a tag" 
+  fi
+  
+  logInfo "Verifying that the NPM_TOKEN is available"
+  if [[ -z ${NPM_TOKEN+x} ]]; then
+    NPM_TOKEN=""
+  fi
+
+  if [[ ${NPM_TOKEN} == "" ]]; then
+    logTrace "Not publishing because the NPM_TOKEN environment variable is is not defined correctly" 1
+    exit 0;
+  fi
+fi
+
+travisFoldEnd "publish checks"
+
+travisFoldStart "publish" "no-xtrace"
+logInfo "Publishing all packages"
+
+for PACKAGE in ${ALL_PACKAGES[@]}
+do
+  travisFoldStart "publishing: ${PACKAGE}" "no-xtrace"
+    PACKAGE_FOLDER=${ROOT_PACKAGES_DIR}/${PACKAGE}
+    logTrace "Package path: ${PACKAGE_FOLDER}" 2
+    cd ${PACKAGE_FOLDER}
+    TGZ_FILES=`find . -maxdepth 1 -type f | egrep -e ".tgz"`;
+    for file in ${TGZ_FILES}; do
+      logInfo "Publishing TGZ file: ${TGZ_FILES}" 2
+      if [[ ${DRY_RUN} == false ]]; then
+        if [[ ${NIGHTLY_BUILD} == false ]]; then
+          logTrace "Publishing the release" 2
+          npm publish ${file} --access public
+        else
+          logTrace "Publishing the nightly release (with tag next)" 2
+          npm publish ${file} --access public --tag next
+        fi
+      else
+        logTrace "DRY RUN, skipping npm publish!" 2
+      fi
+      logInfo "Package published!" 2
+    done
+    cd - > /dev/null; # go back to the previous folder without any output  
+  travisFoldEnd "publishing: ${PACKAGE}"
+done
+
+travisFoldEnd "publish"
+
+# Print return arrows as a log separator
+travisFoldReturnArrows
diff --git a/scripts/ci/print-logs.sh b/scripts/ci/print-logs.sh
new file mode 100644
index 0000000000..2c14d45499
--- /dev/null
+++ b/scripts/ci/print-logs.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+set -u -e -o pipefail
+
+# Setup environment
+readonly thisDir=$(cd $(dirname $0); pwd)
+source ${thisDir}/_travis-fold.sh
+
+
+for FILE in ${LOGS_DIR}/*; do
+  travisFoldStart "print log file: ${FILE}"
+    cat $FILE
+  travisFoldEnd "print log file: ${FILE}"
+done
+
+# Print return arrows as a log separator
+travisFoldReturnArrows
diff --git a/util-functions.sh b/util-functions.sh
new file mode 100644
index 0000000000..04365c6492
--- /dev/null
+++ b/util-functions.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+
+# Three-Fingered Claw technique :)
+# Reference: https://stackoverflow.com/questions/1378274/in-a-bash-script-how-can-i-exit-the-entire-script-if-a-certain-condition-occurs
+yell() { echo "$0: $*" >&2; }
+die() { yell "$*"; exit 111; }
+try() { "$@" || die "cannot $*"; }
+
+#######################################
+# Echo the passed message if verbose mode is enabled
+# Arguments:
+#   param1 - message to log if verbose mode is enabled
+#   param2 - depth: spaces to add before the string
+#######################################
+logDebug() {
+  if [[ ${VERBOSE} == true ]] || [[ ${TRACE} == true ]]; then
+    logInfo "$@"
+  fi
+}
+
+#######################################
+# Echo the passed message if trace mode is enabled
+# Arguments:
+#   param1 - message to log if trace mode is enabled
+#   param2 - depth: spaces to add before the string
+#######################################
+logTrace() {
+  if [[ ${TRACE} == true ]]; then
+    logInfo "$@"
+  fi
+}
+
+#######################################
+# Echo the passed message
+# Arguments:
+#   param1 - message to log if verbose mode is enabled
+#   param2 - (optional) depth: spaces to add before the string (defaults to 0)
+#######################################
+#log() {
+#  local message=${1:-NO MESSAGE TO LOG GIVEN TO log function (this is probably a mistake)}
+#  local numSpaces=${2:-0}
+#  printf "%${numSpaces}s$message\n"
+#}
+logInfo() {
+  local message="${1:-NO MESSAGE TO LOG GIVEN TO log function (this is probably a mistake)}"
+  local numSpaces="${2:-0}"
+  printf -v spacing '%*s' "$numSpaces"
+  printf "${spacing}%s\n" "$message"
+}