File: build_aws_lambda_layer.py

package info (click to toggle)
sentry-python 2.18.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,004 kB
  • sloc: python: 55,908; makefile: 114; sh: 111; xml: 2
file content (140 lines) | stat: -rw-r--r-- 4,709 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import os
import shutil
import subprocess
import sys
import tempfile
from typing import TYPE_CHECKING

from sentry_sdk.consts import VERSION as SDK_VERSION

if TYPE_CHECKING:
    from typing import Optional

DIST_PATH = "dist"  # created by "make dist" that is called by "make aws-lambda-layer"
PYTHON_SITE_PACKAGES = "python"  # see https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-path


class LayerBuilder:
    def __init__(
        self,
        base_dir,  # type: str
        out_zip_filename=None,  # type: Optional[str]
    ):
        # type: (...) -> None
        self.base_dir = base_dir
        self.python_site_packages = os.path.join(self.base_dir, PYTHON_SITE_PACKAGES)
        self.out_zip_filename = (
            f"sentry-python-serverless-{SDK_VERSION}.zip"
            if out_zip_filename is None
            else out_zip_filename
        )

    def make_directories(self):
        # type: (...) -> None
        os.makedirs(self.python_site_packages)

    def install_python_packages(self):
        # type: (...) -> None
        # Install requirements for Lambda Layer (these are more limited than the SDK requirements,
        # because Lambda does not support the newest versions of some packages)
        subprocess.check_call(
            [
                sys.executable,
                "-m",
                "pip",
                "install",
                "-r",
                "requirements-aws-lambda-layer.txt",
                "--target",
                self.python_site_packages,
            ],
        )

        sentry_python_sdk = os.path.join(
            DIST_PATH,
            f"sentry_sdk-{SDK_VERSION}-py2.py3-none-any.whl",  # this is generated by "make dist" that is called by "make aws-lambda-layer"
        )
        subprocess.run(
            [
                "pip",
                "install",
                "--no-cache-dir",  # always access PyPI
                "--no-deps",  # the right depencencies have been installed in the call above
                "--quiet",
                sentry_python_sdk,
                "--target",
                self.python_site_packages,
            ],
            check=True,
        )

    def create_init_serverless_sdk_package(self):
        # type: (...) -> None
        """
        Method that creates the init_serverless_sdk pkg in the
        sentry-python-serverless zip
        """
        serverless_sdk_path = (
            f"{self.python_site_packages}/sentry_sdk/"
            f"integrations/init_serverless_sdk"
        )
        if not os.path.exists(serverless_sdk_path):
            os.makedirs(serverless_sdk_path)
        shutil.copy(
            "scripts/init_serverless_sdk.py", f"{serverless_sdk_path}/__init__.py"
        )

    def zip(self):
        # type: (...) -> None
        subprocess.run(
            [
                "zip",
                "-q",  # Quiet
                "-x",  # Exclude files
                "**/__pycache__/*",  # Files to be excluded
                "-r",  # Recurse paths
                self.out_zip_filename,  # Output filename
                PYTHON_SITE_PACKAGES,  # Files to be zipped
            ],
            cwd=self.base_dir,
            check=True,  # Raises CalledProcessError if exit status is non-zero
        )

        shutil.copy(
            os.path.join(self.base_dir, self.out_zip_filename),
            os.path.abspath(DIST_PATH),
        )


def build_packaged_zip(base_dir=None, make_dist=False, out_zip_filename=None):
    if base_dir is None:
        base_dir = tempfile.mkdtemp()

    if make_dist:
        # Same thing that is done by "make dist"
        # (which is a dependency of "make aws-lambda-layer")
        subprocess.check_call(
            [sys.executable, "setup.py", "sdist", "bdist_wheel", "-d", DIST_PATH],
        )

    layer_builder = LayerBuilder(base_dir, out_zip_filename=out_zip_filename)
    layer_builder.make_directories()
    layer_builder.install_python_packages()
    layer_builder.create_init_serverless_sdk_package()
    layer_builder.zip()

    # Just for debugging
    dist_path = os.path.abspath(DIST_PATH)
    print("Created Lambda Layer package with this information:")
    print(" - Base directory for generating package: {}".format(layer_builder.base_dir))
    print(
        " - Created Python SDK distribution (in `{}`): {}".format(dist_path, make_dist)
    )
    if not make_dist:
        print("    If 'False' we assume it was already created (by 'make dist')")
    print(" - Package zip filename: {}".format(layer_builder.out_zip_filename))
    print(" - Copied package zip to: {}".format(dist_path))


if __name__ == "__main__":
    build_packaged_zip()