This is an automated email from the ASF dual-hosted git repository.
msciabarra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openwhisk-runtime-swift.git
The following commit(s) were added to refs/heads/master by this push:
new 08ea221 Swift51 support (#107)
08ea221 is described below
commit 08ea221ab76dd6c7bff4d52721ae0944b70f1af8
Author: Andrea Scuderi <[email protected]>
AuthorDate: Sat Nov 23 19:31:21 2019 +0000
Swift51 support (#107)
* support for swift 5.1 - wip
* adding support for swift 5.1
* using the latest proxy
* adding a test
* adding the new 51 runtime
* Update CI
* implementing tests and binary compilation
* making scancode happy
* - Add Unit Test for SwiftRequest and SwiftyRequestCodable for swift 5
* fixed test compilation
* use a single default runtime
* force build
* tests assming 4.2 is the default
* Fix actionKind
* Fix trailing space
* Trailing whitespace
* another whitespace
* fixed test binaries
* Update README
* Add nightly build
* reverted swift312 support
---
.gitignore | 4 +
.travis.yml | 5 +
README.md | 110 +++++++++++++-
ansible/environments/local/group_vars/all | 5 +
core/swift51Action/Dockerfile | 49 ++++++
.../swift51Action/Package.swift | 43 +++---
core/swift51Action/_Whisk.swift | 167 +++++++++++++++++++++
settings.gradle => core/swift51Action/build.gradle | 25 +--
settings.gradle => core/swift51Action/main.swift | 30 +---
core/swift51Action/swiftbuild.py | 119 +++++++++++++++
core/swift51Action/swiftbuild.py.launcher.swift | 133 ++++++++++++++++
.../swift51Action/swiftbuildandlink.sh | 15 +-
settings.gradle | 2 +
tests/build.gradle | 5 +
.../dat/actions/HelloSwift5/Package.swift | 43 +++---
.../dat/actions/HelloSwift5/Sources/main.swift | 32 ++--
.../dat/actions/HelloSwift5Codable/Package.swift | 43 +++---
.../actions/HelloSwift5Codable/Sources/main.swift | 41 +++--
tests/dat/actions/Makefile | 16 +-
tests/dat/actions/SwiftyRequest5/Package.resolved | 79 ++++++++++
.../dat/actions/SwiftyRequest5/Package.swift | 47 +++---
.../dat/actions/SwiftyRequest5/Sources/main.swift | 52 +++++++
.../actions/SwiftyRequestCodable5/Package.resolved | 79 ++++++++++
.../actions/SwiftyRequestCodable5/Package.swift | 47 +++---
.../SwiftyRequestCodable5/Sources/main.swift | 50 +++---
tests/dat/actions/sdk/swift5/createRule.swift | 36 +++++
.../dat/actions/sdk/swift5/createTrigger.swift | 36 ++---
.../dat/actions/sdk/swift5/hello.swift | 32 ++--
tests/dat/actions/sdk/swift5/invoke.swift | 47 ++++++
.../dat/actions/sdk/swift5/invokeNonBlocking.swift | 42 ++++++
.../dat/actions/sdk/swift5/trigger.swift | 37 ++---
tests/dat/build.sh | 6 +
tests/dat/build/swift311/HelloSwift3.zip | Bin 498321 -> 0 bytes
tests/dat/build/swift4.1/HelloSwift4.zip | Bin 12049 -> 12053 bytes
tests/dat/build/swift4.1/HelloSwift4Codable.zip | Bin 17234 -> 17237 bytes
tests/dat/build/swift4.1/SwiftyRequest.zip | Bin 155592 -> 200346 bytes
tests/dat/build/swift4.1/SwiftyRequestCodable.zip | Bin 158942 -> 203924 bytes
tests/dat/build/swift5.1/HelloSwift5.zip | Bin 0 -> 12611 bytes
tests/dat/build/swift5.1/HelloSwift5Codable.zip | Bin 0 -> 20600 bytes
tests/dat/build/swift5.1/SwiftyRequest5.zip | Bin 0 -> 2427796 bytes
tests/dat/build/swift5.1/SwiftyRequestCodable5.zip | Bin 0 -> 2433716 bytes
.../Swift51ActionContainerTests.scala | 121 +++++++++++++++
.../Swift51CodableActionContainerTests.scala | 29 +---
.../test/scala/runtime/sdk/Swift51SDKTests.scala | 28 +---
tools/build/compile.sh | 5 +-
tests/dat/build.sh => tools/build/compile5.sh | 20 +--
tools/travis/build.sh | 1 +
tools/travis/publish.sh | 2 +
48 files changed, 1311 insertions(+), 372 deletions(-)
diff --git a/.gitignore b/.gitignore
index 100215f..557d0a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,6 +72,10 @@ ansible/roles/nginx/files/*cert.pem
!tests/dat/build/swift4.1/SwiftyRequest.zip
!tests/dat/build/swift4.1/SwiftyRequestCodable.zip
!tests/dat/build/swift4.1/HelloSwift4Codable.zip
+!tests/dat/build/swift5.1/HelloSwift5.zip
+!tests/dat/build/swift5.1/HelloSwift5Codable.zip
+!tests/dat/build/swift5.1/SwiftyRequest5.zip
+!tests/dat/build/swift5.1/SwiftyRequestCodable5.zip
# Makefile artifacts
test.json
diff --git a/.travis.yml b/.travis.yml
index ae24d2d..c8d0eab 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -46,6 +46,11 @@ deploy:
on:
branch: master
repo: apache/openwhisk-runtime-swift
+ - provider: script
+ script: "./tools/travis/publish.sh openwhisk 5.1 nightly &&
./tools/travis/publish.sh openwhisk 5.1 nightly"
+ on:
+ branch: master
+ repo: apache/openwhisk-runtime-swift
env:
global:
- secure:
YqQG7kchpqrqYNCBHmoXs5QJFJQmtuy30WYQnQtudVuqZ1/PqsTJXy6+kNxQ88z5NoU4XZKClB61V8ZVHqGsbQd3lAsTy11QKxf+s4kfsGBuoRlow4eQmnUnnaF3E6KVV2nJ4oXro7RQhP3WwLjpsThrMk322B1ZtlSRALR9hK5wCit8Q1ifSJqmKLwuoNSNQzd7onlDF19Q9pyKkgVu9wLKU5epo76wuFkRfkbr1mB3fF2le2WRNXer2N8rL8McHousFPYA03IIdo6zdX27yGmqSW3teCiVYieGrqtaGhH0WCE7dcmoQ/gs7IBqn1K80wJSR1lbkKDiWzmb73FWScKuXmRn5c4HCq/wPya2I5JNUGyPg5YI0HyMDxGTJ/OdXv2Aizyh3hyNMFjtbjK4N6gz6kFAn8Uo6wFs441Bq+S3+ipLAQ41KIQ7E4/Di6ERSG8KKWKy+LlnA5Qy60CQHRIyJCg3+aqf
[...]
diff --git a/README.md b/README.md
index ea58e5a..4056260 100644
--- a/README.md
+++ b/README.md
@@ -31,15 +31,122 @@
### Simple swift action hello.swift
The traditional support for dictionary still works:
```swift
+import Foundation
+
func main(args: [String:Any]) -> [String:Any] {
if let name = args["name"] as? String {
return [ "greeting" : "Hello \(name)!" ]
} else {
- return [ "greeting" : "Hello swif4!" ]
+ return [ "greeting" : "Hello stranger!" ]
}
}
```
+## Swift 5.x support
+
+Some examples of using Codable In and Out
+### Codable style function signature
+Create file `helloCodableAsync.swift`
+```swift
+
+import Foundation
+
+// Domain model/entity
+struct Employee: Codable {
+ let id: Int?
+ let name: String?
+}
+// codable main function
+func main(input: Employee, respondWith: (Employee?, Error?) -> Void) -> Void {
+ // For simplicity, just passing same Employee instance forward
+ respondWith(input, nil)
+}
+```
+```
+wsk action update helloCodableAsync helloCodableAsync.swift swift:5.1
+```
+```
+ok: updated action helloCodableAsync
+```
+```
+wsk action invoke helloCodableAsync -r -p id 73 -p name Andrea
+```
+```json
+{
+ "id": 73,
+ "name": "Andrea"
+}
+```
+
+### Codable Error Handling
+Create file `helloCodableAsync.swift`
+```swift
+
+import Foundation
+
+struct Employee: Codable {
+ let id: Int?
+ let name: String?
+}
+enum VendingMachineError: Error {
+ case invalidSelection
+ case insufficientFunds(coinsNeeded: Int)
+ case outOfStock
+}
+func main(input: Employee, respondWith: (Employee?, Error?) -> Void) -> Void {
+ // Return real error
+ do {
+ throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
+ } catch {
+ respondWith(nil, error)
+ }
+}
+```
+```
+wsk action update helloCodableError helloCodableError.swift swift:5.1
+```
+```
+ok: updated action helloCodableError
+```
+```
+wsk action invoke helloCodableError -b -p id 51 -p name Carlos
+```
+```json
+{
+"name": "helloCodableError",
+"response": {
+ "result": {
+ "error": "insufficientFunds(5)"
+ },
+"status": "application error",
+"success": false
+}
+```
+
+## Packaging an action as a Swift executable using Swift 5.x
+
+When you create an OpenWhisk Swift action with a Swift source file, it has to
be compiled into a binary before the action is run. Once done, subsequent calls
to the action are much faster until the container holding your action is
purged. This delay is known as the cold-start delay.
+
+To avoid the cold-start delay, you can compile your Swift file into a binary
and then upload to OpenWhisk in a zip file. As you need the OpenWhisk
scaffolding, the easiest way to create the binary is to build it within the
same environment as it will be run in.
+
+### Compiling Swift 5.x
+
+### Compiling Swift 5.x single file
+
+Use the docker container and pass the single source file as stdin.
+Pass the name of the method to the flag `-compile`
+```
+docker run -i openwhisk/action-swift-v5.1 -compile main <main.swift
>../action.zip
+```
+
+### Compiling Swift 5.1 multiple files with dependencies
+Use the docker container and pass a zip archive containing a `Package.swift`
and source files a main source file in the location `Sources/main.swift`.
+```
+zip - -r * | docker run -i openwhisk/action-swift-v5.1 -compile main
>../action.zip
+```
+
+For more build examples see [here](./examples/)
+
## Swift 4.x support
Some examples of using Codable In and Out
@@ -415,7 +522,6 @@ Using IntelliJ:
- Import project as gradle project.
- Make sure working directory is root of the project/repo
-
#### Using container image to test
To use as docker action push to your own dockerhub account
```
diff --git a/ansible/environments/local/group_vars/all
b/ansible/environments/local/group_vars/all
index 64dd3f0..b4826e8 100644
--- a/ansible/environments/local/group_vars/all
+++ b/ansible/environments/local/group_vars/all
@@ -59,6 +59,11 @@ runtimes_manifest:
image:
name: "action-swift-v4.2"
deprecated: false
+ - kind: "swift:5.1"
+ default: false
+ image:
+ name: "action-swift-v5.1"
+ deprecated: false
blackboxes:
- name: "dockerskeleton"
diff --git a/core/swift51Action/Dockerfile b/core/swift51Action/Dockerfile
new file mode 100644
index 0000000..337caff
--- /dev/null
+++ b/core/swift51Action/Dockerfile
@@ -0,0 +1,49 @@
+#
+# 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 golang:1.12 as builder
+RUN curl -sL \
+
https://github.com/apache/openwhisk-runtime-go/archive/[email protected]\
+ | tar xzf -\
+ && cd openwhisk-runtime-go-*/main\
+ && GO111MODULE=on go build -o /bin/proxy
+FROM swift:5.1.2
+
+RUN rm -rf /var/lib/apt/lists/* && apt-get clean && apt-get -qq update \
+ && apt-get install -y --no-install-recommends locales python3 vim
libssl-dev libicu-dev \
+ && rm -rf /var/lib/apt/lists/* \
+ && locale-gen en_US.UTF-8
+
+ENV LANG="en_US.UTF-8" \
+ LANGUAGE="en_US:en" \
+ LC_ALL="en_US.UTF-8"
+
+RUN mkdir -p /swiftAction
+WORKDIR /swiftAction
+
+COPY --from=builder /bin/proxy /bin/proxy
+ADD swiftbuild.py /bin/compile
+ADD swiftbuild.py.launcher.swift /bin/compile.launcher.swift
+COPY _Whisk.swift /swiftAction/Sources/
+COPY Package.swift /swiftAction/
+COPY swiftbuildandlink.sh /swiftAction/
+COPY main.swift /swiftAction/Sources/
+RUN swift build -c release; \
+ touch /swiftAction/Sources/main.swift; \
+ rm /swiftAction/.build/release/Action
+
+ENV OW_COMPILER=/bin/compile
+ENTRYPOINT [ "/bin/proxy" ]
diff --git a/settings.gradle b/core/swift51Action/Package.swift
similarity index 63%
copy from settings.gradle
copy to core/swift51Action/Package.swift
index 7b18e3c..181e352 100644
--- a/settings.gradle
+++ b/core/swift51Action/Package.swift
@@ -1,3 +1,6 @@
+// swift-tools-version:4.2
+// The swift-tools-version declares the minimum version of Swift required to
build this package.
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,26 +18,20 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import PackageDescription
+
+let package = Package(
+ name: "Action",
+ products: [
+ .executable(
+ name: "Action",
+ targets: ["Action"]
+ )
+ ],
+ targets: [
+ .target(
+ name: "Action",
+ path: "."
+ )
+ ]
+)
diff --git a/core/swift51Action/_Whisk.swift b/core/swift51Action/_Whisk.swift
new file mode 100644
index 0000000..3f18e9d
--- /dev/null
+++ b/core/swift51Action/_Whisk.swift
@@ -0,0 +1,167 @@
+/*
+ * 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 Foundation
+import Dispatch
+#if canImport(FoundationNetworking)
+import FoundationNetworking
+#endif
+
+class Whisk {
+
+ static var baseUrl = ProcessInfo.processInfo.environment["__OW_API_HOST"]
+ static var apiKey = ProcessInfo.processInfo.environment["__OW_API_KEY"]
+ // This will allow user to modify the default JSONDecoder and JSONEncoder
used by epilogue
+ static var jsonDecoder = JSONDecoder()
+ static var jsonEncoder = JSONEncoder()
+
+ class func invoke(actionNamed action : String, withParameters params :
[String:Any], blocking: Bool = true) -> [String:Any] {
+ let parsedAction = parseQualifiedName(name: action)
+ let strBlocking = blocking ? "true" : "false"
+ let path =
"/api/v1/namespaces/\(parsedAction.namespace)/actions/\(parsedAction.name)?blocking=\(strBlocking)"
+
+ return sendWhiskRequestSyncronish(uriPath: path, params: params,
method: "POST")
+ }
+
+ class func trigger(eventNamed event : String, withParameters params :
[String:Any]) -> [String:Any] {
+ let parsedEvent = parseQualifiedName(name: event)
+ let path =
"/api/v1/namespaces/\(parsedEvent.namespace)/triggers/\(parsedEvent.name)?blocking=true"
+
+ return sendWhiskRequestSyncronish(uriPath: path, params: params,
method: "POST")
+ }
+
+ class func createTrigger(triggerNamed trigger: String, withParameters
params : [String:Any]) -> [String:Any] {
+ let parsedTrigger = parseQualifiedName(name: trigger)
+ let path =
"/api/v1/namespaces/\(parsedTrigger.namespace)/triggers/\(parsedTrigger.name)"
+ return sendWhiskRequestSyncronish(uriPath: path, params: params,
method: "PUT")
+ }
+
+ class func createRule(ruleNamed ruleName: String, withTrigger triggerName:
String, andAction actionName: String) -> [String:Any] {
+ let parsedRule = parseQualifiedName(name: ruleName)
+ let path =
"/api/v1/namespaces/\(parsedRule.namespace)/rules/\(parsedRule.name)"
+ let params = ["trigger":triggerName, "action":actionName]
+ return sendWhiskRequestSyncronish(uriPath: path, params: params,
method: "PUT")
+ }
+
+ // handle the GCD dance to make the post async, but then obtain/return
+ // the result from this function sync
+ private class func sendWhiskRequestSyncronish(uriPath path: String, params
: [String:Any], method: String) -> [String:Any] {
+ var response : [String:Any]!
+
+ let queue = DispatchQueue.global()
+ let invokeGroup = DispatchGroup()
+
+ invokeGroup.enter()
+ queue.async {
+ postUrlSession(uriPath: path, params: params, method: method,
group: invokeGroup) { result in
+ response = result
+ }
+ }
+
+ // On one hand, FOREVER seems like an awfully long time...
+ // But on the other hand, I think we can rely on the system to kill
this
+ // if it exceeds a reasonable execution time.
+ switch invokeGroup.wait(timeout: DispatchTime.distantFuture) {
+ case DispatchTimeoutResult.success:
+ break
+ case DispatchTimeoutResult.timedOut:
+ break
+ }
+
+ return response
+ }
+
+
+ /**
+ * Using new UrlSession
+ */
+ private class func postUrlSession(uriPath: String, params : [String:Any],
method: String,group: DispatchGroup, callback : @escaping([String:Any]) ->
Void) {
+
+ guard let encodedPath =
uriPath.addingPercentEncoding(withAllowedCharacters:
CharacterSet.urlQueryAllowed) else {
+ callback(["error": "Error encoding uri path to make openwhisk REST
call."])
+ return
+ }
+
+ let urlStr = "\(baseUrl!)\(encodedPath)"
+ if let url = URL(string: urlStr) {
+ var request = URLRequest(url: url)
+ request.httpMethod = method
+
+ do {
+ request.addValue("application/json", forHTTPHeaderField:
"Content-Type")
+ request.httpBody = try JSONSerialization.data(withJSONObject:
params)
+
+ let loginData: Data = apiKey!.data(using:
String.Encoding.utf8, allowLossyConversion: false)!
+ let base64EncodedAuthKey =
loginData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue:
0))
+ request.addValue("Basic \(base64EncodedAuthKey)",
forHTTPHeaderField: "Authorization")
+ let session = URLSession(configuration:
URLSessionConfiguration.default)
+
+ let task = session.dataTask(with: request, completionHandler:
{data, response, error -> Void in
+
+ // exit group after we are done
+ defer {
+ group.leave()
+ }
+
+ if let error = error {
+ callback(["error":error.localizedDescription])
+ } else {
+
+ if let data = data {
+ do {
+ //let outputStr = String(data: data,
encoding: String.Encoding.utf8) as String!
+ //print(outputStr)
+ let respJson = try
JSONSerialization.jsonObject(with: data)
+ if respJson is [String:Any] {
+ callback(respJson as! [String:Any])
+ } else {
+ callback(["error":" response from server
is not a dictionary"])
+ }
+ } catch {
+ callback(["error":"Error creating json from
response: \(error)"])
+ }
+ }
+ }
+ })
+
+ task.resume()
+ } catch {
+ callback(["error":"Got error creating params body: \(error)"])
+ }
+ }
+ }
+
+ // separate an OpenWhisk qualified name (e.g. "/whisk.system/samples/date")
+ // into namespace and name components
+ private class func parseQualifiedName(name qualifiedName : String) ->
(namespace : String, name : String) {
+ let defaultNamespace = "_"
+ let delimiter = "/"
+
+ let segments :[String] = qualifiedName.components(separatedBy:
delimiter)
+
+ if segments.count > 2 {
+ return (segments[1],
Array(segments[2..<segments.count]).joined(separator: delimiter))
+ } else if segments.count == 2 {
+ // case "/action" or "package/action"
+ let name = qualifiedName.hasPrefix(delimiter) ? segments[1] :
segments.joined(separator: delimiter)
+ return (defaultNamespace, name)
+ } else {
+ return (defaultNamespace, segments[0])
+ }
+ }
+
+}
diff --git a/settings.gradle b/core/swift51Action/build.gradle
similarity index 63%
copy from settings.gradle
copy to core/swift51Action/build.gradle
index 7b18e3c..db14d50 100644
--- a/settings.gradle
+++ b/core/swift51Action/build.gradle
@@ -15,26 +15,5 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+ext.dockerImageName = 'action-swift-v5.1'
+apply from: '../../gradle/docker.gradle'
diff --git a/settings.gradle b/core/swift51Action/main.swift
similarity index 63%
copy from settings.gradle
copy to core/swift51Action/main.swift
index 7b18e3c..75071a3 100644
--- a/settings.gradle
+++ b/core/swift51Action/main.swift
@@ -15,26 +15,10 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+func main(args: [String:Any]) -> [String:Any] {
+ if let name = args["name"] as? String {
+ return [ "greeting" : "Hello \(name)!" ]
+ } else {
+ return [ "greeting" : "Hello stranger!" ]
+ }
+}
diff --git a/core/swift51Action/swiftbuild.py b/core/swift51Action/swiftbuild.py
new file mode 100755
index 0000000..9b40903
--- /dev/null
+++ b/core/swift51Action/swiftbuild.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+"""Swift Action Compiler
+#
+# 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 re
+import sys
+import codecs
+import subprocess
+from io import StringIO
+
+def eprint(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
+
+def sources(launcher, source_dir, main):
+ actiondir = "%s/Sources" % source_dir
+ # copy the launcher fixing the main
+ dst = "%s/main.swift" % actiondir
+ with codecs.open(dst, 'a', 'utf-8') as d:
+ with codecs.open(launcher, 'r', 'utf-8') as e:
+ code = e.read()
+ code += "while let inputStr: String = readLine() {\n"
+ code += " let json = inputStr.data(using: .utf8,
allowLossyConversion: true)!\n"
+ code += " let parsed = try JSONSerialization.jsonObject(with:
json, options: []) as! [String: Any]\n"
+ code += " for (key, value) in parsed {\n"
+ code += " if key != \"value\" {\n"
+ code += " setenv(\"__OW_\\(key.uppercased())\",value as!
String,1)\n"
+ code += " }\n"
+ code += " }\n"
+ code += " let jsonData = try
JSONSerialization.data(withJSONObject: parsed[\"value\"] as Any, options: [])\n"
+ code += " _run_main(mainFunction: %s, json: jsonData)\n" % main
+ code += "} \n"
+ d.write(code)
+
+def swift_build(dir, buildcmd):
+ # compile...
+ env = {
+ "PATH": os.environ["PATH"]
+ }
+ p = subprocess.Popen(buildcmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=dir,
+ env=env)
+ (o, e) = p.communicate()
+ # stdout/stderr may be either text or bytes, depending on Python
+ # version, so if bytes, decode to text. Note that in Python 2
+ # a string will match both types; so also skip decoding in that case
+ if isinstance(o, bytes) and not isinstance(o, str):
+ o = o.decode('utf-8')
+ if isinstance(e, bytes) and not isinstance(e, str):
+ e = e.decode('utf-8')
+ return p.returncode, o, e
+
+def build(source_dir, target_file, buildcmd):
+ r, o, e = swift_build(source_dir, buildcmd)
+ #if e: print(e)
+ #if o: print(o)
+ if r != 0:
+ print(e)
+ print(o)
+ print(r)
+ return
+
+ bin_file = "%s/.build/release/Action" % source_dir
+ os.rename(bin_file, target_file)
+ if not os.path.isfile(target_file):
+ print("failed %s -> %s" % (bin_file, target_file))
+ return
+
+
+def main(argv):
+ if len(argv) < 4:
+ print("usage: <main-function> <source-dir> <target-dir>")
+ sys.exit(1)
+
+ main = argv[1]
+ source_dir = os.path.abspath(argv[2])
+ target = os.path.abspath("%s/exec" % argv[3])
+ launch = os.path.abspath(argv[0]+".launcher.swift")
+
+ src = "%s/exec" % source_dir
+
+ #check if single source
+ if os.path.isfile(src):
+ actiondir = os.path.abspath("Sources")
+ if not os.path.isdir(actiondir):
+ os.makedirs(actiondir, mode=0o755)
+ dst = "%s/main.swift" % actiondir
+ os.rename(src, dst)
+ sources(launch, os.path.abspath("."), main)
+ build(os.path.abspath("."), target, ["./swiftbuildandlink.sh"])
+ else:
+ actiondir = "%s/Sources" % source_dir
+ if not os.path.isdir(actiondir):
+ os.makedirs(actiondir, mode=0o755)
+
os.rename(os.path.abspath("Sources/_Whisk.swift"),"%s/Sources/_Whisk.swift" %
source_dir)
+ sources(launch, source_dir, main)
+ build(source_dir, target, ["swift", "build", "-c", "release"])
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/core/swift51Action/swiftbuild.py.launcher.swift
b/core/swift51Action/swiftbuild.py.launcher.swift
new file mode 100644
index 0000000..a1a2cf0
--- /dev/null
+++ b/core/swift51Action/swiftbuild.py.launcher.swift
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+// Imports
+import Foundation
+#if os(Linux)
+ import Glibc
+#else
+ import Darwin
+#endif
+
+func _whisk_print_error(message: String, error: Error?){
+ var errStr = "{\"error\":\"\(message)\"}\n"
+ if let error = error {
+ errStr = "{\"error\":\"\(message) \(error.localizedDescription)\"\n}"
+ }
+ _whisk_print_buffer(jsonString: errStr)
+}
+func _whisk_print_result(jsonData: Data){
+ let jsonString = String(data: jsonData, encoding: .utf8)!
+ _whisk_print_buffer(jsonString: jsonString)
+}
+func _whisk_print_buffer(jsonString: String){
+ var buf : [UInt8] = Array(jsonString.utf8)
+ buf.append(10)
+ fflush(stdout)
+ fflush(stderr)
+ write(3, buf, buf.count)
+}
+
+// snippet of code "injected" (wrapper code for invoking traditional main)
+func _run_main(mainFunction: ([String: Any]) -> [String: Any], json: Data) ->
Void {
+ do {
+ let parsed = try JSONSerialization.jsonObject(with: json, options: [])
as! [String: Any]
+ let result = mainFunction(parsed)
+ if JSONSerialization.isValidJSONObject(result) {
+ do {
+ let jsonData = try JSONSerialization.data(withJSONObject:
result, options: [])
+ _whisk_print_result(jsonData: jsonData)
+ } catch {
+ _whisk_print_error(message: "Failed to encode Dictionary type
to JSON string:", error: error)
+ }
+ } else {
+ _whisk_print_error(message: "Error serializing JSON, data does not
appear to be valid JSON", error: nil)
+ }
+ } catch {
+ _whisk_print_error(message: "Failed to execute action handler with
error:", error: error)
+ return
+ }
+}
+
+// Codable main signature input Codable
+func _run_main<In: Decodable, Out: Encodable>(mainFunction: (In, @escaping
(Out?, Error?) -> Void) -> Void, json: Data) {
+ do {
+ let input = try Whisk.jsonDecoder.decode(In.self, from: json)
+ let resultHandler = { (out: Out?, error: Error?) in
+ if let error = error {
+ _whisk_print_error(message: "Action handler callback returned
an error:", error: error)
+ return
+ }
+ guard let out = out else {
+ _whisk_print_error(message: "Action handler callback did not
return response or error.", error: nil)
+ return
+ }
+ do {
+ let jsonData = try Whisk.jsonEncoder.encode(out)
+ _whisk_print_result(jsonData: jsonData)
+ } catch let error as EncodingError {
+ _whisk_print_error(message: "JSONEncoder failed to encode
Codable type to JSON string:", error: error)
+ return
+ } catch {
+ _whisk_print_error(message: "Failed to execute action handler
with error:", error: error)
+ return
+ }
+ }
+ let _ = mainFunction(input, resultHandler)
+ } catch let error as DecodingError {
+ _whisk_print_error(message: "JSONDecoder failed to decode JSON string
\(String(data: json, encoding: .utf8)!.replacingOccurrences(of: "\"", with:
"\\\"")) to Codable type:", error: error)
+ return
+ } catch {
+ _whisk_print_error(message: "Failed to execute action handler with
error:", error: error)
+ return
+ }
+}
+
+// Codable main signature no input
+func _run_main<Out: Encodable>(mainFunction: ( @escaping (Out?, Error?) ->
Void) -> Void, json: Data) {
+ let resultHandler = { (out: Out?, error: Error?) in
+ if let error = error {
+ _whisk_print_error(message: "Action handler callback returned an
error:", error: error)
+ return
+ }
+ guard let out = out else {
+ _whisk_print_error(message: "Action handler callback did not
return response or error.", error: nil)
+ return
+ }
+ do {
+ let jsonData = try Whisk.jsonEncoder.encode(out)
+ _whisk_print_result(jsonData: jsonData)
+ } catch let error as EncodingError {
+ _whisk_print_error(message: "JSONEncoder failed to encode Codable
type to JSON string:", error: error)
+ return
+ } catch {
+ _whisk_print_error(message: "Failed to execute action handler with
error:", error: error)
+ return
+ }
+ }
+ let _ = mainFunction(resultHandler)
+}
+
+// snippets of code "injected", dependending on the type of function the
developer
+// wants to use traditional vs codable
+
+
+
+
+
+
+
diff --git a/tests/dat/build.sh b/core/swift51Action/swiftbuildandlink.sh
similarity index 69%
copy from tests/dat/build.sh
copy to core/swift51Action/swiftbuildandlink.sh
index 8ece524..c35a1ba 100755
--- a/tests/dat/build.sh
+++ b/core/swift51Action/swiftbuildandlink.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -15,15 +15,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-set -e
-
-../../tools/build/compile.sh HelloSwift3 swift:3.1.1 "-v"
-
-../../tools/build/compile.sh HelloSwift4 swift:4.1 "-v"
-../../tools/build/compile.sh SwiftyRequest swift:4.1 "-v"
-../../tools/build/compile.sh SwiftyRequestCodable swift:4.1 "-v"
-../../tools/build/compile.sh HelloSwift4Codable swift:4.1 "-v"
-
-cd actions
-make all
+swift build -c release
diff --git a/settings.gradle b/settings.gradle
index 7b18e3c..75ce138 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -23,6 +23,8 @@ include 'core:swift41Action'
include 'core:swift42Action'
+include 'core:swift51Action'
+
rootProject.name = 'runtime-swift'
gradle.ext.openwhisk = [
diff --git a/tests/build.gradle b/tests/build.gradle
index b56d3ad..952f18a 100644
--- a/tests/build.gradle
+++ b/tests/build.gradle
@@ -47,3 +47,8 @@ task testSwift4(type: Test) {
exclude 'runtime/sdk/Swift311**'
exclude 'runtime/actionContainers/Swift311**'
}
+
+task testSwift5(type: Test) {
+ exclude 'runtime/sdk/Swift311**'
+ exclude 'runtime/actionContainers/Swift311**'
+}
diff --git a/settings.gradle b/tests/dat/actions/HelloSwift5/Package.swift
similarity index 63%
copy from settings.gradle
copy to tests/dat/actions/HelloSwift5/Package.swift
index 7b18e3c..aeee156 100644
--- a/settings.gradle
+++ b/tests/dat/actions/HelloSwift5/Package.swift
@@ -1,3 +1,6 @@
+// swift-tools-version:5.0
+// The swift-tools-version declares the minimum version of Swift required to
build this package.
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,26 +18,20 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import PackageDescription
+
+let package = Package(
+ name: "Action",
+ products: [
+ .executable(
+ name: "Action",
+ targets: ["Action"]
+ )
+ ],
+ targets: [
+ .target(
+ name: "Action",
+ path: "."
+ )
+ ]
+)
diff --git a/settings.gradle b/tests/dat/actions/HelloSwift5/Sources/main.swift
similarity index 63%
copy from settings.gradle
copy to tests/dat/actions/HelloSwift5/Sources/main.swift
index 7b18e3c..a8bfed4 100644
--- a/settings.gradle
+++ b/tests/dat/actions/HelloSwift5/Sources/main.swift
@@ -15,26 +15,12 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import Foundation
+
+func main(args: [String:Any]) -> [String:Any] {
+ if let name = args["name"] as? String {
+ return [ "greeting" : "Hello \(name)!" ]
+ } else {
+ return [ "greeting" : "Hello stranger!" ]
+ }
+}
diff --git a/settings.gradle
b/tests/dat/actions/HelloSwift5Codable/Package.swift
similarity index 63%
copy from settings.gradle
copy to tests/dat/actions/HelloSwift5Codable/Package.swift
index 7b18e3c..aeee156 100644
--- a/settings.gradle
+++ b/tests/dat/actions/HelloSwift5Codable/Package.swift
@@ -1,3 +1,6 @@
+// swift-tools-version:5.0
+// The swift-tools-version declares the minimum version of Swift required to
build this package.
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,26 +18,20 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import PackageDescription
+
+let package = Package(
+ name: "Action",
+ products: [
+ .executable(
+ name: "Action",
+ targets: ["Action"]
+ )
+ ],
+ targets: [
+ .target(
+ name: "Action",
+ path: "."
+ )
+ ]
+)
diff --git a/settings.gradle
b/tests/dat/actions/HelloSwift5Codable/Sources/main.swift
similarity index 63%
copy from settings.gradle
copy to tests/dat/actions/HelloSwift5Codable/Sources/main.swift
index 7b18e3c..0c8b0fc 100644
--- a/settings.gradle
+++ b/tests/dat/actions/HelloSwift5Codable/Sources/main.swift
@@ -15,26 +15,21 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import Foundation
+
+struct AnInput: Codable {
+ let name: String?
+}
+struct AnOutput: Codable {
+ let greeting: String?
+}
+
+func main(input: AnInput, respondWith: (AnOutput?, Error?) -> Void) -> Void {
+ if let name = input.name {
+ let answer = AnOutput(greeting: "Hello \(name)!")
+ respondWith(answer, nil)
+ } else {
+ let answer = AnOutput(greeting: "Hello stranger!")
+ respondWith(answer, nil)
+ }
+}
diff --git a/tests/dat/actions/Makefile b/tests/dat/actions/Makefile
index 2469e53..0710c7b 100644
--- a/tests/dat/actions/Makefile
+++ b/tests/dat/actions/Makefile
@@ -25,6 +25,18 @@ Swifty:
SwiftyCodable:
$(call BuildWithLib,SwiftyRequestCodable)
-all: Hello HelloCodable Swifty SwiftyCodable
+Hello5:
+ $(call Build,HelloSwift5)
-.PHONY: Hello HelloCodable Swifty SwiftyCodable
\ No newline at end of file
+HelloCodable5:
+ $(call Build,HelloSwift5Codable)
+
+Swifty5:
+ $(call BuildWithLib,SwiftyRequest5)
+
+SwiftyCodable5:
+ $(call BuildWithLib,SwiftyRequestCodable5)
+
+all: Hello HelloCodable Swifty SwiftyCodable Hello5 HelloCodable5 Swifty5
SwiftyCodable5
+
+.PHONY: Hello HelloCodable Swifty SwiftyCodable Hello5 HelloCodable5 Swifty5
SwiftyCodable5
\ No newline at end of file
diff --git a/tests/dat/actions/SwiftyRequest5/Package.resolved
b/tests/dat/actions/SwiftyRequest5/Package.resolved
new file mode 100644
index 0000000..ff2bbd2
--- /dev/null
+++ b/tests/dat/actions/SwiftyRequest5/Package.resolved
@@ -0,0 +1,79 @@
+{
+ "object": {
+ "pins": [
+ {
+ "package": "async-http-client",
+ "repositoryURL":
"https://github.com/swift-server/async-http-client.git",
+ "state": {
+ "branch": null,
+ "revision": "51dc885a30ca704b02fa803099b0a9b5b38067b6",
+ "version": "1.0.0"
+ }
+ },
+ {
+ "package": "CircuitBreaker",
+ "repositoryURL": "https://github.com/IBM-Swift/CircuitBreaker.git",
+ "state": {
+ "branch": null,
+ "revision": "e9345aa721ca4da428777f2e953b9ad534017675",
+ "version": "5.0.3"
+ }
+ },
+ {
+ "package": "LoggerAPI",
+ "repositoryURL": "https://github.com/IBM-Swift/LoggerAPI.git",
+ "state": {
+ "branch": null,
+ "revision": "3357dd9526cdf9436fa63bb792b669e6efdc43da",
+ "version": "1.9.0"
+ }
+ },
+ {
+ "package": "swift-log",
+ "repositoryURL": "https://github.com/apple/swift-log.git",
+ "state": {
+ "branch": null,
+ "revision": "74d7b91ceebc85daf387ebb206003f78813f71aa",
+ "version": "1.2.0"
+ }
+ },
+ {
+ "package": "swift-nio",
+ "repositoryURL": "https://github.com/apple/swift-nio.git",
+ "state": {
+ "branch": null,
+ "revision": "bc661cbb771328e09faa65432628e9ff6fd333d5",
+ "version": "2.10.0"
+ }
+ },
+ {
+ "package": "swift-nio-extras",
+ "repositoryURL": "https://github.com/apple/swift-nio-extras.git",
+ "state": {
+ "branch": null,
+ "revision": "ed97628fa310c314c4a5cd8038445054b2991f07",
+ "version": "1.3.1"
+ }
+ },
+ {
+ "package": "swift-nio-ssl",
+ "repositoryURL": "https://github.com/apple/swift-nio-ssl.git",
+ "state": {
+ "branch": null,
+ "revision": "e5c1af45ac934ac0a6117b2927a51d845cf4f705",
+ "version": "2.4.3"
+ }
+ },
+ {
+ "package": "SwiftyRequest",
+ "repositoryURL": "https://github.com/IBM-Swift/SwiftyRequest.git",
+ "state": {
+ "branch": null,
+ "revision": "34cf8de7c3920220392d557c8c84b9f06c8c3978",
+ "version": "3.1.0"
+ }
+ }
+ ]
+ },
+ "version": 1
+}
diff --git a/settings.gradle b/tests/dat/actions/SwiftyRequest5/Package.swift
similarity index 59%
copy from settings.gradle
copy to tests/dat/actions/SwiftyRequest5/Package.swift
index 7b18e3c..41acbc7 100644
--- a/settings.gradle
+++ b/tests/dat/actions/SwiftyRequest5/Package.swift
@@ -1,3 +1,6 @@
+// swift-tools-version:5.0
+// The swift-tools-version declares the minimum version of Swift required to
build this package.
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,26 +18,24 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import PackageDescription
+
+let package = Package(
+ name: "Action",
+ products: [
+ .executable(
+ name: "Action",
+ targets: ["Action"]
+ )
+ ],
+ dependencies: [
+ .package(url: "https://github.com/IBM-Swift/SwiftyRequest.git",
.upToNextMajor(from: "3.0.0"))
+ ],
+ targets: [
+ .target(
+ name: "Action",
+ dependencies: ["SwiftyRequest"],
+ path: "."
+ ),
+ ]
+)
diff --git a/tests/dat/actions/SwiftyRequest5/Sources/main.swift
b/tests/dat/actions/SwiftyRequest5/Sources/main.swift
new file mode 100644
index 0000000..8aac40a
--- /dev/null
+++ b/tests/dat/actions/SwiftyRequest5/Sources/main.swift
@@ -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.
+ */
+
+import SwiftyRequest
+import Dispatch
+import Foundation
+
+func main(args: [String:Any]) -> [String:Any] {
+ var resp :[String:Any] = ["error":"Action failed"]
+ let echoURL = "http://httpbin.org/post"
+
+ // setting body data to {"Data":"string"}
+ let origJson: [String: Any] = args
+ guard let data = try? JSONSerialization.data(withJSONObject: origJson,
options: []) else {
+ return ["error": "Could not encode json"]
+ }
+ let request = RestRequest(method: .post, url: echoURL)
+ request.messageBody = data
+ let semaphore = DispatchSemaphore(value: 0)
+ //sending with query ?hour=9
+ request.responseData(queryItems: [URLQueryItem(name: "hour", value: "9")])
{ result in
+ switch result {
+ case .success(let retval):
+ if let json = try? JSONSerialization.jsonObject(with: retval.body,
options: []) as? [String:Any] {
+ resp = json
+ } else {
+ resp = ["error":"Response from server is not a dictionary
like"]
+ }
+ case .failure(let error):
+ resp = ["error":"Failed to get data response: \(error)"]
+ }
+ semaphore.signal()
+ }
+ _ = semaphore.wait(timeout: .distantFuture)
+ return resp
+}
+//let r = main(args:["message":"serverless"])
+//print(r)
diff --git a/tests/dat/actions/SwiftyRequestCodable5/Package.resolved
b/tests/dat/actions/SwiftyRequestCodable5/Package.resolved
new file mode 100644
index 0000000..ff2bbd2
--- /dev/null
+++ b/tests/dat/actions/SwiftyRequestCodable5/Package.resolved
@@ -0,0 +1,79 @@
+{
+ "object": {
+ "pins": [
+ {
+ "package": "async-http-client",
+ "repositoryURL":
"https://github.com/swift-server/async-http-client.git",
+ "state": {
+ "branch": null,
+ "revision": "51dc885a30ca704b02fa803099b0a9b5b38067b6",
+ "version": "1.0.0"
+ }
+ },
+ {
+ "package": "CircuitBreaker",
+ "repositoryURL": "https://github.com/IBM-Swift/CircuitBreaker.git",
+ "state": {
+ "branch": null,
+ "revision": "e9345aa721ca4da428777f2e953b9ad534017675",
+ "version": "5.0.3"
+ }
+ },
+ {
+ "package": "LoggerAPI",
+ "repositoryURL": "https://github.com/IBM-Swift/LoggerAPI.git",
+ "state": {
+ "branch": null,
+ "revision": "3357dd9526cdf9436fa63bb792b669e6efdc43da",
+ "version": "1.9.0"
+ }
+ },
+ {
+ "package": "swift-log",
+ "repositoryURL": "https://github.com/apple/swift-log.git",
+ "state": {
+ "branch": null,
+ "revision": "74d7b91ceebc85daf387ebb206003f78813f71aa",
+ "version": "1.2.0"
+ }
+ },
+ {
+ "package": "swift-nio",
+ "repositoryURL": "https://github.com/apple/swift-nio.git",
+ "state": {
+ "branch": null,
+ "revision": "bc661cbb771328e09faa65432628e9ff6fd333d5",
+ "version": "2.10.0"
+ }
+ },
+ {
+ "package": "swift-nio-extras",
+ "repositoryURL": "https://github.com/apple/swift-nio-extras.git",
+ "state": {
+ "branch": null,
+ "revision": "ed97628fa310c314c4a5cd8038445054b2991f07",
+ "version": "1.3.1"
+ }
+ },
+ {
+ "package": "swift-nio-ssl",
+ "repositoryURL": "https://github.com/apple/swift-nio-ssl.git",
+ "state": {
+ "branch": null,
+ "revision": "e5c1af45ac934ac0a6117b2927a51d845cf4f705",
+ "version": "2.4.3"
+ }
+ },
+ {
+ "package": "SwiftyRequest",
+ "repositoryURL": "https://github.com/IBM-Swift/SwiftyRequest.git",
+ "state": {
+ "branch": null,
+ "revision": "34cf8de7c3920220392d557c8c84b9f06c8c3978",
+ "version": "3.1.0"
+ }
+ }
+ ]
+ },
+ "version": 1
+}
diff --git a/settings.gradle
b/tests/dat/actions/SwiftyRequestCodable5/Package.swift
similarity index 59%
copy from settings.gradle
copy to tests/dat/actions/SwiftyRequestCodable5/Package.swift
index 7b18e3c..031e5d1 100644
--- a/settings.gradle
+++ b/tests/dat/actions/SwiftyRequestCodable5/Package.swift
@@ -1,3 +1,6 @@
+// swift-tools-version:5.0
+// The swift-tools-version declares the minimum version of Swift required to
build this package.
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,26 +18,24 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import PackageDescription
+
+let package = Package(
+ name: "Action",
+ products: [
+ .executable(
+ name: "Action",
+ targets: ["Action"]
+ )
+ ],
+ dependencies: [
+ .package(url: "https://github.com/IBM-Swift/SwiftyRequest.git",
.upToNextMajor(from: "3.0.0"))
+ ],
+ targets: [
+ .target(
+ name: "Action",
+ dependencies: ["SwiftyRequest"],
+ path: "."
+ )
+ ]
+)
diff --git a/settings.gradle
b/tests/dat/actions/SwiftyRequestCodable5/Sources/main.swift
similarity index 52%
copy from settings.gradle
copy to tests/dat/actions/SwiftyRequestCodable5/Sources/main.swift
index 7b18e3c..004ae53 100644
--- a/settings.gradle
+++ b/tests/dat/actions/SwiftyRequestCodable5/Sources/main.swift
@@ -15,26 +15,30 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import SwiftyRequest
+import Dispatch
+import Foundation
+
+enum RequestError: Error {
+ case requetError
+}
+struct AnInput: Codable {
+ let url: String?
+}
+struct AnOutput: Codable {
+ let greeting: String?
+}
+func main(param: AnInput, completion: @escaping (AnOutput?, Error?) -> Void)
-> Void {
+ let echoURL = param.url ?? "https://httpbin.org/get"
+ let request = RestRequest(method: .get, url: echoURL)
+ request.responseString { result in
+ switch result {
+ case .success(let response):
+ print(response)
+ completion(AnOutput(greeting:"success"),nil)
+ case .failure(let error):
+ print(error)
+ completion(nil,RequestError.requetError)
+ }
+ }
+}
diff --git a/tests/dat/actions/sdk/swift5/createRule.swift
b/tests/dat/actions/sdk/swift5/createRule.swift
new file mode 100644
index 0000000..7f7a88b
--- /dev/null
+++ b/tests/dat/actions/sdk/swift5/createRule.swift
@@ -0,0 +1,36 @@
+/*
+ * 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 Foundation
+
+func main(args: [String:Any]) -> [String:Any] {
+ if let baseUrl = args["baseUrl"] as? String {
+ //Overriding WHISK API HOST using baseUrl, only applicable in testing with
self sign ssl certs"
+ Whisk.baseUrl = baseUrl
+ }
+ guard let triggerName = args["triggerName"] as? String else {
+ return ["error": "You must specify a triggerName parameter!"]
+ }
+ guard let actionName = args["actionName"] as? String else {
+ return ["error": "You must specify a actionName parameter!"]
+ }
+ guard let ruleName = args["ruleName"] as? String else {
+ return ["error": "You must specify a ruleName parameter!"]
+ }
+ print("Rule Name: \(ruleName), Trigger Name: \(triggerName), actionName:
\(actionName)")
+ return Whisk.createRule(ruleNamed: ruleName, withTrigger: triggerName,
andAction: actionName)
+}
diff --git a/settings.gradle b/tests/dat/actions/sdk/swift5/createTrigger.swift
similarity index 61%
copy from settings.gradle
copy to tests/dat/actions/sdk/swift5/createTrigger.swift
index 7b18e3c..bd3e497 100644
--- a/settings.gradle
+++ b/tests/dat/actions/sdk/swift5/createTrigger.swift
@@ -15,26 +15,16 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import Foundation
+
+func main(args: [String:Any]) -> [String:Any] {
+ if let baseUrl = args["baseUrl"] as? String {
+ //Overriding WHISK API HOST using baseUrl, only applicable in testing with
self sign ssl certs"
+ Whisk.baseUrl = baseUrl
+ }
+ guard let triggerName = args["triggerName"] as? String else {
+ return ["error": "You must specify a triggerName parameter!"]
+ }
+ print("Trigger Name: \(triggerName)")
+ return Whisk.createTrigger(triggerNamed: triggerName, withParameters: [:])
+}
diff --git a/settings.gradle b/tests/dat/actions/sdk/swift5/hello.swift
similarity index 63%
copy from settings.gradle
copy to tests/dat/actions/sdk/swift5/hello.swift
index 7b18e3c..a8bfed4 100644
--- a/settings.gradle
+++ b/tests/dat/actions/sdk/swift5/hello.swift
@@ -15,26 +15,12 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import Foundation
+
+func main(args: [String:Any]) -> [String:Any] {
+ if let name = args["name"] as? String {
+ return [ "greeting" : "Hello \(name)!" ]
+ } else {
+ return [ "greeting" : "Hello stranger!" ]
+ }
+}
diff --git a/tests/dat/actions/sdk/swift5/invoke.swift
b/tests/dat/actions/sdk/swift5/invoke.swift
new file mode 100644
index 0000000..ba03066
--- /dev/null
+++ b/tests/dat/actions/sdk/swift5/invoke.swift
@@ -0,0 +1,47 @@
+/*
+ * 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 Foundation
+
+struct Result: Decodable {
+ let date: String
+}
+struct Response: Decodable {
+ let result:Result
+}
+struct Activation: Decodable {
+ let response: Response
+ let activationId: String
+}
+
+func main(args: [String:Any]) -> [String:Any] {
+ if let baseUrl = args["baseUrl"] as? String {
+ //Overriding WHISK API HOST using baseUrl, only applicable in testing with
self sign ssl certs"
+ Whisk.baseUrl = baseUrl
+ }
+ let invokeResult = Whisk.invoke(actionNamed: "/whisk.system/utils/date",
withParameters: [:])
+ let jsonData = try! JSONSerialization.data(withJSONObject: invokeResult)
+ let dateActivation = try! JSONDecoder().decode(Activation.self, from:
jsonData)
+ let dateString = dateActivation.response.result.date
+ if dateString.isEmpty{
+ print("Could not parse date of of the response.")
+ } else {
+ print("It is now \(dateString)")
+ }
+ // return the entire invokeResult
+ return invokeResult
+}
diff --git a/tests/dat/actions/sdk/swift5/invokeNonBlocking.swift
b/tests/dat/actions/sdk/swift5/invokeNonBlocking.swift
new file mode 100644
index 0000000..043e0b4
--- /dev/null
+++ b/tests/dat/actions/sdk/swift5/invokeNonBlocking.swift
@@ -0,0 +1,42 @@
+/*
+ * 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 Foundation
+
+struct Activation: Decodable {
+ let activationId: String
+}
+
+func main(args: [String:Any]) -> [String:Any] {
+ if let baseUrl = args["baseUrl"] as? String {
+ //Overriding WHISK API HOST using baseUrl, only applicable in testing with
self sign ssl certs"
+ Whisk.baseUrl = baseUrl
+ }
+ let invokeResult = Whisk.invoke(actionNamed: "/whisk.system/utils/date",
withParameters: [:], blocking: false)
+ let jsonData = try! JSONSerialization.data(withJSONObject: invokeResult)
+ let dateActivation = try! JSONDecoder().decode(Activation.self, from:
jsonData)
+ // the date we are looking for is the result inside the date activation
+ let activationId = dateActivation.activationId
+ if activationId.isEmpty{
+ print("Failed to invoke.")
+ } else {
+ print("Invoked.")
+ }
+
+ // return the entire invokeResult
+ return invokeResult
+}
diff --git a/settings.gradle b/tests/dat/actions/sdk/swift5/trigger.swift
similarity index 61%
copy from settings.gradle
copy to tests/dat/actions/sdk/swift5/trigger.swift
index 7b18e3c..0481e23 100644
--- a/settings.gradle
+++ b/tests/dat/actions/sdk/swift5/trigger.swift
@@ -15,26 +15,17 @@
* limitations under the License.
*/
-include 'tests'
-
-include 'core:swift3.1.1Action'
-
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+import Foundation
+
+func main(args: [String:Any]) -> [String:Any] {
+ if let baseUrl = args["baseUrl"] as? String {
+ //Overriding WHISK API HOST using baseUrl, only applicable in testing with
self sign ssl certs"
+ Whisk.baseUrl = baseUrl
+ }
+ if let triggerName = args["triggerName"] as? String {
+ print("Trigger Name: \(triggerName)")
+ return Whisk.trigger(eventNamed: triggerName, withParameters: [:])
+ } else {
+ return ["error": "You must specify a triggerName parameter!"]
+ }
+}
diff --git a/tests/dat/build.sh b/tests/dat/build.sh
index 8ece524..f016d00 100755
--- a/tests/dat/build.sh
+++ b/tests/dat/build.sh
@@ -25,5 +25,11 @@ set -e
../../tools/build/compile.sh SwiftyRequestCodable swift:4.1 "-v"
../../tools/build/compile.sh HelloSwift4Codable swift:4.1 "-v"
+../../tools/build/compile5.sh action-swift-v5.1 HelloSwift5 swift5.1 "-v"
+../../tools/build/compile5.sh action-swift-v5.1 HelloSwift5Codable swift5.1
"-v"
+../../tools/build/compile5.sh action-swift-v5.1 SwiftyRequest5 swift:5.1 "-v"
+../../tools/build/compile5.sh action-swift-v5.1 SwiftyRequestCodable5
swift:5.1 "-v"
+
+
cd actions
make all
diff --git a/tests/dat/build/swift311/HelloSwift3.zip
b/tests/dat/build/swift311/HelloSwift3.zip
deleted file mode 100644
index 4a8588a..0000000
Binary files a/tests/dat/build/swift311/HelloSwift3.zip and /dev/null differ
diff --git a/tests/dat/build/swift4.1/HelloSwift4.zip
b/tests/dat/build/swift4.1/HelloSwift4.zip
index c7542ae..ab486a9 100644
Binary files a/tests/dat/build/swift4.1/HelloSwift4.zip and
b/tests/dat/build/swift4.1/HelloSwift4.zip differ
diff --git a/tests/dat/build/swift4.1/HelloSwift4Codable.zip
b/tests/dat/build/swift4.1/HelloSwift4Codable.zip
index a183e8c..3c5ce7b 100644
Binary files a/tests/dat/build/swift4.1/HelloSwift4Codable.zip and
b/tests/dat/build/swift4.1/HelloSwift4Codable.zip differ
diff --git a/tests/dat/build/swift4.1/SwiftyRequest.zip
b/tests/dat/build/swift4.1/SwiftyRequest.zip
index 5766c39..faec590 100644
Binary files a/tests/dat/build/swift4.1/SwiftyRequest.zip and
b/tests/dat/build/swift4.1/SwiftyRequest.zip differ
diff --git a/tests/dat/build/swift4.1/SwiftyRequestCodable.zip
b/tests/dat/build/swift4.1/SwiftyRequestCodable.zip
index 201e604..ee36592 100644
Binary files a/tests/dat/build/swift4.1/SwiftyRequestCodable.zip and
b/tests/dat/build/swift4.1/SwiftyRequestCodable.zip differ
diff --git a/tests/dat/build/swift5.1/HelloSwift5.zip
b/tests/dat/build/swift5.1/HelloSwift5.zip
new file mode 100644
index 0000000..931ea9e
Binary files /dev/null and b/tests/dat/build/swift5.1/HelloSwift5.zip differ
diff --git a/tests/dat/build/swift5.1/HelloSwift5Codable.zip
b/tests/dat/build/swift5.1/HelloSwift5Codable.zip
new file mode 100644
index 0000000..b953a72
Binary files /dev/null and b/tests/dat/build/swift5.1/HelloSwift5Codable.zip
differ
diff --git a/tests/dat/build/swift5.1/SwiftyRequest5.zip
b/tests/dat/build/swift5.1/SwiftyRequest5.zip
new file mode 100644
index 0000000..e286745
Binary files /dev/null and b/tests/dat/build/swift5.1/SwiftyRequest5.zip differ
diff --git a/tests/dat/build/swift5.1/SwiftyRequestCodable5.zip
b/tests/dat/build/swift5.1/SwiftyRequestCodable5.zip
new file mode 100644
index 0000000..529f208
Binary files /dev/null and b/tests/dat/build/swift5.1/SwiftyRequestCodable5.zip
differ
diff --git
a/tests/src/test/scala/runtime/actionContainers/Swift51ActionContainerTests.scala
b/tests/src/test/scala/runtime/actionContainers/Swift51ActionContainerTests.scala
new file mode 100644
index 0000000..183f867
--- /dev/null
+++
b/tests/src/test/scala/runtime/actionContainers/Swift51ActionContainerTests.scala
@@ -0,0 +1,121 @@
+/*
+ * 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 actionContainers.ResourceHelpers
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+import spray.json.{JsObject, JsString}
+
+@RunWith(classOf[JUnitRunner])
+class Swift51ActionContainerTests extends SwiftActionContainerTests {
+ override lazy val swiftContainerImageName = "action-swift-v5.1"
+ override lazy val swiftBinaryName =
"tests/dat/build/swift5.1/HelloSwift5.zip"
+ lazy val partyCompile = "tests/dat/build/swift5.1/SwiftyRequest5.zip"
+ lazy val partyCompileCodable =
"tests/dat/build/swift5.1/SwiftyRequestCodable5.zip"
+
+ val httpCode = """
+ | import Foundation
+ | import Dispatch
+ | #if canImport(FoundationNetworking)
+ | import FoundationNetworking
+ | #endif
+ | func main(args:[String: Any]) -> [String:Any] {
+ | var resp :[String:Any] = ["error":"getUrl failed"]
+ | guard let urlStr = args["getUrl"] as? String else {
+ | return ["error":"getUrl not found in action
input"]
+ | }
+ | guard let url = URL(string: urlStr) else {
+ | return ["error":"invalid url string \(urlStr)"]
+ | }
+ | let request = URLRequest(url: url)
+ | let session = URLSession(configuration: .default)
+ | let semaphore = DispatchSemaphore(value: 0)
+ | let task = session.dataTask(with: request,
completionHandler: {data, response, error -> Void in
+ | print("done with http request")
+ | if let error = error {
+ | print("There was an error \(error)")
+ | } else if let data = data,
+ | let response = response as? HTTPURLResponse,
+ | response.statusCode == 200 {
+ | do {
+ | let respJson = try
JSONSerialization.jsonObject(with: data)
+ | if respJson is [String:Any] {
+ | resp = respJson as! [String:Any]
+ | } else {
+ | resp = ["error":"Response from server
is not a dictionary"]
+ | }
+ | } catch {
+ | resp = ["error":"Error creating json from
response: \(error)"]
+ | }
+ | }
+ | semaphore.signal()
+ | })
+ | task.resume()
+ | _ = semaphore.wait(timeout: .distantFuture)
+ | return resp
+ | }
+ """.stripMargin
+
+ it should "support ability to use 3rd party packages like SwiftyRequest" in {
+ val zip = new File(partyCompile).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("message" -> (JsString("serverless")))
+ val (runCode, runRes) = c.run(runPayload(args))
+
+ runCode should be(200)
+ val json = runRes.get.fields.get("json")
+ json shouldBe Some(args)
+ }
+
+ checkStreams(out, err, {
+ case (o, e) =>
+ if (enforceEmptyOutputStream) o shouldBe empty
+ e shouldBe empty
+ })
+ }
+
+ it should "support ability to use escaping completion in Codable" in {
+ val zip = new File(partyCompileCodable).toPath
+ val code = ResourceHelpers.readAsBase64(zip)
+
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, initRes) = c.init(initPayload(code, main = "mainCodable"))
+ initCode should be(200)
+
+ val (runCode, runRes) = c.run(runPayload(JsObject()))
+
+ runCode should be(200)
+ runRes.get.fields.get("greeting") shouldBe Some(JsString("success"))
+
+ }
+
+ checkStreams(out, err, {
+ case (o, e) =>
+ if (enforceEmptyOutputStream) o shouldBe empty
+ e shouldBe empty
+ })
+ }
+}
diff --git a/settings.gradle
b/tests/src/test/scala/runtime/actionContainers/Swift51CodableActionContainerTests.scala
similarity index 63%
copy from settings.gradle
copy to
tests/src/test/scala/runtime/actionContainers/Swift51CodableActionContainerTests.scala
index 7b18e3c..b584420 100644
--- a/settings.gradle
+++
b/tests/src/test/scala/runtime/actionContainers/Swift51CodableActionContainerTests.scala
@@ -15,26 +15,13 @@
* limitations under the License.
*/
-include 'tests'
+package runtime.actionContainers
-include 'core:swift3.1.1Action'
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+@RunWith(classOf[JUnitRunner])
+class Swift51CodableActionContainerTests extends
SwiftCodableActionContainerTests {
+ override lazy val swiftContainerImageName = "action-swift-v5.1"
+ override lazy val swiftBinaryName =
"tests/dat/build/swift5.1/HelloSwift5Codable.zip"
+}
diff --git a/settings.gradle
b/tests/src/test/scala/runtime/sdk/Swift51SDKTests.scala
similarity index 63%
copy from settings.gradle
copy to tests/src/test/scala/runtime/sdk/Swift51SDKTests.scala
index 7b18e3c..777c388 100644
--- a/settings.gradle
+++ b/tests/src/test/scala/runtime/sdk/Swift51SDKTests.scala
@@ -15,26 +15,12 @@
* limitations under the License.
*/
-include 'tests'
+package runtime.sdk
-include 'core:swift3.1.1Action'
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
-include 'core:swift41Action'
-
-include 'core:swift42Action'
-
-rootProject.name = 'runtime-swift'
-
-gradle.ext.openwhisk = [
- version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
- version: '2.12.7',
- compileFlags: ['-feature', '-unchecked', '-deprecation',
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
- version: '1.5.0',
- config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+@RunWith(classOf[JUnitRunner])
+class Swift51SDKTests extends SwiftSDKTests {
+ override lazy val actionKind = "swift:5.1"
+}
diff --git a/tools/build/compile.sh b/tools/build/compile.sh
index 38c2495..42d5fca 100755
--- a/tools/build/compile.sh
+++ b/tools/build/compile.sh
@@ -53,13 +53,14 @@ fi
echo "Using runtime $RUNTIME to compile swift"
-docker run --rm --name=compile-ow-swift -it -v "$(pwd):/owexec" $RUNTIME bash
-ex -c "
+docker run --rm --name=compile-ow-swift -it -v "$(pwd):/owexec" $RUNTIME -ex
-c "
if [ -f \"/owexec/$OUTPUT_DIR/$1.zip\" ] ; then
rm \"/owexec/$OUTPUT_DIR/$1.zip\"
fi
echo 'Setting up build...'
+mkdir -p $DEST_SOURCE
cp /owexec/actions/$1/Sources/*.swift $DEST_SOURCE/
# action file can be either {action name}.swift or main.swift
@@ -71,7 +72,7 @@ fi
cat $BASE_PATH/epilogue.swift >> $DEST_SOURCE/main.swift
echo '_run_main(mainFunction:main)' >> $DEST_SOURCE/main.swift
-# Only for Swift4
+# Only for Swift4 and Swift5
if [ ${2} != "swift:3.1.1" ]; then
echo 'Adding wait to deal with escaping'
echo '_ = _whisk_semaphore.wait(timeout: .distantFuture)' >>
$DEST_SOURCE/main.swift
diff --git a/tests/dat/build.sh b/tools/build/compile5.sh
similarity index 70%
copy from tests/dat/build.sh
copy to tools/build/compile5.sh
index 8ece524..ea71d4b 100755
--- a/tests/dat/build.sh
+++ b/tools/build/compile5.sh
@@ -15,15 +15,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-set -e
-
-../../tools/build/compile.sh HelloSwift3 swift:3.1.1 "-v"
-
-../../tools/build/compile.sh HelloSwift4 swift:4.1 "-v"
-../../tools/build/compile.sh SwiftyRequest swift:4.1 "-v"
-../../tools/build/compile.sh SwiftyRequestCodable swift:4.1 "-v"
-../../tools/build/compile.sh HelloSwift4Codable swift:4.1 "-v"
-
-cd actions
-make all
+RUNTIME="${1:?runtime image1}"
+NAME="${2:?action name}"
+DIR="${3?target dir}"
+pushd "actions/$NAME"
+zip -r ../$NAME.zip *
+popd
+mkdir -p "build/$DIR"
+docker run -i $RUNTIME -compile main <actions/$NAME.zip >build/$DIR/$NAME.zip
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index ac99de8..67962d1 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -56,4 +56,5 @@ cd $ROOTDIR
TERM=dumb ./gradlew \
:core:swift41Action:distDocker \
:core:swift42Action:distDocker \
+:core:swift51Action:distDocker \
-PdockerImagePrefix=${IMAGE_PREFIX}
diff --git a/tools/travis/publish.sh b/tools/travis/publish.sh
index 8f7058f..c7db0b0 100755
--- a/tools/travis/publish.sh
+++ b/tools/travis/publish.sh
@@ -36,6 +36,8 @@ elif [ ${RUNTIME_VERSION} == "4.1" ]; then
RUNTIME="swift41Action"
elif [ ${RUNTIME_VERSION} == "4.2" ]; then
RUNTIME="swift42Action"
+elif [ ${RUNTIME_VERSION} == "5.1" ]; then
+ RUNTIME="swift51Action"
fi
if [[ ! -z ${DOCKER_USER} ]] && [[ ! -z ${DOCKER_PASSWORD} ]]; then