diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index f0657f0d..814e6ed5 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -16,11 +16,11 @@ jobs: name: Unit tests uses: apple/swift-nio/.github/workflows/unit_tests.yml@main with: - linux_5_8_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" - linux_5_9_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" - linux_5_10_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" - linux_nightly_6_0_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" - linux_nightly_main_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error" + linux_5_8_enabled: false + linux_5_9_enabled: false + linux_5_10_enabled: false + linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error" + linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" swift-6-language-mode: name: Swift 6 Language Mode diff --git a/Package.swift b/Package.swift index cb9c5321..38a18f83 100644 --- a/Package.swift +++ b/Package.swift @@ -1,21 +1,23 @@ -// swift-tools-version:5.9 +// swift-tools-version:6.0 import PackageDescription +#if os(macOS) +let platforms: [PackageDescription.SupportedPlatform]? = [.macOS(.v15)] +#else +let platforms: [PackageDescription.SupportedPlatform]? = nil +#endif + let package = Package( name: "swift-aws-lambda-runtime", - platforms: [ - .macOS(.v12), - .iOS(.v15), - .tvOS(.v15), - .watchOS(.v8), - ], + platforms: platforms, products: [ // this library exports `AWSLambdaRuntimeCore` and adds Foundation convenience methods .library(name: "AWSLambdaRuntime", targets: ["AWSLambdaRuntime"]), // this has all the main functionality for lambda and it does not link Foundation .library(name: "AWSLambdaRuntimeCore", targets: ["AWSLambdaRuntimeCore"]), // plugin to package the lambda, creating an archive that can be uploaded to AWS + // requires Linux or at least macOS v15 .plugin(name: "AWSLambdaPackager", targets: ["AWSLambdaPackager"]), // for testing only .library(name: "AWSLambdaTesting", targets: ["AWSLambdaTesting"]), @@ -23,7 +25,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/apple/swift-nio.git", .upToNextMajor(from: "2.67.0")), .package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.5.4")), - .package(url: "https://github.com/apple/swift-docc-plugin", exact: "1.3.0"), + .package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.0.0"), ], targets: [ .target( @@ -32,7 +34,8 @@ let package = Package( .byName(name: "AWSLambdaRuntimeCore"), .product(name: "NIOCore", package: "swift-nio"), .product(name: "NIOFoundationCompat", package: "swift-nio"), - ] + ], + swiftSettings: [.swiftLanguageMode(.v5)] ), .target( name: "AWSLambdaRuntimeCore", @@ -42,7 +45,8 @@ let package = Package( .product(name: "NIOCore", package: "swift-nio"), .product(name: "NIOConcurrencyHelpers", package: "swift-nio"), .product(name: "NIOPosix", package: "swift-nio"), - ] + ], + swiftSettings: [.swiftLanguageMode(.v5)] ), .plugin( name: "AWSLambdaPackager", @@ -60,14 +64,16 @@ let package = Package( .byName(name: "AWSLambdaRuntimeCore"), .product(name: "NIOTestUtils", package: "swift-nio"), .product(name: "NIOFoundationCompat", package: "swift-nio"), - ] + ], + swiftSettings: [.swiftLanguageMode(.v5)] ), .testTarget( name: "AWSLambdaRuntimeTests", dependencies: [ .byName(name: "AWSLambdaRuntimeCore"), .byName(name: "AWSLambdaRuntime"), - ] + ], + swiftSettings: [.swiftLanguageMode(.v5)] ), // testing helper .target( @@ -75,16 +81,22 @@ let package = Package( dependencies: [ .byName(name: "AWSLambdaRuntime"), .product(name: "NIO", package: "swift-nio"), - ] + ], + swiftSettings: [.swiftLanguageMode(.v5)] + ), + .testTarget( + name: "AWSLambdaTestingTests", + dependencies: ["AWSLambdaTesting"], + swiftSettings: [.swiftLanguageMode(.v5)] ), - .testTarget(name: "AWSLambdaTestingTests", dependencies: ["AWSLambdaTesting"]), // for perf testing .executableTarget( name: "MockServer", dependencies: [ .product(name: "NIOHTTP1", package: "swift-nio"), .product(name: "NIO", package: "swift-nio"), - ] + ], + swiftSettings: [.swiftLanguageMode(.v5)] ), ] ) diff --git a/Package@swift-5.8.swift b/Package@swift-5.8.swift deleted file mode 100644 index 7add120b..00000000 --- a/Package@swift-5.8.swift +++ /dev/null @@ -1,92 +0,0 @@ -// swift-tools-version:5.7 - -import PackageDescription - -let package = Package( - name: "swift-aws-lambda-runtime", - platforms: [ - .macOS(.v12), - .iOS(.v15), - .tvOS(.v15), - .watchOS(.v8), - ], - products: [ - // this library exports `AWSLambdaRuntimeCore` and adds Foundation convenience methods - .library(name: "AWSLambdaRuntime", targets: ["AWSLambdaRuntime"]), - // this has all the main functionality for lambda and it does not link Foundation - .library(name: "AWSLambdaRuntimeCore", targets: ["AWSLambdaRuntimeCore"]), - // plugin to package the lambda, creating an archive that can be uploaded to AWS - .plugin(name: "AWSLambdaPackager", targets: ["AWSLambdaPackager"]), - // for testing only - .library(name: "AWSLambdaTesting", targets: ["AWSLambdaTesting"]), - ], - dependencies: [ - .package(url: "https://github.com/apple/swift-nio.git", .upToNextMajor(from: "2.43.1")), - .package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.4.2")), - .package(url: "https://github.com/swift-server/swift-backtrace.git", .upToNextMajor(from: "1.2.3")), - .package(url: "https://github.com/apple/swift-docc-plugin", exact: "1.3.0"), - ], - targets: [ - .target( - name: "AWSLambdaRuntime", - dependencies: [ - .byName(name: "AWSLambdaRuntimeCore"), - .product(name: "NIOCore", package: "swift-nio"), - .product(name: "NIOFoundationCompat", package: "swift-nio"), - ] - ), - .target( - name: "AWSLambdaRuntimeCore", - dependencies: [ - .product(name: "Logging", package: "swift-log"), - .product(name: "Backtrace", package: "swift-backtrace"), - .product(name: "NIOHTTP1", package: "swift-nio"), - .product(name: "NIOCore", package: "swift-nio"), - .product(name: "NIOConcurrencyHelpers", package: "swift-nio"), - .product(name: "NIOPosix", package: "swift-nio"), - ] - ), - .plugin( - name: "AWSLambdaPackager", - capability: .command( - intent: .custom( - verb: "archive", - description: - "Archive the Lambda binary and prepare it for uploading to AWS. Requires docker on macOS or non Amazonlinux 2 distributions." - ) - ) - ), - .testTarget( - name: "AWSLambdaRuntimeCoreTests", - dependencies: [ - .byName(name: "AWSLambdaRuntimeCore"), - .product(name: "NIOTestUtils", package: "swift-nio"), - .product(name: "NIOFoundationCompat", package: "swift-nio"), - ] - ), - .testTarget( - name: "AWSLambdaRuntimeTests", - dependencies: [ - .byName(name: "AWSLambdaRuntimeCore"), - .byName(name: "AWSLambdaRuntime"), - ] - ), - // testing helper - .target( - name: "AWSLambdaTesting", - dependencies: [ - .byName(name: "AWSLambdaRuntime"), - .product(name: "NIO", package: "swift-nio"), - ] - ), - .testTarget(name: "AWSLambdaTestingTests", dependencies: ["AWSLambdaTesting"]), - // for perf testing - .executableTarget( - name: "MockServer", - dependencies: [ - .product(name: "NIOHTTP1", package: "swift-nio"), - .product(name: "NIO", package: "swift-nio"), - ] - ), - ] -) diff --git a/Plugins/AWSLambdaPackager/Plugin.swift b/Plugins/AWSLambdaPackager/Plugin.swift index 9ae2ad04..a0ea999b 100644 --- a/Plugins/AWSLambdaPackager/Plugin.swift +++ b/Plugins/AWSLambdaPackager/Plugin.swift @@ -15,19 +15,9 @@ import Dispatch import Foundation import PackagePlugin +import Synchronization -#if os(macOS) -import Darwin -#elseif canImport(Glibc) -import Glibc -#elseif canImport(Musl) -import Musl -#elseif os(Windows) -import ucrt -#else -#error("Unsupported platform") -#endif - +@available(macOS 15.0, *) @main struct AWSLambdaPackager: CommandPlugin { func performCommand(context: PackagePlugin.PluginContext, arguments: [String]) async throws { @@ -282,10 +272,23 @@ struct AWSLambdaPackager: CommandPlugin { print("\(executable.string) \(arguments.joined(separator: " "))") } - var output = "" + let fd = dup(1) + let stdout = fdopen(fd, "rw")! + defer { fclose(stdout) } + + // We need to use an unsafe transfer here to get the fd into our Sendable closure. + // This transfer is fine, because we guarantee that the code in the outputHandler + // is run before we continue the functions execution, where the fd is used again. + // See `process.waitUntilExit()` and the following `outputSync.wait()` + struct UnsafeTransfer: @unchecked Sendable { + let value: Value + } + + let outputMutex = Mutex("") let outputSync = DispatchGroup() let outputQueue = DispatchQueue(label: "AWSLambdaPackager.output") - let outputHandler = { (data: Data?) in + let unsafeTransfer = UnsafeTransfer(value: stdout) + let outputHandler = { @Sendable (data: Data?) in dispatchPrecondition(condition: .onQueue(outputQueue)) outputSync.enter() @@ -299,7 +302,9 @@ struct AWSLambdaPackager: CommandPlugin { return } - output += _output + "\n" + outputMutex.withLock { output in + output += _output + "\n" + } switch logLevel { case .silent: @@ -307,7 +312,7 @@ struct AWSLambdaPackager: CommandPlugin { case .debug(let outputIndent), .output(let outputIndent): print(String(repeating: " ", count: outputIndent), terminator: "") print(_output) - fflush(stdout) + fflush(unsafeTransfer.value) } } @@ -336,6 +341,8 @@ struct AWSLambdaPackager: CommandPlugin { // wait for output to be full processed outputSync.wait() + let output = outputMutex.withLock { $0 } + if process.terminationStatus != 0 { // print output on failure and if not already printed if logLevel < .output { @@ -359,6 +366,7 @@ struct AWSLambdaPackager: CommandPlugin { } } +@available(macOS 15.0, *) private struct Configuration: CustomStringConvertible { public let outputDirectory: Path public let products: [Product]