Add support for Swift 5.4 (#140)
* Add support for Swift 5.4
- Added suport for Swift 5.4 by copying and adapting core of Swift 5.3. Files Modified during this Process (version set to 5.4 from 5.3):
-- core/swift54Action/build.gradle
-- core/swift54Action/CHANGELOG.md
-- core/swift54Action/Dockerfile
- Added Swift 5.4 entries to:
-- settings.gradle
-- .travis.yml
-- README.md
-- ansible/files/runtimes.json
* Fix build by adapting akka versions (#139)
* Add fixes from #139
Co-authored-by: Martin Henke <martin.henke@web.de>
diff --git a/.travis.yml b/.travis.yml
index 6d780d2..d3eb103 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -47,7 +47,7 @@
branch: master
repo: apache/openwhisk-runtime-swift
- provider: script
- script: "./tools/travis/publish.sh openwhisk 5.1 nightly && ./tools/travis/publish.sh openwhisk 5.3 nightly"
+ script: "./tools/travis/publish.sh openwhisk 5.1 nightly && ./tools/travis/publish.sh openwhisk 5.3 nightly && ./tools/travis/publish.sh openwhisk 5.4 nightly"
on:
branch: master
repo: apache/openwhisk-runtime-swift
diff --git a/README.md b/README.md
index 9838634..c1d76c6 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@
- [Swift 4.2 CHANGELOG.md](core/swift42Action/CHANGELOG.md)
- [Swift 5.1 CHANGELOG.md](core/swift51Action/CHANGELOG.md)
- [Swift 5.3 CHANGELOG.md](core/swift53Action/CHANGELOG.md)
+- [Swift 5.4 CHANGELOG.md](core/swift54Action/CHANGELOG.md)
## Quick Swift Action
### Simple swift action hello.swift
diff --git a/ansible/files/runtimes.json b/ansible/files/runtimes.json
index dbc4f3b..4239c7f 100644
--- a/ansible/files/runtimes.json
+++ b/ansible/files/runtimes.json
@@ -71,6 +71,20 @@
"attachmentName": "codefile",
"attachmentType": "text/plain"
}
+ },
+ {
+ "kind": "swift:5.4",
+ "default": false,
+ "image": {
+ "prefix": "testing",
+ "name": "action-swift-v5.4",
+ "tag": "latest"
+ },
+ "deprecated": false,
+ "attached": {
+ "attachmentName": "codefile",
+ "attachmentType": "text/plain"
+ }
}
]
},
diff --git a/core/swift54Action/CHANGELOG.md b/core/swift54Action/CHANGELOG.md
new file mode 100644
index 0000000..395d500
--- /dev/null
+++ b/core/swift54Action/CHANGELOG.md
@@ -0,0 +1,23 @@
+<!--
+#
+# 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.
+#
+-->
+
+# Apache OpenWhisk Swift 5.4 Runtime Container
+
+## 1.16.0
+ - Initial Release
diff --git a/core/swift54Action/Dockerfile b/core/swift54Action/Dockerfile
new file mode 100644
index 0000000..d6156d6
--- /dev/null
+++ b/core/swift54Action/Dockerfile
@@ -0,0 +1,67 @@
+#
+# 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.
+#
+
+# build go proxy from source
+FROM golang:1.15 AS builder_source
+ARG GO_PROXY_GITHUB_USER=apache
+ARG GO_PROXY_GITHUB_BRANCH=master
+RUN git clone --branch ${GO_PROXY_GITHUB_BRANCH} \
+ https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src ;\
+ cd /src ; env GO111MODULE=on CGO_ENABLED=0 go build main/proxy.go && \
+ mv proxy /bin/proxy
+
+# or build it from a release
+FROM golang:1.15 AS builder_release
+ARG GO_PROXY_RELEASE_VERSION=1.15@1.17.0
+RUN curl -sL \
+ https://github.com/apache/openwhisk-runtime-go/archive/{$GO_PROXY_RELEASE_VERSION}.tar.gz\
+ | tar xzf -\
+ && cd openwhisk-runtime-go-*/main\
+ && GO111MODULE=on go build -o /bin/proxy
+
+FROM swift:5.4
+
+# select the builder to use
+ARG GO_PROXY_BUILD_FROM=release
+
+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_source /bin/proxy /bin/proxy_source
+COPY --from=builder_release /bin/proxy /bin/proxy_release
+RUN mv /bin/proxy_${GO_PROXY_BUILD_FROM} /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/core/swift54Action/Package.swift b/core/swift54Action/Package.swift
new file mode 100644
index 0000000..181e352
--- /dev/null
+++ b/core/swift54Action/Package.swift
@@ -0,0 +1,37 @@
+// 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
+ * 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",
+ products: [
+ .executable(
+ name: "Action",
+ targets: ["Action"]
+ )
+ ],
+ targets: [
+ .target(
+ name: "Action",
+ path: "."
+ )
+ ]
+)
diff --git a/core/swift54Action/_Whisk.swift b/core/swift54Action/_Whisk.swift
new file mode 100644
index 0000000..3f18e9d
--- /dev/null
+++ b/core/swift54Action/_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/core/swift54Action/build.gradle b/core/swift54Action/build.gradle
new file mode 100644
index 0000000..b666103
--- /dev/null
+++ b/core/swift54Action/build.gradle
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+ext.dockerImageName = 'action-swift-v5.4'
+apply from: '../../gradle/docker.gradle'
diff --git a/core/swift54Action/main.swift b/core/swift54Action/main.swift
new file mode 100644
index 0000000..75071a3
--- /dev/null
+++ b/core/swift54Action/main.swift
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+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/swift54Action/swiftbuild.py b/core/swift54Action/swiftbuild.py
new file mode 100755
index 0000000..9b40903
--- /dev/null
+++ b/core/swift54Action/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/swift54Action/swiftbuild.py.launcher.swift b/core/swift54Action/swiftbuild.py.launcher.swift
new file mode 100644
index 0000000..3405777
--- /dev/null
+++ b/core/swift54Action/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", depending on the type of function the developer
+// wants to use traditional vs codable
+
+
+
+
+
+
+
diff --git a/core/swift54Action/swiftbuildandlink.sh b/core/swift54Action/swiftbuildandlink.sh
new file mode 100755
index 0000000..c35a1ba
--- /dev/null
+++ b/core/swift54Action/swiftbuildandlink.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# 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.
+#
+swift build -c release
diff --git a/settings.gradle b/settings.gradle
index ab6a605..7ae6f5e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -23,6 +23,9 @@
include 'core:swift53Action'
+include 'core:swift54Action'
+
+
rootProject.name = 'runtime-swift'
gradle.ext.openwhisk = [
@@ -40,6 +43,6 @@
config: new File(rootProject.projectDir, '.scalafmt.conf')
]
-
gradle.ext.akka = [version : '2.6.12']
gradle.ext.akka_http = [version : '10.2.4']
+
diff --git a/tests/dat/build.sh b/tests/dat/build.sh
index 29315e0..3abba0c 100755
--- a/tests/dat/build.sh
+++ b/tests/dat/build.sh
@@ -32,3 +32,8 @@
../../tools/build/compile5.sh action-swift-v5.3 HelloSwift5Codable swift5.3 "-v"
../../tools/build/compile5.sh action-swift-v5.3 SwiftyRequest5 swift5.3 "-v"
../../tools/build/compile5.sh action-swift-v5.3 SwiftyRequestCodable5 swift5.3 "-v"
+
+../../tools/build/compile5.sh action-swift-v5.4 HelloSwift5 swift5.4 "-v"
+../../tools/build/compile5.sh action-swift-v5.4 HelloSwift5Codable swift5.4 "-v"
+../../tools/build/compile5.sh action-swift-v5.4 SwiftyRequest5 swift5.4 "-v"
+../../tools/build/compile5.sh action-swift-v5.4 SwiftyRequestCodable5 swift5.4 "-v"
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index 3b9e7dc..8104212 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -49,6 +49,7 @@
:core:swift42Action:distDocker \
:core:swift51Action:distDocker \
:core:swift53Action:distDocker \
+:core:swift54Action:distDocker \
-PdockerImagePrefix=${IMAGE_PREFIX}
# Compile test files
diff --git a/tools/travis/publish.sh b/tools/travis/publish.sh
index 2e46b8f..8a0ece3 100755
--- a/tools/travis/publish.sh
+++ b/tools/travis/publish.sh
@@ -36,6 +36,8 @@
RUNTIME="swift51Action"
elif [ ${RUNTIME_VERSION} == "5.3" ]; then
RUNTIME="swift53Action"
+elif [ ${RUNTIME_VERSION} == "5.4" ]; then
+ RUNTIME="swift54Action"
fi
if [[ ! -z ${DOCKER_USER} ]] && [[ ! -z ${DOCKER_PASSWORD} ]]; then