swift-server / swift-aws-lambda-runtime

Swift implementation of AWS Lambda Runtime
Apache License 2.0
1.12k stars 101 forks source link

[plugin] LocalDebugging example - archive fails because of Shared code #276

Open sebsto opened 1 year ago

sebsto commented 1 year ago

Expected behavior

I expect the archive plugin to package the MyLambda function part of the Examples/Localdebugging The archive command fails because part of the MyLambda function relies on Shared code which is not under MyLambda directory.

Actual behavior

The archive fails because the Lambda function relies on shared code outside of the MyLambda directory structure.

 swift package --disable-sandbox archive --verbose 1 --output-path dist                    
-------------------------------------------------------------------------
configuration
-------------------------------------------------------------------------
{
  outputDirectory: dist
  products: ["MyLambda"]
  buildConfiguration: release
  baseDockerImage: swift:amazonlinux2
}
-------------------------------------------------------------------------
building "mylambda" in docker
-------------------------------------------------------------------------
updating "swift:amazonlinux2" docker image
  amazonlinux2: Pulling from library/swift
  Digest: sha256:0b645a7589aa5f1759f976c42a9ffba48fd930b27b3481b0ab32e271e701d444
  Status: Image is up to date for swift:amazonlinux2
  docker.io/library/swift:amazonlinux2
/usr/local/bin/docker run --rm -v /Users/stormacq/Documents/amazon/code/lambda/swift/swift-aws-lambda-runtime/Examples/LocalDebugging/MyLambda:/workspace -w /workspace swift:amazonlinux2 bash -cl swift build -c release --show-bin-path
  /workspace/.build/aarch64-unknown-linux-gnu/release
building "MyLambda"
/usr/local/bin/docker run --rm -v /Users/stormacq/Documents/amazon/code/lambda/swift/swift-aws-lambda-runtime/Examples/LocalDebugging/MyLambda:/workspace -w /workspace swift:amazonlinux2 bash -cl swift build -c release --product MyLambda --static-swift-stdlib
  error: the package at '/Shared' cannot be accessed (Error Domain=NSCocoaErrorDomain Code=260 "The file doesn’t exist.")
error: /usr/local/bin/docker run --rm -v /Users/stormacq/Documents/amazon/code/lambda/swift/swift-aws-lambda-runtime/Examples/LocalDebugging/MyLambda:/workspace -w /workspace swift:amazonlinux2 bash -cl swift build -c release --product MyLambda --static-swift-stdlib failed with code 1

Steps to reproduce

git clone https://github.com/swift-server/swift-aws-lambda-runtime.git
cd swift-aws-lambda-runtime/Examples/LocalDebugging
swift package --disable-sandbox archive --verbose 1

If possible, minimal yet complete reproducer code (or URL to code)

see main branch of repository

SwiftAWSLambdaRuntime version/commit hash

https://github.com/swift-server/swift-aws-lambda-runtime/tree/dc64ce195b1c51356f6655935c3509e296c35696

Swift & OS version (output of swift --version && uname -a)

✗ swift --version && uname -a
swift-driver version: 1.62.15 Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51)
Target: arm64-apple-macosx13.0
Darwin bcd07458a91c 22.1.0 Darwin Kernel Version 22.1.0: Sun Oct  9 20:15:09 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T6000 arm64
sebsto commented 1 year ago

One solution that worked for me is to consider both MyLambda and Shared as one package, i.e.

import PackageDescription

let package = Package(
    name: "MyLambda",
    platforms: [
        .macOS(.v12),
    ],
    products: [
        .executable(name: "MyLambda", targets: ["MyLambda"]),
        .library(name: "Shared", targets: ["Shared"]),
    ],
    dependencies: [
        // this is the dependency on the swift-aws-lambda-runtime library
        // in real-world projects this would say
        .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", branch: "main"),
//        .package(name: "swift-aws-lambda-runtime", path: "../../.."),
    ],
    targets: [
        .executableTarget(
            name: "MyLambda",
            dependencies: [
                .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
                .byName(name: "Shared"),
            ],
            path: "./MyLambda",
            exclude: ["scripts/", "Dockerfile"]
        ),
        .target(name: "Shared", 
                dependencies: [],
                path: "./Shared") 
    ]
)

