diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8850aaddc7..76c6ba8fca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: ci +name: CI on: push: @@ -9,54 +9,10 @@ on: pull_request: jobs: - dist: - name: distribution packages - timeout-minutes: 10 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 - - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - run: | - pip install virtualenv - make aws-lambda-layer-build - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: | - dist/* - dist-serverless/* - - docs: - timeout-minutes: 10 - name: build documentation - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 - - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - - run: | - pip install virtualenv - make apidocs - cd docs/_build && zip -r gh-pages ./ - - - uses: actions/upload-artifact@v2 - with: - name: ${{ github.sha }} - path: docs/_build/gh-pages.zip - lint: - timeout-minutes: 10 + name: Lint Sources runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v2 @@ -69,9 +25,10 @@ jobs: tox -e linters test: - continue-on-error: true - timeout-minutes: 45 + name: Run Tests runs-on: ${{ matrix.linux-version }} + timeout-minutes: 45 + continue-on-error: true strategy: matrix: linux-version: [ubuntu-latest] @@ -125,7 +82,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: setup + - name: Setup Test Env env: PGHOST: localhost PGPASSWORD: sentry @@ -134,7 +91,7 @@ jobs: psql -c 'create database test_travis_ci_test;' -U postgres pip install codecov tox - - name: run tests + - name: Run Tests env: CI_PYTHON_VERSION: ${{ matrix.python-version }} timeout-minutes: 45 @@ -144,3 +101,64 @@ jobs: coverage combine .coverage* coverage xml -i codecov --file coverage.xml + + dist: + name: Build AWS Lambda Layer + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + - uses: actions/setup-python@v2 + with: + python-version: 3.9 + + - run: | + echo "Creating directory containing Python SDK Lambda Layer" + pip install virtualenv + make aws-lambda-layer + + echo "Saving SDK_VERSION for later" + export SDK_VERSION=$(grep "VERSION = " sentry_sdk/consts.py | cut -f3 -d' ' | tr -d '"') + echo "SDK_VERSION=$SDK_VERSION" + echo "SDK_VERSION=$SDK_VERSION" >> $GITHUB_ENV + + - uses: actions/upload-artifact@v3 + with: + name: ${{ github.sha }} + path: | + dist-serverless/* + + - uses: getsentry/action-build-aws-lambda-extension@v1 + with: + artifact_name: ${{ github.sha }} + zip_file_name: sentry-python-serverless-${{ env.SDK_VERSION }}.zip + + - name: Upload Zip + uses: actions/upload-artifact@v3 + with: + name: ${{ github.sha }} + path: sentry-python-serverless-${{ env.SDK_VERSION }}.zip + + docs: + name: Build SDK API Doc + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + - uses: actions/setup-python@v2 + with: + python-version: 3.9 + + - run: | + pip install virtualenv + make apidocs + cd docs/_build && zip -r gh-pages ./ + + - uses: actions/upload-artifact@v2 + with: + name: ${{ github.sha }} + path: docs/_build/gh-pages.zip diff --git a/Makefile b/Makefile index 577dd58740..bf13e1117c 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ help: @echo "make test: Run basic tests (not testing most integrations)" @echo "make test-all: Run ALL tests (slow, closest to CI)" @echo "make format: Run code formatters (destructive)" - @echo "make aws-lambda-layer-build: Build serverless ZIP dist package" + @echo "make aws-lambda-layer: Build AWS Lambda layer directory for serverless integration" @echo @echo "Also make sure to read ./CONTRIBUTING.md" @false @@ -19,9 +19,8 @@ help: $(VENV_PATH)/bin/pip install tox dist: .venv - rm -rf dist build + rm -rf dist dist-serverless build $(VENV_PATH)/bin/python setup.py sdist bdist_wheel - .PHONY: dist format: .venv @@ -46,7 +45,6 @@ lint: .venv echo "Bad formatting? Run: make format"; \ echo "================================"; \ false) - .PHONY: lint apidocs: .venv @@ -60,8 +58,8 @@ apidocs-hotfix: apidocs @$(VENV_PATH)/bin/ghp-import -pf docs/_build .PHONY: apidocs-hotfix -aws-lambda-layer-build: dist +aws-lambda-layer: dist $(VENV_PATH)/bin/pip install urllib3 $(VENV_PATH)/bin/pip install certifi - $(VENV_PATH)/bin/python -m scripts.build_awslambda_layer -.PHONY: aws-lambda-layer-build + $(VENV_PATH)/bin/python -m scripts.build_aws_lambda_layer +.PHONY: aws-lambda-layer diff --git a/scripts/build_aws_lambda_layer.py b/scripts/build_aws_lambda_layer.py new file mode 100644 index 0000000000..d694d15ba7 --- /dev/null +++ b/scripts/build_aws_lambda_layer.py @@ -0,0 +1,72 @@ +import os +import shutil +import subprocess +import tempfile + +from sentry_sdk.consts import VERSION as SDK_VERSION + +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 + ): + # type: (...) -> None + self.base_dir = base_dir + self.python_site_packages = os.path.join(self.base_dir, PYTHON_SITE_PACKAGES) + + def make_directories(self): + # type: (...) -> None + os.makedirs(self.python_site_packages) + + def install_python_packages(self): + # type: (...) -> None + 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-lamber-layer" + ) + subprocess.run( + [ + "pip", + "install", + "--no-cache-dir", # always access PyPI + "--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 build_layer_dir(): + with tempfile.TemporaryDirectory() as base_dir: + layer_builder = LayerBuilder(base_dir) + layer_builder.make_directories() + layer_builder.install_python_packages() + layer_builder.create_init_serverless_sdk_package() + + shutil.copytree(base_dir, "dist-serverless") + + +if __name__ == "__main__": + build_layer_dir() diff --git a/scripts/build_awslambda_layer.py b/scripts/build_awslambda_layer.py deleted file mode 100644 index 1fda06e79f..0000000000 --- a/scripts/build_awslambda_layer.py +++ /dev/null @@ -1,117 +0,0 @@ -import os -import subprocess -import tempfile -import shutil - -from sentry_sdk.consts import VERSION as SDK_VERSION -from sentry_sdk._types import MYPY - -if MYPY: - from typing import Union - - -class PackageBuilder: - def __init__( - self, - base_dir, # type: str - pkg_parent_dir, # type: str - dist_rel_path, # type: str - ): - # type: (...) -> None - self.base_dir = base_dir - self.pkg_parent_dir = pkg_parent_dir - self.dist_rel_path = dist_rel_path - self.packages_dir = self.get_relative_path_of(pkg_parent_dir) - - def make_directories(self): - # type: (...) -> None - os.makedirs(self.packages_dir) - - def install_python_binaries(self): - # type: (...) -> None - wheels_filepath = os.path.join( - self.dist_rel_path, f"sentry_sdk-{SDK_VERSION}-py2.py3-none-any.whl" - ) - subprocess.run( - [ - "pip", - "install", - "--no-cache-dir", # Disables the cache -> always accesses PyPI - "-q", # Quiet - wheels_filepath, # Copied to the target directory before installation - "-t", # Target directory flag - self.packages_dir, - ], - 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.packages_dir}/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, filename # type: str - ): - # type: (...) -> None - subprocess.run( - [ - "zip", - "-q", # Quiet - "-x", # Exclude files - "**/__pycache__/*", # Files to be excluded - "-r", # Recurse paths - filename, # Output filename - self.pkg_parent_dir, # Files to be zipped - ], - cwd=self.base_dir, - check=True, # Raises CalledProcessError if exit status is non-zero - ) - - def get_relative_path_of( - self, subfile # type: str - ): - # type: (...) -> str - return os.path.join(self.base_dir, subfile) - - -# Ref to `pkg_parent_dir` Top directory in the ZIP file. -# Placing the Sentry package in `/python` avoids -# creating a directory for a specific version. For more information, see -# https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-path -def build_packaged_zip( - dist_rel_path="dist", # type: str - dest_zip_filename=f"sentry-python-serverless-{SDK_VERSION}.zip", # type: str - pkg_parent_dir="python", # type: str - dest_abs_path=None, # type: Union[str, None] -): - # type: (...) -> None - if dest_abs_path is None: - dest_abs_path = os.path.abspath( - os.path.join(os.path.dirname(__file__), "..", dist_rel_path) - ) - with tempfile.TemporaryDirectory() as tmp_dir: - package_builder = PackageBuilder(tmp_dir, pkg_parent_dir, dist_rel_path) - package_builder.make_directories() - package_builder.install_python_binaries() - package_builder.create_init_serverless_sdk_package() - package_builder.zip(dest_zip_filename) - if not os.path.exists(dist_rel_path): - os.makedirs(dist_rel_path) - shutil.copy( - package_builder.get_relative_path_of(dest_zip_filename), dest_abs_path - ) - - -if __name__ == "__main__": - build_packaged_zip() diff --git a/tests/integrations/aws_lambda/client.py b/tests/integrations/aws_lambda/client.py index 784a4a9006..d8e430f3d7 100644 --- a/tests/integrations/aws_lambda/client.py +++ b/tests/integrations/aws_lambda/client.py @@ -25,11 +25,9 @@ def build_no_code_serverless_function_and_layer( sdk by creating a layer containing the Python-sdk, and then creating a func that uses that layer """ - from scripts.build_awslambda_layer import ( - build_packaged_zip, - ) + from scripts.build_aws_lambda_layer import build_layer_dir - build_packaged_zip(dest_abs_path=tmpdir, dest_zip_filename="serverless-ball.zip") + build_layer_dir(dest_abs_path=tmpdir) with open(os.path.join(tmpdir, "serverless-ball.zip"), "rb") as serverless_zip: response = client.publish_layer_version(