Add travis hooks to test and publish docker images. (#2)

Co-authored-by: Rodric Rabbah <rodric@gmail.com>
Co-authored-by: Carlos Santana <csantanapr@apache.org>
Co-authored-by: David Grove <dgrove-oss@users.noreply.github.com>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6a25af9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+.vscode
+.idea
+*.iml
+*~
+
+.gradle/
+tests/build
+tests/out/
+.settings
+tests/bin/
+.project
+.classpath
diff --git a/.scalafmt.conf b/.scalafmt.conf
new file mode 100644
index 0000000..7084efe
--- /dev/null
+++ b/.scalafmt.conf
@@ -0,0 +1,9 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements; and to You under the Apache License, Version 2.0.
+
+style = intellij
+danglingParentheses = false
+maxColumn = 120
+docstrings = JavaDoc
+rewrite.rules = [SortImports]
+project.git = true
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..f19648f
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,52 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+sudo: required
+group: deprecated-2017Q3
+language: csharp
+dotnet: 2.1.300
+services:
+- docker
+notifications:
+  email: false
+  webhooks:
+    urls:
+      # travis2slack webhook to enable DMs on openwhisk-team.slack.com to PR authors with TravisCI results
+      secure: y6caEKjRnby723P1W8Rup+yioJRBV1YmqwGEEgPxNu9YGdef0m7TO8fp1BZaa/hHErYzYrfvOo3gwXBB7lkmZ9p1NfF/Cb5bjy5UwSx+EFaEjugFIoCCg+xPPTS4SM24+bXljiFZd7ZZGXu4beGdcgxmYsufRQoWJBF4Itcr424wEw+fSrPPknAotgAXjUyOOmr/xHng50mFqyfal1miR9vOiX1y/cdeAmaCmuagv20ry0ZpnOyMYCdH0LtWIDAxSDn/GTXBAwLBy2Wn05uE+Yqh6EI7xRvYBtT0PfaBFwb28pmkArYG9ZpXB8cwUhuLQZ51zFt0uHMetzlThbw6pO0X9FzGcT/BBlUaZbUaY6zar8FkRzija72HLKOY/yAN8VkhGlDOz2RSI3Tw05vep4Y7ZVRF9/wW0KnKB68VMJuwCbzgtCvWpgRXbxxLcKvKYsBVnkcWY/fwMxG5q8gQ2ZELf65975MVMn/oejwAcJkP2EOBBFpHGsWvEwNV4ymTD00XX1qeebfYQYTsxUOEUFrvu3p4GgqI2MQksgWusGaHaOTG0XHZ7afbZ+4EdPA098rPFaIcnq5E8PVZ+IRzn+5aupAqXy/tY0i4V1U7H4rtF+6u3PJpAIcgVo03wmzNcnsw0rVcAqKbIxn/oyMaIaGtb1VaKYQZJ4t4CCo0cEo=
+before_install:
+- "./tools/travis/setup.sh"
+install: true
+script:
+- "./tools/travis/build.sh && ./tools/travis/test.sh"
+deploy:
+- provider: script
+  script: "./tools/travis/publish.sh openwhisk ${TRAVIS_TAG%@*} ${TRAVIS_TAG##*@}"
+  on:
+    tags: true
+    all_branches: true
+    repo: apache/incubator-openwhisk-runtime-dotnet
+- provider: script
+  script: "./tools/travis/publish.sh openwhisk 2.1 latest"
+  on:
+    branch: master
+    repo: apache/incubator-openwhisk-runtime-dotnet
+env:
+  global:
+  - secure: Y1ldwIQ6bc3/3Pc0E+qQ6K2M830B9BObYDlsNilPwF/kak3YSfF7SuXuRbJGjTdhH2KOotZD2CwONgP2yvOSPBToC/HpnXYfAGtgblrxQORvgdik88CFWa3Lli1pwlpdzKQNWhBvglzq+IIS98wqzmwqGr8zKA+Iau2ByHdb1j3M9rrIY9V6oU9Gwim1apcRyfI/as3+QfPtt8BUAl2U7+PprxwJigyF/mcZnBJbd7IjrilE2gldZLxKlBiffoKVBinrEg3IQGJPt6k8riw264pBQEpcA0ZBsPUvMaISSxLb+d1ymp3WsiTJUjv+URR/HcdDa7P9jY+ouc8PQz4Yt+Ii38lM2tQU480APfVTyfj6drkjL/+54mYuxm8TzkBWcM2j6/FYT+8HvK/pF35wDJ3El+jGq7BARXg8HVxFsZgynJnhqhWDQb3xX9fK+N4K8+ct+HlsOSa5mP5i5Yo6WRTrWrFpyxVnv9crKePCiYqA2Y8ta8Wnh0sM06nLRtDbfbDjvXPQbaZqSnL4B2Cto08YoT/W/lu8QgJ3EEFlUdDOke4kv9yoXtuE0h7+8dwOvBNMVrBis3G2EYObgR4WmWjk4loYhqT9h3jrH0/5bGLzSKc++qYW0rOZ/RB21cRSe1ILQvSzWkImUoPI8b0i5baGSDq3EjTXYr3pIXSYpQk=
+  - secure: DOg+FgllLbyv7nEK3JJZfO/cvXy5K0L6QI/S9EJ/ivm4XBDCw1ayhrSQXvp1tMTPbWBEIv2gomPsHghJ+hVvX3dgwYdoNz9WZaNBB6lOO9U8OQW0LBsO5Eai6grzqOP35OuKtthuyR3dGJHAZo/XjhZM/jL0z6q1kNDzdS7ASwRwHJG0rHPGVlGeolH4nAity4KNJvyAspS1FYaIj9FEC/M7UT6nJVACbr9iMt/83teF/Oo2uoFI6Pa4K3nE2NViVFibToNOM3CV8kArDPDoNJviXxQ07ZM6fNijwehZ80waiPSaxFY8PLSntQNxGyB3DbomSTCcdVvtuHHQVmZgpVdvOJE8wk3R09+nq9U9FuUWLiRYSRbF1eF48YFnssPW1jEeVSenFRADcQ37e4B21ssLvXRHpQHpPVrYBZ8ffDamS7pKtEqocX/3Syc6irxHGCpxEdhvQ0Of5AWHhzB714VCijJJQiH9J4hEKXhMeAZ5SSt4eUavEHJKMhUcJ/aaku5w1+KtiYeOso1fTRbTYkEYb1A0bSNdXlGrYRRT+N683W7+ENiQIT+hTp617L/m5WQLIHfKe3gy5qt46kHFiUL3R3YlBI5OKjnLkDnUiA+0d4SFtJC/TBuPmH1fG4isAuvggTjzCb3kUG3ysin8AW0AKaXW0eqjKa/nsHWDKmc=
+  - secure: rouRBDS18tqR2nkOyR1PVJrVBlpKrjq9LlwFMYuVmL/NqrPNaEMENvwm0aCbfbaJKz9TlyceAphSXj0uyloEe5bqxl0ZhagLkWLyCCwTZTVhFDsZ0R0s9k9rthWDQ2kC5BBwWsCejy5grg7yYU1I7Xkhwzj1iM7TRp3Tp1PJSHsWBYd44TzBStMAZOc+9IsywBjaeyvwZN3j3eLXjHrsej/8l16pu1IjtMZmrz+0M6Cp4qOMTGwXHcwLw1TpwQuQZw4Jvi6TlvIPgkY83Pt0oO7TIF46W6O6OjhKrgHEFfy0nu2JwKYT7kbFTlbLlXLj3OBJhwdXz8G1qJ3IHayd7rxF7gj2ToYFrv8ms2Q4IqRM1bDSm9TeC0nlbgpUSWDT6fzvJXE18KW5/YJVern1Q8fU2ejfpTdmDdWjOOaZZzDFfdog5kcOFVQOPHBT45Lklga/rY3lNMRtx9sJUMYfdR3obnBRmW6nQu8mRd5JHX1EROVjEHW9tnLvDQow6tbs6x1LMwM0oOvs99cPqE2NrhRJPU8/eLMg3Lxiz3cqm/oYhQlP30CO6ynCIM6Jxpj+Xpn28YM6GfET0qzNHmxkWS+oNUjO2NJNddyvE/W2qDGuUQYrJxTIiKVFsFXWIoaurnCWr20jdCLUY0MBpb9vIRK0lcrgWkrIH7WIOMeJcgI=
+  - secure: QIfsMObT4b1K2l/xsUAI4MqyCorEJMu0zgmMZnoms878e9You6VClexEOuQNJhWX1lzhRJdX+a6jkkWOz1aMbI1iDjt/rjEZuciHpv0KHqQ2xHlkg1v56Y8WOSOSrc5XHtwe9auw9owbaYyc0XuuubhtdJMv6/oCSSPSNKOT2wmGTkqbJtKZ4ToFphCwMKErhe3pbbIqZ51hbZDUuZ0N3kZKXKQoQBBVlVGi/2/YqUq03j4D8HHyvs2EoZD/H/DOLy+QA/i067ZSC7ahRZwsabWNfbB99yVaN1VmFAZXCasQ4WdP2Wo3Qm1+cUT5G7wiZDVtoRArhVZ+29qd3xSuHmHw87E8Uay6RjbwBYqxh4jxdj1QDfEpH3XbhxW5FxvgiI9twiMc7gANj5AMVyvuQPwX+P2rk44s8TpTBaOZ5qN4ys6VMX6HPpLsJ7yQBVd94O7jrDrKC3anp/0Hfa5SB1wFExlbQM9NYQwbyvr0oldgexTepOx62ZSRUKW4jtmxJglcuGvZOy39WB8LfcmokVFxkZvSsfmmjpgIO8pyjeQx19sLeSn37zYr7SgVFMgaFQQLqHoeCHnzpUUkrg6ITFm7+Irf3K7QOkHe4rNnKT0Vh2WCqIr+aYP2rGEDOTvxsOqWI4vSnMX259H+hIK5wV5Xond9ke2g7WHU9fvT+eY=
diff --git a/tests/src/test/scala/actionContainers/DotNetActionContainerTests.scala b/tests/src/test/scala/actionContainers/DotNetActionContainerTests.scala
index d4c04d1..4a618ea 100644
--- a/tests/src/test/scala/actionContainers/DotNetActionContainerTests.scala
+++ b/tests/src/test/scala/actionContainers/DotNetActionContainerTests.scala
@@ -44,31 +44,19 @@
   }
 
   override val testEnv = {
-    TestConfig(
-      functionb64,
-      main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Environment::Main"
-    )
+    TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Environment::Main")
   }
 
   override val testEcho = {
-    TestConfig(
-      functionb64,
-      main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.AltEcho::Main"
-    )
+    TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.AltEcho::Main")
   }
 
   val testEchoNoWrite = {
-    TestConfig(
-      functionb64,
-      main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo::Main"
-    )
+    TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo::Main")
   }
 
   override val testUnicode = {
-    TestConfig(
-      functionb64,
-      main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Unicode::Main"
-    )
+    TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Unicode::Main")
   }
 
   override val testInitCannotBeCalledMoreThanOnce = testEchoNoWrite
