Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b2e59ff

Browse files
authoredJan 26, 2025··
Merge branch 'main' into sebsto/servicelifecycle
2 parents d865a0f + 7aa746f commit b2e59ff

26 files changed

+906
-450
lines changed
 

‎.github/workflows/integration_tests.yml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ on:
1919
type: boolean
2020
description: "Boolean to enable the compilation of examples. Defaults to true."
2121
default: true
22+
archive_plugin_examples:
23+
type: string
24+
description: "The list of examples to run through the archive plugin test. Pass a String with a valid JSON array such as \"[ 'HelloWorld', 'APIGateway' ]\""
25+
required: true
26+
default: ""
2227
archive_plugin_enabled:
2328
type: boolean
2429
description: "Boolean to enable the test of the archive plugin. Defaults to true."
@@ -54,7 +59,7 @@ jobs:
5459
# We are using only one Swift version
5560
swift:
5661
- image: ${{ inputs.matrix_linux_swift_container_image }}
57-
swift_version: "6.0.1-amazonlinux2"
62+
swift_version: "6.0.3-amazonlinux2"
5863
container:
5964
image: ${{ matrix.swift.image }}
6065
steps:
@@ -98,6 +103,10 @@ jobs:
98103
name: Test archive plugin
99104
if: ${{ inputs.archive_plugin_enabled }}
100105
runs-on: ubuntu-latest
106+
strategy:
107+
fail-fast: false
108+
matrix:
109+
examples: ${{ fromJson(inputs.archive_plugin_examples) }}
101110
steps:
102111
- name: Checkout repository
103112
uses: actions/checkout@v4
@@ -107,8 +116,10 @@ jobs:
107116
# https://github.com/actions/checkout/issues/766
108117
run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
109118
- name: Test the archive plugin
119+
env:
120+
EXAMPLE: ${{ matrix.examples }}
110121
run: |
111-
.github/workflows/scripts/check-archive-plugin.sh
122+
.github/workflows/scripts/check-archive-plugin.sh
112123
113124
check-foundation:
114125
name: No dependencies on Foundation

‎.github/workflows/pull_request.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ jobs:
3636
# We pass the list of examples here, but we can't pass an array as argument
3737
# Instead, we pass a String with a valid JSON array.
3838
# The workaround is mentioned here https://github.com/orgs/community/discussions/11692
39-
examples: "[ 'APIGateway', 'APIGateway+LambdaAuthorizer', 'BackgroundTasks', 'HelloJSON', 'HelloWorld', 'S3_AWSSDK', 'S3_Soto', 'Streaming', 'Testing', 'Tutorial' ]"
40-
39+
examples: "[ 'APIGateway', 'APIGateway+LambdaAuthorizer', 'BackgroundTasks', 'HelloJSON', 'HelloWorld', 'ResourcesPackaging', 'S3_AWSSDK', 'S3_Soto', 'Streaming', 'Testing', 'Tutorial' ]"
40+
archive_plugin_examples: "[ 'HelloWorld', 'ResourcesPackaging' ]"
4141
archive_plugin_enabled: true
4242

4343
swift-6-language-mode:

‎.github/workflows/scripts/check-archive-plugin.sh

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@
1313
##
1414
##===----------------------------------------------------------------------===##
1515

16-
EXAMPLE=HelloWorld
16+
log() { printf -- "** %s\n" "$*" >&2; }
17+
error() { printf -- "** ERROR: %s\n" "$*" >&2; }
18+
fatal() { error "$@"; exit 1; }
19+
20+
test -n "${EXAMPLE:-}" || fatal "EXAMPLE unset"
21+
1722
OUTPUT_DIR=.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager
1823
OUTPUT_FILE=${OUTPUT_DIR}/MyLambda/bootstrap
1924
ZIP_FILE=${OUTPUT_DIR}/MyLambda/MyLambda.zip
2025

21-
pushd Examples/${EXAMPLE} || exit 1
26+
pushd "Examples/${EXAMPLE}" || exit 1
2227

2328
# package the example (docker and swift toolchain are installed on the GH runner)
2429
LAMBDA_USE_LOCAL_DEPS=../.. swift package archive --allow-network-connections docker || exit 1
@@ -33,5 +38,10 @@ file "${OUTPUT_FILE}" | grep --silent ELF
3338
# does the ZIP file contain the bootstrap?
3439
unzip -l "${ZIP_FILE}" | grep --silent bootstrap
3540