That allows to build and archive the Shared library and the MyLambda lambda function.

➜  LocalDebugging git:(master) ✗ swift build
warning: 'localdebugging': found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target
    /Users/stormacq/Documents/amazon/code/lambda/swift/swift-aws-lambda-runtime/Examples/LocalDebugging/Shared/Package.swift.ignore

warning: 'localdebugging': found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target
    /Users/stormacq/Documents/amazon/code/lambda/swift/swift-aws-lambda-runtime/Examples/LocalDebugging/MyLambda/Package.swift.ignore

[1/1] Planning buildCompiling plugin AWSLambdaPackager...
Building for debugging...
Build complete! (0.30s)
➜  LocalDebugging git:(master) ✗ 
➜  LocalDebugging git:(master) ✗ swift package --disable-sandbox archive --verbose 1 --output-path dist 
-------------------------------------------------------------------------
configuration
-------------------------------------------------------------------------
{
  outputDirectory: dist
  products: ["MyLambda"]
  buildConfiguration: release
  baseDockerImage: swift:amazonlinux2
}
-------------------------------------------------------------------------
building "localdebugging" in docker
-------------------------------------------------------------------------
updating "swift:amazonlinux2" docker image
  amazonlinux2: Pulling from library/swift
  Digest: sha256:0b645a7589aa5f1759f976c42a9ffba48fd930b27b3481b0ab32e271e701d444
  Status: Image is up to date for swift:amazonlinux2
  docker.io/library/swift:amazonlinux2
/usr/local/bin/docker run --rm -v /Users/stormacq/Documents/amazon/code/lambda/swift/swift-aws-lambda-runtime/Examples/LocalDebugging:/workspace -w /workspace swift:amazonlinux2 bash -cl swift build -c release --show-bin-path
  /workspace/.build/aarch64-unknown-linux-gnu/release
building "MyLambda"
/usr/local/bin/docker run --rm -v /Users/stormacq/Documents/amazon/code/lambda/swift/swift-aws-lambda-runtime/Examples/LocalDebugging:/workspace -w /workspace swift:amazonlinux2 bash -cl swift build -c release --product MyLambda --static-swift-stdlib
  warning: 'workspace': found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target
    /workspace/Shared/Package.swift.ignore

warning: 'workspace': found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target
    /workspace/MyLambda/Package.swift.ignore
  [0/1] Planning build
  Building for production...
  Build complete! (2.00s)
-------------------------------------------------------------------------
archiving "MyLambda"
-------------------------------------------------------------------------
/usr/bin/zip --junk-paths --symlinks dist/MyLambda/MyLambda.zip dist/MyLambda/MyLambda dist/MyLambda/bootstrap
    adding: MyLambda
   (deflated 66%)
  adding: bootstrap
   (stored 0%)
1 archive created
  * MyLambda at dist/MyLambda/MyLambda.zip
tomerd commented 1 year ago

interesting issue. the archive plugin assumes the lambda is self contained and no external file system dependencies outside the package directory. in concept, the command should be invoked from Examples/LocalDebugging/MyLambda and not the root of the example Examples/LocalDebugging, but as mentioned above the docker bind mount will not "see" the shared module. this requires more thinking. I think re-arranging the example as suggested defeats the idea of having a shared module across the lambda and iOS app?

sebsto commented 1 year ago

Thank you Tom. Looks like the old debate about mono vs. multi repositories.

I re-arranged the package structure to share the same Package.swift for the targets MyLambda and Shared. This allows the plugin to build and archive MyLamba. At the same time, I also made minimum changes to the Xcode workspace to continue to be able to build and debug from Xcode.

That way, the iOS app still depends on the Swift package. However, with this approach, Xcode sees both MyLambda and Shared. This structure kind off transfers "ownership" of the shared library to the "MyLambda" project. It will not work in larger teams where three different teams would maintain these three artifacts.

Project now builds with swift build It runs with export LOCAL_LAMBDA_SERVER_ENABLED=true && swift run MyLambda. It packages with swift package --disable-sandbox archive It runs by selecting the MyLambda target in Xcode It runs by selecting the MyApp target in Xcode

Agree with you that more thinking or feedback is required on that one.