You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2017/12/01 02:08:13 UTC

[GitHub] dubeejw closed pull request #8: remove swift:3 runtime

dubeejw closed pull request #8: remove swift:3 runtime
URL: https://github.com/apache/incubator-openwhisk-runtime-swift/pull/8
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/ansible/environments/local/group_vars/all b/ansible/environments/local/group_vars/all
index 307c06d..5d6a325 100755
--- a/ansible/environments/local/group_vars/all
+++ b/ansible/environments/local/group_vars/all
@@ -38,7 +38,7 @@ runtimes_manifest:
     - kind: "swift:3"
       image:
         name: "swift3action"
-      deprecated: false
+      deprecated: true
     - kind: "swift:3.1.1"
       default: true
       image:
diff --git a/ansible/environments/local/hosts b/ansible/environments/local/hosts
index c99f195..4715e55 100644
--- a/ansible/environments/local/hosts
+++ b/ansible/environments/local/hosts
@@ -9,8 +9,11 @@ ansible ansible_connection=local
 [controllers]
 controller0         ansible_host=172.17.0.1 ansible_connection=local
 
-[kafka]
-172.17.0.1          ansible_host=172.17.0.1 ansible_connection=local
+[kafkas]
+kafka0              ansible_host=172.17.0.1 ansible_connection=local
+
+[zookeepers:children]
+kafkas
 
 [invokers]
 invoker0            ansible_host=172.17.0.1 ansible_connection=local
diff --git a/core/swift3.1.1Action/build.gradle b/core/swift3.1.1Action/build.gradle
index d26283e..c977a30 100755
--- a/core/swift3.1.1Action/build.gradle
+++ b/core/swift3.1.1Action/build.gradle
@@ -1,10 +1,6 @@
 ext.dockerImageName = 'action-swift-v3.1.1'
 apply from: '../../gradle/docker.gradle'
 distDocker.dependsOn 'copyProxy'