36-
echo "✅ The archive plugin is OK"
41+
# if EXAMPLE is ResourcesPackaging, check if the ZIP file contains hello.txt
42+
if [ "$EXAMPLE" == "ResourcesPackaging" ]; then
43+
unzip -l "${ZIP_FILE}" | grep --silent hello.txt
44+
fi
45+
46+
echo "✅ The archive plugin is OK with example ${EXAMPLE}"
3747
popd || exit 1

‎.licenseignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ Package.resolved
3333
*.yaml
3434
*.yml
3535
**/.npmignore
36-
**/*.json
36+
**/*.json
37+
**/*.txt

‎Examples/CDK/infra/package-lock.json

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// swift-tools-version: 6.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
// needed for CI to test the local version of the library
7+
import struct Foundation.URL
8+
9+
let package = Package(
10+
name: "ResourcesPackaging",
11+
platforms: [.macOS(.v15)],
12+
products: [
13+
.executable(name: "MyLambda", targets: ["MyLambda"])
14+
],
15+
dependencies: [
16+
.package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", branch: "main")
17+
],
18+
targets: [
19+
.executableTarget(
20+
name: "MyLambda",
21+
dependencies: [
22+
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime")
23+
],
24+
path: ".",
25+
resources: [
26+
.process("hello.txt")
27+
]
28+
)
29+
]
30+
)
31+
32+
if let localDepsPath = Context.environment["LAMBDA_USE_LOCAL_DEPS"],
33+
localDepsPath != "",
34+
let v = try? URL(fileURLWithPath: localDepsPath).resourceValues(forKeys: [.isDirectoryKey]),
35+
v.isDirectory == true
36+
{
37+
// when we use the local runtime as deps, let's remove the dependency added above
38+
let indexToRemove = package.dependencies.firstIndex { dependency in
39+
if case .sourceControl(
40+
name: _,
41+
location: "https://github.com/swift-server/swift-aws-lambda-runtime.git",
42+
requirement: _
43+
) = dependency.kind {
44+
return true
45+
}
46+
return false
47+
}
48+
if let indexToRemove {
49+
package.dependencies.remove(at: indexToRemove)
50+
}
51+
52+
// then we add the dependency on LAMBDA_USE_LOCAL_DEPS' path (typically ../..)
53+
print("[INFO] Compiling against swift-aws-lambda-runtime located at \(localDepsPath)")
54+
package.dependencies += [
55+
.package(name: "swift-aws-lambda-runtime", path: localDepsPath)
56+
]
57+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import AWSLambdaRuntime
16+
import Foundation
17+
18+
let runtime = LambdaRuntime {
19+
(event: String, context: LambdaContext) in
20+
guard let fileURL = Bundle.module.url(forResource: "hello", withExtension: "txt") else {
21+
fatalError("no file url")
22+
}
23+
return try String(contentsOf: fileURL, encoding: .utf8)
24+
}
25+
26+
try await runtime.run()

‎Examples/ResourcesPackaging/hello.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello World

‎Package.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ let package = Package(
2323
.library(name: "AWSLambdaTesting", targets: ["AWSLambdaTesting"]),
2424
],
2525
dependencies: [
26-
.package(url: "https://github.com/apple/swift-nio.git", from: "2.76.0"),
26+
.package(url: "https://github.com/apple/swift-nio.git", from: "2.77.0"),
2727
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.4"),
2828
.package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "2.6.3"),
2929
],
@@ -103,11 +103,11 @@ let package = Package(
103103
.executableTarget(
104104
name: "MockServer",
105105
dependencies: [
106+
.product(name: "Logging", package: "swift-log"),
106107
.product(name: "NIOHTTP1", package: "swift-nio"),
107108
.product(name: "NIOCore", package: "swift-nio"),
108109
.product(name: "NIOPosix", package: "swift-nio"),
109-
],
110-
swiftSettings: [.swiftLanguageMode(.v5)]
110+
]
111111
),
112112
]
113113
)

‎Plugins/AWSLambdaPackager/Plugin.swift

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,29 @@ struct AWSLambdaPackager: CommandPlugin {
249249
let resourcesDirectoryName = artifactURL.lastPathComponent
250250
let relocatedResourcesDirectory = workingDirectory.appending(path: resourcesDirectoryName)
251251
if FileManager.default.fileExists(atPath: artifactURL.path()) {
252-
try FileManager.default.copyItem(
253-
atPath: artifactURL.path(),
254-
toPath: relocatedResourcesDirectory.path()
255-
)
256-
arguments.append(resourcesDirectoryName)
252+
do {
253+
try FileManager.default.copyItem(
254+
atPath: artifactURL.path(),
255+
toPath: relocatedResourcesDirectory.path()
256+
)
257+
arguments.append(resourcesDirectoryName)
258+
} catch let error as CocoaError {
259+
260+
// On Linux, when the build has been done with Docker,
261+
// the source file are owned by root
262+
// this causes a permission error **after** the files have been copied
263+
// see https://github.com/swift-server/swift-aws-lambda-runtime/issues/449
264+
// see https://forums.swift.org/t/filemanager-copyitem-on-linux-fails-after-copying-the-files/77282
265+
266+
// because this error happens after the files have been copied, we can ignore it
267+
// this code checks if the destination file exists
268+
// if they do, just ignore error, otherwise throw it up to the caller.
269+
if !(error.code == CocoaError.Code.fileWriteNoPermission
270+
&& FileManager.default.fileExists(atPath: relocatedResourcesDirectory.path()))
271+
{
272+
throw error
273+
} // else just ignore it
274+
}
257275
}
258276
}
259277

‎Sources/AWSLambdaRuntimeCore/Lambda+LocalServer.swift

Lines changed: 350 additions & 242 deletions
Large diffs are not rendered by default.
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2017-2025 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Logging
16+
import NIOCore
17+
import NIOHTTP1
18+
import NIOPosix
19+
import Synchronization
20+
21+
// for UUID and Date
22+
#if canImport(FoundationEssentials)
23+
import FoundationEssentials
24+
#else
25+
import Foundation
26+
#endif
27+
28+
@main
29+
struct HttpServer {
30+
/// The server's host. (default: 127.0.0.1)
31+
private let host: String
32+
/// The server's port. (default: 7000)
33+
private let port: Int
34+
/// The server's event loop group. (default: MultiThreadedEventLoopGroup.singleton)
35+
private let eventLoopGroup: MultiThreadedEventLoopGroup
36+
/// the mode. Are we mocking a server for a Lambda function that expects a String or a JSON document? (default: string)
37+
private let mode: Mode
38+
/// the number of connections this server must accept before shutting down (default: 1)
39+
private let maxInvocations: Int
40+
/// the logger (control verbosity with LOG_LEVEL environment variable)
41+
private let logger: Logger
42+
43+
static func main() async throws {
44+
var log = Logger(label: "MockServer")
45+
log.logLevel = env("LOG_LEVEL").flatMap(Logger.Level.init) ?? .info
46+
47+
let server = HttpServer(
48+
host: env("HOST") ?? "127.0.0.1",
49+
port: env("PORT").flatMap(Int.init) ?? 7000,
50+
eventLoopGroup: .singleton,
51+
mode: env("MODE").flatMap(Mode.init) ?? .string,
52+
maxInvocations: env("MAX_INVOCATIONS").flatMap(Int.init) ?? 1,
53+
logger: log
54+
)
55+
try await server.run()
56+
}
57+
58+
/// This method starts the server and handles one unique incoming connections
59+
/// The Lambda function will send two HTTP requests over this connection: one for the next invocation and one for the response.
60+
private func run() async throws {
61+
let channel = try await ServerBootstrap(group: self.eventLoopGroup)
62+
.serverChannelOption(.backlog, value: 256)
63+
.serverChannelOption(.socketOption(.so_reuseaddr), value: 1)
64+
.childChannelOption(.maxMessagesPerRead, value: 1)
65+
.bind(
66+
host: self.host,
67+
port: self.port
68+
) { channel in
69+
channel.eventLoop.makeCompletedFuture {
70+
71+
try channel.pipeline.syncOperations.configureHTTPServerPipeline(
72+
withErrorHandling: true
73+
)
74+
75+
return try NIOAsyncChannel(
76+
wrappingChannelSynchronously: channel,
77+
configuration: NIOAsyncChannel.Configuration(
78+
inboundType: HTTPServerRequestPart.self,
79+
outboundType: HTTPServerResponsePart.self
80+
)
81+
)
82+
}
83+
}
84+
85+
logger.info(
86+
"Server started and listening",
87+
metadata: [
88+
"host": "\(channel.channel.localAddress?.ipAddress?.debugDescription ?? "")",
89+
"port": "\(channel.channel.localAddress?.port ?? 0)",
90+
"maxInvocations": "\(self.maxInvocations)",
91+
]
92+
)
93+
94+
// This counter is used to track the number of incoming connections.
95+
// This mock servers accepts n TCP connection then shutdowns
96+
let connectionCounter = SharedCounter(maxValue: self.maxInvocations)
97+
98+
// We are handling each incoming connection in a separate child task. It is important
99+
// to use a discarding task group here which automatically discards finished child tasks.
100+
// A normal task group retains all child tasks and their outputs in memory until they are
101+
// consumed by iterating the group or by exiting the group. Since, we are never consuming
102+
// the results of the group we need the group to automatically discard them; otherwise, this
103+
// would result in a memory leak over time.
104+
try await withThrowingDiscardingTaskGroup { group in
105+
try await channel.executeThenClose { inbound in
106+
for try await connectionChannel in inbound {
107+
108+
let counter = connectionCounter.current()
109+
logger.trace("Handling new connection", metadata: ["connectionNumber": "\(counter)"])
110+
111+
group.addTask {
112+
await self.handleConnection(channel: connectionChannel)
113+
logger.trace("Done handling connection", metadata: ["connectionNumber": "\(counter)"])
114+
}
115+
116+
if connectionCounter.increment() {
117+
logger.info(
118+
"Maximum number of connections reached, shutting down after current connection",
119+
metadata: ["maxConnections": "\(self.maxInvocations)"]
120+
)
121+
break // this causes the server to shutdown after handling the connection
122+
}
123+
}
124+
}
125+
}
126+
logger.info("Server shutting down")
127+
}
128+
129+
/// This method handles a single connection by responsing hard coded value to a Lambda function request.
130+
/// It handles two requests: one for the next invocation and one for the response.
131+
/// when the maximum number of requests is reached, it closes the connection.
132+
private func handleConnection(
133+
channel: NIOAsyncChannel<HTTPServerRequestPart, HTTPServerResponsePart>
134+
) async {
135+
136+
var requestHead: HTTPRequestHead!
137+
var requestBody: ByteBuffer?
138+
139+
// each Lambda invocation results in TWO HTTP requests (next and response)
140+
let requestCount = SharedCounter(maxValue: 2)
141+
142+
// Note that this method is non-throwing and we are catching any error.
143+
// We do this since we don't want to tear down the whole server when a single connection
144+
// encounters an error.
145+
do {
146+
try await channel.executeThenClose { inbound, outbound in
147+
for try await inboundData in inbound {
148+
let requestNumber = requestCount.current()
149+
logger.trace("Handling request", metadata: ["requestNumber": "\(requestNumber)"])
150+
151+
if case .head(let head) = inboundData {
152+
logger.trace("Received request head", metadata: ["head": "\(head)"])
153+
requestHead = head
154+
}
155+
if case .body(let body) = inboundData {
156+
logger.trace("Received request body", metadata: ["body": "\(body)"])
157+
requestBody = body
158+
}
159+
if case .end(let end) = inboundData {
160+
logger.trace("Received request end", metadata: ["end": "\(String(describing: end))"])
161+
162+
precondition(requestHead != nil, "Received .end without .head")
163+
let (responseStatus, responseHeaders, responseBody) = self.processRequest(
164+
requestHead: requestHead,
165+
requestBody: requestBody
166+
)
167+
168+
try await self.sendResponse(
169+
responseStatus: responseStatus,
170+
responseHeaders: responseHeaders,
171+
responseBody: responseBody,
172+
outbound: outbound
173+
)
174+
175+
requestHead = nil
176+
177+
if requestCount.increment() {
178+
logger.info(
179+
"Maximum number of requests reached, closing this connection",
180+
metadata: ["maxRequest": "2"]
181+
)
182+
break // this finishes handiling request on this connection
183+
}
184+
}
185+
}
186+
}
187+
} catch {
188+
logger.error("Hit error: \(error)")
189+
}
190+
}
191+
/// This function process the requests and return an hard-coded response (string or JSON depending on the mode).
192+
/// We ignore the requestBody.
193+
private func processRequest(
194+
requestHead: HTTPRequestHead,
195+
requestBody: ByteBuffer?
196+
) -> (HTTPResponseStatus, [(String, String)], String) {
197+
var responseStatus: HTTPResponseStatus = .ok
198+
var responseBody: String = ""
199+
var responseHeaders: [(String, String)] = []
200+
201+
logger.trace(
202+
"Processing request",
203+
metadata: ["VERB": "\(requestHead.method)", "URI": "\(requestHead.uri)"]
204+
)
205+
206+
if requestHead.uri.hasSuffix("/next") {
207+
responseStatus = .accepted
208+
209+
let requestId = UUID().uuidString
210+
switch self.mode {
211+
case .string:
212+
responseBody = "\"Seb\"" // must be a valid JSON document
213+
case .json:
214+
responseBody = "{ \"name\": \"Seb\", \"age\" : 52 }"
215+
}
216+
let deadline = Int64(Date(timeIntervalSinceNow: 60).timeIntervalSince1970 * 1000)
217+
responseHeaders = [
218+
(AmazonHeaders.requestID, requestId),
219+
(AmazonHeaders.invokedFunctionARN, "arn:aws:lambda:us-east-1:123456789012:function:custom-runtime"),
220+
(AmazonHeaders.traceID, "Root=1-5bef4de7-ad49b0e87f6ef6c87fc2e700;Parent=9a9197af755a6419;Sampled=1"),
221+
(AmazonHeaders.deadline, String(deadline)),
222+
]
223+
} else if requestHead.uri.hasSuffix("/response") {
224+
responseStatus = .accepted
225+
} else if requestHead.uri.hasSuffix("/error") {
226+
responseStatus = .ok
227+
} else {
228+
responseStatus = .notFound
229+
}
230+
logger.trace("Returning response: \(responseStatus), \(responseHeaders), \(responseBody)")
231+
return (responseStatus, responseHeaders, responseBody)
232+
}
233+
234+
private func sendResponse(
235+
responseStatus: HTTPResponseStatus,
236+
responseHeaders: [(String, String)],
237+
responseBody: String,
238+
outbound: NIOAsyncChannelOutboundWriter<HTTPServerResponsePart>
239+
) async throws {
240+
var headers = HTTPHeaders(responseHeaders)
241+
headers.add(name: "Content-Length", value: "\(responseBody.utf8.count)")
242+
headers.add(name: "KeepAlive", value: "timeout=1, max=2")
243+
244+
logger.trace("Writing response head")
245+
try await outbound.write(
246+
HTTPServerResponsePart.head(
247+
HTTPResponseHead(
248+
version: .init(major: 1, minor: 1), // use HTTP 1.1 it keeps connection alive between requests
249+
status: responseStatus,
250+
headers: headers
251+
)
252+
)
253+
)
254+
logger.trace("Writing response body")
255+
try await outbound.write(HTTPServerResponsePart.body(.byteBuffer(ByteBuffer(string: responseBody))))
256+
logger.trace("Writing response end")
257+
try await outbound.write(HTTPServerResponsePart.end(nil))
258+
}
259+
260+
private enum Mode: String {
261+
case string
262+
case json
263+
}
264+
265+
private static func env(_ name: String) -> String? {
266+
guard let value = getenv(name) else {
267+
return nil
268+
}
269+
return String(cString: value)
270+
}
271+
272+
private enum AmazonHeaders {
273+
static let requestID = "Lambda-Runtime-Aws-Request-Id"
274+
static let traceID = "Lambda-Runtime-Trace-Id"
275+
static let clientContext = "X-Amz-Client-Context"
276+
static let cognitoIdentity = "X-Amz-Cognito-Identity"
277+
static let deadline = "Lambda-Runtime-Deadline-Ms"
278+
static let invokedFunctionARN = "Lambda-Runtime-Invoked-Function-Arn"
279+
}
280+
281+
private final class SharedCounter: Sendable {
282+
private let counterMutex = Mutex<Int>(0)
283+
private let maxValue: Int
284+
285+
init(maxValue: Int) {
286+
self.maxValue = maxValue
287+
}
288+
func current() -> Int {
289+
counterMutex.withLock { $0 }
290+
}
291+
func increment() -> Bool {
292+
counterMutex.withLock {
293+
$0 += 1
294+
return $0 >= maxValue
295+
}
296+
}
297+
}
298+
}

‎Sources/MockServer/main.swift

Lines changed: 0 additions & 177 deletions
This file was deleted.

‎readme.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
> [!IMPORTANT]
22
> The documentation included here refers to the Swift AWS Lambda Runtime v2 (code from the main branch). If you're developing for the runtime v1.x, check this [readme](https://github.com/swift-server/swift-aws-lambda-runtime/blob/v1/readme.md) instead.
33
4-
> [!WARNING]
5-
> The Swift AWS Runtime v2 is work in progress. We will add more documentation and code examples over time.
6-
74
This guide contains the follwoing sections:
85

96
- [The Swift AWS Lambda Runtime](#the-swift-aws-lambda-runtime)
@@ -282,7 +279,7 @@ try await runtime.run()
282279

283280
### Integration with Swift Service LifeCycle
284281

285-
tbd + link to docc
282+
Support for [Swift Service Lifecycle](https://github.com/swift-server/swift-service-lifecycle) is currently being implemented. You can follow https://github.com/swift-server/swift-aws-lambda-runtime/issues/374 for more details and teh current status. Your contributions are welcome.
286283

287284
### Use Lambda Background Tasks
288285

‎scripts/ubuntu-install-swift.sh

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/bin/bash
2+
##===----------------------------------------------------------------------===##
3+
##
4+
## This source file is part of the SwiftAWSLambdaRuntime open source project
5+
##
6+
## Copyright (c) 2025 Apple Inc. and the SwiftAWSLambdaRuntime project authors
7+
## Licensed under Apache License v2.0
8+
##
9+
## See LICENSE.txt for license information
10+
## See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
11+
##
12+
## SPDX-License-Identifier: Apache-2.0
13+
##
14+
##===----------------------------------------------------------------------===##
15+
16+
sudo apt update && sudo apt -y upgrade
17+
18+
# Install Swift 6.0.3
19+
sudo apt-get -y install \
20+
binutils \
21+
git \
22+
gnupg2 \
23+
libc6-dev \
24+
libcurl4-openssl-dev \
25+
libedit2 \
26+
libgcc-13-dev \
27+
libncurses-dev \
28+
libpython3-dev \
29+
libsqlite3-0 \
30+
libstdc++-13-dev \
31+
libxml2-dev \
32+
libz3-dev \
33+
pkg-config \
34+
tzdata \
35+
unzip \
36+
zip \
37+
zlib1g-dev
38+
39+
wget https://download.swift.org/swift-6.0.3-release/ubuntu2404-aarch64/swift-6.0.3-RELEASE/swift-6.0.3-RELEASE-ubuntu24.04-aarch64.tar.gz
40+
41+
tar xfvz swift-6.0.3-RELEASE-ubuntu24.04-aarch64.tar.gz
42+
43+
export PATH=/home/ubuntu/swift-6.0.3-RELEASE-ubuntu24.04-aarch64/usr/bin:"${PATH}"
44+
45+
swift --version
46+
47+
# Install Docker
48+
sudo apt-get update
49+
sudo apt-get install -y ca-certificates curl
50+
sudo install -m 0755 -d /etc/apt/keyrings
51+
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
52+
sudo chmod a+r /etc/apt/keyrings/docker.asc
53+
54+
# Add the repository to Apt sources:
55+
# shellcheck source=/etc/os-release
56+
# shellcheck disable=SC1091
57+
. /etc/os-release
58+
echo \
59+
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
60+
$VERSION_CODENAME stable" | \
61+
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
62+
sudo apt-get update
63+
64+
sudo apt-get -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
65+
66+
# Add the current user to the docker group
67+
sudo usermod -aG docker "$USER"
68+
69+
# LOGOUT and LOGIN to apply the changes
70+
exit 0

‎scripts/ubuntu-test-plugin.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
##===----------------------------------------------------------------------===##
3+
##
4+
## This source file is part of the SwiftAWSLambdaRuntime open source project
5+
##
6+
## Copyright (c) 2025 Apple Inc. and the SwiftAWSLambdaRuntime project authors
7+
## Licensed under Apache License v2.0
8+
##
9+
## See LICENSE.txt for license information
10+
## See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
11+
##
12+
## SPDX-License-Identifier: Apache-2.0
13+
##
14+
##===----------------------------------------------------------------------===##
15+
16+
# Connect with ssh
17+
18+
export PATH=/home/ubuntu/swift-6.0.3-RELEASE-ubuntu24.04-aarch64/usr/bin:"${PATH}"
19+
20+
# clone a project
21+
git clone https://github.com/swift-server/swift-aws-lambda-runtime.git
22+
23+
# be sure Swift is install.
24+
# Youc an install swift with the following command: ./scripts/ubuntu-install-swift.sh
25+
26+
# build the project
27+
cd swift-aws-lambda-runtime/Examples/ResourcesPackaging/ || exit 1
28+
LAMBDA_USE_LOCAL_DEPS=../.. swift package archive --allow-network-connections docker

0 commit comments

Comments
 (0)
Please sign in to comment.