From 86dd1a7065a6f7f1bf556f139b2d18df58614fb6 Mon Sep 17 00:00:00 2001 From: Camden Fullmer Date: Fri, 21 Jun 2024 12:23:26 -0400 Subject: [PATCH 1/5] Add support for resources when packaging using the SwiftPM plugin. --- Plugins/AWSLambdaPackager/Plugin.swift | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Plugins/AWSLambdaPackager/Plugin.swift b/Plugins/AWSLambdaPackager/Plugin.swift index 4d8b5a09..58cecf77 100644 --- a/Plugins/AWSLambdaPackager/Plugin.swift +++ b/Plugins/AWSLambdaPackager/Plugin.swift @@ -202,8 +202,27 @@ struct AWSLambdaPackager: CommandPlugin { try FileManager.default.copyItem(atPath: artifactPath.string, toPath: relocatedArtifactPath.string) try FileManager.default.createSymbolicLink(atPath: symbolicLinkPath.string, withDestinationPath: relocatedArtifactPath.lastComponent) + // add resources + let contentsDirectory = workingDirectory.appending("Contents") + try FileManager.default.createDirectory(atPath: contentsDirectory.string, withIntermediateDirectories: true) + let relocatedResourcesDirectory = contentsDirectory.appending("Resources") + let artifactDirectory = artifactPath.removingLastComponent() + let resourcesDirectoryName = try FileManager.default.contentsOfDirectory(atPath: artifactDirectory.string) + .first(where: { $0.hasSuffix(".resources") && $0.contains(product.name) }) + if let resourcesDirectoryName { + let resourcesDirectory = artifactDirectory.appending(resourcesDirectoryName) + try FileManager.default.copyItem(atPath: resourcesDirectory.string, toPath: relocatedResourcesDirectory.string) + } + #if os(macOS) || os(Linux) - let arguments = ["--junk-paths", "--symlinks", zipfilePath.string, relocatedArtifactPath.string, symbolicLinkPath.string] + let arguments = [ + "--recurse-paths", + "--symlinks", + zipfilePath.lastComponent, + relocatedArtifactPath.lastComponent, + symbolicLinkPath.lastComponent, + contentsDirectory.lastComponent, + ] #else let arguments = [String]() throw Errors.unsupportedPlatform("can't or don't know how to create a zip file on this platform") @@ -213,6 +232,7 @@ struct AWSLambdaPackager: CommandPlugin { try self.execute( executable: zipToolPath, arguments: arguments, + customWorkingDirectory: workingDirectory, logLevel: verboseLogging ? .debug : .silent ) From 7554ed7c8f08316b831409ecb6464a38e031aafa Mon Sep 17 00:00:00 2001 From: Camden Fullmer Date: Thu, 1 Aug 2024 14:10:54 -0400 Subject: [PATCH 2/5] Copy the resources directory to the working directory instead of recreating the directroy structure. --- Plugins/AWSLambdaPackager/Plugin.swift | 29 +++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Plugins/AWSLambdaPackager/Plugin.swift b/Plugins/AWSLambdaPackager/Plugin.swift index 8b02189a..33cf00e3 100644 --- a/Plugins/AWSLambdaPackager/Plugin.swift +++ b/Plugins/AWSLambdaPackager/Plugin.swift @@ -67,6 +67,7 @@ struct AWSLambdaPackager: CommandPlugin { // create the archive let archives = try self.package( + packageName: context.package.displayName, products: builtProducts, toolsProvider: { name in try context.tool(named: name).path }, outputDirectory: configuration.outputDirectory, @@ -183,6 +184,7 @@ struct AWSLambdaPackager: CommandPlugin { // TODO: explore using ziplib or similar instead of shelling out private func package( + packageName: String, products: [LambdaProduct: Path], toolsProvider: (String) throws -> Path, outputDirectory: Path, @@ -210,32 +212,29 @@ struct AWSLambdaPackager: CommandPlugin { try FileManager.default.copyItem(atPath: artifactPath.string, toPath: relocatedArtifactPath.string) try FileManager.default.createSymbolicLink(atPath: symbolicLinkPath.string, withDestinationPath: relocatedArtifactPath.lastComponent) - // add resources - let contentsDirectory = workingDirectory.appending("Contents") - try FileManager.default.createDirectory(atPath: contentsDirectory.string, withIntermediateDirectories: true) - let relocatedResourcesDirectory = contentsDirectory.appending("Resources") - let artifactDirectory = artifactPath.removingLastComponent() - let resourcesDirectoryName = try FileManager.default.contentsOfDirectory(atPath: artifactDirectory.string) - .first(where: { $0.hasSuffix(".resources") && $0.contains(product.name) }) - if let resourcesDirectoryName { - let resourcesDirectory = artifactDirectory.appending(resourcesDirectoryName) - try FileManager.default.copyItem(atPath: resourcesDirectory.string, toPath: relocatedResourcesDirectory.string) - } - + var arguments: [String] = [] #if os(macOS) || os(Linux) - let arguments = [ + arguments = [ "--recurse-paths", "--symlinks", zipfilePath.lastComponent, relocatedArtifactPath.lastComponent, symbolicLinkPath.lastComponent, - contentsDirectory.lastComponent, ] #else - let arguments = [String]() throw Errors.unsupportedPlatform("can't or don't know how to create a zip file on this platform") #endif + // add resources + let artifactDirectory = artifactPath.removingLastComponent() + let resourcesDirectoryName = "\(packageName)_\(product.name).resources" + let resourcesDirectory = artifactDirectory.appending(resourcesDirectoryName) + let relocatedResourcesDirectory = workingDirectory.appending(resourcesDirectoryName) + if FileManager.default.fileExists(atPath: resourcesDirectory.string) { + try FileManager.default.copyItem(atPath: resourcesDirectory.string, toPath: relocatedResourcesDirectory.string) + arguments.append(resourcesDirectoryName) + } + // run the zip tool try self.execute( executable: zipToolPath, From 05dee3419162bb4e20620e529a75a6a43bfe88bd Mon Sep 17 00:00:00 2001 From: Camden Fullmer Date: Thu, 1 Aug 2024 14:11:16 -0400 Subject: [PATCH 3/5] Add resource packaging example. --- Examples/ResourcePackaging/Lambda.swift | 30 ++++++++++++++++++++ Examples/ResourcePackaging/Package.swift | 36 ++++++++++++++++++++++++ Examples/ResourcePackaging/hello.txt | 1 + 3 files changed, 67 insertions(+) create mode 100644 Examples/ResourcePackaging/Lambda.swift create mode 100644 Examples/ResourcePackaging/Package.swift create mode 100644 Examples/ResourcePackaging/hello.txt diff --git a/Examples/ResourcePackaging/Lambda.swift b/Examples/ResourcePackaging/Lambda.swift new file mode 100644 index 00000000..97ada1ad --- /dev/null +++ b/Examples/ResourcePackaging/Lambda.swift @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftAWSLambdaRuntime open source project +// +// Copyright (c) 2024 Apple Inc. and the SwiftAWSLambdaRuntime project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import AWSLambdaRuntime +import Foundation + +// in this example we are reading from a bundled resource and responding with the contents + +@main +struct MyLambda: SimpleLambdaHandler { + func handle(_ input: String, context: LambdaContext) async throws -> String { + let fileName = "hello.txt" + guard let resourceURL = Bundle.module.resourceURL else { + fatalError("unable to locate bundle resource url") + } + let fileURL = resourceURL.appendingPathComponent(fileName) + return try String(contentsOf: fileURL) + } +} diff --git a/Examples/ResourcePackaging/Package.swift b/Examples/ResourcePackaging/Package.swift new file mode 100644 index 00000000..cfb4db28 --- /dev/null +++ b/Examples/ResourcePackaging/Package.swift @@ -0,0 +1,36 @@ +// swift-tools-version:5.7 + +import class Foundation.ProcessInfo // needed for CI to test the local version of the library +import PackageDescription + +let package = Package( + name: "swift-aws-lambda-runtime-example", + platforms: [ + .macOS(.v12), + ], + products: [ + .executable(name: "MyLambda", targets: ["MyLambda"]), + ], + dependencies: [ + .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", from: "1.0.0-alpha"), + ], + targets: [ + .executableTarget( + name: "MyLambda", + dependencies: [ + .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"), + ], + path: ".", + resources: [ + .process("hello.txt"), + ] + ), + ] +) + +// for CI to test the local version of the library +if ProcessInfo.processInfo.environment["LAMBDA_USE_LOCAL_DEPS"] != nil { + package.dependencies = [ + .package(name: "swift-aws-lambda-runtime", path: "../.."), + ] +} diff --git a/Examples/ResourcePackaging/hello.txt b/Examples/ResourcePackaging/hello.txt new file mode 100644 index 00000000..b45ef6fe --- /dev/null +++ b/Examples/ResourcePackaging/hello.txt @@ -0,0 +1 @@ +Hello, World! \ No newline at end of file From 33f295297c29ecd256ab1b96ca48ecacf71ddff8 Mon Sep 17 00:00:00 2001 From: Camden Fullmer Date: Thu, 1 Aug 2024 14:22:13 -0400 Subject: [PATCH 4/5] Use the bundle's url function to locate the file url. --- Examples/ResourcePackaging/Lambda.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Examples/ResourcePackaging/Lambda.swift b/Examples/ResourcePackaging/Lambda.swift index 97ada1ad..92789c76 100644 --- a/Examples/ResourcePackaging/Lambda.swift +++ b/Examples/ResourcePackaging/Lambda.swift @@ -20,11 +20,9 @@ import Foundation @main struct MyLambda: SimpleLambdaHandler { func handle(_ input: String, context: LambdaContext) async throws -> String { - let fileName = "hello.txt" - guard let resourceURL = Bundle.module.resourceURL else { - fatalError("unable to locate bundle resource url") + guard let fileURL = Bundle.module.url(forResource: "hello", withExtension: "txt") else { + fatalError("no file url") } - let fileURL = resourceURL.appendingPathComponent(fileName) return try String(contentsOf: fileURL) } } From 7623f28647c6d03622a529919386f090c08dd891 Mon Sep 17 00:00:00 2001 From: Camden Fullmer Date: Thu, 1 Aug 2024 21:41:46 -0400 Subject: [PATCH 5/5] Fix year for soundness check. --- Examples/ResourcePackaging/Lambda.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/ResourcePackaging/Lambda.swift b/Examples/ResourcePackaging/Lambda.swift index 92789c76..5e71a688 100644 --- a/Examples/ResourcePackaging/Lambda.swift +++ b/Examples/ResourcePackaging/Lambda.swift @@ -2,7 +2,7 @@ // // This source file is part of the SwiftAWSLambdaRuntime open source project // -// Copyright (c) 2024 Apple Inc. and the SwiftAWSLambdaRuntime project authors +// Copyright (c) 2021 Apple Inc. and the SwiftAWSLambdaRuntime project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information