-distDocker.dependsOn 'copyEpilogue'
-distDocker.dependsOn 'copySwiftRunner'
-distDocker.dependsOn 'copyWhisk'
-distDocker.dependsOn 'copyWhiskJsonUtils'
 distDocker.finalizedBy('cleanup')
 
 task copyProxy(type: Copy) {
@@ -12,30 +8,7 @@ task copyProxy(type: Copy) {
     into './actionproxy.py'
 }
 
-task copyEpilogue(type: Copy) {
-    from '../swift3Action/epilogue.swift'
-    into '.'
-}
-
-task copySwiftRunner(type: Copy) {
-    from '../swift3Action/swift3runner.py'
-    into '.'
-}
-
-task copyWhisk(type: Copy) {
-    from '../swift3Action/spm-build/_Whisk.swift'
-    into './spm-build'
-}
-
-task copyWhiskJsonUtils(type: Copy) {
-    from '../swift3Action/spm-build/_WhiskJSONUtils.swift'
-    into './spm-build'
-}
-
 task cleanup(type: Delete) {
     delete 'actionproxy.py'
-    delete 'epilogue.swift'
     delete 'swift3runner.py'
-    delete 'spm-build/_Whisk.swift'
-    delete 'spm-build/_WhiskJSONUtils.swift'
 }
diff --git a/core/swift3Action/epilogue.swift b/core/swift3.1.1Action/epilogue.swift
similarity index 100%
rename from core/swift3Action/epilogue.swift
rename to core/swift3.1.1Action/epilogue.swift
diff --git a/core/swift3Action/spm-build/_Whisk.swift b/core/swift3.1.1Action/spm-build/_Whisk.swift
similarity index 100%
rename from core/swift3Action/spm-build/_Whisk.swift
rename to core/swift3.1.1Action/spm-build/_Whisk.swift
diff --git a/core/swift3Action/spm-build/_WhiskJSONUtils.swift b/core/swift3.1.1Action/spm-build/_WhiskJSONUtils.swift
similarity index 100%
rename from core/swift3Action/spm-build/_WhiskJSONUtils.swift
rename to core/swift3.1.1Action/spm-build/_WhiskJSONUtils.swift
diff --git a/core/swift3Action/swift3runner.py b/core/swift3.1.1Action/swift3runner.py
similarity index 100%
rename from core/swift3Action/swift3runner.py
rename to core/swift3.1.1Action/swift3runner.py
diff --git a/core/swift3Action/Dockerfile b/core/swift3Action/Dockerfile
deleted file mode 100644
index aa766d4..0000000
--- a/core/swift3Action/Dockerfile
+++ /dev/null
@@ -1,68 +0,0 @@
-# Dockerfile for swift actions, overrides and extends ActionRunner from actionProxy
-# This Dockerfile is partially based on: https://github.com/swiftdocker/docker-swift/
-FROM buildpack-deps:trusty
-
-ENV DEBIAN_FRONTEND noninteractive
-
-# Upgrade and install basic Python dependencies
-RUN apt-get -y purge \
- && apt-get -y update \
- && apt-get -y install --fix-missing python2.7 python-gevent python-flask \
-\
-# Upgrade and install Swift dependencies
- && apt-get -y install --fix-missing build-essential curl wget libicu-dev \
-\
-# Install zip for compiling Swift actions
- && apt-get -y install zip \
-\
-# Clean up
- && apt-get clean
-
-# Install clang manually, since SPM wants at least Clang 3-6
-RUN cd / &&\
-(curl -L -k http://llvm.org/releases/3.6.2/clang+llvm-3.6.2-x86_64-linux-gnu-ubuntu-14.04.tar.xz | tar xJ) &&\
-cp -r /clang+llvm-3.6.2-x86_64-linux-gnu-ubuntu-14.04/* /usr/ &&\
-rm -rf /clang+llvm-3.6.2-x86_64-linux-gnu-ubuntu-14.04
-
-RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/clang++ 20
-RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/clang 20
-
-# Install Swift keys
-RUN wget --no-verbose -O - https://swift.org/keys/all-keys.asc | gpg --import - && \
-    gpg --keyserver hkp://pool.sks-keyservers.net --refresh-keys Swift
-
-# Install Swift Ubuntu 14.04 Snapshot
-#https://swift.org/builds/swift-3.0.1-release/ubuntu1404/swift-3.0.1-RELEASE/swift-3.0.1-RELEASE-ubuntu14.04.tar.gz
-
-ENV SWIFT_VERSION 3.0.2
-ENV SWIFT_RELEASE_TYPE RELEASE
-ENV SWIFT_PLATFORM ubuntu14.04
-
-RUN SWIFT_ARCHIVE_NAME=swift-$SWIFT_VERSION-$SWIFT_RELEASE_TYPE-$SWIFT_PLATFORM && \
-    SWIFT_URL=https://swift.org/builds/swift-$SWIFT_VERSION-$(echo "$SWIFT_RELEASE_TYPE" | tr '[:upper:]' '[:lower:]')/$(echo "$SWIFT_PLATFORM" | tr -d .)/swift-$SWIFT_VERSION-$SWIFT_RELEASE_TYPE/$SWIFT_ARCHIVE_NAME.tar.gz && \
-    echo $SWIFT_URL && \
-    wget --no-verbose $SWIFT_URL && \
-    wget --no-verbose $SWIFT_URL.sig && \
-    gpg --verify $SWIFT_ARCHIVE_NAME.tar.gz.sig && \
-    tar -xzf $SWIFT_ARCHIVE_NAME.tar.gz --directory / --strip-components=1 && \
-    rm -rf $SWIFT_ARCHIVE_NAME* /tmp/* /var/tmp/*
-
-# Add the action proxy
-RUN mkdir -p /actionProxy
-ADD actionproxy.py /actionProxy
-
-# Add files needed to build and run action
-RUN mkdir -p /swift3Action
-ADD epilogue.swift /swift3Action
-ADD buildandrecord.py /swift3Action
-ADD swift3runner.py /swift3Action
-ADD spm-build /swift3Action/spm-build
-
-
-# Build kitura net
-RUN touch /swift3Action/spm-build/main.swift
-RUN python /swift3Action/buildandrecord.py && rm /swift3Action/spm-build/.build/release/Action
-#RUN cd /swift3Action/spm-build; swift build -c release; rm /swift3Action/spm-build/.build/release/Action
-ENV FLASK_PROXY_PORT 8080
-
-CMD ["/bin/bash", "-c", "cd /swift3Action && PYTHONIOENCODING='utf-8' python -u swift3runner.py"]
\ No newline at end of file
diff --git a/core/swift3Action/build.gradle b/core/swift3Action/build.gradle
deleted file mode 100644
index 0148e31..0000000
--- a/core/swift3Action/build.gradle
+++ /dev/null
@@ -1,13 +0,0 @@
-ext.dockerImageName = 'swift3action'
-apply from: '../../gradle/docker.gradle'
-distDocker.dependsOn 'copyProxy'
-distDocker.finalizedBy('rmProxy')
-
-task copyProxy(type: Copy) {
-    from '../actionProxy/actionproxy.py'
-    into './actionproxy.py'
-}
-
-task rmProxy(type: Delete) {
-    delete 'actionproxy.py'
-}
diff --git a/core/swift3Action/buildandrecord.py b/core/swift3Action/buildandrecord.py
deleted file mode 100644
index c83c024..0000000
--- a/core/swift3Action/buildandrecord.py
+++ /dev/null
@@ -1,76 +0,0 @@
-"""Python to generate build script.
-
-/*
- * 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.
- */
-"""
-from __future__ import print_function
-import os
-import sys
-from subprocess import check_output
-
-# Settings
-COMPILE_PREFIX = "/usr/bin/swiftc -module-name Action "
-LINKER_PREFIX = "/usr/bin/swiftc -Xlinker '-rpath=$ORIGIN' " \
-                "'-L/swift3Action/spm-build/.build/release' " \
-                "-o '/swift3Action/spm-build/.build/release/Action'"
-GENERATED_BUILD_SCRIPT = "/swift3Action/spm-build/swiftbuildandlink.sh"
-SPM_DIRECTORY = "/swift3Action/spm-build"
-BUILD_COMMAND = ["swift", "build", "-v", "-c", "release"]
-
-# Build Swift package and capture step trace
-print("Building action")
-out = check_output(BUILD_COMMAND, cwd=SPM_DIRECTORY)
-print("action built. Decoding compile and link commands")
-
-# Look for compile and link commands in step trace
-compileCommand = None
-linkCommand = None
-
-buildInstructions = out.decode("utf-8").splitlines()
-
-for instruction in buildInstructions:
-    if instruction.startswith(COMPILE_PREFIX):
-        compileCommand = instruction
-
-        # add flag to quiet warnings
-        compileCommand += " -suppress-warnings"
-
-    elif instruction.startswith(LINKER_PREFIX):
-        linkCommand = instruction
-
-# Create build script if found, exit otherwise
-if compileCommand is not None and linkCommand is not None:
-    print("Success, command and link commands found.")
-    with open(GENERATED_BUILD_SCRIPT, "a") as buildScript:
-        buildScript.write("#!/bin/bash\n")
-        buildScript.write("echo \"Compiling\"\n")
-        buildScript.write("%s\n" % compileCommand)
-        buildScript.write("swiftStatus=$?\n")
-        buildScript.write("echo swiftc status is $swiftStatus\n")
-        buildScript.write("if [[ \"$swiftStatus\" -eq \"0\" ]]; then\n")
-        buildScript.write("echo \"Linking\"\n")
-        buildScript.write("%s\n" % linkCommand)
-        buildScript.write("else\n")
-        buildScript.write(">&2 echo \"Action did not compile\"\n")
-        buildScript.write("exit 1\n")
-        buildScript.write("fi")
-
-    os.chmod(GENERATED_BUILD_SCRIPT, 0o777)
-    sys.exit(0)
-else:
-    print("Cannot generate build script: compile or link command not found")
-    sys.exit(1)
diff --git a/core/swift3Action/spm-build/Package.swift b/core/swift3Action/spm-build/Package.swift
deleted file mode 100644
index 64268c2..0000000
--- a/core/swift3Action/spm-build/Package.swift
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-import PackageDescription
-
-let package = Package(
-    name: "Action",
-        dependencies: [
-            .Package(url: "https://github.com/IBM-Swift/CCurl.git", "0.2.3"),
-            .Package(url: "https://github.com/IBM-Swift/Kitura-net.git", "1.0.1"),
-            .Package(url: "https://github.com/IBM-Swift/SwiftyJSON.git", "14.2.0"),
-            .Package(url: "https://github.com/csantanapr/swift-watson-sdk.git", "0.4.1")
-        ]
-)
diff --git a/settings.gradle b/settings.gradle
index f9536a8..a0f56d4 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -8,7 +8,6 @@ include 'whisktests'; project(':whisktests').projectDir = new File(owDirectory,
 
 include 'tests'
 
-include 'core:swift3Action'
 include 'core:swift3.1.1Action'
 
 rootProject.name = 'runtime-swift'
diff --git a/tests/src/test/scala/actionContainers/Swift311ActionContainerTests.scala b/tests/src/test/scala/actionContainers/Swift311ActionContainerTests.scala
index e5c248d..058ef75 100644
--- a/tests/src/test/scala/actionContainers/Swift311ActionContainerTests.scala
+++ b/tests/src/test/scala/actionContainers/Swift311ActionContainerTests.scala
@@ -17,14 +17,68 @@
 
 package runtime.actionContainers
 
+import java.io.File
+
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
 
+import ActionContainer.withContainer
+import common.WskActorSystem
+import spray.json.JsObject
+import spray.json.JsString
+import common.TestUtils
+
 @RunWith(classOf[JUnitRunner])
-class Swift311ActionContainerTests extends Swift3ActionContainerTests {
-  override lazy val swiftContainerImageName = "action-swift-v3.1.1"
+class Swift3ActionContainerTests extends BasicActionRunnerTests with WskActorSystem {
+
+  // note: "out" will likely not be empty in some swift build as the compiler
+  // prints status messages and there doesn't seem to be a way to quiet them
+  val enforceEmptyOutputStream = false
+  lazy val swiftContainerImageName = "action-swift-v3.1.1"
+  lazy val envCode = makeEnvCode("ProcessInfo.processInfo")
+
+  def makeEnvCode(processInfo: String) = ("""
+         |func main(args: [String: Any]) -> [String: Any] {
+         |     let env = """ + processInfo + """.environment
+         |     var a = "???"
+         |     var b = "???"
+         |     var c = "???"
+         |     var d = "???"
+         |     var e = "???"
+         |     var f = "???"
+         |     if let v : String = env["__OW_API_HOST"] {
+         |         a = "\(v)"
+         |     }
+         |     if let v : String = env["__OW_API_KEY"] {
+         |         b = "\(v)"
+         |     }
+         |     if let v : String = env["__OW_NAMESPACE"] {
+         |         c = "\(v)"
+         |     }
+         |     if let v : String = env["__OW_ACTION_NAME"] {
+         |         d = "\(v)"
+         |     }
+         |     if let v : String = env["__OW_ACTIVATION_ID"] {
+         |         e = "\(v)"
+         |     }
+         |     if let v : String = env["__OW_DEADLINE"] {
+         |         f = "\(v)"
+         |     }
+         |     return ["api_host": a, "api_key": b, "namespace": c, "action_name": d, "activation_id": e, "deadline": f]
+         |}
+         """).stripMargin
 
-  override lazy val watsonCode = """
+  lazy val errorCode = """
+                | // You need an indirection, or swiftc detects the div/0
+                | // at compile-time. Smart.
+                | func div(x: Int, y: Int) -> Int {
+                |     return x/y
+                | }
+                | func main(args: [String: Any]) -> [String: Any] {
+                |     return [ "divBy0": div(x:5, y:0) ]
+                | }
+            """.stripMargin
+  lazy val watsonCode = """
                 | import AlchemyDataNewsV1
                 | import ConversationV1
                 | import DiscoveryV1
@@ -41,5 +95,277 @@ class Swift311ActionContainerTests extends Swift3ActionContainerTests {
                 |     return ["message": "I compiled and was able to import Watson SDKs"]
                 | }
             """.stripMargin
-  override lazy val swiftBinaryName = "helloSwift311.zip"
+  lazy val swiftBinaryName = "helloSwift311.zip"
+
+  // Helpers specific to swift actions
+  override def withActionContainer(env: Map[String, String] = Map.empty)(code: ActionContainer => Unit) = {
+    withContainer(swiftContainerImageName, env)(code)
+  }
+
+  behavior of swiftContainerImageName
+
+  // remove this test: it will not even compile under Swift 3 anymore
+  // so it should not be possible to write an action that does not return
+  // a [String:Any]
+  /*testNotReturningJson(
+        """
+        |func main(args: [String: Any]) -> String {
+        |    return "not a json object"
+        |}
+        """.stripMargin)
+   */
+
+  testEcho(Seq {
+    (
+      "swift",
+      """
+         | import Foundation
+         |
+         | extension FileHandle : TextOutputStream {
+         |     public func write(_ string: String) {
+         |         guard let data = string.data(using: .utf8) else { return }
+         |         self.write(data)
+         |     }
+         | }
+         |
+         | func main(args: [String: Any]) -> [String: Any] {
+         |     print("hello stdout")
+         |     var standardError = FileHandle.standardError
+         |     print("hello stderr", to: &standardError)
+         |     return args
+         | }
+        """.stripMargin)
+  })
+
+  testUnicode(Seq {
+    (
+      "swift",
+      """
+         | func main(args: [String: Any]) -> [String: Any] {
+         |     if let str = args["delimiter"] as? String {
+         |         let msg = "\(str) ? \(str)"
+         |         print(msg)
+         |         return [ "winter" : msg ]
+         |     } else {
+         |         return [ "error" : "no delimiter" ]
+         |     }
+         | }
+         """.stripMargin.trim)
+  })
+
+  testEnv(Seq {
+    ("swift", envCode)
+  }, enforceEmptyOutputStream)
+
+  it should "support actions using non-default entry points" in {
+    withActionContainer() { c =>
+      val code = """
+                | func niam(args: [String: Any]) -> [String: Any] {
+                |     return [ "result": "it works" ]
+                | }
+                |""".stripMargin
+
+      val (initCode, initRes) = c.init(initPayload(code, main = "niam"))
+      initCode should be(200)
+
+      val (_, runRes) = c.run(runPayload(JsObject()))
+      runRes.get.fields.get("result") shouldBe Some(JsString("it works"))
+    }
+  }
+
+  it should "return some error on action error" in {
+    val (out, err) = withActionContainer() { c =>
+      val code = errorCode
+
+      val (initCode, _) = c.init(initPayload(code))
+      initCode should be(200)
+
+      val (runCode, runRes) = c.run(runPayload(JsObject()))
+      runCode should be(502)
+
+      runRes shouldBe defined
+      runRes.get.fields.get("error") shouldBe defined
+    }
+
+    checkStreams(out, err, {
+      case (o, e) =>
+        if (enforceEmptyOutputStream) o shouldBe empty
+        e shouldBe empty
+    })
+  }
+
+  it should "log compilation errors" in {
+    val (out, err) = withActionContainer() { c =>
+      val code = """
+              | 10 PRINT "Hello!"
+              | 20 GOTO 10
+            """.stripMargin
+
+      val (initCode, _) = c.init(initPayload(code))
+      initCode should not be (200)
+    }
+
+    checkStreams(out, err, {
+      case (o, e) =>
+        if (enforceEmptyOutputStream) o shouldBe empty
+        e.toLowerCase should include("error")
+    })
+  }
+
+  it should "support application errors" in {
+    val (out, err) = withActionContainer() { c =>
+      val code = """
+                | func main(args: [String: Any]) -> [String: Any] {
+                |     return [ "error": "sorry" ]
+                | }
+            """.stripMargin
+
+      val (initCode, _) = c.init(initPayload(code))
+      initCode should be(200)
+
+      val (runCode, runRes) = c.run(runPayload(JsObject()))
+      runCode should be(200) // action writer returning an error is OK
+
+      runRes shouldBe defined
+      runRes should be(Some(JsObject("error" -> JsString("sorry"))))
+    }
+
+    checkStreams(out, err, {
+      case (o, e) =>
+        if (enforceEmptyOutputStream) o shouldBe empty
+        e shouldBe empty
+    })
+  }
+
+  it should "support support multiple files in a zip file" in {
+    val zip = new File(TestUtils.getTestActionFilename("multiSwift.zip")).toPath
+    val code = ResourceHelpers.readAsBase64(zip)
+
+    val (out, err) = withActionContainer() { c =>
+      val (initCode, initRes) = c.init(initPayload(code))
+      initCode should be(200)
+
+      val args = JsObject()
+      val (runCode, runRes) = c.run(runPayload(args))
+
+      runCode should be(200)
+      runRes.get shouldBe JsObject("greeting" -> (JsString("Hello stranger!")))
+    }
+
+    checkStreams(out, err, {
+      case (o, e) =>
+        if (enforceEmptyOutputStream) o shouldBe empty
+        e shouldBe empty
+    })
+  }
+
+  it should "support pre-compiled binary in a zip file" in {
+    val zip = new File(TestUtils.getTestActionFilename(swiftBinaryName)).toPath
+    val code = ResourceHelpers.readAsBase64(zip)
+
+    val (out, err) = withActionContainer() { c =>
+      val (initCode, initRes) = c.init(initPayload(code))
+      initCode should be(200)
+
+      val args = JsObject()
+      val (runCode, runRes) = c.run(runPayload(args))
+
+      runCode should be(200)
+      runRes.get shouldBe JsObject("greeting" -> (JsString("Hello stranger!")))
+    }
+
+    checkStreams(out, err, {
+      case (o, e) =>
+        if (enforceEmptyOutputStream) o shouldBe empty
+        e shouldBe empty
+    })
+  }
+
+  it should "properly use KituraNet and Dispatch" in {
+    val (out, err) = withActionContainer() { c =>
+      val code = """
+                | import KituraNet
+                | import Foundation
+                | import Dispatch
+                | func main(args:[String: Any]) -> [String:Any] {
+                |       let retries = 3
+                |       var resp = [String:Any]()
+                |       var attempts = 0
+                |       if let url = args["getUrl"] as? String {
+                |           while attempts < retries {
+                |               let group = DispatchGroup()
+                |               let queue = DispatchQueue.global(qos: .default)
+                |               group.enter()
+                |               queue.async {
+                |                   HTTP.get(url, callback: { response in
+                |                       if let response = response {
+                |                           do {
+                |                               var jsonData = Data()
+                |                               try response.readAllData(into: &jsonData)
+                |                               if let dic = WhiskJsonUtils.jsonDataToDictionary(jsonData: jsonData) {
+                |                                   resp = dic
+                |                               } else {
+                |                                   resp = ["error":"response from server is not JSON"]
+                |                               }
+                |                           } catch {
+                |                              resp["error"] = error.localizedDescription
+                |                           }
+                |                       }
+                |                       group.leave()
+                |                   })
+                |               }
+                |            switch group.wait(timeout: DispatchTime.distantFuture) {
+                |                case DispatchTimeoutResult.success:
+                |                    resp["attempts"] = attempts
+                |                    return resp
+                |                case DispatchTimeoutResult.timedOut:
+                |                    attempts = attempts + 1
+                |            }
+                |        }
+                |     }
+                |     return ["status":"Exceeded \(retries) attempts, aborting."]
+                | }
+            """.stripMargin
+
+      val (initCode, _) = c.init(initPayload(code))
+
+      initCode should be(200)
+
+      val argss = List(JsObject("getUrl" -> JsString("https://openwhisk.ng.bluemix.net/api/v1")))
+
+      for (args <- argss) {
+        val (runCode, out) = c.run(runPayload(args))
+        runCode should be(200)
+      }
+    }
+
+    // in side try catch finally print (out file)
+    // in catch block an error has occurred, get docker logs and print
+    // throw
+
+    checkStreams(out, err, {
+      case (o, e) =>
+        if (enforceEmptyOutputStream) o shouldBe empty
+        e shouldBe empty
+    })
+  }
+
+  it should "make Watson SDKs available to action authors" in {
+    val (out, err) = withActionContainer() { c =>
+      val code = watsonCode
+
+      val (initCode, _) = c.init(initPayload(code))
+
+      initCode should be(200)
+
+      val (runCode, out) = c.run(runPayload(JsObject()))
+      runCode should be(200)
+    }
+
+    checkStreams(out, err, {
+      case (o, e) =>
+        if (enforceEmptyOutputStream) o shouldBe empty
+        e shouldBe empty
+    })
+  }
 }
diff --git a/tests/src/test/scala/actionContainers/Swift3ActionContainerTests.scala b/tests/src/test/scala/actionContainers/Swift3ActionContainerTests.scala
deleted file mode 100644
index 435d07e..0000000
--- a/tests/src/test/scala/actionContainers/Swift3ActionContainerTests.scala
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * 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.
- */
-
-package runtime.actionContainers
-
-import java.io.File
-
-import org.junit.runner.RunWith
-import org.scalatest.junit.JUnitRunner
-
-import ActionContainer.withContainer
-import common.WskActorSystem
-import spray.json.JsObject
-import spray.json.JsString
-import common.TestUtils
-
-@RunWith(classOf[JUnitRunner])
-class Swift3ActionContainerTests extends BasicActionRunnerTests with WskActorSystem {
-
-  // note: "out" will likely not be empty in some swift build as the compiler
-  // prints status messages and there doesn't seem to be a way to quiet them
-  val enforceEmptyOutputStream = false
-  lazy val swiftContainerImageName = "swift3action"
-  lazy val envCode = makeEnvCode("ProcessInfo.processInfo")
-
-  def makeEnvCode(processInfo: String) = ("""
-         |func main(args: [String: Any]) -> [String: Any] {
-         |     let env = """ + processInfo + """.environment
-         |     var a = "???"
-         |     var b = "???"
-         |     var c = "???"
-         |     var d = "???"
-         |     var e = "???"
-         |     var f = "???"
-         |     if let v : String = env["__OW_API_HOST"] {
-         |         a = "\(v)"
-         |     }
-         |     if let v : String = env["__OW_API_KEY"] {
-         |         b = "\(v)"
-         |     }
-         |     if let v : String = env["__OW_NAMESPACE"] {
-         |         c = "\(v)"
-         |     }
-         |     if let v : String = env["__OW_ACTION_NAME"] {
-         |         d = "\(v)"
-         |     }
-         |     if let v : String = env["__OW_ACTIVATION_ID"] {
-         |         e = "\(v)"
-         |     }
-         |     if let v : String = env["__OW_DEADLINE"] {
-         |         f = "\(v)"
-         |     }
-         |     return ["api_host": a, "api_key": b, "namespace": c, "action_name": d, "activation_id": e, "deadline": f]
-         |}
-         """).stripMargin
-
-  lazy val errorCode = """
-                | // You need an indirection, or swiftc detects the div/0
-                | // at compile-time. Smart.
-                | func div(x: Int, y: Int) -> Int {
-                |     return x/y
-                | }
-                | func main(args: [String: Any]) -> [String: Any] {
-                |     return [ "divBy0": div(x:5, y:0) ]
-                | }
-            """.stripMargin
-  lazy val watsonCode = """
-                | import RestKit
-                | import WeatherCompanyData
-                | import AlchemyVision
-                |
-                | func main(args: [String:Any]) -> [String:Any] {
-                |     return ["message": "I compiled and was able to import Watson SDKs"]
-                | }
-            """.stripMargin
-  lazy val swiftBinaryName = "helloSwift3.zip"
-
-  // Helpers specific to swift actions
-  override def withActionContainer(env: Map[String, String] = Map.empty)(code: ActionContainer => Unit) = {
-    withContainer(swiftContainerImageName, env)(code)
-  }
-
-  behavior of swiftContainerImageName
-
-  // remove this test: it will not even compile under Swift 3 anymore
-  // so it should not be possible to write an action that does not return
-  // a [String:Any]
-  /*testNotReturningJson(
-        """
-        |func main(args: [String: Any]) -> String {
-        |    return "not a json object"
-        |}
-        """.stripMargin)
-   */
-
-  testEcho(Seq {
-    (
-      "swift",
-      """
-         | import Foundation
-         |
-         | extension FileHandle : TextOutputStream {
-         |     public func write(_ string: String) {
-         |         guard let data = string.data(using: .utf8) else { return }
-         |         self.write(data)
-         |     }
-         | }
-         |
-         | func main(args: [String: Any]) -> [String: Any] {
-         |     print("hello stdout")
-         |     var standardError = FileHandle.standardError
-         |     print("hello stderr", to: &standardError)
-         |     return args
-         | }
-        """.stripMargin)
-  })
-
-  testUnicode(Seq {
-    (
-      "swift",
-      """
-         | func main(args: [String: Any]) -> [String: Any] {
-         |     if let str = args["delimiter"] as? String {
-         |         let msg = "\(str) ? \(str)"
-         |         print(msg)
-         |         return [ "winter" : msg ]
-         |     } else {
-         |         return [ "error" : "no delimiter" ]
-         |     }
-         | }
-         """.stripMargin.trim)
-  })
-
-  testEnv(Seq {
-    ("swift", envCode)
-  }, enforceEmptyOutputStream)
-
-  it should "support actions using non-default entry points" in {
-    withActionContainer() { c =>
-      val code = """
-                | func niam(args: [String: Any]) -> [String: Any] {
-                |     return [ "result": "it works" ]
-                | }
-                |""".stripMargin
-
-      val (initCode, initRes) = c.init(initPayload(code, main = "niam"))
-      initCode should be(200)
-
-      val (_, runRes) = c.run(runPayload(JsObject()))
-      runRes.get.fields.get("result") shouldBe Some(JsString("it works"))
-    }
-  }
-
-  it should "return some error on action error" in {
-    val (out, err) = withActionContainer() { c =>
-      val code = errorCode
-
-      val (initCode, _) = c.init(initPayload(code))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-      runCode should be(502)
-
-      runRes shouldBe defined
-      runRes.get.fields.get("error") shouldBe defined
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        if (enforceEmptyOutputStream) o shouldBe empty
-        e shouldBe empty
-    })
-  }
-
-  it should "log compilation errors" in {
-    val (out, err) = withActionContainer() { c =>
-      val code = """
-              | 10 PRINT "Hello!"
-              | 20 GOTO 10
-            """.stripMargin
-
-      val (initCode, _) = c.init(initPayload(code))
-      initCode should not be (200)
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        if (enforceEmptyOutputStream) o shouldBe empty
-        e.toLowerCase should include("error")
-    })
-  }
-
-  it should "support application errors" in {
-    val (out, err) = withActionContainer() { c =>
-      val code = """
-                | func main(args: [String: Any]) -> [String: Any] {
-                |     return [ "error": "sorry" ]
-                | }
-            """.stripMargin
-
-      val (initCode, _) = c.init(initPayload(code))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-      runCode should be(200) // action writer returning an error is OK
-
-      runRes shouldBe defined
-      runRes should be(Some(JsObject("error" -> JsString("sorry"))))
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        if (enforceEmptyOutputStream) o shouldBe empty
-        e shouldBe empty
-    })
-  }
-
-  it should "support support multiple files in a zip file" in {
-    val zip = new File(TestUtils.getTestActionFilename("multiSwift.zip")).toPath
-    val code = ResourceHelpers.readAsBase64(zip)
-
-    val (out, err) = withActionContainer() { c =>
-      val (initCode, initRes) = c.init(initPayload(code))
-      initCode should be(200)
-
-      val args = JsObject()
-      val (runCode, runRes) = c.run(runPayload(args))
-
-      runCode should be(200)
-      runRes.get shouldBe JsObject("greeting" -> (JsString("Hello stranger!")))
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        if (enforceEmptyOutputStream) o shouldBe empty
-        e shouldBe empty
-    })
-  }
-
-  it should "support pre-compiled binary in a zip file" in {
-    val zip = new File(TestUtils.getTestActionFilename(swiftBinaryName)).toPath
-    val code = ResourceHelpers.readAsBase64(zip)
-
-    val (out, err) = withActionContainer() { c =>
-      val (initCode, initRes) = c.init(initPayload(code))
-      initCode should be(200)
-
-      val args = JsObject()
-      val (runCode, runRes) = c.run(runPayload(args))
-
-      runCode should be(200)
-      runRes.get shouldBe JsObject("greeting" -> (JsString("Hello stranger!")))
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        if (enforceEmptyOutputStream) o shouldBe empty
-        e shouldBe empty
-    })
-  }
-
-  it should "properly use KituraNet and Dispatch" in {
-    val (out, err) = withActionContainer() { c =>
-      val code = """
-                | import KituraNet
-                | import Foundation
-                | import Dispatch
-                | func main(args:[String: Any]) -> [String:Any] {
-                |       let retries = 3
-                |       var resp = [String:Any]()
-                |       var attempts = 0
-                |       if let url = args["getUrl"] as? String {
-                |           while attempts < retries {
-                |               let group = DispatchGroup()
-                |               let queue = DispatchQueue.global(qos: .default)
-                |               group.enter()
-                |               queue.async {
-                |                   HTTP.get(url, callback: { response in
-                |                       if let response = response {
-                |                           do {
-                |                               var jsonData = Data()
-                |                               try response.readAllData(into: &jsonData)
-                |                               if let dic = WhiskJsonUtils.jsonDataToDictionary(jsonData: jsonData) {
-                |                                   resp = dic
-                |                               } else {
-                |                                   resp = ["error":"response from server is not JSON"]
-                |                               }
-                |                           } catch {
-                |                              resp["error"] = error.localizedDescription
-                |                           }
-                |                       }
-                |                       group.leave()
-                |                   })
-                |               }
-                |            switch group.wait(timeout: DispatchTime.distantFuture) {
-                |                case DispatchTimeoutResult.success:
-                |                    resp["attempts"] = attempts
-                |                    return resp
-                |                case DispatchTimeoutResult.timedOut:
-                |                    attempts = attempts + 1
-                |            }
-                |        }
-                |     }
-                |     return ["status":"Exceeded \(retries) attempts, aborting."]
-                | }
-            """.stripMargin
-
-      val (initCode, _) = c.init(initPayload(code))
-
-      initCode should be(200)
-
-      val argss = List(JsObject("getUrl" -> JsString("https://openwhisk.ng.bluemix.net/api/v1")))
-
-      for (args <- argss) {
-        val (runCode, out) = c.run(runPayload(args))
-        runCode should be(200)
-      }
-    }
-
-    // in side try catch finally print (out file)
-    // in catch block an error has occurred, get docker logs and print
-    // throw
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        if (enforceEmptyOutputStream) o shouldBe empty
-        e shouldBe empty
-    })
-  }
-
-  it should "make Watson SDKs available to action authors" in {
-    val (out, err) = withActionContainer() { c =>
-      val code = watsonCode
-
-      val (initCode, _) = c.init(initPayload(code))
-
-      initCode should be(200)
-
-      val (runCode, out) = c.run(runPayload(JsObject()))
-      runCode should be(200)
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        if (enforceEmptyOutputStream) o shouldBe empty
-        e shouldBe empty
-    })
-  }
-}
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index 608a15d..1ac1e5a 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -14,7 +14,7 @@ IMAGE_PREFIX="testing"
 # Build runtime
 cd $ROOTDIR
 TERM=dumb ./gradlew \
-:core:swift3Action:distDocker :core:swift3.1.1Action:distDocker \
+:core:swift3.1.1Action:distDocker \
 -PdockerImagePrefix=${IMAGE_PREFIX}
 
 
diff --git a/tools/travis/publish.sh b/tools/travis/publish.sh
index f997078..979089a 100755
--- a/tools/travis/publish.sh
+++ b/tools/travis/publish.sh
@@ -13,9 +13,7 @@ IMAGE_PREFIX=$1
 RUNTIME_VERSION=$2
 IMAGE_TAG=$3
 
-if [ ${RUNTIME_VERSION} == "3" ]; then
-  RUNTIME="swift3Action"
-elif [ ${RUNTIME_VERSION} == "3.1.1" ]; then
+if [ ${RUNTIME_VERSION} == "3.1.1" ]; then
   RUNTIME="swift3.1.1Action"
 fi
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services