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

[Feature request] Generate AWS lambda zips using uv build #9350

Open
kishaningithub opened this issue Nov 22, 2024 · 12 comments
Open

[Feature request] Generate AWS lambda zips using uv build #9350

kishaningithub opened this issue Nov 22, 2024 · 12 comments
Labels
enhancement New feature or improvement to existing functionality needs-design Needs discussion, investigation, or design

Comments

@kishaningithub
Copy link

Generating python lambda zips is a cumbersome process. It would be great if uv build can have the ability to generate AWS Lambda zip files which can be used to create lambda function in AWS.

AWS Documentation Link: https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-create-dependencies

@samypr100
Copy link
Collaborator

Could you expand on how are you currently using uv to generate these?

@kishaningithub
Copy link
Author

kishaningithub commented Nov 23, 2024

My shell script does the following

  • Use uv to build wheel file

  • Extract the wheel file

  • Copy contents of the wheel into a directory

  • Copy Install project runtime dependencies into the same directory using pip install --target

  • Zip the directory

  • Upload the zip to AWS

@samypr100
Copy link
Collaborator

Is there a reason you wouldn't be able to use --target like the AWS lambda guide says? I'm trying to understand if there's a compatibility gap with what pip enables you to do.

@kishaningithub
Copy link
Author

The 4th point of copying runtime dependencies is exactly a pip install --target. I guess "installing" would have been a better word than "copying".. will update the above

@samypr100 samypr100 added the enhancement New feature or improvement to existing functionality label Nov 24, 2024
@zanieb
Copy link
Member

zanieb commented Nov 26, 2024

At the very least it'd be nice to include some documentation for this process.

I'm not sure how we'd expose this if we did. An alternative uv build output format?

@zanieb zanieb added the needs-design Needs discussion, investigation, or design label Nov 26, 2024
@doron98
Copy link

doron98 commented Nov 27, 2024

What is tricky is including path dependencies sst/sst#5132

@kishaningithub
Copy link
Author

@zanieb In my mind it was an alternative uv build output format

@williamrjribeiro
Copy link

Hi @kishaningithub , I'm struggling with this issue as well. Can you share your shell script please?

@kishaningithub
Copy link
Author

@williamrjribeiro The script i am using is basically the same as the in the AWS documentation. Can you let know the issue you are facing?

@toddlers
Copy link

here is something worked out for me @williamrjribeiro , I didn't try to use pip, because that's what I am running away from.

#!/usr/bin/env bash

# Exit immediately if a command exits with a non-zero status
set -e

# Step 1: Clean up old builds
echo "Cleaning up old builds..."
rm -rf build dist lambda_package lambda_function.zip

# Step 2: Verify the virtual environment exists
if [ ! -d ".venv" ]; then
    echo "Error: Virtual environment '.venv' not found!"
    exit 1
fi

# Step 4: Build the wheel file using `uv`
echo "Building the wheel package..."
uv build --wheel


# Step 3: Use `uv run` to determine the Python version
echo "Detecting Python version..."
PYTHON_VERSION=$(echo "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"|uv run -)
if [ -z "$PYTHON_VERSION" ]; then
    echo "Error: Could not determine Python version!"
    exit 1
fi
echo "Detected Python version: $PYTHON_VERSION"


# Step 4: Locate site-packages directory
VENV_SITE_PACKAGES=".venv/lib/python$PYTHON_VERSION/site-packages"
if [ ! -d "$VENV_SITE_PACKAGES" ]; then
    echo "Error: Could not locate site-packages in the virtual environment at $VENV_SITE_PACKAGES!"
    exit 1
fi


# Step 5: Extract the wheel file
echo "Extracting the wheel file..."
WHEEL_FILE=$(ls dist/*.whl | head -n 1)  # Get the first wheel file
if [ -z "$WHEEL_FILE" ]; then
    echo "Error: No wheel file found in 'dist/' directory!"
    exit 1
fi
mkdir -p lambda_package
unzip -q "$WHEEL_FILE" -d lambda_package

# Step 6: Copy dependencies from the virtual environment
echo "Copying dependencies from virtual environment..."
cp -r "$VENV_SITE_PACKAGES/"* lambda_package/

# Step 7: Package the Lambda deployment
echo "Packaging Lambda deployment..."
cd lambda_package

# here using -u option helped me and it speed up the zip creation too
# Replace (update) an existing entry in the zip archive only if it has been 
# modified more recently than the version already in the zip archive

zip -qr ../lambda_function.zip .
cd ..

echo "Lambda deployment package created successfully: lambda_function.zip"

# Step 8: Upload to AWS Lambda
LAMBDA_FUNCTION_NAME="delete_me"  # Replace with your Lambda function name
echo "Uploading to AWS Lambda: $LAMBDA_FUNCTION_NAME"
aws lambda update-function-code --function-name "$LAMBDA_FUNCTION_NAME" --zip-file fileb://lambda_function.zip

echo "Deployment complete!"

@williamrjribeiro
Copy link

@toddlers Thank you for the script! 🙏

I'm using SST+Pulumi to deploy my little Python script to a lambda function. The lambda fails when it runs with error [ERROR] Runtime.ImportModuleError: Unable to import module 'main': No module named 'main' Traceback (most recent call last):

Here's my pyporject.toml:

[project]
name = "poc-events_python-consumer"
version = "0.0.0"

dependencies = [
    "sst",
    "pydantic>=2.10.2",
    "cloudevents[pydantic]",
]

requires-python = "~=3.12"

[tool.uv.pip]
no-strip-extras = true

[tool.uv.sources]
sst = { git = "https://github.com/sst/sst.git", subdirectory = "sdk/python", branch = "dev" }
cloudevents = { git = "https://github.com/cloudevents/sdk-python.git", branch = "main" }

[tool.setuptools]
py-modules = []

[project.scripts]
handler = "lambda:handler"

The script path is python-consumer/src/lambda/__init__.py which has the def handler function.

This is how the lambda function is created with Pulumi:

const pythonConsumer = new aws.lambda.Function("PocEventPythonConsumer", {
      role: lambdaRole.arn,
      runtime: "python3.12",
      handler: "lambda.handler",
      code: $asset("packages/python-consumer/lambda_package/"),
    });

Maybe I should just wait for sst/sst#5132 to be merged and released.

@kucharzyk-sebastian
Copy link

In case anyone is looking for a solution using Python, UV, and AWS CDK, it seems they're going to support it in #31238

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or improvement to existing functionality needs-design Needs discussion, investigation, or design
Projects
None yet
Development

No branches or pull requests

7 participants