@@ -81,20 +69,22 @@
     val (out, err) = withActionContainer() { c =>
       val brokenArchive = ("NOTAVALIDZIPFILE")
 
-      val (initCode, initRes) = c.init(initPayload(brokenArchive, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Invalid::Main"))
+      val (initCode, initRes) =
+        c.init(initPayload(brokenArchive, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Invalid::Main"))
       initCode should not be (200)
 
       initRes shouldBe defined
 
       initRes should {
-          be(Some(JsObject("error" -> JsString("Unable to decompress package."))))
+        be(Some(JsObject("error" -> JsString("Unable to decompress package."))))
       }
     }
   }
 
   it should "return some error on action error" in {
     val (out, err) = withActionContainer() { c =>
-      val (initCode, _) = c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Exception::Main"))
+      val (initCode, _) =
+        c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Exception::Main"))
       initCode should be(200)
 
       val (runCode, runRes) = c.run(runPayload(JsObject.empty))
@@ -112,7 +102,8 @@
 
   it should "support application errors" in {
     val (out, err) = withActionContainer() { c =>
-      val (initCode, _) = c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Error::Main"))
+      val (initCode, _) =
+        c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Error::Main"))
       initCode should be(200)
 
       val (runCode, runRes) = c.run(runPayload(JsObject.empty))
@@ -131,46 +122,58 @@
 
   it should "fails on invalid assembly reference" in {
     val (out, err) = withActionContainer() { c =>
-      val (initCode, initRes) = c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet.DoesntExist::Apache.OpenWhisk.Tests.Dotnet.Echo::Main"))
+      val (initCode, initRes) = c.init(
+        initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet.DoesntExist::Apache.OpenWhisk.Tests.Dotnet.Echo::Main"))
       initCode should be(502)
 
       initRes shouldBe defined
 
       initRes should {
-          be(Some(JsObject("error" -> JsString("Unable to locate requested assembly (\"Apache.OpenWhisk.Tests.Dotnet.DoesntExist.dll\")."))))
+        be(
+          Some(JsObject("error" -> JsString(
+            "Unable to locate requested assembly (\"Apache.OpenWhisk.Tests.Dotnet.DoesntExist.dll\")."))))
       }
     }
   }
 
   it should "fails on invalid type reference" in {
     val (out, err) = withActionContainer() { c =>
-      val (initCode, initRes) = c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.FakeType::Main"))
+      val (initCode, initRes) =
+        c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.FakeType::Main"))
       initCode should be(502)
 
       initRes should {
-          be(Some(JsObject("error" -> JsString("Unable to locate requested type (\"Apache.OpenWhisk.Tests.Dotnet.FakeType\")."))))
+        be(
+          Some(JsObject(
+            "error" -> JsString("Unable to locate requested type (\"Apache.OpenWhisk.Tests.Dotnet.FakeType\")."))))
       }
     }
   }
 
   it should "fails on invalid method reference" in {
     val (out, err) = withActionContainer() { c =>
-      val (initCode, initRes) = c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo::FakeMethod"))
+      val (initCode, initRes) = c.init(
+        initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo::FakeMethod"))
       initCode should be(502)
 
       initRes should {
-          be(Some(JsObject("error" -> JsString("Unable to locate requested method (\"FakeMethod\")."))))
+        be(Some(JsObject("error" -> JsString("Unable to locate requested method (\"FakeMethod\")."))))
       }
     }
   }
 
   it should "fails on type with no empty constructor" in {
     val (out, err) = withActionContainer() { c =>
-      val (initCode, initRes) = c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.NonEmptyConstructor::Main"))
+      val (initCode, initRes) = c.init(
+        initPayload(
+          functionb64,
+          "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.NonEmptyConstructor::Main"))
       initCode should be(502)
 
       initRes should {
-          be(Some(JsObject("error" -> JsString("Unable to locate appropriate constructor for (\"Apache.OpenWhisk.Tests.Dotnet.NonEmptyConstructor\")."))))
+        be(
+          Some(JsObject("error" -> JsString(
+            "Unable to locate appropriate constructor for (\"Apache.OpenWhisk.Tests.Dotnet.NonEmptyConstructor\")."))))
       }
     }
   }
@@ -181,25 +184,27 @@
       initCode should not be (200)
 
       initRes should {
-          be(Some(JsObject("error" -> JsString("main required format is \"Assembly::Type::Function\"."))))
+        be(Some(JsObject("error" -> JsString("main required format is \"Assembly::Type::Function\"."))))
       }
     }
   }
 
   it should "validate main string format 2" in {
     val (out, err) = withActionContainer() { c =>
-      val (initCode, initRes) = c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo"))
+      val (initCode, initRes) =
+        c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo"))
       initCode should not be (200)
 
       initRes should {
-          be(Some(JsObject("error" -> JsString("main required format is \"Assembly::Type::Function\"."))))
+        be(Some(JsObject("error" -> JsString("main required format is \"Assembly::Type::Function\"."))))
       }
     }
   }
 
   it should "enforce that the user returns an object" in {
     val (out, err) = withActionContainer() { c =>
-      val (initCode, _) = c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Nuller::Main"))
+      val (initCode, _) =
+        c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Nuller::Main"))
       initCode should be(200)
 
       val (runCode, runRes) = c.run(runPayload(JsObject.empty))
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
new file mode 100755
index 0000000..7fd1f4d
--- /dev/null
+++ b/tools/travis/build.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -ex
+
+# Build script for Travis-CI.
+
+SCRIPTDIR=$(cd $(dirname "$0") && pwd)
+ROOTDIR="$SCRIPTDIR/../.."
+WHISKDIR="$ROOTDIR/../openwhisk"
+UTILDIR="$ROOTDIR/../incubator-openwhisk-utilities"
+
+export OPENWHISK_HOME=$WHISKDIR
+
+# run scancode using the ASF Release configuration
+cd $UTILDIR
+scancode/scanCode.py --config scancode/ASF-Release.cfg $ROOTDIR
+
+# Build OpenWhisk deps before we run tests
+cd $WHISKDIR
+TERM=dumb ./gradlew install
+# Mock file (works around bug upstream)
+echo "openwhisk.home=$WHISKDIR" > whisk.properties
+echo "vcap.services.file=" >> whisk.properties
+
+# Upgrade docker version
+curl -fsSL https://get.docker.com -o get-docker.sh
+sudo sh get-docker.sh
+docker version
+
+# Build runtime and dependencies
+cd $ROOTDIR
+
+# Build runtime & test dependencies
+TERM=dumb ./gradlew distDocker
diff --git a/tools/travis/publish.sh b/tools/travis/publish.sh
new file mode 100755
index 0000000..b230016
--- /dev/null
+++ b/tools/travis/publish.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -eux
+
+# Build script for Travis-CI.
+
+SCRIPTDIR=$(cd $(dirname "$0") && pwd)
+ROOTDIR="$SCRIPTDIR/../.."
+WHISKDIR="$ROOTDIR/../openwhisk"
+
+export OPENWHISK_HOME=$WHISKDIR
+
+IMAGE_PREFIX=$1
+RUNTIME_VERSION=$2
+IMAGE_TAG=$3
+
+if [[ ! -z ${DOCKER_USER} ]] && [[ ! -z ${DOCKER_PASSWORD} ]]; then
+docker login -u "${DOCKER_USER}" -p "${DOCKER_PASSWORD}"
+fi
+
+if [[ ! -z ${RUNTIME} ]]; then
+TERM=dumb ./gradlew \
+:core:${RUNTIME}:distDocker \
+-PdockerRegistry=docker.io \
+-PdockerImagePrefix=${IMAGE_PREFIX} \
+-PdockerImageTag=${IMAGE_TAG}
+
+  # if doing latest also push a tag with the hash commit
+  if [ ${IMAGE_TAG} == "latest" ]; then
+  SHORT_COMMIT=`git rev-parse --short HEAD`
+  TERM=dumb ./gradlew \
+  :core:${RUNTIME}:distDocker \
+  -PdockerRegistry=docker.io \
+  -PdockerImagePrefix=${IMAGE_PREFIX} \
+  -PdockerImageTag=${SHORT_COMMIT}
+  fi
+
+fi
diff --git a/tools/travis/setup.sh b/tools/travis/setup.sh
new file mode 100755
index 0000000..3424cdb
--- /dev/null
+++ b/tools/travis/setup.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -e
+
+# Build script for Travis-CI.
+
+SCRIPTDIR=$(cd $(dirname "$0") && pwd)
+ROOTDIR="$SCRIPTDIR/../.."
+HOMEDIR="$SCRIPTDIR/../../../"
+
+# clone OpenWhisk utilities repo. in order to run scanCode
+cd $HOMEDIR
+git clone https://github.com/apache/incubator-openwhisk-utilities.git
+
+# clone main openwhisk repo. for testing purposes
+git clone --depth=1 https://github.com/apache/incubator-openwhisk.git openwhisk
+cd openwhisk
+./tools/travis/setup.sh
diff --git a/tools/travis/test.sh b/tools/travis/test.sh
new file mode 100755
index 0000000..a5b249d
--- /dev/null
+++ b/tools/travis/test.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -ex
+
+# Build script for Travis-CI.
+
+SCRIPTDIR=$(cd $(dirname "$0") && pwd)
+ROOTDIR="$SCRIPTDIR/../.."
+WHISKDIR="$ROOTDIR/../openwhisk"
+
+export OPENWHISK_HOME=$WHISKDIR
+cd ${ROOTDIR}
+TERM=dumb ./gradlew :tests:checkScalafmtAll
+TERM=dumb ./gradlew :tests:test