Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for resources when packaging using the SwiftPM plugin #333

Merged
merged 6 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions Examples/ResourcePackaging/Lambda.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftAWSLambdaRuntime open source project
//
// Copyright (c) 2021 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 {
guard let fileURL = Bundle.module.url(forResource: "hello", withExtension: "txt") else {
fatalError("no file url")
}
return try String(contentsOf: fileURL)
}
}
36 changes: 36 additions & 0 deletions Examples/ResourcePackaging/Package.swift
Original file line number Diff line number Diff line change
@@ -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: "../.."),
]
}
1 change: 1 addition & 0 deletions Examples/ResourcePackaging/hello.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, World!
23 changes: 21 additions & 2 deletions Plugins/AWSLambdaPackager/Plugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct AWSLambdaPackager: CommandPlugin {

// create the archive
let archives = try self.package(
packageName: context.package.displayName,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't sure if there was a better way to get the package name when creating the resources directory name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the only way to retrieve a package name.
See https://github.com/swiftlang/swift-package-manager/blob/b24cc8b547f952ee4a954db939f115a26946fe2b/Sources/PackagePlugin/PackageModel.swift#L16

The other option is to use the directory name but it's not necessarily the same.

products: builtProducts,
toolsProvider: { name in try context.tool(named: name).path },
outputDirectory: configuration.outputDirectory,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -210,17 +212,34 @@ struct AWSLambdaPackager: CommandPlugin {
try FileManager.default.copyItem(atPath: artifactPath.string, toPath: relocatedArtifactPath.string)
try FileManager.default.createSymbolicLink(atPath: symbolicLinkPath.string, withDestinationPath: relocatedArtifactPath.lastComponent)

var arguments: [String] = []
#if os(macOS) || os(Linux)
let arguments = ["--junk-paths", "--symlinks", zipfilePath.string, relocatedArtifactPath.string, symbolicLinkPath.string]
arguments = [
"--recurse-paths",
"--symlinks",
zipfilePath.lastComponent,
relocatedArtifactPath.lastComponent,
symbolicLinkPath.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,
arguments: arguments,
customWorkingDirectory: workingDirectory,
logLevel: verboseLogging ? .debug : .silent
)

Expand Down