From 0f9272f744f435bcbc1543f0851a8c0a39f51d28 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 14:15:15 +0200 Subject: [PATCH 01/73] chore(ci): layer docs update (#2619) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 27 +++--- docs/index.md | 128 ++++++++++++++--------------- examples/logger/sam/template.yaml | 2 +- examples/metrics/sam/template.yaml | 2 +- examples/tracer/sam/template.yaml | 2 +- 5 files changed, 83 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4dac62493a..18b751450f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ # Unreleased + + +## [v2.19.0] - 2023-06-30 ## Bug Fixes * **e2e:** fix idempotency tests ([#2576](https://github.com/aws-powertools/powertools-lambda-python/issues/2576)) @@ -26,26 +29,27 @@ ## Maintenance +* version bump * **analytics:** update docs base origin url ([#2560](https://github.com/aws-powertools/powertools-lambda-python/issues/2560)) * **ci:** replace flake8 with Ruff as a linter ([#2495](https://github.com/aws-powertools/powertools-lambda-python/issues/2495)) * **ci:** enable Ruff rule E501 and fix errors ([#2587](https://github.com/aws-powertools/powertools-lambda-python/issues/2587)) -* **ci:** enable Ruff rule ERA001 and fix errors ([#2591](https://github.com/aws-powertools/powertools-lambda-python/issues/2591)) -* **ci:** enable Ruff autofix rules ([#2599](https://github.com/aws-powertools/powertools-lambda-python/issues/2599)) -* **ci:** enable Ruff rules ISC, I001, B018 and fix the errors ([#2597](https://github.com/aws-powertools/powertools-lambda-python/issues/2597)) * **ci:** enable Ruff rule COM812 and fix the errors ([#2595](https://github.com/aws-powertools/powertools-lambda-python/issues/2595)) * **ci:** enable Ruff rules PLW, PLR, PLC and PLE and fix the errors ([#2593](https://github.com/aws-powertools/powertools-lambda-python/issues/2593)) -* **deps:** bump release-drafter/release-drafter from 5.23.0 to 5.24.0 ([#2603](https://github.com/aws-powertools/powertools-lambda-python/issues/2603)) +* **ci:** enable Ruff autofix rules ([#2599](https://github.com/aws-powertools/powertools-lambda-python/issues/2599)) +* **ci:** enable Ruff rules ISC, I001, B018 and fix the errors ([#2597](https://github.com/aws-powertools/powertools-lambda-python/issues/2597)) +* **ci:** enable Ruff rule ERA001 and fix errors ([#2591](https://github.com/aws-powertools/powertools-lambda-python/issues/2591)) +* **deps:** bump pypa/gh-action-pypi-publish from 1.8.6 to 1.8.7 ([#2573](https://github.com/aws-powertools/powertools-lambda-python/issues/2573)) * **deps:** bump docker/setup-buildx-action from 2.7.0 to 2.8.0 ([#2604](https://github.com/aws-powertools/powertools-lambda-python/issues/2604)) * **deps:** bump ossf/scorecard-action from 2.1.3 to 2.2.0 ([#2563](https://github.com/aws-powertools/powertools-lambda-python/issues/2563)) -* **deps:** bump pypa/gh-action-pypi-publish from 1.8.6 to 1.8.7 ([#2573](https://github.com/aws-powertools/powertools-lambda-python/issues/2573)) -* **deps-dev:** bump ruff from 0.0.272 to 0.0.275 ([#2586](https://github.com/aws-powertools/powertools-lambda-python/issues/2586)) -* **deps-dev:** bump mypy from 1.4.0 to 1.4.1 ([#2574](https://github.com/aws-powertools/powertools-lambda-python/issues/2574)) -* **deps-dev:** bump mkdocs-material from 9.1.16 to 9.1.17 ([#2564](https://github.com/aws-powertools/powertools-lambda-python/issues/2564)) -* **deps-dev:** bump mypy-boto3-lambda from 1.26.157 to 1.26.163 ([#2607](https://github.com/aws-powertools/powertools-lambda-python/issues/2607)) +* **deps:** bump release-drafter/release-drafter from 5.23.0 to 5.24.0 ([#2603](https://github.com/aws-powertools/powertools-lambda-python/issues/2603)) * **deps-dev:** bump mypy-boto3-s3 from 1.26.155 to 1.26.163 ([#2608](https://github.com/aws-powertools/powertools-lambda-python/issues/2608)) -* **deps-dev:** bump pytest from 7.3.2 to 7.4.0 ([#2557](https://github.com/aws-powertools/powertools-lambda-python/issues/2557)) +* **deps-dev:** bump mypy-boto3-lambda from 1.26.157 to 1.26.163 ([#2607](https://github.com/aws-powertools/powertools-lambda-python/issues/2607)) +* **deps-dev:** bump mkdocs-material from 9.1.16 to 9.1.17 ([#2564](https://github.com/aws-powertools/powertools-lambda-python/issues/2564)) +* **deps-dev:** bump ruff from 0.0.272 to 0.0.275 ([#2586](https://github.com/aws-powertools/powertools-lambda-python/issues/2586)) * **deps-dev:** bump mypy-boto3-ssm from 1.26.97 to 1.26.162 ([#2606](https://github.com/aws-powertools/powertools-lambda-python/issues/2606)) +* **deps-dev:** bump pytest from 7.3.2 to 7.4.0 ([#2557](https://github.com/aws-powertools/powertools-lambda-python/issues/2557)) * **deps-dev:** bump aws-cdk from 2.85.0 to 2.86.0 ([#2613](https://github.com/aws-powertools/powertools-lambda-python/issues/2613)) +* **deps-dev:** bump mypy from 1.4.0 to 1.4.1 ([#2574](https://github.com/aws-powertools/powertools-lambda-python/issues/2574)) @@ -3458,7 +3462,8 @@ * Merge pull request [#5](https://github.com/aws-powertools/powertools-lambda-python/issues/5) from jfuss/feat/python38 -[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.18.0...HEAD +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.19.0...HEAD +[v2.19.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.18.0...v2.19.0 [v2.18.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.17.0...v2.18.0 [v2.17.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.16.2...v2.17.0 [v2.16.2]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.16.1...v2.16.2 diff --git a/docs/index.md b/docs/index.md index 9e7d54ac71f..939a2da9c29 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,8 +26,8 @@ Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverles You can install Powertools for AWS Lambda (Python) using one of the following options: -* **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:36**](#){: .copyMe}:clipboard: -* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36**](#){: .copyMe}:clipboard: +* **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37**](#){: .copyMe}:clipboard: +* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37**](#){: .copyMe}:clipboard: * **Pip**: **[`pip install "aws-lambda-powertools"`](#){: .copyMe}:clipboard:** ??? question "Using Pip? You might need to install additional dependencies." @@ -78,60 +78,60 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd | Region | Layer ARN | | ---------------- | ---------------------------------------------------------------------------------------------------------- | - | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-south-2` | [arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ap-southeast-4` | [arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `eu-central-2` | [arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `eu-south-2` | [arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `me-central-1` | [arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:36](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-south-2` | [arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ap-southeast-4` | [arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `eu-central-2` | [arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `eu-south-2` | [arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `me-central-1` | [arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:37](#){: .copyMe}:clipboard: | === "arm64" | Region | Layer ARN | | ---------------- | ---------------------------------------------------------------------------------------------------------------- | - | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37](#){: .copyMe}:clipboard: | ??? note "Note: Click to expand and copy code snippets for popular frameworks" @@ -144,7 +144,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd Type: AWS::Serverless::Function Properties: Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37 ``` === "Serverless framework" @@ -154,7 +154,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd hello: handler: lambda_function.lambda_handler layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:36 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37 ``` === "CDK" @@ -170,7 +170,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:36" + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37" ) aws_lambda.Function(self, 'sample-app-lambda', @@ -219,7 +219,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:36"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } @@ -272,7 +272,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37 ❯ amplify push -y @@ -283,7 +283,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:36 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:37 ? Do you want to edit the local lambda function now? No ``` @@ -297,7 +297,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd Properties: Architectures: [arm64] Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37 ``` === "Serverless framework" @@ -308,7 +308,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37 ``` === "CDK" @@ -324,7 +324,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36" + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37" ) aws_lambda.Function(self, 'sample-app-lambda', @@ -374,7 +374,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37"] architectures = ["arm64"] source_code_hash = filebase64sha256("lambda_function_payload.zip") @@ -430,7 +430,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37 ❯ amplify push -y @@ -441,7 +441,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:36 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37 ? Do you want to edit the local lambda function now? No ``` @@ -449,7 +449,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd Change {region} to your AWS region, e.g. `eu-west-1` ```bash title="AWS CLI" - aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:36 --region {region} + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37 --region {region} ``` The pre-signed URL to download this Lambda Layer will be within `Location` key. diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index 841b53ef7c0..2472b332651 100644 --- a/examples/logger/sam/template.yaml +++ b/examples/logger/sam/template.yaml @@ -14,7 +14,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37 Resources: LoggerLambdaHandlerExample: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index b26f56d2ce7..c49b9e0f733 100644 --- a/examples/metrics/sam/template.yaml +++ b/examples/metrics/sam/template.yaml @@ -15,7 +15,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37 Resources: CaptureLambdaHandlerExample: diff --git a/examples/tracer/sam/template.yaml b/examples/tracer/sam/template.yaml index fcc5740f1eb..6cc811d1b2a 100644 --- a/examples/tracer/sam/template.yaml +++ b/examples/tracer/sam/template.yaml @@ -13,7 +13,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:36 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37 Resources: CaptureLambdaHandlerExample: From c6dfd48e678590822f1c44fb0708aeabd9a96b5c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 14:15:32 +0200 Subject: [PATCH 02/73] chore(ci): bump version to 2.19.0 (#2618) Co-authored-by: Powertools for AWS Lambda (Python) bot --- aws_lambda_powertools/shared/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/version.py b/aws_lambda_powertools/shared/version.py index fe65542b043..24ce0f2fd70 100644 --- a/aws_lambda_powertools/shared/version.py +++ b/aws_lambda_powertools/shared/version.py @@ -1,3 +1,3 @@ """Exposes version constant to avoid circular dependencies.""" -VERSION = "2.18.0" +VERSION = "2.19.0" diff --git a/pyproject.toml b/pyproject.toml index 34b102b24e4..e01dd94c976 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "2.18.0" +version = "2.19.0" description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"] From a6f6f931985eb3ba066f95025f4ae699bbf0a1b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 14:29:11 +0200 Subject: [PATCH 03/73] chore(deps-dev): bump mypy-boto3-dynamodb from 1.26.158 to 1.26.164 (#2622) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7aa76f16be9..0b6133d868d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1484,13 +1484,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-dynamodb" -version = "1.26.158" -description = "Type annotations for boto3.DynamoDB 1.26.158 service generated with mypy-boto3-builder 7.14.5" +version = "1.26.164" +description = "Type annotations for boto3.DynamoDB 1.26.164 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-dynamodb-1.26.158.tar.gz", hash = "sha256:cbce7bd1c12a3d7ac15cb33690d14e9ca0591b57936bf3ad47562105280e1356"}, - {file = "mypy_boto3_dynamodb-1.26.158-py3-none-any.whl", hash = "sha256:9cecd3d3328f0ab7382a4517b0bc533d565c251d39467c086ae41700588c950e"}, + {file = "mypy-boto3-dynamodb-1.26.164.tar.gz", hash = "sha256:5a832531ac2c81b01dea20ef79f7dd5a2014c3736566a498585f5f46d642adc4"}, + {file = "mypy_boto3_dynamodb-1.26.164-py3-none-any.whl", hash = "sha256:a527270b304f1a517093fff3709c7831fc5616a91bb1c9b6164fa71e37481d84"}, ] [package.dependencies] @@ -2745,4 +2745,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "62ecb7d9b450e2660cab635fbaeef83dbe84baf7b4edb93f927aff38f7298444" +content-hash = "906d8206a4d10f9ac939fbbac0e8427e41ee232dd006ce3043de8a5348fd9c11" diff --git a/pyproject.toml b/pyproject.toml index e01dd94c976..202b88de6d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ python-snappy = "^0.6.1" mypy-boto3-appconfig = "^1.26.71" mypy-boto3-cloudformation = "^1.26.156" mypy-boto3-cloudwatch = "^1.26.127" -mypy-boto3-dynamodb = "^1.26.158" +mypy-boto3-dynamodb = "^1.26.164" mypy-boto3-lambda = "^1.26.163" mypy-boto3-logs = "^1.26.149" mypy-boto3-secretsmanager = "^1.26.135" From 19f77760ad49e221505c6bc470397dc69f8b3677 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 14:36:56 +0200 Subject: [PATCH 04/73] chore(deps): bump pydantic from 1.10.9 to 1.10.10 (#2624) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 74 ++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0b6133d868d..4474ff229b4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1739,47 +1739,47 @@ files = [ [[package]] name = "pydantic" -version = "1.10.9" +version = "1.10.10" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e692dec4a40bfb40ca530e07805b1208c1de071a18d26af4a2a0d79015b352ca"}, - {file = "pydantic-1.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c52eb595db83e189419bf337b59154bdcca642ee4b2a09e5d7797e41ace783f"}, - {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:939328fd539b8d0edf244327398a667b6b140afd3bf7e347cf9813c736211896"}, - {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b48d3d634bca23b172f47f2335c617d3fcb4b3ba18481c96b7943a4c634f5c8d"}, - {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f0b7628fb8efe60fe66fd4adadd7ad2304014770cdc1f4934db41fe46cc8825f"}, - {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e1aa5c2410769ca28aa9a7841b80d9d9a1c5f223928ca8bec7e7c9a34d26b1d4"}, - {file = "pydantic-1.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:eec39224b2b2e861259d6f3c8b6290d4e0fbdce147adb797484a42278a1a486f"}, - {file = "pydantic-1.10.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d111a21bbbfd85c17248130deac02bbd9b5e20b303338e0dbe0faa78330e37e0"}, - {file = "pydantic-1.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e9aec8627a1a6823fc62fb96480abe3eb10168fd0d859ee3d3b395105ae19a7"}, - {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07293ab08e7b4d3c9d7de4949a0ea571f11e4557d19ea24dd3ae0c524c0c334d"}, - {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ee829b86ce984261d99ff2fd6e88f2230068d96c2a582f29583ed602ef3fc2c"}, - {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4b466a23009ff5cdd7076eb56aca537c745ca491293cc38e72bf1e0e00de5b91"}, - {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7847ca62e581e6088d9000f3c497267868ca2fa89432714e21a4fb33a04d52e8"}, - {file = "pydantic-1.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:7845b31959468bc5b78d7b95ec52fe5be32b55d0d09983a877cca6aedc51068f"}, - {file = "pydantic-1.10.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:517a681919bf880ce1dac7e5bc0c3af1e58ba118fd774da2ffcd93c5f96eaece"}, - {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67195274fd27780f15c4c372f4ba9a5c02dad6d50647b917b6a92bf00b3d301a"}, - {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2196c06484da2b3fded1ab6dbe182bdabeb09f6318b7fdc412609ee2b564c49a"}, - {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6257bb45ad78abacda13f15bde5886efd6bf549dd71085e64b8dcf9919c38b60"}, - {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3283b574b01e8dbc982080d8287c968489d25329a463b29a90d4157de4f2baaf"}, - {file = "pydantic-1.10.9-cp37-cp37m-win_amd64.whl", hash = "sha256:5f8bbaf4013b9a50e8100333cc4e3fa2f81214033e05ac5aa44fa24a98670a29"}, - {file = "pydantic-1.10.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9cd67fb763248cbe38f0593cd8611bfe4b8ad82acb3bdf2b0898c23415a1f82"}, - {file = "pydantic-1.10.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f50e1764ce9353be67267e7fd0da08349397c7db17a562ad036aa7c8f4adfdb6"}, - {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73ef93e5e1d3c8e83f1ff2e7fdd026d9e063c7e089394869a6e2985696693766"}, - {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:128d9453d92e6e81e881dd7e2484e08d8b164da5507f62d06ceecf84bf2e21d3"}, - {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ad428e92ab68798d9326bb3e5515bc927444a3d71a93b4a2ca02a8a5d795c572"}, - {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fab81a92f42d6d525dd47ced310b0c3e10c416bbfae5d59523e63ea22f82b31e"}, - {file = "pydantic-1.10.9-cp38-cp38-win_amd64.whl", hash = "sha256:963671eda0b6ba6926d8fc759e3e10335e1dc1b71ff2a43ed2efd6996634dafb"}, - {file = "pydantic-1.10.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:970b1bdc6243ef663ba5c7e36ac9ab1f2bfecb8ad297c9824b542d41a750b298"}, - {file = "pydantic-1.10.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7e1d5290044f620f80cf1c969c542a5468f3656de47b41aa78100c5baa2b8276"}, - {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83fcff3c7df7adff880622a98022626f4f6dbce6639a88a15a3ce0f96466cb60"}, - {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0da48717dc9495d3a8f215e0d012599db6b8092db02acac5e0d58a65248ec5bc"}, - {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0a2aabdc73c2a5960e87c3ffebca6ccde88665616d1fd6d3db3178ef427b267a"}, - {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9863b9420d99dfa9c064042304868e8ba08e89081428a1c471858aa2af6f57c4"}, - {file = "pydantic-1.10.9-cp39-cp39-win_amd64.whl", hash = "sha256:e7c9900b43ac14110efa977be3da28931ffc74c27e96ee89fbcaaf0b0fe338e1"}, - {file = "pydantic-1.10.9-py3-none-any.whl", hash = "sha256:6cafde02f6699ce4ff643417d1a9223716ec25e228ddc3b436fe7e2d25a1f305"}, - {file = "pydantic-1.10.9.tar.gz", hash = "sha256:95c70da2cd3b6ddf3b9645ecaa8d98f3d80c606624b6d245558d202cd23ea3be"}, + {file = "pydantic-1.10.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:adad1ee4ab9888f12dac2529276704e719efcf472e38df7813f5284db699b4ec"}, + {file = "pydantic-1.10.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a7db03339893feef2092ff7b1afc9497beed15ebd4af84c3042a74abce02d48"}, + {file = "pydantic-1.10.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b3714b97ff84b2689654851c2426389bcabfac9080617bcf4306c69db606f6"}, + {file = "pydantic-1.10.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edfdf0a5abc5c9bf2052ebaec20e67abd52e92d257e4f2d30e02c354ed3e6030"}, + {file = "pydantic-1.10.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20a3b30fd255eeeb63caa9483502ba96b7795ce5bf895c6a179b3d909d9f53a6"}, + {file = "pydantic-1.10.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db4c7f7e60ca6f7d6c1785070f3e5771fcb9b2d88546e334d2f2c3934d949028"}, + {file = "pydantic-1.10.10-cp310-cp310-win_amd64.whl", hash = "sha256:a2d5be50ac4a0976817144c7d653e34df2f9436d15555189f5b6f61161d64183"}, + {file = "pydantic-1.10.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:566a04ba755e8f701b074ffb134ddb4d429f75d5dced3fbd829a527aafe74c71"}, + {file = "pydantic-1.10.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f79db3652ed743309f116ba863dae0c974a41b688242482638b892246b7db21d"}, + {file = "pydantic-1.10.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c62376890b819bebe3c717a9ac841a532988372b7e600e76f75c9f7c128219d5"}, + {file = "pydantic-1.10.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4870f13a4fafd5bc3e93cff3169222534fad867918b188e83ee0496452978437"}, + {file = "pydantic-1.10.10-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:990027e77cda6072a566e433b6962ca3b96b4f3ae8bd54748e9d62a58284d9d7"}, + {file = "pydantic-1.10.10-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8c40964596809eb616d94f9c7944511f620a1103d63d5510440ed2908fc410af"}, + {file = "pydantic-1.10.10-cp311-cp311-win_amd64.whl", hash = "sha256:ea9eebc2ebcba3717e77cdeee3f6203ffc0e78db5f7482c68b1293e8cc156e5e"}, + {file = "pydantic-1.10.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:762aa598f79b4cac2f275d13336b2dd8662febee2a9c450a49a2ab3bec4b385f"}, + {file = "pydantic-1.10.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dab5219659f95e357d98d70577b361383057fb4414cfdb587014a5f5c595f7b"}, + {file = "pydantic-1.10.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3d4ee957a727ccb5a36f1b0a6dbd9fad5dedd2a41eada99a8df55c12896e18d"}, + {file = "pydantic-1.10.10-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b69f9138dec566962ec65623c9d57bee44412d2fc71065a5f3ebb3820bdeee96"}, + {file = "pydantic-1.10.10-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7aa75d1bd9cc275cf9782f50f60cddaf74cbaae19b6ada2a28e737edac420312"}, + {file = "pydantic-1.10.10-cp37-cp37m-win_amd64.whl", hash = "sha256:9f62a727f5c590c78c2d12fda302d1895141b767c6488fe623098f8792255fe5"}, + {file = "pydantic-1.10.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:aac218feb4af73db8417ca7518fb3bade4534fcca6e3fb00f84966811dd94450"}, + {file = "pydantic-1.10.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88546dc10a40b5b52cae87d64666787aeb2878f9a9b37825aedc2f362e7ae1da"}, + {file = "pydantic-1.10.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c41bbaae89e32fc582448e71974de738c055aef5ab474fb25692981a08df808a"}, + {file = "pydantic-1.10.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b71bd504d1573b0b722ae536e8ffb796bedeef978979d076bf206e77dcc55a5"}, + {file = "pydantic-1.10.10-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e088e3865a2270ecbc369924cd7d9fbc565667d9158e7f304e4097ebb9cf98dd"}, + {file = "pydantic-1.10.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3403a090db45d4027d2344859d86eb797484dfda0706cf87af79ace6a35274ef"}, + {file = "pydantic-1.10.10-cp38-cp38-win_amd64.whl", hash = "sha256:e0014e29637125f4997c174dd6167407162d7af0da73414a9340461ea8573252"}, + {file = "pydantic-1.10.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9965e49c6905840e526e5429b09e4c154355b6ecc0a2f05492eda2928190311d"}, + {file = "pydantic-1.10.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:748d10ab6089c5d196e1c8be9de48274f71457b01e59736f7a09c9dc34f51887"}, + {file = "pydantic-1.10.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86936c383f7c38fd26d35107eb669c85d8f46dfceae873264d9bab46fe1c7dde"}, + {file = "pydantic-1.10.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a26841be620309a9697f5b1ffc47dce74909e350c5315ccdac7a853484d468a"}, + {file = "pydantic-1.10.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:409b810f387610cc7405ab2fa6f62bdf7ea485311845a242ebc0bd0496e7e5ac"}, + {file = "pydantic-1.10.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ce937a2a2c020bcad1c9fde02892392a1123de6dda906ddba62bfe8f3e5989a2"}, + {file = "pydantic-1.10.10-cp39-cp39-win_amd64.whl", hash = "sha256:37ebddef68370e6f26243acc94de56d291e01227a67b2ace26ea3543cf53dd5f"}, + {file = "pydantic-1.10.10-py3-none-any.whl", hash = "sha256:a5939ec826f7faec434e2d406ff5e4eaf1716eb1f247d68cd3d0b3612f7b4c8a"}, + {file = "pydantic-1.10.10.tar.gz", hash = "sha256:3b8d5bd97886f9eb59260594207c9f57dce14a6f869c6ceea90188715d29921a"}, ] [package.dependencies] From 70683c4b8a721e157d9c46d5384d30f3566d4d13 Mon Sep 17 00:00:00 2001 From: Simon Thulbourn Date: Mon, 3 Jul 2023 14:26:44 +0200 Subject: [PATCH 05/73] fix(docs): ensure version alias is in an array to prevent "you're not viewing the latest version" incorrect message (#2629) --- .github/workflows/reusable_publish_docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index 830a8fad37b..829f1f80152 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -120,7 +120,7 @@ jobs: s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-python/versions.json \ versions_old.json jq 'del(.[].aliases[] | select(. == "${{ env.ALIAS }}"))' < versions_old.json > versions_proc.json - jq '. as $o | [{"title": "${{ env.VERSION }}", "version": "${{ env.VERSION }}", "aliases": "${{env.ALIAS}}" }] as $n | $n | if .[0].title | test("[a-z]+") or any($o[].title == "${{ env.VERSION }}";.) then $o else $n + $o end' < versions_proc.json > versions.json + jq '. as $o | [{"title": "${{ env.VERSION }}", "version": "${{ env.VERSION }}", "aliases": ["${{env.ALIAS}}"] }] as $n | $n | if .[0].title | test("[a-z]+") or any($o[].title == "${{ env.VERSION }}";.) then $o else $n + $o end' < versions_proc.json > versions.json aws s3 cp \ versions.json \ s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-python/versions.json From 2a9c48784e1aeaebae2c86a44f976a05abe2b6dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 00:18:25 +0100 Subject: [PATCH 06/73] chore(deps-dev): bump mypy-boto3-appconfigdata from 1.26.70 to 1.27.0 (#2636) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- Makefile | 2 +- poetry.lock | 320 ++++++++++++++++++++++++++++++++++--------------- pyproject.toml | 2 +- 3 files changed, 227 insertions(+), 97 deletions(-) diff --git a/Makefile b/Makefile index fcf29f82a56..5bfbf031949 100644 --- a/Makefile +++ b/Makefile @@ -110,4 +110,4 @@ mypy: dev-version-plugin: - poetry self add git+https://github.com/monim67/poetry-bumpversion@ef49c63acef7fe8680789ddb31f376cc898f0012 + poetry self add git+https://github.com/monim67/poetry-bumpversion@315fe3324a699fa12ec20e202eb7375d4327d1c4 diff --git a/poetry.lock b/poetry.lock index 4474ff229b4..876339a69f7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "anyio" version = "3.7.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -26,6 +27,7 @@ trio = ["trio (<0.22)"] name = "attrs" version = "23.1.0" description = "Classes Without Boilerplate" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -45,13 +47,14 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte [[package]] name = "aws-cdk-asset-awscli-v1" -version = "2.2.199" +version = "2.2.200" description = "A library that contains the AWS CLI for use in Lambda Layers" +category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.asset-awscli-v1-2.2.199.tar.gz", hash = "sha256:d2da639d36c739452734ef00858e56cdf6bc4638087ee58e208e3c7fce73fcd3"}, - {file = "aws_cdk.asset_awscli_v1-2.2.199-py3-none-any.whl", hash = "sha256:dc1799314b36dddbe5800a5a9db08e7741544936632718511303d2eb21d117a4"}, + {file = "aws-cdk.asset-awscli-v1-2.2.200.tar.gz", hash = "sha256:af4d67ef7aa4183073e63be5f88d1ce1912b24d2ebac35148e84678d674bdfcd"}, + {file = "aws_cdk.asset_awscli_v1-2.2.200-py3-none-any.whl", hash = "sha256:ed1b881402b255daec151e386581a627ce13f4d5cb94b7184e6efc38d27584b0"}, ] [package.dependencies] @@ -63,6 +66,7 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-cdk-asset-kubectl-v20" version = "2.1.2" description = "A library that contains kubectl for use in Lambda Layers" +category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -79,6 +83,7 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-cdk-asset-node-proxy-agent-v5" version = "2.0.165" description = "@aws-cdk/asset-node-proxy-agent-v5" +category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -93,17 +98,18 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-alpha" -version = "2.85.0a0" +version = "2.86.0a0" description = "The CDK Construct Library for AWS::APIGatewayv2" +category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-alpha-2.85.0a0.tar.gz", hash = "sha256:bac434ff40df5913cf9f92530c29f11a42c8d0edf0e48320c0453fd9e4bbe6b2"}, - {file = "aws_cdk.aws_apigatewayv2_alpha-2.85.0a0-py3-none-any.whl", hash = "sha256:e0f71cfcb6343902827e287ba70f2780ebb0a7cdea5f8991b1cc43b82c8ea6a3"}, + {file = "aws-cdk.aws-apigatewayv2-alpha-2.86.0a0.tar.gz", hash = "sha256:0ec4baaabb661170210f9ca7cd1e0eca13f573701e52689bc66e81c18e700d42"}, + {file = "aws_cdk.aws_apigatewayv2_alpha-2.86.0a0-py3-none-any.whl", hash = "sha256:6d3aa74bb1518bd09becba5c78c0578db1b2c9372c24f6273364154a26b233fa"}, ] [package.dependencies] -aws-cdk-lib = "2.85.0" +aws-cdk-lib = "2.86.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.82.0,<2.0.0" publication = ">=0.0.3" @@ -111,18 +117,19 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-authorizers-alpha" -version = "2.85.0a0" +version = "2.86.0a0" description = "Authorizers for AWS APIGateway V2" +category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-authorizers-alpha-2.85.0a0.tar.gz", hash = "sha256:699e752702643034e699da3c01ace2fe276c90b4851c84deb6fea46ac6927e63"}, - {file = "aws_cdk.aws_apigatewayv2_authorizers_alpha-2.85.0a0-py3-none-any.whl", hash = "sha256:7d23afe56d8d804e3f6306bfedcc1d0fb4bea45cabf26d7c34e54ca0740998f3"}, + {file = "aws-cdk.aws-apigatewayv2-authorizers-alpha-2.86.0a0.tar.gz", hash = "sha256:86624b7347558ecfa603170e2a5f4088ff6ff1a318af766f09ff9f327a9fd891"}, + {file = "aws_cdk.aws_apigatewayv2_authorizers_alpha-2.86.0a0-py3-none-any.whl", hash = "sha256:1e051aff7e0c92e2219ff42470c66eaafda90a1ec501b23bdc793f1cc70f98d7"}, ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.85.0.a0" -aws-cdk-lib = "2.85.0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.86.0.a0" +aws-cdk-lib = "2.86.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.82.0,<2.0.0" publication = ">=0.0.3" @@ -130,18 +137,19 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-integrations-alpha" -version = "2.85.0a0" +version = "2.86.0a0" description = "Integrations for AWS APIGateway V2" +category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.85.0a0.tar.gz", hash = "sha256:a280f9a5bfd5520e6356c733b385a642b27aced83597c5b6bacf55b2a95223ed"}, - {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.85.0a0-py3-none-any.whl", hash = "sha256:dd0fcfcae9a2fb4588a0e04b16a864773b7f7aaf22c17414a9661c11ba876d9a"}, + {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.86.0a0.tar.gz", hash = "sha256:a0a8566e41af4fbac97c107d5c91e6b33856b11d64f64e9dcc7cc33401d67b95"}, + {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.86.0a0-py3-none-any.whl", hash = "sha256:f1c75a6129f3991a120b95e1bb1504be3ae6d098138a38a67f02301e25fddcc5"}, ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.85.0.a0" -aws-cdk-lib = "2.85.0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.86.0.a0" +aws-cdk-lib = "2.86.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.82.0,<2.0.0" publication = ">=0.0.3" @@ -149,13 +157,14 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-lib" -version = "2.85.0" +version = "2.86.0" description = "Version 2 of the AWS Cloud Development Kit library" +category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk-lib-2.85.0.tar.gz", hash = "sha256:cbd13ec361a841077db0a0acb1d84c44c030ff198ad0a8e6d47760b3f8362ed4"}, - {file = "aws_cdk_lib-2.85.0-py3-none-any.whl", hash = "sha256:b5b388c0478b39820d8facee6ed7b07a1e1e1e7c01dded3d17f86797fb8dddb3"}, + {file = "aws-cdk-lib-2.86.0.tar.gz", hash = "sha256:bd8b0c4c531aadc7b49dcb504e77fc97768e7df8d3b4c97dd084c1c980ba6fef"}, + {file = "aws_cdk_lib-2.86.0-py3-none-any.whl", hash = "sha256:d9c3c2857190695ea7b2ed4655ea3879774aa54e8513d3d799aa3d149fe04879"}, ] [package.dependencies] @@ -171,6 +180,7 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-requests-auth" version = "0.4.3" description = "AWS signature version 4 signing process for the python requests module" +category = "dev" optional = false python-versions = "*" files = [ @@ -185,6 +195,7 @@ requests = ">=0.14.0" name = "aws-sam-translator" version = "1.70.0" description = "AWS SAM Translator is a library that transform SAM templates into AWS CloudFormation templates" +category = "dev" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ @@ -193,18 +204,19 @@ files = [ ] [package.dependencies] -boto3 = ">=1.19.5,<2.dev0" +boto3 = ">=1.19.5,<2.0.0" jsonschema = ">=3.2,<5" pydantic = ">=1.8,<2.0" typing-extensions = ">=4.4,<5" [package.extras] -dev = ["black (==23.1.0)", "boto3 (>=1.23,<2)", "boto3-stubs[appconfig,serverlessrepo] (>=1.19.5,<2.dev0)", "coverage (>=5.3,<8)", "dateparser (>=1.1,<2.0)", "importlib-metadata", "mypy (>=1.1.0,<1.2.0)", "parameterized (>=0.7,<1.0)", "pytest (>=6.2,<8)", "pytest-cov (>=2.10,<5)", "pytest-env (>=0.6,<1)", "pytest-rerunfailures (>=9.1,<12)", "pytest-xdist (>=2.5,<4)", "pyyaml (>=6.0,<7.0)", "requests (>=2.28,<3.0)", "ruamel.yaml (==0.17.21)", "ruff (==0.0.263)", "tenacity (>=8.0,<9.0)", "types-PyYAML (>=6.0,<7.0)", "types-jsonschema (>=3.2,<4.0)"] +dev = ["black (==23.1.0)", "boto3 (>=1.23,<2)", "boto3-stubs[appconfig,serverlessrepo] (>=1.19.5,<2.0.0)", "coverage (>=5.3,<8)", "dateparser (>=1.1,<2.0)", "importlib-metadata", "mypy (>=1.1.0,<1.2.0)", "parameterized (>=0.7,<1.0)", "pytest (>=6.2,<8)", "pytest-cov (>=2.10,<5)", "pytest-env (>=0.6,<1)", "pytest-rerunfailures (>=9.1,<12)", "pytest-xdist (>=2.5,<4)", "pyyaml (>=6.0,<7.0)", "requests (>=2.28,<3.0)", "ruamel.yaml (==0.17.21)", "ruff (==0.0.263)", "tenacity (>=8.0,<9.0)", "types-PyYAML (>=6.0,<7.0)", "types-jsonschema (>=3.2,<4.0)"] [[package]] name = "aws-xray-sdk" version = "2.12.0" description = "The AWS X-Ray SDK for Python (the SDK) enables Python developers to record and emit information from within their applications to the AWS X-Ray service." +category = "main" optional = true python-versions = "*" files = [ @@ -220,6 +232,7 @@ wrapt = "*" name = "bandit" version = "1.7.5" description = "Security oriented static analyser for python code." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -243,6 +256,7 @@ yaml = ["PyYAML"] name = "black" version = "23.3.0" description = "The uncompromising code formatter." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -291,17 +305,18 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.26.161" +version = "1.27.0" description = "The AWS SDK for Python" +category = "main" optional = false python-versions = ">= 3.7" files = [ - {file = "boto3-1.26.161-py3-none-any.whl", hash = "sha256:f66e5c9dbe7f34383bcf64fa6070771355c11a44dd75c7f1279f2f37e1c89183"}, - {file = "boto3-1.26.161.tar.gz", hash = "sha256:662731e464d14af1035f44fc6a46b0e3112ee011ac0a5ed416d205daa3e15f25"}, + {file = "boto3-1.27.0-py3-none-any.whl", hash = "sha256:e1e535e9fb23977252f13652ed2fa9b4f2d59a53b04a5f2fad3ee415b6a3b2b0"}, + {file = "boto3-1.27.0.tar.gz", hash = "sha256:908f9c277325d68963dfcfce963a05336f0eb19505fc239c0ab9d01f4cba0296"}, ] [package.dependencies] -botocore = ">=1.29.161,<1.30.0" +botocore = ">=1.30.0,<1.31.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.6.0,<0.7.0" @@ -310,13 +325,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.29.161" +version = "1.30.0" description = "Low-level, data-driven core of boto 3." +category = "main" optional = false python-versions = ">= 3.7" files = [ - {file = "botocore-1.29.161-py3-none-any.whl", hash = "sha256:b906999dd53dda2ef0ef6f7f55fcc81a4b06b9f1c8a9f65c546e0b981f959f5f"}, - {file = "botocore-1.29.161.tar.gz", hash = "sha256:a50edd715eb510343e27849f36483804aae4b871590db4d4996aa53368dcac40"}, + {file = "botocore-1.30.0-py3-none-any.whl", hash = "sha256:cac1333f41ec98e6f75bbba3f2c74b9e76aa3847469ecea6e7773a0af0049bee"}, + {file = "botocore-1.30.0.tar.gz", hash = "sha256:b9cb5b78a289f0615a48d85066f01869029aa41b95993f2c0c55003df037c23f"}, ] [package.dependencies] @@ -331,6 +347,7 @@ crt = ["awscrt (==0.16.9)"] name = "cattrs" version = "23.1.2" description = "Composable complex class support for attrs and dataclasses." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -356,6 +373,7 @@ ujson = ["ujson (>=5.4.0,<6.0.0)"] name = "certifi" version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -367,6 +385,7 @@ files = [ name = "cfn-lint" version = "0.77.10" description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved" +category = "dev" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ @@ -390,6 +409,7 @@ sympy = ">=1.0.0" name = "charset-normalizer" version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -474,6 +494,7 @@ files = [ name = "checksumdir" version = "1.2.0" description = "Compute a single hash of the file contents of a directory." +category = "dev" optional = false python-versions = ">=3.6,<4.0" files = [ @@ -485,6 +506,7 @@ files = [ name = "click" version = "8.1.3" description = "Composable command line interface toolkit" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -500,6 +522,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -509,13 +532,14 @@ files = [ [[package]] name = "constructs" -version = "10.2.61" +version = "10.2.67" description = "A programming model for software-defined state" +category = "dev" optional = false python-versions = "~=3.7" files = [ - {file = "constructs-10.2.61-py3-none-any.whl", hash = "sha256:13de50a13ef1199f2dcc573f269b6486fa5c0c4a028372e7c053118c3acd27b1"}, - {file = "constructs-10.2.61.tar.gz", hash = "sha256:27b33a3944e5112dedc5aee307151e3655df988694428ac7a9c71961b4ba211c"}, + {file = "constructs-10.2.67-py3-none-any.whl", hash = "sha256:dbc93e7c0f3e6dba96abee6f1ed66dd11ab14920a5177a1c3ed3e785eb60fdfa"}, + {file = "constructs-10.2.67.tar.gz", hash = "sha256:b5bba5454dd38994b85b0e24991d68333a62cf6f079b742993af46d9de8e6811"}, ] [package.dependencies] @@ -527,6 +551,7 @@ typeguard = ">=2.13.3,<2.14.0" name = "coverage" version = "7.2.7" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -602,6 +627,7 @@ toml = ["tomli"] name = "decorator" version = "5.1.1" description = "Decorators for Humans" +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -611,13 +637,14 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.1.2" description = "Backport of PEP 654 (exception groups)" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, + {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"}, + {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"}, ] [package.extras] @@ -627,6 +654,7 @@ test = ["pytest (>=6)"] name = "execnet" version = "1.9.0" description = "execnet: rapid multi-Python deployment" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -641,6 +669,7 @@ testing = ["pre-commit"] name = "fastjsonschema" version = "2.17.1" description = "Fastest Python implementation of JSON schema" +category = "main" optional = true python-versions = "*" files = [ @@ -655,6 +684,7 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc name = "filelock" version = "3.12.2" description = "A platform independent file lock." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -670,6 +700,7 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "p name = "future" version = "0.18.3" description = "Clean single-source support for Python 3 and 2" +category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -680,6 +711,7 @@ files = [ name = "ghp-import" version = "2.1.0" description = "Copy your docs directly to the gh-pages branch." +category = "dev" optional = false python-versions = "*" files = [ @@ -697,6 +729,7 @@ dev = ["flake8", "markdown", "twine", "wheel"] name = "gitdb" version = "4.0.10" description = "Git Object Database" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -711,6 +744,7 @@ smmap = ">=3.0.1,<6" name = "gitpython" version = "3.1.31" description = "GitPython is a Python library used to interact with Git repositories" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -726,6 +760,7 @@ typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\"" name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -740,6 +775,7 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""} name = "httpcore" version = "0.17.2" description = "A minimal low-level HTTP client." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -751,16 +787,17 @@ files = [ anyio = ">=3.0,<5.0" certifi = "*" h11 = ">=0.13,<0.15" -sniffio = "==1.*" +sniffio = ">=1.0.0,<2.0.0" [package.extras] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "httpx" version = "0.24.1" description = "The next generation HTTP client." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -776,14 +813,15 @@ sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "hvac" version = "1.1.1" description = "HashiCorp Vault API client" +category = "dev" optional = false python-versions = ">=3.6.2,<4.0.0" files = [ @@ -799,6 +837,7 @@ requests = ">=2.27.1,<3.0.0" name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -810,6 +849,7 @@ files = [ name = "ijson" version = "3.2.2" description = "Iterative JSON parser with standard Python iterator interfaces" +category = "dev" optional = false python-versions = "*" files = [ @@ -897,6 +937,7 @@ files = [ name = "importlib-metadata" version = "6.7.0" description = "Read metadata from Python packages" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -917,6 +958,7 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs name = "importlib-resources" version = "5.12.0" description = "Read resources from Python packages" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -935,6 +977,7 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -946,6 +989,7 @@ files = [ name = "isort" version = "5.11.5" description = "A Python utility / library to sort Python imports." +category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -963,6 +1007,7 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -980,6 +1025,7 @@ i18n = ["Babel (>=2.7)"] name = "jmespath" version = "1.0.1" description = "JSON Matching Expressions" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -991,6 +1037,7 @@ files = [ name = "jschema-to-python" version = "1.2.3" description = "Generate source code for Python classes from a JSON schema." +category = "dev" optional = false python-versions = ">= 2.7" files = [ @@ -1007,6 +1054,7 @@ pbr = "*" name = "jsii" version = "1.84.0" description = "Python client for jsii runtime" +category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -1027,11 +1075,11 @@ typing-extensions = ">=3.7,<5.0" name = "jsonpatch" version = "1.33" description = "Apply JSON-Patches (RFC 6902)" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, - {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, ] [package.dependencies] @@ -1041,6 +1089,7 @@ jsonpointer = ">=1.9" name = "jsonpickle" version = "3.0.1" description = "Python library for serializing any arbitrary object graph into JSON" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1060,17 +1109,18 @@ testing-libs = ["simplejson", "ujson"] name = "jsonpointer" version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, - {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, ] [[package]] name = "jsonschema" version = "4.17.3" description = "An implementation of JSON Schema validation for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1094,6 +1144,7 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "junit-xml" version = "1.9" description = "Creates JUnit XML test result documents that can be read by tools such as Jenkins" +category = "dev" optional = false python-versions = "*" files = [ @@ -1108,6 +1159,7 @@ six = "*" name = "mako" version = "1.2.4" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1128,6 +1180,7 @@ testing = ["pytest"] name = "mando" version = "0.6.4" description = "Create Python CLI apps with little to no effort at all!" +category = "dev" optional = false python-versions = "*" files = [ @@ -1145,6 +1198,7 @@ restructuredtext = ["rst2ansi"] name = "markdown" version = "3.3.7" description = "Python implementation of Markdown." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1162,6 +1216,7 @@ testing = ["coverage", "pyyaml"] name = "markdown-it-py" version = "2.2.0" description = "Python port of markdown-it. Markdown parsing, done right!" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1187,6 +1242,7 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1246,6 +1302,7 @@ files = [ name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1257,6 +1314,7 @@ files = [ name = "mergedeep" version = "1.3.4" description = "A deep merge function for 🐍." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1268,6 +1326,7 @@ files = [ name = "mike" version = "1.1.2" description = "Manage multiple versions of your MkDocs-powered documentation" +category = "dev" optional = false python-versions = "*" files = [ @@ -1289,6 +1348,7 @@ test = ["coverage", "flake8 (>=3.0)", "shtab"] name = "mkdocs" version = "1.4.3" description = "Project documentation with Markdown." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1318,6 +1378,7 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp name = "mkdocs-git-revision-date-plugin" version = "0.3.2" description = "MkDocs plugin for setting revision date from git per markdown file." +category = "dev" optional = false python-versions = ">=3.4" files = [ @@ -1331,13 +1392,14 @@ mkdocs = ">=0.17" [[package]] name = "mkdocs-material" -version = "9.1.17" +version = "9.1.18" description = "Documentation that simply works" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mkdocs_material-9.1.17-py3-none-any.whl", hash = "sha256:809ed68427fbab0330b0b07bc93175824c3b98f4187060a5c7b46aa8ae398a75"}, - {file = "mkdocs_material-9.1.17.tar.gz", hash = "sha256:5a076524625047bf4ee4da1509ec90626f8fce915839dc07bdae6b59ff4f36f9"}, + {file = "mkdocs_material-9.1.18-py3-none-any.whl", hash = "sha256:5bcf8fb79ac2f253c0ffe93fa181cba87718c6438f459dc4180ac7418cc9a450"}, + {file = "mkdocs_material-9.1.18.tar.gz", hash = "sha256:981dd39979723d4cda7cfc77bbbe5e54922d5761a7af23fb8ba9edb52f114b13"}, ] [package.dependencies] @@ -1355,6 +1417,7 @@ requests = ">=2.26" name = "mkdocs-material-extensions" version = "1.1.1" description = "Extension pack for Python Markdown and MkDocs Material." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1366,6 +1429,7 @@ files = [ name = "mpmath" version = "1.3.0" description = "Python library for arbitrary-precision floating-point arithmetic" +category = "dev" optional = false python-versions = "*" files = [ @@ -1383,6 +1447,7 @@ tests = ["pytest (>=4.6)"] name = "mypy" version = "1.4.1" description = "Optional static typing for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1428,41 +1493,44 @@ reports = ["lxml"] [[package]] name = "mypy-boto3-appconfig" -version = "1.26.71" -description = "Type annotations for boto3.AppConfig 1.26.71 service generated with mypy-boto3-builder 7.12.3" +version = "1.27.0" +description = "Type annotations for boto3.AppConfig 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-appconfig-1.26.71.tar.gz", hash = "sha256:239c467e2aa6646011fb15c3f632e0988fd9e8af7d46e490f756bd012087dfb7"}, - {file = "mypy_boto3_appconfig-1.26.71-py3-none-any.whl", hash = "sha256:6e1e722f5cc1e4a16632af279d02c1727c2f36ed4b7df10606a7fc3d0d4c2abe"}, + {file = "mypy-boto3-appconfig-1.27.0.tar.gz", hash = "sha256:223cda564d54cf18f57b43b7438535c71edc610a5b260ed66af207c768ca115b"}, + {file = "mypy_boto3_appconfig-1.27.0-py3-none-any.whl", hash = "sha256:8e7a84286489b28ea5ffa7553573a15b74d911f9f166d6b4098aeae61f67347a"}, ] [package.dependencies] -typing-extensions = ">=4.1.0" +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-appconfigdata" -version = "1.26.70" -description = "Type annotations for boto3.AppConfigData 1.26.70 service generated with mypy-boto3-builder 7.12.3" +version = "1.27.0" +description = "Type annotations for boto3.AppConfigData 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-appconfigdata-1.26.70.tar.gz", hash = "sha256:fafa2cb8500d8291c0a51369f323ce01e15bdf71ef3d07a4a16d5e12b7b545ab"}, - {file = "mypy_boto3_appconfigdata-1.26.70-py3-none-any.whl", hash = "sha256:c04e24f56bf1cf3127939571875617529b290a7adba7a49cb04a68476f4dfe9e"}, + {file = "mypy-boto3-appconfigdata-1.27.0.tar.gz", hash = "sha256:a240f3c7b4f8b559d2b9a572c756884fe8247643fbc8c609d22f7414a79aa462"}, + {file = "mypy_boto3_appconfigdata-1.27.0-py3-none-any.whl", hash = "sha256:cfe864dab8557b66654d903104ac5a259079e24d43edd06469bd4715f5173a42"}, ] [package.dependencies] -typing-extensions = ">=4.1.0" +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudformation" -version = "1.26.156" -description = "Type annotations for boto3.CloudFormation 1.26.156 service generated with mypy-boto3-builder 7.14.5" +version = "1.27.0" +description = "Type annotations for boto3.CloudFormation 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudformation-1.26.156.tar.gz", hash = "sha256:cf5c568fae32ba216749d01208239ae5342b1e1c0842fae115c0176e911a441a"}, - {file = "mypy_boto3_cloudformation-1.26.156-py3-none-any.whl", hash = "sha256:0c9007a1c0a74d2a857761305c0365f971d6b44b1a10648b52c115f46ecaf53f"}, + {file = "mypy-boto3-cloudformation-1.27.0.tar.gz", hash = "sha256:9a9395d79d86f9ed2b18cf796eb9906a47f76bac30fe60c20fd22e082e4b1d5c"}, + {file = "mypy_boto3_cloudformation-1.27.0-py3-none-any.whl", hash = "sha256:979f61f7466ed3fad239e79f54227b1927a2683a7cfe44993d146279cfba2980"}, ] [package.dependencies] @@ -1470,13 +1538,14 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudwatch" -version = "1.26.127" -description = "Type annotations for boto3.CloudWatch 1.26.127 service generated with mypy-boto3-builder 7.14.5" +version = "1.27.0" +description = "Type annotations for boto3.CloudWatch 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudwatch-1.26.127.tar.gz", hash = "sha256:08281b75414293f112135eaaa9937ab2621e1db0762285a1face66ab937b4e0f"}, - {file = "mypy_boto3_cloudwatch-1.26.127-py3-none-any.whl", hash = "sha256:e2da3e956b1c67a3bc4374ced3331fff97172f98d63e56efea805dc1e5fa28e9"}, + {file = "mypy-boto3-cloudwatch-1.27.0.tar.gz", hash = "sha256:802f7cd086c67fdf23bce9e8b6fe558258c98cc9cfe926d5c19774359ad984d9"}, + {file = "mypy_boto3_cloudwatch-1.27.0-py3-none-any.whl", hash = "sha256:d5f97615e903ebc774a1ef4335c11cd7b965acbd238a295ee1254f0cfe4c443b"}, ] [package.dependencies] @@ -1484,13 +1553,14 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-dynamodb" -version = "1.26.164" -description = "Type annotations for boto3.DynamoDB 1.26.164 service generated with mypy-boto3-builder 7.14.5" +version = "1.27.0" +description = "Type annotations for boto3.DynamoDB 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-dynamodb-1.26.164.tar.gz", hash = "sha256:5a832531ac2c81b01dea20ef79f7dd5a2014c3736566a498585f5f46d642adc4"}, - {file = "mypy_boto3_dynamodb-1.26.164-py3-none-any.whl", hash = "sha256:a527270b304f1a517093fff3709c7831fc5616a91bb1c9b6164fa71e37481d84"}, + {file = "mypy-boto3-dynamodb-1.27.0.tar.gz", hash = "sha256:8c6642e56a324c5bdf161e19277dd08475d87af8fadfe0a6f86824bbbebfbd99"}, + {file = "mypy_boto3_dynamodb-1.27.0-py3-none-any.whl", hash = "sha256:56bb013af0086ae891ef39d332dab0c5f2a4ea39afb16b567eb0de1f16e8edcb"}, ] [package.dependencies] @@ -1498,13 +1568,14 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-lambda" -version = "1.26.163" -description = "Type annotations for boto3.Lambda 1.26.163 service generated with mypy-boto3-builder 7.14.5" +version = "1.27.0" +description = "Type annotations for boto3.Lambda 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-lambda-1.26.163.tar.gz", hash = "sha256:fd36cf8a3f5e733f6e80c755af19538ce0a50c3eafb1be7cf7de0c29c40788a0"}, - {file = "mypy_boto3_lambda-1.26.163-py3-none-any.whl", hash = "sha256:f6ca7fd11c8e9c81218fdbeae163c343c6dc3b7df88a70c30c0c7b30c90163d9"}, + {file = "mypy-boto3-lambda-1.27.0.tar.gz", hash = "sha256:40c8f9b102ff1a341d5fcbeff601c73c06727e0aa4a29bc7e862c18e52fc69e5"}, + {file = "mypy_boto3_lambda-1.27.0-py3-none-any.whl", hash = "sha256:5e0a19c919ef1bcc9519d95209a715208af965e12ecf349815a3d69ecf65238e"}, ] [package.dependencies] @@ -1512,13 +1583,14 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-logs" -version = "1.26.149" -description = "Type annotations for boto3.CloudWatchLogs 1.26.149 service generated with mypy-boto3-builder 7.14.5" +version = "1.27.0" +description = "Type annotations for boto3.CloudWatchLogs 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-logs-1.26.149.tar.gz", hash = "sha256:4a592d7d8180d45197197af4dc959f61b5c4d989a0ba615ecde6e21661c4013f"}, - {file = "mypy_boto3_logs-1.26.149-py3-none-any.whl", hash = "sha256:6d913c9be74c9eff71910b5af18f8beeeae524dae273fea7b47ead0ee1a09134"}, + {file = "mypy-boto3-logs-1.27.0.tar.gz", hash = "sha256:f7c527864a2d21c037f174b7a6d4099d593b23c072d14e8e515f29207e0f7226"}, + {file = "mypy_boto3_logs-1.27.0-py3-none-any.whl", hash = "sha256:acc9ee5407c985c023be151957ceadb34e3ad964b310c32b599d707cc22e0b23"}, ] [package.dependencies] @@ -1526,13 +1598,14 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-s3" -version = "1.26.163" -description = "Type annotations for boto3.S3 1.26.163 service generated with mypy-boto3-builder 7.14.5" +version = "1.27.0" +description = "Type annotations for boto3.S3 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-s3-1.26.163.tar.gz", hash = "sha256:47d3639cd097aa142dcaca43b431fa7a7eefb56e1596ebff625f571f16bd7623"}, - {file = "mypy_boto3_s3-1.26.163-py3-none-any.whl", hash = "sha256:39417a3e4128c61e7b9353d080b93293f9ca9a4acf059a255d8357b9a4e12db2"}, + {file = "mypy-boto3-s3-1.27.0.tar.gz", hash = "sha256:12c3c9d0e818c2de88f879cdad5f68fb6a7bfbc8cf01c85ae354a9f6b6c38558"}, + {file = "mypy_boto3_s3-1.27.0-py3-none-any.whl", hash = "sha256:0edcbebb22c564721d9ddc3db19537672382d4e9f05d132223be92eabea4f9bc"}, ] [package.dependencies] @@ -1540,13 +1613,14 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-secretsmanager" -version = "1.26.135" -description = "Type annotations for boto3.SecretsManager 1.26.135 service generated with mypy-boto3-builder 7.14.5" +version = "1.27.0" +description = "Type annotations for boto3.SecretsManager 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-secretsmanager-1.26.135.tar.gz", hash = "sha256:cf523d3e4f6729e244e24d97c692855883e69fa270d11f5021a293fb2aa483e8"}, - {file = "mypy_boto3_secretsmanager-1.26.135-py3-none-any.whl", hash = "sha256:15cf8d8a16eb0a49984ef9f19821a1d2b97bf1e6b56c703f27973a27b32aef4c"}, + {file = "mypy-boto3-secretsmanager-1.27.0.tar.gz", hash = "sha256:e03060559b4ab234ea08b45f5271a9e1f256061ffda7a4f912b463d7fcd3a219"}, + {file = "mypy_boto3_secretsmanager-1.27.0-py3-none-any.whl", hash = "sha256:a1fd92a98f7dd421808f708430a7b3fd2e14ca564f52fe53499f57e54868c4f5"}, ] [package.dependencies] @@ -1554,13 +1628,14 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-ssm" -version = "1.26.162" -description = "Type annotations for boto3.SSM 1.26.162 service generated with mypy-boto3-builder 7.14.5" +version = "1.27.0" +description = "Type annotations for boto3.SSM 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-ssm-1.26.162.tar.gz", hash = "sha256:a5d9d7e4c7dbf4788dddcc02410afa349d7356a24fbffe5b7a36cd0c04211f06"}, - {file = "mypy_boto3_ssm-1.26.162-py3-none-any.whl", hash = "sha256:42c52e55a94b5d5ce14d628b4bc168b2b4230e130050172bf54747edb7b8da14"}, + {file = "mypy-boto3-ssm-1.27.0.tar.gz", hash = "sha256:1803f1aa582a2f7f2c6a8aa17c1f5f5eccd9f66ae8f5d1f8b2ae26dc237b4a94"}, + {file = "mypy_boto3_ssm-1.27.0-py3-none-any.whl", hash = "sha256:07e0a2ab5957439e527c8381a54d9479d07b9e95b96a7cfcfcefddf3c4a78e29"}, ] [package.dependencies] @@ -1568,13 +1643,14 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-xray" -version = "1.26.122" -description = "Type annotations for boto3.XRay 1.26.122 service generated with mypy-boto3-builder 7.14.5" +version = "1.27.0" +description = "Type annotations for boto3.XRay 1.27.0 service generated with mypy-boto3-builder 7.14.5" +category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-xray-1.26.122.tar.gz", hash = "sha256:0231b717443e6eafe4ff689423c5b54a5ee47682f7c19d3f66bfe7e00e87bf7c"}, - {file = "mypy_boto3_xray-1.26.122-py3-none-any.whl", hash = "sha256:6cfe3167ecb92942519d8334bb145d83a6d727bdb7b812c1d9692f938caf6a7f"}, + {file = "mypy-boto3-xray-1.27.0.tar.gz", hash = "sha256:8f4b75eeb77f17e3807d1aab21284748f1651dd6a15cc700279d91897bacbc49"}, + {file = "mypy_boto3_xray-1.27.0-py3-none-any.whl", hash = "sha256:4e7092b6dc070561360087471c34497ea2cc9c9bd9ae4b46896c690388ae9902"}, ] [package.dependencies] @@ -1584,6 +1660,7 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1595,6 +1672,7 @@ files = [ name = "networkx" version = "2.6.3" description = "Python package for creating and manipulating graphs and networks" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1613,6 +1691,7 @@ test = ["codecov (>=2.1)", "pytest (>=6.2)", "pytest-cov (>=2.12)"] name = "packaging" version = "23.1" description = "Core utilities for Python packages" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1624,6 +1703,7 @@ files = [ name = "pathspec" version = "0.11.1" description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1635,6 +1715,7 @@ files = [ name = "pbr" version = "5.11.1" description = "Python Build Reasonableness" +category = "dev" optional = false python-versions = ">=2.6" files = [ @@ -1646,6 +1727,7 @@ files = [ name = "pdoc3" version = "0.10.0" description = "Auto-generate API documentation for Python projects." +category = "dev" optional = false python-versions = ">= 3.6" files = [ @@ -1661,6 +1743,7 @@ markdown = ">=3.0" name = "pkgutil-resolve-name" version = "1.3.10" description = "Resolve a name to an object." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1672,6 +1755,7 @@ files = [ name = "platformdirs" version = "3.8.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1690,6 +1774,7 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest- name = "pluggy" version = "1.2.0" description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1708,6 +1793,7 @@ testing = ["pytest", "pytest-benchmark"] name = "publication" version = "0.0.3" description = "Publication helps you maintain public-api-friendly modules by preventing unintentional access to private implementation details via introspection." +category = "dev" optional = false python-versions = "*" files = [ @@ -1719,6 +1805,7 @@ files = [ name = "py" version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1730,6 +1817,7 @@ files = [ name = "py-cpuinfo" version = "9.0.0" description = "Get CPU info with pure Python" +category = "dev" optional = false python-versions = "*" files = [ @@ -1741,6 +1829,7 @@ files = [ name = "pydantic" version = "1.10.10" description = "Data validation and settings management using python type hints" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1793,6 +1882,7 @@ email = ["email-validator (>=1.0.3)"] name = "pygments" version = "2.15.1" description = "Pygments is a syntax highlighting package written in Python." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1807,6 +1897,7 @@ plugins = ["importlib-metadata"] name = "pyhcl" version = "0.4.4" description = "HCL configuration parser for python" +category = "dev" optional = false python-versions = "*" files = [ @@ -1817,6 +1908,7 @@ files = [ name = "pymdown-extensions" version = "10.0.1" description = "Extension pack for Python Markdown." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1832,6 +1924,7 @@ pyyaml = "*" name = "pyrsistent" version = "0.19.3" description = "Persistent/Functional/Immutable data structures" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1868,6 +1961,7 @@ files = [ name = "pytest" version = "7.4.0" description = "pytest: simple powerful testing with Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1891,6 +1985,7 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-asyncio" version = "0.21.0" description = "Pytest support for asyncio" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1910,6 +2005,7 @@ testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy name = "pytest-benchmark" version = "4.0.0" description = "A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1930,6 +2026,7 @@ histogram = ["pygal", "pygaljs"] name = "pytest-cov" version = "4.1.0" description = "Pytest plugin for measuring coverage." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1948,6 +2045,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-mock" version = "3.11.1" description = "Thin-wrapper around the mock package for easier use with pytest" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1965,6 +2063,7 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] name = "pytest-xdist" version = "3.3.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1985,6 +2084,7 @@ testing = ["filelock"] name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -1999,6 +2099,7 @@ six = ">=1.5" name = "python-snappy" version = "0.6.1" description = "Python library for the snappy compression library from Google" +category = "dev" optional = false python-versions = "*" files = [ @@ -2056,6 +2157,7 @@ files = [ name = "pyyaml" version = "6.0" description = "YAML parser and emitter for Python" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2105,6 +2207,7 @@ files = [ name = "pyyaml-env-tag" version = "0.1" description = "A custom YAML tag for referencing environment variables in YAML files. " +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2119,6 +2222,7 @@ pyyaml = "*" name = "radon" version = "5.1.0" description = "Code Metrics in Python" +category = "dev" optional = false python-versions = "*" files = [ @@ -2135,6 +2239,7 @@ mando = ">=0.6,<0.7" name = "regex" version = "2023.6.3" description = "Alternative regular expression module, to replace re." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2232,6 +2337,7 @@ files = [ name = "requests" version = "2.31.0" description = "Python HTTP for Humans." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2253,6 +2359,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "retry" version = "0.9.2" description = "Easy to use retry decorator." +category = "dev" optional = false python-versions = "*" files = [ @@ -2268,6 +2375,7 @@ py = ">=1.4.26,<2.0.0" name = "rich" version = "13.4.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -2287,6 +2395,7 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "ruff" version = "0.0.275" description = "An extremely fast Python linter, written in Rust." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2313,6 +2422,7 @@ files = [ name = "s3transfer" version = "0.6.1" description = "An Amazon S3 Transfer Manager" +category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -2330,6 +2440,7 @@ crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] name = "sarif-om" version = "1.0.4" description = "Classes implementing the SARIF 2.1.0 object model." +category = "dev" optional = false python-versions = ">= 2.7" files = [ @@ -2345,6 +2456,7 @@ pbr = "*" name = "sentry-sdk" version = "1.26.0" description = "Python client for Sentry (https://sentry.io)" +category = "dev" optional = false python-versions = "*" files = [ @@ -2387,6 +2499,7 @@ tornado = ["tornado (>=5)"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2398,6 +2511,7 @@ files = [ name = "smmap" version = "5.0.0" description = "A pure Python implementation of a sliding window memory map manager" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2409,6 +2523,7 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2420,6 +2535,7 @@ files = [ name = "stevedore" version = "3.5.2" description = "Manage dynamic plugins for Python applications" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2435,6 +2551,7 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0" name = "sympy" version = "1.10.1" description = "Computer algebra system (CAS) in Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2449,6 +2566,7 @@ mpmath = ">=0.19" name = "tomli" version = "2.0.1" description = "A lil' TOML parser" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2460,6 +2578,7 @@ files = [ name = "typed-ast" version = "1.5.4" description = "a fork of Python 2 and 3 ast modules with type comment support" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2493,6 +2612,7 @@ files = [ name = "typeguard" version = "2.13.3" description = "Run-time type checker for Python" +category = "dev" optional = false python-versions = ">=3.5.3" files = [ @@ -2508,6 +2628,7 @@ test = ["mypy", "pytest", "typing-extensions"] name = "types-python-dateutil" version = "2.8.19.13" description = "Typing stubs for python-dateutil" +category = "dev" optional = false python-versions = "*" files = [ @@ -2519,6 +2640,7 @@ files = [ name = "types-requests" version = "2.31.0.1" description = "Typing stubs for requests" +category = "dev" optional = false python-versions = "*" files = [ @@ -2533,6 +2655,7 @@ types-urllib3 = "*" name = "types-urllib3" version = "1.26.25.13" description = "Typing stubs for urllib3" +category = "dev" optional = false python-versions = "*" files = [ @@ -2542,19 +2665,21 @@ files = [ [[package]] name = "typing-extensions" -version = "4.6.3" +version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"}, - {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"}, + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, ] [[package]] name = "urllib3" version = "1.26.16" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -2571,6 +2696,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "verspec" version = "0.1.0" description = "Flexible version handling" +category = "dev" optional = false python-versions = "*" files = [ @@ -2585,6 +2711,7 @@ test = ["coverage", "flake8 (>=3.7)", "mypy", "pretend", "pytest"] name = "watchdog" version = "3.0.0" description = "Filesystem events monitoring" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2624,6 +2751,7 @@ watchmedo = ["PyYAML (>=3.10)"] name = "wrapt" version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." +category = "main" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -2708,6 +2836,7 @@ files = [ name = "xenon" version = "0.9.0" description = "Monitor code metrics for Python on your CI server" +category = "dev" optional = false python-versions = "*" files = [ @@ -2724,6 +2853,7 @@ requests = ">=2.0,<3.0" name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2745,4 +2875,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "906d8206a4d10f9ac939fbbac0e8427e41ee232dd006ce3043de8a5348fd9c11" +content-hash = "ea4b3b7ff32e0f70d48ec58b0610b4a0b18e86a53e3c125767c3ff8b38020bf6" diff --git a/pyproject.toml b/pyproject.toml index 202b88de6d6..2ee7a5936a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,7 +72,7 @@ typing-extensions = "^4.6.2" mkdocs-material = "^9.1.17" filelock = "^3.12.2" checksumdir = "^1.2.0" -mypy-boto3-appconfigdata = "^1.26.70" +mypy-boto3-appconfigdata = "^1.27.0" ijson = "^3.2.2" typed-ast = { version = "^1.5.4", python = "< 3.8"} hvac = "^1.1.1" From b2e43b3424c7e2fbea2c96451434a79dc4e921dc Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Tue, 4 Jul 2023 12:03:28 +0200 Subject: [PATCH 07/73] chore(ci): prevent merging PRs that do not meet minimum requirements (#2639) --- .github/workflows/on_pr_updates.yml | 36 +++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/on_pr_updates.yml diff --git a/.github/workflows/on_pr_updates.yml b/.github/workflows/on_pr_updates.yml new file mode 100644 index 00000000000..003bc0880a8 --- /dev/null +++ b/.github/workflows/on_pr_updates.yml @@ -0,0 +1,36 @@ +# Fail PR check if do-not-merge label is present +name: PR requirements + +# PROCESS +# +# 1. Verify whether 'do-not-merge' label is present +# 2. Fail PR to prevent merging until resolved +# 3. Pass PR if do-not-merge label is removed by a maintainer + +# USAGE +# +# Always triggered on PR labeling changes. + +# NOTES +# +# PR requirements are checked async in on_opened_pr.yml and enforced here synchronously +# due to limitations in GH API. + +on: + pull_request: + types: + - opened + - labeled + - unlabeled + +permissions: {} # no permission required + +jobs: + fail-for-draft: + runs-on: ubuntu-latest + steps: + - name: Block if it doesn't minimum requirements + if: contains(github.event.pull_request.labels.*.name, 'do-not-merge') + run: | + echo "This PR does not meet minimum requirements (check PR comments)." + exit 1 From cdd28fe0b0a58e8db9ffab2585bc98d92539e0cc Mon Sep 17 00:00:00 2001 From: StepSecurity Bot Date: Tue, 4 Jul 2023 03:08:22 -0700 Subject: [PATCH 08/73] chore(ci): enforce top-level permission to minimum fail-safe permission as per openssf (#2638) --- .github/workflows/build_changelog.yml | 3 +++ .github/workflows/codeql-analysis.yml | 3 +++ .github/workflows/dependency-review.yml | 22 +++++++++++++++++++ .github/workflows/label_pr_on_title.yml | 3 +++ .github/workflows/on_closed_issues.yml | 3 +++ .github/workflows/on_label_added.yml | 3 +++ .github/workflows/on_merged_pr.yml | 3 +++ .github/workflows/on_opened_pr.yml | 3 +++ .github/workflows/on_push_docs.yml | 3 +++ .github/workflows/publish_v2_layer.yml | 3 +++ .github/workflows/quality_check.yml | 3 +++ .github/workflows/rebuild_latest_docs.yml | 3 +++ .github/workflows/record_pr.yml | 3 +++ .github/workflows/release-drafter.yml | 3 +++ .github/workflows/release.yml | 3 +++ .../reusable_deploy_v2_layer_stack.yml | 3 +++ .../workflows/reusable_export_pr_details.yml | 3 +++ .../workflows/reusable_publish_changelog.yml | 3 +++ .github/workflows/run-e2e-tests.yml | 3 +++ .github/workflows/secure_workflows.yml | 3 +++ 20 files changed, 79 insertions(+) create mode 100644 .github/workflows/dependency-review.yml diff --git a/.github/workflows/build_changelog.yml b/.github/workflows/build_changelog.yml index 1be01306109..a167868be05 100644 --- a/.github/workflows/build_changelog.yml +++ b/.github/workflows/build_changelog.yml @@ -17,6 +17,9 @@ on: branches: - develop +permissions: + contents: read + jobs: changelog: permissions: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ac4e4812eee..d8ef363c8f9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -17,6 +17,9 @@ on: branches: - develop +permissions: + contents: read + jobs: analyze: name: Analyze diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 00000000000..627c9ca205b --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,22 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, +# PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: 'Dependency Review' + uses: actions/dependency-review-action@0efb1d1d84fc9633afcdaad14c485cbbc90ef46c # v2.5.1 diff --git a/.github/workflows/label_pr_on_title.yml b/.github/workflows/label_pr_on_title.yml index 41bdeed0ec9..48fb24b2476 100644 --- a/.github/workflows/label_pr_on_title.yml +++ b/.github/workflows/label_pr_on_title.yml @@ -26,6 +26,9 @@ on: types: - completed +permissions: + contents: read + jobs: get_pr_details: permissions: diff --git a/.github/workflows/on_closed_issues.yml b/.github/workflows/on_closed_issues.yml index 9b8af4a7690..61a14b028d4 100644 --- a/.github/workflows/on_closed_issues.yml +++ b/.github/workflows/on_closed_issues.yml @@ -12,6 +12,9 @@ name: Closed Issue Message on: issues: types: [closed] +permissions: + contents: read + jobs: auto_comment: runs-on: ubuntu-latest diff --git a/.github/workflows/on_label_added.yml b/.github/workflows/on_label_added.yml index 17ee840a7ea..d378a5d3e9d 100644 --- a/.github/workflows/on_label_added.yml +++ b/.github/workflows/on_label_added.yml @@ -25,6 +25,9 @@ on: types: - completed +permissions: + contents: read + jobs: get_pr_details: permissions: diff --git a/.github/workflows/on_merged_pr.yml b/.github/workflows/on_merged_pr.yml index e9ac01f1c17..f3896118d10 100644 --- a/.github/workflows/on_merged_pr.yml +++ b/.github/workflows/on_merged_pr.yml @@ -26,6 +26,9 @@ on: types: - completed +permissions: + contents: read + jobs: get_pr_details: permissions: diff --git a/.github/workflows/on_opened_pr.yml b/.github/workflows/on_opened_pr.yml index 5e7914b09a3..79e77bd9488 100644 --- a/.github/workflows/on_opened_pr.yml +++ b/.github/workflows/on_opened_pr.yml @@ -26,6 +26,9 @@ on: types: - completed +permissions: + contents: read + jobs: get_pr_details: permissions: diff --git a/.github/workflows/on_push_docs.yml b/.github/workflows/on_push_docs.yml index ec6e14c4273..fc1aa3786e6 100644 --- a/.github/workflows/on_push_docs.yml +++ b/.github/workflows/on_push_docs.yml @@ -20,6 +20,9 @@ on: - "examples/**" - "CHANGELOG.md" +permissions: + contents: read + jobs: release-docs: permissions: diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index 67a073e627b..864fc74241a 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -49,6 +49,9 @@ on: type: boolean required: false +permissions: + contents: read + jobs: build-layer: permissions: diff --git a/.github/workflows/quality_check.yml b/.github/workflows/quality_check.yml index 51eebc668ff..74da419bab3 100644 --- a/.github/workflows/quality_check.yml +++ b/.github/workflows/quality_check.yml @@ -35,6 +35,9 @@ on: branches: - develop +permissions: + contents: read + jobs: quality_check: runs-on: ubuntu-latest diff --git a/.github/workflows/rebuild_latest_docs.yml b/.github/workflows/rebuild_latest_docs.yml index 927d6f8dc91..665cad81dd1 100644 --- a/.github/workflows/rebuild_latest_docs.yml +++ b/.github/workflows/rebuild_latest_docs.yml @@ -23,6 +23,9 @@ on: default: "2.16.3" required: true +permissions: + contents: read + jobs: release-docs: permissions: diff --git a/.github/workflows/record_pr.yml b/.github/workflows/record_pr.yml index 55377f06981..0cdcb9bc8ad 100644 --- a/.github/workflows/record_pr.yml +++ b/.github/workflows/record_pr.yml @@ -37,6 +37,9 @@ on: pull_request: types: [opened, edited, closed, labeled] +permissions: + contents: read + jobs: record_pr: runs-on: ubuntu-latest diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 1f766d070d9..8781eba3bef 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -18,6 +18,9 @@ on: - develop workflow_dispatch: +permissions: + contents: read + jobs: update_release_draft: runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f7dfedeec00..566fe9db3da 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,6 +51,9 @@ on: type: boolean required: false +permissions: + contents: read + jobs: # This job bumps the package version to the release version diff --git a/.github/workflows/reusable_deploy_v2_layer_stack.yml b/.github/workflows/reusable_deploy_v2_layer_stack.yml index 04abcfaee1b..76b6950267c 100644 --- a/.github/workflows/reusable_deploy_v2_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v2_layer_stack.yml @@ -47,6 +47,9 @@ on: required: true type: string +permissions: + contents: read + jobs: deploy-cdk-stack: runs-on: ubuntu-latest diff --git a/.github/workflows/reusable_export_pr_details.yml b/.github/workflows/reusable_export_pr_details.yml index c81c0915af4..30eb9241b08 100644 --- a/.github/workflows/reusable_export_pr_details.yml +++ b/.github/workflows/reusable_export_pr_details.yml @@ -50,6 +50,9 @@ on: description: "Whether PR is merged" value: ${{ jobs.export_pr_details.outputs.prIsMerged }} +permissions: + contents: read + jobs: export_pr_details: permissions: diff --git a/.github/workflows/reusable_publish_changelog.yml b/.github/workflows/reusable_publish_changelog.yml index 23139b77729..1df1ceb5953 100644 --- a/.github/workflows/reusable_publish_changelog.yml +++ b/.github/workflows/reusable_publish_changelog.yml @@ -10,6 +10,9 @@ env: PULL_REQUEST_TITLE: "chore(ci): changelog rebuild" FILES_TO_COMMIT: "CHANGELOG.md" +permissions: + contents: read + jobs: publish_changelog: # Force Github action to run only a single job at a time (based on the group name) diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 7648eb77c53..8173596769f 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -35,6 +35,9 @@ env: concurrency: e2e +permissions: + contents: read + jobs: run: runs-on: aws-powertools_ubuntu-latest_8-core diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml index 1430e91d6f2..bf0823b091b 100644 --- a/.github/workflows/secure_workflows.yml +++ b/.github/workflows/secure_workflows.yml @@ -19,6 +19,9 @@ on: paths: - ".github/workflows/**" +permissions: + contents: read + jobs: enforce_pinned_workflows: name: Harden Security From c246e66a346ed0550a587aedc38bdf23e60efa13 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Tue, 4 Jul 2023 14:15:53 +0200 Subject: [PATCH 09/73] chore(ci): propagate checkout permission to nested workflows (#2642) --- .github/workflows/label_pr_on_title.yml | 1 + .github/workflows/on_label_added.yml | 1 + .github/workflows/on_merged_pr.yml | 1 + .github/workflows/on_opened_pr.yml | 1 + .github/workflows/on_pr_updates.yml | 4 ++-- 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/label_pr_on_title.yml b/.github/workflows/label_pr_on_title.yml index 48fb24b2476..c69f0f8d7a8 100644 --- a/.github/workflows/label_pr_on_title.yml +++ b/.github/workflows/label_pr_on_title.yml @@ -33,6 +33,7 @@ jobs: get_pr_details: permissions: actions: read # download PR artifact + contents: read # checkout code # Guardrails to only ever run if PR recording workflow was indeed # run in a PR event and ran successfully if: ${{ github.event.workflow_run.conclusion == 'success' }} diff --git a/.github/workflows/on_label_added.yml b/.github/workflows/on_label_added.yml index d378a5d3e9d..8f7194097e3 100644 --- a/.github/workflows/on_label_added.yml +++ b/.github/workflows/on_label_added.yml @@ -32,6 +32,7 @@ jobs: get_pr_details: permissions: actions: read # download PR artifact + contents: read # checkout code if: ${{ github.event.workflow_run.conclusion == 'success' }} uses: ./.github/workflows/reusable_export_pr_details.yml with: diff --git a/.github/workflows/on_merged_pr.yml b/.github/workflows/on_merged_pr.yml index f3896118d10..e435d59951d 100644 --- a/.github/workflows/on_merged_pr.yml +++ b/.github/workflows/on_merged_pr.yml @@ -33,6 +33,7 @@ jobs: get_pr_details: permissions: actions: read # download PR artifact + contents: read # checkout code if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' uses: ./.github/workflows/reusable_export_pr_details.yml with: diff --git a/.github/workflows/on_opened_pr.yml b/.github/workflows/on_opened_pr.yml index 79e77bd9488..1b9cb2f4de2 100644 --- a/.github/workflows/on_opened_pr.yml +++ b/.github/workflows/on_opened_pr.yml @@ -33,6 +33,7 @@ jobs: get_pr_details: permissions: actions: read # download PR artifact + contents: read # checkout code if: ${{ github.event.workflow_run.conclusion == 'success' }} uses: ./.github/workflows/reusable_export_pr_details.yml with: diff --git a/.github/workflows/on_pr_updates.yml b/.github/workflows/on_pr_updates.yml index 003bc0880a8..2663d707399 100644 --- a/.github/workflows/on_pr_updates.yml +++ b/.github/workflows/on_pr_updates.yml @@ -17,7 +17,7 @@ name: PR requirements # due to limitations in GH API. on: - pull_request: + pull_request: types: - opened - labeled @@ -26,7 +26,7 @@ on: permissions: {} # no permission required jobs: - fail-for-draft: + check-requirements: runs-on: ubuntu-latest steps: - name: Block if it doesn't minimum requirements From 783e2424e700d1aaaadc6f05189cabcafb7c7dbf Mon Sep 17 00:00:00 2001 From: Simon Thulbourn Date: Tue, 4 Jul 2023 15:33:30 +0200 Subject: [PATCH 10/73] fix(docs): ensure alias is applied to versioned releases (#2644) --- .github/workflows/reusable_publish_docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index 829f1f80152..3ca16a25b5a 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -120,7 +120,7 @@ jobs: s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-python/versions.json \ versions_old.json jq 'del(.[].aliases[] | select(. == "${{ env.ALIAS }}"))' < versions_old.json > versions_proc.json - jq '. as $o | [{"title": "${{ env.VERSION }}", "version": "${{ env.VERSION }}", "aliases": ["${{env.ALIAS}}"] }] as $n | $n | if .[0].title | test("[a-z]+") or any($o[].title == "${{ env.VERSION }}";.) then $o else $n + $o end' < versions_proc.json > versions.json + jq '. as $o | [{"title": "${{ env.VERSION }}", "version": "${{ env.VERSION }}", "aliases": ["${{ env.ALIAS }}"] }] as $n | $n | if .[0].title | test("[a-z]+") or any($o[].title == $n[0].title;.) then [($o | .[] | select(.title == $n[0].title).aliases += $n[0].aliases | . )] else $n + $o end' < versions_proc.json > versions.json aws s3 cp \ versions.json \ s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-python/versions.json From e1e9d6045072ca008a90e775943b89d5978fb274 Mon Sep 17 00:00:00 2001 From: StepSecurity Bot Date: Tue, 4 Jul 2023 08:50:01 -0700 Subject: [PATCH 11/73] chore(ci): improves dependabot based on ossf scorecard recommendations (#2647) --- .github/dependabot.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8ee55d976b0..b77092dc807 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -46,3 +46,28 @@ updates: # commit-message: # prefix: chore # include: scope + + - package-ecosystem: pip + directory: /benchmark/src/instrumented + schedule: + interval: daily + + - package-ecosystem: pip + directory: /benchmark/src/reference + schedule: + interval: daily + + - package-ecosystem: docker + directory: /docs + schedule: + interval: daily + + - package-ecosystem: pip + directory: /examples/event_handler_graphql/src + schedule: + interval: daily + + - package-ecosystem: gomod + directory: /layer/scripts/layer-balancer + schedule: + interval: daily From 2fc0588f32f24feddca0361f078cb4b2682be414 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:02:55 +0200 Subject: [PATCH 12/73] chore(deps): bump github.com/aws/aws-sdk-go-v2 from 1.16.16 to 1.18.1 in /layer/scripts/layer-balancer (#2654) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 6 +++--- layer/scripts/layer-balancer/go.sum | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index fba6faafc2f..a264b493c45 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -3,9 +3,10 @@ module layerbalancer go 1.18 require ( - github.com/aws/aws-sdk-go-v2 v1.16.16 + github.com/aws/aws-sdk-go-v2 v1.18.1 github.com/aws/aws-sdk-go-v2/config v1.17.8 github.com/aws/aws-sdk-go-v2/service/lambda v1.24.6 + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.1.0 ) @@ -19,7 +20,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 // indirect - github.com/aws/smithy-go v1.13.3 // indirect + github.com/aws/smithy-go v1.13.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index a23150519d8..d1e3eb65872 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,5 +1,6 @@ -github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= +github.com/aws/aws-sdk-go-v2 v1.18.1 h1:+tefE750oAb7ZQGzla6bLkOwfcQCEtC5y2RqoqCeqKo= +github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/config v1.17.8 h1:b9LGqNnOdg9vR4Q43tBTVWk4J6F+W774MSchvKJsqnE= github.com/aws/aws-sdk-go-v2/config v1.17.8/go.mod h1:UkCI3kb0sCdvtjiXYiU4Zx5h07BOpgBTtkPu/49r+kA= github.com/aws/aws-sdk-go-v2/credentials v1.12.21 h1:4tjlyCD0hRGNQivh5dN8hbP30qQhMLBE/FgQR1vHHWM= @@ -22,13 +23,18 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 h1:OwhhKc1P9ElfWbMKPIbMMZBV github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6/go.mod h1:csZuQY65DAdFBt1oIjO5hhBR49kQqop4+lcuCjf2arA= github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 h1:9pPi0PsFNAGILFfPCk8Y0iyEBGc6lu6OQ97U7hmdesg= github.com/aws/aws-sdk-go-v2/service/sts v1.16.19/go.mod h1:h4J3oPZQbxLhzGnk+j9dfYHi5qIOVJ5kczZd658/ydM= -github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA= github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= +github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= @@ -36,4 +42,5 @@ golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 991c7185d0a9533af6f592fac36bc8bc874a506f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:03:44 +0200 Subject: [PATCH 13/73] chore(deps): bump actions/dependency-review-action from 2.5.1 to 3.0.6 (#2650) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 627c9ca205b..1ffd05de307 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -19,4 +19,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: 'Dependency Review' - uses: actions/dependency-review-action@0efb1d1d84fc9633afcdaad14c485cbbc90ef46c # v2.5.1 + uses: actions/dependency-review-action@1360a344ccb0ab6e9475edef90ad2f46bf8003b1 # v3.0.6 From 4760b6a9fc00bdc02e5ba2cab83775c9bd7597f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:04:16 +0200 Subject: [PATCH 14/73] chore(deps): bump golang.org/x/sync from 0.1.0 to 0.3.0 in /layer/scripts/layer-balancer (#2649) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 2 +- layer/scripts/layer-balancer/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index a264b493c45..c93602bcd75 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -7,7 +7,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.17.8 github.com/aws/aws-sdk-go-v2/service/lambda v1.24.6 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 - golang.org/x/sync v0.1.0 + golang.org/x/sync v0.3.0 ) require ( diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index d1e3eb65872..d808fb0c29e 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -39,8 +39,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 8595f1b2deeabf391c38dc4988977a63fbd27dae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:04:44 +0200 Subject: [PATCH 15/73] chore(deps): bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.24.6 to 1.37.0 in /layer/scripts/layer-balancer (#2653) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 7 ++++--- layer/scripts/layer-balancer/go.sum | 12 ++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index c93602bcd75..41625d33151 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -5,16 +5,17 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.18.1 github.com/aws/aws-sdk-go-v2/config v1.17.8 - github.com/aws/aws-sdk-go-v2/service/lambda v1.24.6 + github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 ) require ( + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.12.21 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index d808fb0c29e..b591762cb95 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,22 +1,26 @@ github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= github.com/aws/aws-sdk-go-v2 v1.18.1 h1:+tefE750oAb7ZQGzla6bLkOwfcQCEtC5y2RqoqCeqKo= github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= github.com/aws/aws-sdk-go-v2/config v1.17.8 h1:b9LGqNnOdg9vR4Q43tBTVWk4J6F+W774MSchvKJsqnE= github.com/aws/aws-sdk-go-v2/config v1.17.8/go.mod h1:UkCI3kb0sCdvtjiXYiU4Zx5h07BOpgBTtkPu/49r+kA= github.com/aws/aws-sdk-go-v2/credentials v1.12.21 h1:4tjlyCD0hRGNQivh5dN8hbP30qQhMLBE/FgQR1vHHWM= github.com/aws/aws-sdk-go-v2/credentials v1.12.21/go.mod h1:O+4XyAt4e+oBAoIwNUYkRg3CVMscaIJdmZBOcPgJ8D8= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 h1:r08j4sbZu/RVi+BNxkBJwPMUYY3P8mgSDuKkZ/ZN1lE= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17/go.mod h1:yIkQcCDYNsZfXpd5UX2Cy+sWA1jPgIhGTw9cOBzfVnQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 h1:s4g/wnzMf+qepSNgTvaQQHNxyMLKSawNhKCPNy++2xY= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 h1:/K482T5A3623WJgWT8w1yRAFK4RzGzEl7y39yhtn9eA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 h1:A5UqQEmPaCFpedKouS4v+dHCTUo2sKqhoKO9U5kxyWo= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34/go.mod h1:wZpTEecJe0Btj3IYnDx/VlUzor9wm3fJHyvLpQF0VwY= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 h1:srIVS45eQuewqz6fKKu6ZGXaq6FuFg5NzgQBAM6g8Y4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28/go.mod h1:7VRpKQQedkfIEXb4k52I7swUnZP0wohVajJMRn3vsUw= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 h1:wj5Rwc05hvUSvKuOF29IYb9QrCLjU+rHAy/x/o0DK2c= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24/go.mod h1:jULHjqqjDlbyTa7pfM7WICATnOv+iOhjletM3N0Xbu8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 h1:Jrd/oMh0PKQc6+BowB+pLEwLIgaQF29eYbe7E1Av9Ug= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI= -github.com/aws/aws-sdk-go-v2/service/lambda v1.24.6 h1:N7RkXX2SJbN+TCp295J3LdMR0KRFd2Bhi5nIO+svLQY= -github.com/aws/aws-sdk-go-v2/service/lambda v1.24.6/go.mod h1:oTJIIluTaJCRT6xP1AZpuU3JwRHBC0Q5O4Hg+SUxFHw= +github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 h1:xzyM5ZR9kZW0/Bkw5EiihOy6B+BYclp5K+yb6OHjc7s= +github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0/go.mod h1:Q8zQi5nZpjUF/H55dKEpKfEvFWJkgZzjjqvDb2AR5b4= github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 h1:pwvCchFUEnlceKIgPUouBJwK81aCkQ8UDMORfeFtW10= github.com/aws/aws-sdk-go-v2/service/sso v1.11.23/go.mod h1:/w0eg9IhFGjGyyncHIQrXtU8wvNsTJOP0R6PPj0wf80= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 h1:OwhhKc1P9ElfWbMKPIbMMZBV6hzJlL2JKD76wNNVzgQ= From 38b096711bc578f4b2ed0e9d476e2f547173b886 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:06:58 +0200 Subject: [PATCH 16/73] chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.17.8 to 1.18.27 in /layer/scripts/layer-balancer (#2651) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 16 ++++++------- layer/scripts/layer-balancer/go.sum | 36 +++++++++++++---------------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index 41625d33151..2bf2bb59af0 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.18.1 - github.com/aws/aws-sdk-go-v2/config v1.17.8 + github.com/aws/aws-sdk-go-v2/config v1.18.27 github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 @@ -12,15 +12,15 @@ require ( require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.12.21 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.26 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index b591762cb95..a006ad16887 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,33 +1,29 @@ -github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= github.com/aws/aws-sdk-go-v2 v1.18.1 h1:+tefE750oAb7ZQGzla6bLkOwfcQCEtC5y2RqoqCeqKo= github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= -github.com/aws/aws-sdk-go-v2/config v1.17.8 h1:b9LGqNnOdg9vR4Q43tBTVWk4J6F+W774MSchvKJsqnE= -github.com/aws/aws-sdk-go-v2/config v1.17.8/go.mod h1:UkCI3kb0sCdvtjiXYiU4Zx5h07BOpgBTtkPu/49r+kA= -github.com/aws/aws-sdk-go-v2/credentials v1.12.21 h1:4tjlyCD0hRGNQivh5dN8hbP30qQhMLBE/FgQR1vHHWM= -github.com/aws/aws-sdk-go-v2/credentials v1.12.21/go.mod h1:O+4XyAt4e+oBAoIwNUYkRg3CVMscaIJdmZBOcPgJ8D8= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 h1:r08j4sbZu/RVi+BNxkBJwPMUYY3P8mgSDuKkZ/ZN1lE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17/go.mod h1:yIkQcCDYNsZfXpd5UX2Cy+sWA1jPgIhGTw9cOBzfVnQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= +github.com/aws/aws-sdk-go-v2/config v1.18.27 h1:Az9uLwmssTE6OGTpsFqOnaGpLnKDqNYOJzWuC6UAYzA= +github.com/aws/aws-sdk-go-v2/config v1.18.27/go.mod h1:0My+YgmkGxeqjXZb5BYme5pc4drjTnM+x1GJ3zv42Nw= +github.com/aws/aws-sdk-go-v2/credentials v1.13.26 h1:qmU+yhKmOCyujmuPY7tf5MxR/RKyZrOPO3V4DobiTUk= +github.com/aws/aws-sdk-go-v2/credentials v1.13.26/go.mod h1:GoXt2YC8jHUBbA4jr+W3JiemnIbkXOfxSXcisUsZ3os= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 h1:LxK/bitrAr4lnh9LnIS6i7zWbCOdMsfzKFBI6LUCS0I= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4/go.mod h1:E1hLXN/BL2e6YizK1zFlYd8vsfi2GTjbjBazinMmeaM= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 h1:A5UqQEmPaCFpedKouS4v+dHCTUo2sKqhoKO9U5kxyWo= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34/go.mod h1:wZpTEecJe0Btj3IYnDx/VlUzor9wm3fJHyvLpQF0VwY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 h1:srIVS45eQuewqz6fKKu6ZGXaq6FuFg5NzgQBAM6g8Y4= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28/go.mod h1:7VRpKQQedkfIEXb4k52I7swUnZP0wohVajJMRn3vsUw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 h1:wj5Rwc05hvUSvKuOF29IYb9QrCLjU+rHAy/x/o0DK2c= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24/go.mod h1:jULHjqqjDlbyTa7pfM7WICATnOv+iOhjletM3N0Xbu8= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 h1:Jrd/oMh0PKQc6+BowB+pLEwLIgaQF29eYbe7E1Av9Ug= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 h1:LWA+3kDM8ly001vJ1X1waCuLJdtTl48gwkPKWy9sosI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35/go.mod h1:0Eg1YjxE0Bhn56lx+SHJwCzhW+2JGtizsrx+lCqrfm0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 h1:bkRyG4a929RCnpVSTvLM2j/T4ls015ZhhYApbmYs15s= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28/go.mod h1:jj7znCIg05jXlaGBlFMGP8+7UN3VtCkRBG2spnmRQkU= github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 h1:xzyM5ZR9kZW0/Bkw5EiihOy6B+BYclp5K+yb6OHjc7s= github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0/go.mod h1:Q8zQi5nZpjUF/H55dKEpKfEvFWJkgZzjjqvDb2AR5b4= -github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 h1:pwvCchFUEnlceKIgPUouBJwK81aCkQ8UDMORfeFtW10= -github.com/aws/aws-sdk-go-v2/service/sso v1.11.23/go.mod h1:/w0eg9IhFGjGyyncHIQrXtU8wvNsTJOP0R6PPj0wf80= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 h1:OwhhKc1P9ElfWbMKPIbMMZBV6hzJlL2JKD76wNNVzgQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6/go.mod h1:csZuQY65DAdFBt1oIjO5hhBR49kQqop4+lcuCjf2arA= -github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 h1:9pPi0PsFNAGILFfPCk8Y0iyEBGc6lu6OQ97U7hmdesg= -github.com/aws/aws-sdk-go-v2/service/sts v1.16.19/go.mod h1:h4J3oPZQbxLhzGnk+j9dfYHi5qIOVJ5kczZd658/ydM= -github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 h1:nneMBM2p79PGWBQovYO/6Xnc2ryRMw3InnDJq1FHkSY= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.12/go.mod h1:HuCOxYsF21eKrerARYO6HapNeh9GBNq7fius2AcwodY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 h1:2qTR7IFk7/0IN/adSFhYu9Xthr0zVFTgBrmPldILn80= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12/go.mod h1:E4VrHCPzmVB/KFXtqBGKb3c8zpbNBgKe3fisDNLAW5w= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 h1:XFJ2Z6sNUUcAz9poj+245DMkrHE4h2j5I9/xD50RHfE= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.2/go.mod h1:dp0yLPsLBOi++WTxzCjA/oZqi6NPIhoR+uF7GeMU9eg= github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= From 0c80f35fa36d0a2693a8e4c0c98fa26bc92ee0ad Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Tue, 4 Jul 2023 18:16:42 +0200 Subject: [PATCH 17/73] chore(ci): use deps sha for docs and gitpod images based on ossf findings (#2662) --- .gitpod.Dockerfile | 3 +- docs/Dockerfile | 7 +- docs/requirements.in | 1 + docs/requirements.txt | 198 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 docs/requirements.in create mode 100644 docs/requirements.txt diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index 2b055dd9348..6703482891b 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -7,4 +7,5 @@ ADD . /app # Installing pre-commit as system package and not user package. Git needs this to execute pre-commit hooks. RUN export PIP_USER=no -RUN python3 -m pip install pre-commit +# v3.3.3 +RUN python3 -m pip install git+https://github.com/pre-commit/pre-commit@5da4258b17dea7bd4601358de200e185699f9997 \ No newline at end of file diff --git a/docs/Dockerfile b/docs/Dockerfile index 7bf267f4f32..05f56df28ef 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,2 +1,5 @@ -FROM squidfunk/mkdocs-material -RUN pip install mkdocs-git-revision-date-plugin +# v9.1.18 +FROM squidfunk/mkdocs-material@sha256:3837c0f327033a6946a2810760fe80ee1f02fceda4f817638ea69c612b2db837 +# pip-compile --generate-hashes --output-file=requirements.txt requirements.in +COPY requirements.txt /tmp/ +RUN pip install -r /tmp/requirements.txt diff --git a/docs/requirements.in b/docs/requirements.in new file mode 100644 index 00000000000..2424249a446 --- /dev/null +++ b/docs/requirements.in @@ -0,0 +1 @@ +mkdocs-git-revision-date-plugin==0.3.2 diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000000..5030fc70306 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,198 @@ +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# pip-compile --generate-hashes --output-file=requirements.txt requirements.in +# +click==8.1.3 \ + --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ + --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 + # via mkdocs +ghp-import==2.1.0 \ + --hash=sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 \ + --hash=sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343 + # via mkdocs +gitdb==4.0.10 \ + --hash=sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a \ + --hash=sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7 + # via gitpython +gitpython==3.1.31 \ + --hash=sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573 \ + --hash=sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d + # via mkdocs-git-revision-date-plugin +importlib-metadata==6.7.0 \ + --hash=sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4 \ + --hash=sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5 + # via + # markdown + # mkdocs +jinja2==3.1.2 \ + --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ + --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 + # via + # mkdocs + # mkdocs-git-revision-date-plugin +markdown==3.3.7 \ + --hash=sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874 \ + --hash=sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621 + # via mkdocs +markupsafe==2.1.3 \ + --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \ + --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \ + --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \ + --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \ + --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \ + --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \ + --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \ + --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \ + --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \ + --hash=sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9 \ + --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \ + --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \ + --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \ + --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \ + --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \ + --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \ + --hash=sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac \ + --hash=sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52 \ + --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \ + --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \ + --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \ + --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \ + --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \ + --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \ + --hash=sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0 \ + --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \ + --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \ + --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \ + --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \ + --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \ + --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \ + --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \ + --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \ + --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \ + --hash=sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad \ + --hash=sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee \ + --hash=sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc \ + --hash=sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2 \ + --hash=sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48 \ + --hash=sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7 \ + --hash=sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e \ + --hash=sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b \ + --hash=sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa \ + --hash=sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5 \ + --hash=sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e \ + --hash=sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb \ + --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \ + --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \ + --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \ + --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 + # via jinja2 +mergedeep==1.3.4 \ + --hash=sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8 \ + --hash=sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 + # via mkdocs +mkdocs==1.4.3 \ + --hash=sha256:5955093bbd4dd2e9403c5afaf57324ad8b04f16886512a3ee6ef828956481c57 \ + --hash=sha256:6ee46d309bda331aac915cd24aab882c179a933bd9e77b80ce7d2eaaa3f689dd + # via mkdocs-git-revision-date-plugin +mkdocs-git-revision-date-plugin==0.3.2 \ + --hash=sha256:2e67956cb01823dd2418e2833f3623dee8604cdf223bddd005fe36226a56f6ef + # via -r requirements.in +packaging==23.1 \ + --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ + --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f + # via mkdocs +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via ghp-import +pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via + # mkdocs + # pyyaml-env-tag +pyyaml-env-tag==0.1 \ + --hash=sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb \ + --hash=sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069 + # via mkdocs +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via python-dateutil +smmap==5.0.0 \ + --hash=sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94 \ + --hash=sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936 + # via gitdb +watchdog==3.0.0 \ + --hash=sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a \ + --hash=sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100 \ + --hash=sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8 \ + --hash=sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc \ + --hash=sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae \ + --hash=sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41 \ + --hash=sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0 \ + --hash=sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f \ + --hash=sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c \ + --hash=sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9 \ + --hash=sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3 \ + --hash=sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709 \ + --hash=sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83 \ + --hash=sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759 \ + --hash=sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9 \ + --hash=sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3 \ + --hash=sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7 \ + --hash=sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f \ + --hash=sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346 \ + --hash=sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674 \ + --hash=sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397 \ + --hash=sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96 \ + --hash=sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d \ + --hash=sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a \ + --hash=sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64 \ + --hash=sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44 \ + --hash=sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33 + # via mkdocs +zipp==3.15.0 \ + --hash=sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b \ + --hash=sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556 + # via importlib-metadata From 39b70342c0c902ac9c5027bdd514cd2a9a7edafe Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Tue, 4 Jul 2023 18:19:33 +0200 Subject: [PATCH 18/73] chore(ci): use sast on every commit on any supported language (#2646) --- .github/workflows/codeql-analysis.yml | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d8ef363c8f9..b728a4c2400 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -12,10 +12,7 @@ name: "CodeQL" on: push: - paths: - - "aws_lambda_powertools/**" - branches: - - develop + branches: [develop] permissions: contents: read @@ -28,15 +25,6 @@ jobs: security-events: write actions: read - strategy: - fail-fast: false - matrix: - # Override automatic language detection by changing the below list - # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] - language: ["python"] - # Learn more... - # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection - steps: - name: Checkout repository uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -44,12 +32,6 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@f31a31c052207cc13b328d6295c5b728bb49568c # v2.13.1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@f31a31c052207cc13b328d6295c5b728bb49568c # v2.13.1 From 088b7cfb6db2a2ed8a88ff3fbd86ca89c7605706 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Tue, 4 Jul 2023 18:30:56 +0200 Subject: [PATCH 19/73] chore(deps): migrate from retry to retry2 to address CVE-2022-42969 (#2665) --- poetry.lock | 171 ++++--------------------------------------------- pyproject.toml | 2 +- 2 files changed, 15 insertions(+), 158 deletions(-) diff --git a/poetry.lock b/poetry.lock index 876339a69f7..229470d3e5f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "anyio" version = "3.7.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -27,7 +26,6 @@ trio = ["trio (<0.22)"] name = "attrs" version = "23.1.0" description = "Classes Without Boilerplate" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -49,7 +47,6 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte name = "aws-cdk-asset-awscli-v1" version = "2.2.200" description = "A library that contains the AWS CLI for use in Lambda Layers" -category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -66,7 +63,6 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-cdk-asset-kubectl-v20" version = "2.1.2" description = "A library that contains kubectl for use in Lambda Layers" -category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -83,7 +79,6 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-cdk-asset-node-proxy-agent-v5" version = "2.0.165" description = "@aws-cdk/asset-node-proxy-agent-v5" -category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -100,7 +95,6 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-cdk-aws-apigatewayv2-alpha" version = "2.86.0a0" description = "The CDK Construct Library for AWS::APIGatewayv2" -category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -119,7 +113,6 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-cdk-aws-apigatewayv2-authorizers-alpha" version = "2.86.0a0" description = "Authorizers for AWS APIGateway V2" -category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -139,7 +132,6 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-cdk-aws-apigatewayv2-integrations-alpha" version = "2.86.0a0" description = "Integrations for AWS APIGateway V2" -category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -159,7 +151,6 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-cdk-lib" version = "2.86.0" description = "Version 2 of the AWS Cloud Development Kit library" -category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -180,7 +171,6 @@ typeguard = ">=2.13.3,<2.14.0" name = "aws-requests-auth" version = "0.4.3" description = "AWS signature version 4 signing process for the python requests module" -category = "dev" optional = false python-versions = "*" files = [ @@ -195,7 +185,6 @@ requests = ">=0.14.0" name = "aws-sam-translator" version = "1.70.0" description = "AWS SAM Translator is a library that transform SAM templates into AWS CloudFormation templates" -category = "dev" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ @@ -204,19 +193,18 @@ files = [ ] [package.dependencies] -boto3 = ">=1.19.5,<2.0.0" +boto3 = ">=1.19.5,<2.dev0" jsonschema = ">=3.2,<5" pydantic = ">=1.8,<2.0" typing-extensions = ">=4.4,<5" [package.extras] -dev = ["black (==23.1.0)", "boto3 (>=1.23,<2)", "boto3-stubs[appconfig,serverlessrepo] (>=1.19.5,<2.0.0)", "coverage (>=5.3,<8)", "dateparser (>=1.1,<2.0)", "importlib-metadata", "mypy (>=1.1.0,<1.2.0)", "parameterized (>=0.7,<1.0)", "pytest (>=6.2,<8)", "pytest-cov (>=2.10,<5)", "pytest-env (>=0.6,<1)", "pytest-rerunfailures (>=9.1,<12)", "pytest-xdist (>=2.5,<4)", "pyyaml (>=6.0,<7.0)", "requests (>=2.28,<3.0)", "ruamel.yaml (==0.17.21)", "ruff (==0.0.263)", "tenacity (>=8.0,<9.0)", "types-PyYAML (>=6.0,<7.0)", "types-jsonschema (>=3.2,<4.0)"] +dev = ["black (==23.1.0)", "boto3 (>=1.23,<2)", "boto3-stubs[appconfig,serverlessrepo] (>=1.19.5,<2.dev0)", "coverage (>=5.3,<8)", "dateparser (>=1.1,<2.0)", "importlib-metadata", "mypy (>=1.1.0,<1.2.0)", "parameterized (>=0.7,<1.0)", "pytest (>=6.2,<8)", "pytest-cov (>=2.10,<5)", "pytest-env (>=0.6,<1)", "pytest-rerunfailures (>=9.1,<12)", "pytest-xdist (>=2.5,<4)", "pyyaml (>=6.0,<7.0)", "requests (>=2.28,<3.0)", "ruamel.yaml (==0.17.21)", "ruff (==0.0.263)", "tenacity (>=8.0,<9.0)", "types-PyYAML (>=6.0,<7.0)", "types-jsonschema (>=3.2,<4.0)"] [[package]] name = "aws-xray-sdk" version = "2.12.0" description = "The AWS X-Ray SDK for Python (the SDK) enables Python developers to record and emit information from within their applications to the AWS X-Ray service." -category = "main" optional = true python-versions = "*" files = [ @@ -232,7 +220,6 @@ wrapt = "*" name = "bandit" version = "1.7.5" description = "Security oriented static analyser for python code." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -256,7 +243,6 @@ yaml = ["PyYAML"] name = "black" version = "23.3.0" description = "The uncompromising code formatter." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -307,7 +293,6 @@ uvloop = ["uvloop (>=0.15.2)"] name = "boto3" version = "1.27.0" description = "The AWS SDK for Python" -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -327,7 +312,6 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] name = "botocore" version = "1.30.0" description = "Low-level, data-driven core of boto 3." -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -347,7 +331,6 @@ crt = ["awscrt (==0.16.9)"] name = "cattrs" version = "23.1.2" description = "Composable complex class support for attrs and dataclasses." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -373,7 +356,6 @@ ujson = ["ujson (>=5.4.0,<6.0.0)"] name = "certifi" version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -385,7 +367,6 @@ files = [ name = "cfn-lint" version = "0.77.10" description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved" -category = "dev" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ @@ -409,7 +390,6 @@ sympy = ">=1.0.0" name = "charset-normalizer" version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -494,7 +474,6 @@ files = [ name = "checksumdir" version = "1.2.0" description = "Compute a single hash of the file contents of a directory." -category = "dev" optional = false python-versions = ">=3.6,<4.0" files = [ @@ -506,7 +485,6 @@ files = [ name = "click" version = "8.1.3" description = "Composable command line interface toolkit" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -522,7 +500,6 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -534,7 +511,6 @@ files = [ name = "constructs" version = "10.2.67" description = "A programming model for software-defined state" -category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -551,7 +527,6 @@ typeguard = ">=2.13.3,<2.14.0" name = "coverage" version = "7.2.7" description = "Code coverage measurement for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -627,7 +602,6 @@ toml = ["tomli"] name = "decorator" version = "5.1.1" description = "Decorators for Humans" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -639,7 +613,6 @@ files = [ name = "exceptiongroup" version = "1.1.2" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -654,7 +627,6 @@ test = ["pytest (>=6)"] name = "execnet" version = "1.9.0" description = "execnet: rapid multi-Python deployment" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -669,7 +641,6 @@ testing = ["pre-commit"] name = "fastjsonschema" version = "2.17.1" description = "Fastest Python implementation of JSON schema" -category = "main" optional = true python-versions = "*" files = [ @@ -684,7 +655,6 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc name = "filelock" version = "3.12.2" description = "A platform independent file lock." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -700,7 +670,6 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "p name = "future" version = "0.18.3" description = "Clean single-source support for Python 3 and 2" -category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -711,7 +680,6 @@ files = [ name = "ghp-import" version = "2.1.0" description = "Copy your docs directly to the gh-pages branch." -category = "dev" optional = false python-versions = "*" files = [ @@ -729,7 +697,6 @@ dev = ["flake8", "markdown", "twine", "wheel"] name = "gitdb" version = "4.0.10" description = "Git Object Database" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -744,7 +711,6 @@ smmap = ">=3.0.1,<6" name = "gitpython" version = "3.1.31" description = "GitPython is a Python library used to interact with Git repositories" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -760,7 +726,6 @@ typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\"" name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -775,7 +740,6 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""} name = "httpcore" version = "0.17.2" description = "A minimal low-level HTTP client." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -787,17 +751,16 @@ files = [ anyio = ">=3.0,<5.0" certifi = "*" h11 = ">=0.13,<0.15" -sniffio = ">=1.0.0,<2.0.0" +sniffio = "==1.*" [package.extras] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] +socks = ["socksio (==1.*)"] [[package]] name = "httpx" version = "0.24.1" description = "The next generation HTTP client." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -813,15 +776,14 @@ sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] -cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<14)"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] +socks = ["socksio (==1.*)"] [[package]] name = "hvac" version = "1.1.1" description = "HashiCorp Vault API client" -category = "dev" optional = false python-versions = ">=3.6.2,<4.0.0" files = [ @@ -837,7 +799,6 @@ requests = ">=2.27.1,<3.0.0" name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -849,7 +810,6 @@ files = [ name = "ijson" version = "3.2.2" description = "Iterative JSON parser with standard Python iterator interfaces" -category = "dev" optional = false python-versions = "*" files = [ @@ -937,7 +897,6 @@ files = [ name = "importlib-metadata" version = "6.7.0" description = "Read metadata from Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -958,7 +917,6 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs name = "importlib-resources" version = "5.12.0" description = "Read resources from Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -977,7 +935,6 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -989,7 +946,6 @@ files = [ name = "isort" version = "5.11.5" description = "A Python utility / library to sort Python imports." -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -1007,7 +963,6 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1025,7 +980,6 @@ i18n = ["Babel (>=2.7)"] name = "jmespath" version = "1.0.1" description = "JSON Matching Expressions" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1037,7 +991,6 @@ files = [ name = "jschema-to-python" version = "1.2.3" description = "Generate source code for Python classes from a JSON schema." -category = "dev" optional = false python-versions = ">= 2.7" files = [ @@ -1054,7 +1007,6 @@ pbr = "*" name = "jsii" version = "1.84.0" description = "Python client for jsii runtime" -category = "dev" optional = false python-versions = "~=3.7" files = [ @@ -1075,11 +1027,11 @@ typing-extensions = ">=3.7,<5.0" name = "jsonpatch" version = "1.33" description = "Apply JSON-Patches (RFC 6902)" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, + {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, ] [package.dependencies] @@ -1089,7 +1041,6 @@ jsonpointer = ">=1.9" name = "jsonpickle" version = "3.0.1" description = "Python library for serializing any arbitrary object graph into JSON" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1109,18 +1060,17 @@ testing-libs = ["simplejson", "ujson"] name = "jsonpointer" version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, ] [[package]] name = "jsonschema" version = "4.17.3" description = "An implementation of JSON Schema validation for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1144,7 +1094,6 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "junit-xml" version = "1.9" description = "Creates JUnit XML test result documents that can be read by tools such as Jenkins" -category = "dev" optional = false python-versions = "*" files = [ @@ -1159,7 +1108,6 @@ six = "*" name = "mako" version = "1.2.4" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1180,7 +1128,6 @@ testing = ["pytest"] name = "mando" version = "0.6.4" description = "Create Python CLI apps with little to no effort at all!" -category = "dev" optional = false python-versions = "*" files = [ @@ -1198,7 +1145,6 @@ restructuredtext = ["rst2ansi"] name = "markdown" version = "3.3.7" description = "Python implementation of Markdown." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1216,7 +1162,6 @@ testing = ["coverage", "pyyaml"] name = "markdown-it-py" version = "2.2.0" description = "Python port of markdown-it. Markdown parsing, done right!" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1242,7 +1187,6 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1302,7 +1246,6 @@ files = [ name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1314,7 +1257,6 @@ files = [ name = "mergedeep" version = "1.3.4" description = "A deep merge function for 🐍." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1326,7 +1268,6 @@ files = [ name = "mike" version = "1.1.2" description = "Manage multiple versions of your MkDocs-powered documentation" -category = "dev" optional = false python-versions = "*" files = [ @@ -1348,7 +1289,6 @@ test = ["coverage", "flake8 (>=3.0)", "shtab"] name = "mkdocs" version = "1.4.3" description = "Project documentation with Markdown." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1378,7 +1318,6 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp name = "mkdocs-git-revision-date-plugin" version = "0.3.2" description = "MkDocs plugin for setting revision date from git per markdown file." -category = "dev" optional = false python-versions = ">=3.4" files = [ @@ -1394,7 +1333,6 @@ mkdocs = ">=0.17" name = "mkdocs-material" version = "9.1.18" description = "Documentation that simply works" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1417,7 +1355,6 @@ requests = ">=2.26" name = "mkdocs-material-extensions" version = "1.1.1" description = "Extension pack for Python Markdown and MkDocs Material." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1429,7 +1366,6 @@ files = [ name = "mpmath" version = "1.3.0" description = "Python library for arbitrary-precision floating-point arithmetic" -category = "dev" optional = false python-versions = "*" files = [ @@ -1447,7 +1383,6 @@ tests = ["pytest (>=4.6)"] name = "mypy" version = "1.4.1" description = "Optional static typing for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1495,7 +1430,6 @@ reports = ["lxml"] name = "mypy-boto3-appconfig" version = "1.27.0" description = "Type annotations for boto3.AppConfig 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1510,7 +1444,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-appconfigdata" version = "1.27.0" description = "Type annotations for boto3.AppConfigData 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1525,7 +1458,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-cloudformation" version = "1.27.0" description = "Type annotations for boto3.CloudFormation 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1540,7 +1472,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-cloudwatch" version = "1.27.0" description = "Type annotations for boto3.CloudWatch 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1555,7 +1486,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-dynamodb" version = "1.27.0" description = "Type annotations for boto3.DynamoDB 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1570,7 +1500,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-lambda" version = "1.27.0" description = "Type annotations for boto3.Lambda 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1585,7 +1514,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-logs" version = "1.27.0" description = "Type annotations for boto3.CloudWatchLogs 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1600,7 +1528,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-s3" version = "1.27.0" description = "Type annotations for boto3.S3 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1615,7 +1542,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-secretsmanager" version = "1.27.0" description = "Type annotations for boto3.SecretsManager 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1630,7 +1556,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-ssm" version = "1.27.0" description = "Type annotations for boto3.SSM 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1645,7 +1570,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-boto3-xray" version = "1.27.0" description = "Type annotations for boto3.XRay 1.27.0 service generated with mypy-boto3-builder 7.14.5" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1660,7 +1584,6 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1672,7 +1595,6 @@ files = [ name = "networkx" version = "2.6.3" description = "Python package for creating and manipulating graphs and networks" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1691,7 +1613,6 @@ test = ["codecov (>=2.1)", "pytest (>=6.2)", "pytest-cov (>=2.12)"] name = "packaging" version = "23.1" description = "Core utilities for Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1703,7 +1624,6 @@ files = [ name = "pathspec" version = "0.11.1" description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1715,7 +1635,6 @@ files = [ name = "pbr" version = "5.11.1" description = "Python Build Reasonableness" -category = "dev" optional = false python-versions = ">=2.6" files = [ @@ -1727,7 +1646,6 @@ files = [ name = "pdoc3" version = "0.10.0" description = "Auto-generate API documentation for Python projects." -category = "dev" optional = false python-versions = ">= 3.6" files = [ @@ -1743,7 +1661,6 @@ markdown = ">=3.0" name = "pkgutil-resolve-name" version = "1.3.10" description = "Resolve a name to an object." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1755,7 +1672,6 @@ files = [ name = "platformdirs" version = "3.8.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1774,7 +1690,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest- name = "pluggy" version = "1.2.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1793,7 +1708,6 @@ testing = ["pytest", "pytest-benchmark"] name = "publication" version = "0.0.3" description = "Publication helps you maintain public-api-friendly modules by preventing unintentional access to private implementation details via introspection." -category = "dev" optional = false python-versions = "*" files = [ @@ -1801,23 +1715,10 @@ files = [ {file = "publication-0.0.3.tar.gz", hash = "sha256:68416a0de76dddcdd2930d1c8ef853a743cc96c82416c4e4d3b5d901c6276dc4"}, ] -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] - [[package]] name = "py-cpuinfo" version = "9.0.0" description = "Get CPU info with pure Python" -category = "dev" optional = false python-versions = "*" files = [ @@ -1829,7 +1730,6 @@ files = [ name = "pydantic" version = "1.10.10" description = "Data validation and settings management using python type hints" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1882,7 +1782,6 @@ email = ["email-validator (>=1.0.3)"] name = "pygments" version = "2.15.1" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1897,7 +1796,6 @@ plugins = ["importlib-metadata"] name = "pyhcl" version = "0.4.4" description = "HCL configuration parser for python" -category = "dev" optional = false python-versions = "*" files = [ @@ -1908,7 +1806,6 @@ files = [ name = "pymdown-extensions" version = "10.0.1" description = "Extension pack for Python Markdown." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1924,7 +1821,6 @@ pyyaml = "*" name = "pyrsistent" version = "0.19.3" description = "Persistent/Functional/Immutable data structures" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1961,7 +1857,6 @@ files = [ name = "pytest" version = "7.4.0" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1985,7 +1880,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-asyncio" version = "0.21.0" description = "Pytest support for asyncio" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2005,7 +1899,6 @@ testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy name = "pytest-benchmark" version = "4.0.0" description = "A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2026,7 +1919,6 @@ histogram = ["pygal", "pygaljs"] name = "pytest-cov" version = "4.1.0" description = "Pytest plugin for measuring coverage." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2045,7 +1937,6 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-mock" version = "3.11.1" description = "Thin-wrapper around the mock package for easier use with pytest" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2063,7 +1954,6 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] name = "pytest-xdist" version = "3.3.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2084,7 +1974,6 @@ testing = ["filelock"] name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -2099,7 +1988,6 @@ six = ">=1.5" name = "python-snappy" version = "0.6.1" description = "Python library for the snappy compression library from Google" -category = "dev" optional = false python-versions = "*" files = [ @@ -2157,7 +2045,6 @@ files = [ name = "pyyaml" version = "6.0" description = "YAML parser and emitter for Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2207,7 +2094,6 @@ files = [ name = "pyyaml-env-tag" version = "0.1" description = "A custom YAML tag for referencing environment variables in YAML files. " -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2222,7 +2108,6 @@ pyyaml = "*" name = "radon" version = "5.1.0" description = "Code Metrics in Python" -category = "dev" optional = false python-versions = "*" files = [ @@ -2239,7 +2124,6 @@ mando = ">=0.6,<0.7" name = "regex" version = "2023.6.3" description = "Alternative regular expression module, to replace re." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2337,7 +2221,6 @@ files = [ name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2356,26 +2239,22 @@ socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] -name = "retry" -version = "0.9.2" +name = "retry2" +version = "0.9.5" description = "Easy to use retry decorator." -category = "dev" optional = false -python-versions = "*" +python-versions = ">=2.6" files = [ - {file = "retry-0.9.2-py2.py3-none-any.whl", hash = "sha256:ccddf89761fa2c726ab29391837d4327f819ea14d244c232a1d24c67a2f98606"}, - {file = "retry-0.9.2.tar.gz", hash = "sha256:f8bfa8b99b69c4506d6f5bd3b0aabf77f98cdb17f3c9fc3f5ca820033336fba4"}, + {file = "retry2-0.9.5-py2.py3-none-any.whl", hash = "sha256:f7fee13b1e15d0611c462910a6aa72a8919823988dd0412152bc3719c89a4e55"}, ] [package.dependencies] decorator = ">=3.4.2" -py = ">=1.4.26,<2.0.0" [[package]] name = "rich" version = "13.4.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -2395,7 +2274,6 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "ruff" version = "0.0.275" description = "An extremely fast Python linter, written in Rust." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2422,7 +2300,6 @@ files = [ name = "s3transfer" version = "0.6.1" description = "An Amazon S3 Transfer Manager" -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -2440,7 +2317,6 @@ crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] name = "sarif-om" version = "1.0.4" description = "Classes implementing the SARIF 2.1.0 object model." -category = "dev" optional = false python-versions = ">= 2.7" files = [ @@ -2456,7 +2332,6 @@ pbr = "*" name = "sentry-sdk" version = "1.26.0" description = "Python client for Sentry (https://sentry.io)" -category = "dev" optional = false python-versions = "*" files = [ @@ -2499,7 +2374,6 @@ tornado = ["tornado (>=5)"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2511,7 +2385,6 @@ files = [ name = "smmap" version = "5.0.0" description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2523,7 +2396,6 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2535,7 +2407,6 @@ files = [ name = "stevedore" version = "3.5.2" description = "Manage dynamic plugins for Python applications" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2551,7 +2422,6 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0" name = "sympy" version = "1.10.1" description = "Computer algebra system (CAS) in Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2566,7 +2436,6 @@ mpmath = ">=0.19" name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2578,7 +2447,6 @@ files = [ name = "typed-ast" version = "1.5.4" description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2612,7 +2480,6 @@ files = [ name = "typeguard" version = "2.13.3" description = "Run-time type checker for Python" -category = "dev" optional = false python-versions = ">=3.5.3" files = [ @@ -2628,7 +2495,6 @@ test = ["mypy", "pytest", "typing-extensions"] name = "types-python-dateutil" version = "2.8.19.13" description = "Typing stubs for python-dateutil" -category = "dev" optional = false python-versions = "*" files = [ @@ -2640,7 +2506,6 @@ files = [ name = "types-requests" version = "2.31.0.1" description = "Typing stubs for requests" -category = "dev" optional = false python-versions = "*" files = [ @@ -2655,7 +2520,6 @@ types-urllib3 = "*" name = "types-urllib3" version = "1.26.25.13" description = "Typing stubs for urllib3" -category = "dev" optional = false python-versions = "*" files = [ @@ -2667,7 +2531,6 @@ files = [ name = "typing-extensions" version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2679,7 +2542,6 @@ files = [ name = "urllib3" version = "1.26.16" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -2696,7 +2558,6 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "verspec" version = "0.1.0" description = "Flexible version handling" -category = "dev" optional = false python-versions = "*" files = [ @@ -2711,7 +2572,6 @@ test = ["coverage", "flake8 (>=3.7)", "mypy", "pretend", "pytest"] name = "watchdog" version = "3.0.0" description = "Filesystem events monitoring" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2751,7 +2611,6 @@ watchmedo = ["PyYAML (>=3.10)"] name = "wrapt" version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." -category = "main" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -2836,7 +2695,6 @@ files = [ name = "xenon" version = "0.9.0" description = "Monitor code metrics for Python on your CI server" -category = "dev" optional = false python-versions = "*" files = [ @@ -2853,7 +2711,6 @@ requests = ">=2.0,<3.0" name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2875,4 +2732,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "ea4b3b7ff32e0f70d48ec58b0610b4a0b18e86a53e3c125767c3ff8b38020bf6" +content-hash = "772f424467c80f0e73df8fb9115e866f66672dbc08d039b152bc56f9896c21ac" diff --git a/pyproject.toml b/pyproject.toml index 2ee7a5936a5..60c8b296100 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,6 @@ radon = "^5.1.0" xenon = "^0.9.0" mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" -retry = "^0.9.2" pytest-xdist = "^3.3.1" aws-cdk-lib = "^2.75.0" "aws-cdk.aws-apigatewayv2-alpha" = "^2.38.1-alpha.0" @@ -93,6 +92,7 @@ types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" sentry-sdk = "^1.22.2" ruff = ">=0.0.272,<0.0.276" +retry2 = "^0.9.5" [tool.coverage.run] source = ["aws_lambda_powertools"] From 76f63d54a4a3cb5a25abb5c0e97fcd57cde2fce4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:36:49 +0200 Subject: [PATCH 20/73] chore(deps-dev): bump sentry-sdk from 1.26.0 to 1.27.0 (#2652) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 229470d3e5f..1d39124dd7b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2330,13 +2330,13 @@ pbr = "*" [[package]] name = "sentry-sdk" -version = "1.26.0" +version = "1.27.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = "*" files = [ - {file = "sentry-sdk-1.26.0.tar.gz", hash = "sha256:760e4fb6d01c994110507133e08ecd4bdf4d75ee4be77f296a3579796cf73134"}, - {file = "sentry_sdk-1.26.0-py2.py3-none-any.whl", hash = "sha256:0c9f858337ec3781cf4851972ef42bba8c9828aea116b0dbed8f38c5f9a1896c"}, + {file = "sentry-sdk-1.27.0.tar.gz", hash = "sha256:eb2a5080912dc9b397925657669e3761d95d62c8aa4c0c6d6a73d5a31edaafe9"}, + {file = "sentry_sdk-1.27.0-py2.py3-none-any.whl", hash = "sha256:8c0ba7a0ed4e39635d335fdac7c00840b14ce4319bb8629b934243d6306fee7d"}, ] [package.dependencies] From 9429f32d70a281595b38442314bb047128bb52c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:39:04 +0200 Subject: [PATCH 21/73] chore(deps-dev): bump ruff from 0.0.275 to 0.0.276 (#2655) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 38 +++++++++++++++++++------------------- pyproject.toml | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1d39124dd7b..ec1b9c90e9e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2272,28 +2272,28 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.0.275" +version = "0.0.276" description = "An extremely fast Python linter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.0.275-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:5e6554a072e7ce81eb6f0bec1cebd3dcb0e358652c0f4900d7d630d61691e914"}, - {file = "ruff-0.0.275-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:1cc599022fe5ffb143a965b8d659eb64161ab8ab4433d208777eab018a1aab67"}, - {file = "ruff-0.0.275-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5206fc1cd8c1c1deadd2e6360c0dbcd690f1c845da588ca9d32e4a764a402c60"}, - {file = "ruff-0.0.275-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c4e6468da26f77b90cae35319d310999f471a8c352998e9b39937a23750149e"}, - {file = "ruff-0.0.275-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0dbdea02942131dbc15dd45f431d152224f15e1dd1859fcd0c0487b658f60f1a"}, - {file = "ruff-0.0.275-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:22efd9f41af27ef8fb9779462c46c35c89134d33e326c889971e10b2eaf50c63"}, - {file = "ruff-0.0.275-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c09662112cfa22d7467a19252a546291fd0eae4f423e52b75a7a2000a1894db"}, - {file = "ruff-0.0.275-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80043726662144876a381efaab88841c88e8df8baa69559f96b22d4fa216bef1"}, - {file = "ruff-0.0.275-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5859ee543b01b7eb67835dfd505faa8bb7cc1550f0295c92c1401b45b42be399"}, - {file = "ruff-0.0.275-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c8ace4d40a57b5ea3c16555f25a6b16bc5d8b2779ae1912ce2633543d4e9b1da"}, - {file = "ruff-0.0.275-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8347fc16aa185aae275906c4ac5b770e00c896b6a0acd5ba521f158801911998"}, - {file = "ruff-0.0.275-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ec43658c64bfda44fd84bbea9da8c7a3b34f65448192d1c4dd63e9f4e7abfdd4"}, - {file = "ruff-0.0.275-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:508b13f7ca37274cceaba4fb3ea5da6ca192356323d92acf39462337c33ad14e"}, - {file = "ruff-0.0.275-py3-none-win32.whl", hash = "sha256:6afb1c4422f24f361e877937e2a44b3f8176774a476f5e33845ebfe887dd5ec2"}, - {file = "ruff-0.0.275-py3-none-win_amd64.whl", hash = "sha256:d9b264d78621bf7b698b6755d4913ab52c19bd28bee1a16001f954d64c1a1220"}, - {file = "ruff-0.0.275-py3-none-win_arm64.whl", hash = "sha256:a19ce3bea71023eee5f0f089dde4a4272d088d5ac0b675867e074983238ccc65"}, - {file = "ruff-0.0.275.tar.gz", hash = "sha256:a63a0b645da699ae5c758fce19188e901b3033ec54d862d93fcd042addf7f38d"}, + {file = "ruff-0.0.276-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:c150912b8ebde843c10b33db90705d4fee48db6f05441e5d143be9f4c2f35df5"}, + {file = "ruff-0.0.276-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5e9cd7238d34f24d7ccfadcce4dc6807b8c5a390f547dd7236d06488d9d6f40f"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc7dc557cc3fa2a03a88e99425ceee91429cc7432e5a41087850c1629294faed"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13e5983836ae383c04de213954da731f14ea884aaf74467abc47e1d79d8cf1b7"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ac65df96be3e2f4b10bc97bbb624152281611b06ef1068d5bb064b7ad35d800"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d070a64de4affd17e006d6986ef25601dbbc6b373844ece5396c33900f8b8563"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2edcd6948a21fa7fb4594094da37a1aa1d205b7abaa718bd27d48ba1d7977348"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57c49b525d8ca3838d8b614f42e342077bed95aedd9fe6e6ec419f39320c214e"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5980960a748ada3ddfe4ea7ff3a01b9113c456a14cb1a39b4c30783012d4cba6"}, + {file = "ruff-0.0.276-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:12be4f007114cf5ed1242e522762651539521ec32ae0210cc4b8dfe434a872f0"}, + {file = "ruff-0.0.276-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6ed8fc729b3e7b9f20a4e2aa6f24c798b06912f8a94cb3e8fd590eba055780df"}, + {file = "ruff-0.0.276-py3-none-musllinux_1_2_i686.whl", hash = "sha256:735d724031212c2ab63fafdea49d4581ae866a1180d06c29b0b5481228ca6bb9"}, + {file = "ruff-0.0.276-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:100ad9055d50977c2b4ab3de0db62d6e525bcd4aafbb660a842733bdbf650be9"}, + {file = "ruff-0.0.276-py3-none-win32.whl", hash = "sha256:1b34a3673b2e5d97df8f7f04090c0b74e9ae6d3d172921d0e0781192954afddf"}, + {file = "ruff-0.0.276-py3-none-win_amd64.whl", hash = "sha256:02deadc0f6abead6cc2d38ddd7100a52aba27a0d90315facaa44b8b4acdba162"}, + {file = "ruff-0.0.276-py3-none-win_arm64.whl", hash = "sha256:a6bd5b53ac689a43c7afc45bd574a7b3efe0ceb192e26e95a055c770ef2045b9"}, + {file = "ruff-0.0.276.tar.gz", hash = "sha256:d456c86eb6ce9225507f24fcc7bf72fa031bb7cc750023310e62889bf4ad4b6a"}, ] [[package]] @@ -2732,4 +2732,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "772f424467c80f0e73df8fb9115e866f66672dbc08d039b152bc56f9896c21ac" +content-hash = "18c2b745e473c56e594a770a26c8ca8889ad04dbd9432a5fc3186e8b48736595" diff --git a/pyproject.toml b/pyproject.toml index 60c8b296100..eb0c5a04f49 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" sentry-sdk = "^1.22.2" -ruff = ">=0.0.272,<0.0.276" +ruff = ">=0.0.272,<0.0.277" retry2 = "^0.9.5" [tool.coverage.run] From 62be4cd1266a9ef441c1432ab6b62ad8ef315013 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 03:01:03 +0100 Subject: [PATCH 22/73] chore(deps): bump squidfunk/mkdocs-material from `3837c0f` to `a28ed81` in /docs (#2669) --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 05f56df28ef..6f7fc7d26cb 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,5 +1,5 @@ # v9.1.18 -FROM squidfunk/mkdocs-material@sha256:3837c0f327033a6946a2810760fe80ee1f02fceda4f817638ea69c612b2db837 +FROM squidfunk/mkdocs-material@sha256:a28ed811514d6c6cf15a4bcf7a2ce21d03fcb5c8cbdc4e1fec8ba179ef58fbb5 # pip-compile --generate-hashes --output-file=requirements.txt requirements.in COPY requirements.txt /tmp/ RUN pip install -r /tmp/requirements.txt From 5b754ad1a7c5595fc8e27cdf7b39636462b9d741 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 03:01:54 +0100 Subject: [PATCH 23/73] chore(deps-dev): bump typed-ast from 1.5.4 to 1.5.5 (#2670) --- poetry.lock | 69 +++++++++++++++++++++++++++++++------------------- pyproject.toml | 2 +- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/poetry.lock b/poetry.lock index ec1b9c90e9e..502f2aeb8d7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2445,35 +2445,52 @@ files = [ [[package]] name = "typed-ast" -version = "1.5.4" +version = "1.5.5" description = "a fork of Python 2 and 3 ast modules with type comment support" optional = false python-versions = ">=3.6" files = [ - {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, - {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, - {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, - {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, - {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, - {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, - {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, - {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, - {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, - {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, + {file = "typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b"}, + {file = "typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686"}, + {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769"}, + {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04"}, + {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d"}, + {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d"}, + {file = "typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02"}, + {file = "typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee"}, + {file = "typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18"}, + {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88"}, + {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2"}, + {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9"}, + {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8"}, + {file = "typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b"}, + {file = "typed_ast-1.5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:44f214394fc1af23ca6d4e9e744804d890045d1643dd7e8229951e0ef39429b5"}, + {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:118c1ce46ce58fda78503eae14b7664163aa735b620b64b5b725453696f2a35c"}, + {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be4919b808efa61101456e87f2d4c75b228f4e52618621c77f1ddcaae15904fa"}, + {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fc2b8c4e1bc5cd96c1a823a885e6b158f8451cf6f5530e1829390b4d27d0807f"}, + {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:16f7313e0a08c7de57f2998c85e2a69a642e97cb32f87eb65fbfe88381a5e44d"}, + {file = "typed_ast-1.5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:2b946ef8c04f77230489f75b4b5a4a6f24c078be4aed241cfabe9cbf4156e7e5"}, + {file = "typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e"}, + {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e"}, + {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311"}, + {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2"}, + {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4"}, + {file = "typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431"}, + {file = "typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a"}, + {file = "typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437"}, + {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede"}, + {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4"}, + {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6"}, + {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4"}, + {file = "typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b"}, + {file = "typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10"}, + {file = "typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814"}, + {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8"}, + {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274"}, + {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a"}, + {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba"}, + {file = "typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155"}, + {file = "typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd"}, ] [[package]] @@ -2732,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "18c2b745e473c56e594a770a26c8ca8889ad04dbd9432a5fc3186e8b48736595" +content-hash = "a3a0d7c85cdb5e430e87c70c11844e0126d6ebf501fe439ca129469ef1ea6824" diff --git a/pyproject.toml b/pyproject.toml index eb0c5a04f49..7aca726401a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,7 +73,7 @@ filelock = "^3.12.2" checksumdir = "^1.2.0" mypy-boto3-appconfigdata = "^1.27.0" ijson = "^3.2.2" -typed-ast = { version = "^1.5.4", python = "< 3.8"} +typed-ast = { version = "^1.5.5", python = "< 3.8"} hvac = "^1.1.1" aws-requests-auth = "^0.4.3" From 3f2498545a5f207bff7fc283956235d99858b306 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 03:02:49 +0100 Subject: [PATCH 24/73] chore(deps): bump pydantic from 1.10.10 to 1.10.11 (#2671) --- poetry.lock | 74 ++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/poetry.lock b/poetry.lock index 502f2aeb8d7..4e9f3cc437e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1728,47 +1728,47 @@ files = [ [[package]] name = "pydantic" -version = "1.10.10" +version = "1.10.11" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:adad1ee4ab9888f12dac2529276704e719efcf472e38df7813f5284db699b4ec"}, - {file = "pydantic-1.10.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a7db03339893feef2092ff7b1afc9497beed15ebd4af84c3042a74abce02d48"}, - {file = "pydantic-1.10.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b3714b97ff84b2689654851c2426389bcabfac9080617bcf4306c69db606f6"}, - {file = "pydantic-1.10.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edfdf0a5abc5c9bf2052ebaec20e67abd52e92d257e4f2d30e02c354ed3e6030"}, - {file = "pydantic-1.10.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20a3b30fd255eeeb63caa9483502ba96b7795ce5bf895c6a179b3d909d9f53a6"}, - {file = "pydantic-1.10.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db4c7f7e60ca6f7d6c1785070f3e5771fcb9b2d88546e334d2f2c3934d949028"}, - {file = "pydantic-1.10.10-cp310-cp310-win_amd64.whl", hash = "sha256:a2d5be50ac4a0976817144c7d653e34df2f9436d15555189f5b6f61161d64183"}, - {file = "pydantic-1.10.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:566a04ba755e8f701b074ffb134ddb4d429f75d5dced3fbd829a527aafe74c71"}, - {file = "pydantic-1.10.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f79db3652ed743309f116ba863dae0c974a41b688242482638b892246b7db21d"}, - {file = "pydantic-1.10.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c62376890b819bebe3c717a9ac841a532988372b7e600e76f75c9f7c128219d5"}, - {file = "pydantic-1.10.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4870f13a4fafd5bc3e93cff3169222534fad867918b188e83ee0496452978437"}, - {file = "pydantic-1.10.10-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:990027e77cda6072a566e433b6962ca3b96b4f3ae8bd54748e9d62a58284d9d7"}, - {file = "pydantic-1.10.10-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8c40964596809eb616d94f9c7944511f620a1103d63d5510440ed2908fc410af"}, - {file = "pydantic-1.10.10-cp311-cp311-win_amd64.whl", hash = "sha256:ea9eebc2ebcba3717e77cdeee3f6203ffc0e78db5f7482c68b1293e8cc156e5e"}, - {file = "pydantic-1.10.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:762aa598f79b4cac2f275d13336b2dd8662febee2a9c450a49a2ab3bec4b385f"}, - {file = "pydantic-1.10.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dab5219659f95e357d98d70577b361383057fb4414cfdb587014a5f5c595f7b"}, - {file = "pydantic-1.10.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3d4ee957a727ccb5a36f1b0a6dbd9fad5dedd2a41eada99a8df55c12896e18d"}, - {file = "pydantic-1.10.10-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b69f9138dec566962ec65623c9d57bee44412d2fc71065a5f3ebb3820bdeee96"}, - {file = "pydantic-1.10.10-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7aa75d1bd9cc275cf9782f50f60cddaf74cbaae19b6ada2a28e737edac420312"}, - {file = "pydantic-1.10.10-cp37-cp37m-win_amd64.whl", hash = "sha256:9f62a727f5c590c78c2d12fda302d1895141b767c6488fe623098f8792255fe5"}, - {file = "pydantic-1.10.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:aac218feb4af73db8417ca7518fb3bade4534fcca6e3fb00f84966811dd94450"}, - {file = "pydantic-1.10.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88546dc10a40b5b52cae87d64666787aeb2878f9a9b37825aedc2f362e7ae1da"}, - {file = "pydantic-1.10.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c41bbaae89e32fc582448e71974de738c055aef5ab474fb25692981a08df808a"}, - {file = "pydantic-1.10.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b71bd504d1573b0b722ae536e8ffb796bedeef978979d076bf206e77dcc55a5"}, - {file = "pydantic-1.10.10-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e088e3865a2270ecbc369924cd7d9fbc565667d9158e7f304e4097ebb9cf98dd"}, - {file = "pydantic-1.10.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3403a090db45d4027d2344859d86eb797484dfda0706cf87af79ace6a35274ef"}, - {file = "pydantic-1.10.10-cp38-cp38-win_amd64.whl", hash = "sha256:e0014e29637125f4997c174dd6167407162d7af0da73414a9340461ea8573252"}, - {file = "pydantic-1.10.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9965e49c6905840e526e5429b09e4c154355b6ecc0a2f05492eda2928190311d"}, - {file = "pydantic-1.10.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:748d10ab6089c5d196e1c8be9de48274f71457b01e59736f7a09c9dc34f51887"}, - {file = "pydantic-1.10.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86936c383f7c38fd26d35107eb669c85d8f46dfceae873264d9bab46fe1c7dde"}, - {file = "pydantic-1.10.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a26841be620309a9697f5b1ffc47dce74909e350c5315ccdac7a853484d468a"}, - {file = "pydantic-1.10.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:409b810f387610cc7405ab2fa6f62bdf7ea485311845a242ebc0bd0496e7e5ac"}, - {file = "pydantic-1.10.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ce937a2a2c020bcad1c9fde02892392a1123de6dda906ddba62bfe8f3e5989a2"}, - {file = "pydantic-1.10.10-cp39-cp39-win_amd64.whl", hash = "sha256:37ebddef68370e6f26243acc94de56d291e01227a67b2ace26ea3543cf53dd5f"}, - {file = "pydantic-1.10.10-py3-none-any.whl", hash = "sha256:a5939ec826f7faec434e2d406ff5e4eaf1716eb1f247d68cd3d0b3612f7b4c8a"}, - {file = "pydantic-1.10.10.tar.gz", hash = "sha256:3b8d5bd97886f9eb59260594207c9f57dce14a6f869c6ceea90188715d29921a"}, + {file = "pydantic-1.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ff44c5e89315b15ff1f7fdaf9853770b810936d6b01a7bcecaa227d2f8fe444f"}, + {file = "pydantic-1.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6c098d4ab5e2d5b3984d3cb2527e2d6099d3de85630c8934efcfdc348a9760e"}, + {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16928fdc9cb273c6af00d9d5045434c39afba5f42325fb990add2c241402d151"}, + {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0588788a9a85f3e5e9ebca14211a496409cb3deca5b6971ff37c556d581854e7"}, + {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9baf78b31da2dc3d3f346ef18e58ec5f12f5aaa17ac517e2ffd026a92a87588"}, + {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:373c0840f5c2b5b1ccadd9286782852b901055998136287828731868027a724f"}, + {file = "pydantic-1.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:c3339a46bbe6013ef7bdd2844679bfe500347ac5742cd4019a88312aa58a9847"}, + {file = "pydantic-1.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a6c32e1c3809fbc49debb96bf833164f3438b3696abf0fbeceb417d123e6eb"}, + {file = "pydantic-1.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a451ccab49971af043ec4e0d207cbc8cbe53dbf148ef9f19599024076fe9c25b"}, + {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02d24f7b2b365fed586ed73582c20f353a4c50e4be9ba2c57ab96f8091ddae"}, + {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f34739a89260dfa420aa3cbd069fbcc794b25bbe5c0a214f8fb29e363484b66"}, + {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e297897eb4bebde985f72a46a7552a7556a3dd11e7f76acda0c1093e3dbcf216"}, + {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d185819a7a059550ecb85d5134e7d40f2565f3dd94cfd870132c5f91a89cf58c"}, + {file = "pydantic-1.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:4400015f15c9b464c9db2d5d951b6a780102cfa5870f2c036d37c23b56f7fc1b"}, + {file = "pydantic-1.10.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2417de68290434461a266271fc57274a138510dca19982336639484c73a07af6"}, + {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:331c031ba1554b974c98679bd0780d89670d6fd6f53f5d70b10bdc9addee1713"}, + {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8268a735a14c308923e8958363e3a3404f6834bb98c11f5ab43251a4e410170c"}, + {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:44e51ba599c3ef227e168424e220cd3e544288c57829520dc90ea9cb190c3248"}, + {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d7781f1d13b19700b7949c5a639c764a077cbbdd4322ed505b449d3ca8edcb36"}, + {file = "pydantic-1.10.11-cp37-cp37m-win_amd64.whl", hash = "sha256:7522a7666157aa22b812ce14c827574ddccc94f361237ca6ea8bb0d5c38f1629"}, + {file = "pydantic-1.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc64eab9b19cd794a380179ac0e6752335e9555d214cfcb755820333c0784cb3"}, + {file = "pydantic-1.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8dc77064471780262b6a68fe67e013298d130414d5aaf9b562c33987dbd2cf4f"}, + {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe429898f2c9dd209bd0632a606bddc06f8bce081bbd03d1c775a45886e2c1cb"}, + {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:192c608ad002a748e4a0bed2ddbcd98f9b56df50a7c24d9a931a8c5dd053bd3d"}, + {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ef55392ec4bb5721f4ded1096241e4b7151ba6d50a50a80a2526c854f42e6a2f"}, + {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e0bb6efe86281623abbeeb0be64eab740c865388ee934cd3e6a358784aca6e"}, + {file = "pydantic-1.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:265a60da42f9f27e0b1014eab8acd3e53bd0bad5c5b4884e98a55f8f596b2c19"}, + {file = "pydantic-1.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:469adf96c8e2c2bbfa655fc7735a2a82f4c543d9fee97bd113a7fb509bf5e622"}, + {file = "pydantic-1.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e6cbfbd010b14c8a905a7b10f9fe090068d1744d46f9e0c021db28daeb8b6de1"}, + {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abade85268cc92dff86d6effcd917893130f0ff516f3d637f50dadc22ae93999"}, + {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9738b0f2e6c70f44ee0de53f2089d6002b10c33264abee07bdb5c7f03038303"}, + {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:787cf23e5a0cde753f2eabac1b2e73ae3844eb873fd1f5bdbff3048d8dbb7604"}, + {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:174899023337b9fc685ac8adaa7b047050616136ccd30e9070627c1aaab53a13"}, + {file = "pydantic-1.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:1954f8778489a04b245a1e7b8b22a9d3ea8ef49337285693cf6959e4b757535e"}, + {file = "pydantic-1.10.11-py3-none-any.whl", hash = "sha256:008c5e266c8aada206d0627a011504e14268a62091450210eda7c07fabe6963e"}, + {file = "pydantic-1.10.11.tar.gz", hash = "sha256:f66d479cf7eb331372c470614be6511eae96f1f120344c25f3f9bb59fb1b5528"}, ] [package.dependencies] From f297b3fda5947535affb123673e65ffccaab36b2 Mon Sep 17 00:00:00 2001 From: StepSecurity Bot Date: Wed, 5 Jul 2023 04:07:32 -0700 Subject: [PATCH 25/73] chore(ci): add gitleaks in pre-commit hooks as an extra safety measure (#2677) Co-authored-by: Heitor Lessa --- .github/dependabot.yml | 5 +++++ .pre-commit-config.yaml | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b77092dc807..2ed1322608a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -71,3 +71,8 @@ updates: directory: /layer/scripts/layer-balancer schedule: interval: daily + + - package-ecosystem: pip + directory: /docs + schedule: + interval: daily diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 129e01ed039..319afbad0b4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,3 +46,7 @@ repos: - id: terraform_fmt args: - --args=-recursive + - repo: https://github.com/gitleaks/gitleaks + rev: "7804d652c0460f0b61ea9bb2c1f202bfcdbbf144" # v8.16.3 + hooks: + - id: gitleaks From 19d4d77922ddaa6e485cc29e3c012ee6d13621d3 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Wed, 5 Jul 2023 13:08:24 +0200 Subject: [PATCH 26/73] chore(ci): enforce pip --require-hashes to maybe satistify scorecard (#2679) --- .gitpod.Dockerfile | 2 +- .gitpod_requirements.in | 1 + .gitpod_requirements.txt | 85 ++++++++++++++++++++++++++++++++++++++++ docs/Dockerfile | 2 +- 4 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 .gitpod_requirements.in create mode 100644 .gitpod_requirements.txt diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index 6703482891b..efa414f9ac7 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -8,4 +8,4 @@ ADD . /app # Installing pre-commit as system package and not user package. Git needs this to execute pre-commit hooks. RUN export PIP_USER=no # v3.3.3 -RUN python3 -m pip install git+https://github.com/pre-commit/pre-commit@5da4258b17dea7bd4601358de200e185699f9997 \ No newline at end of file +RUN python3 -m pip install --require-hashes -r .gitpod_requirements.txt \ No newline at end of file diff --git a/.gitpod_requirements.in b/.gitpod_requirements.in new file mode 100644 index 00000000000..e88cdf05e74 --- /dev/null +++ b/.gitpod_requirements.in @@ -0,0 +1 @@ +pre-commit==3.3.3 \ No newline at end of file diff --git a/.gitpod_requirements.txt b/.gitpod_requirements.txt new file mode 100644 index 00000000000..db6274738d3 --- /dev/null +++ b/.gitpod_requirements.txt @@ -0,0 +1,85 @@ +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# pip-compile --generate-hashes --output-file=.gitpod_requirements.txt .gitpod_requirements.in +# +cfgv==3.3.1 \ + --hash=sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426 \ + --hash=sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736 + # via pre-commit +distlib==0.3.6 \ + --hash=sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46 \ + --hash=sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e + # via virtualenv +filelock==3.12.2 \ + --hash=sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81 \ + --hash=sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec + # via virtualenv +identify==2.5.24 \ + --hash=sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4 \ + --hash=sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d + # via pre-commit +nodeenv==1.8.0 \ + --hash=sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2 \ + --hash=sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec + # via pre-commit +platformdirs==3.8.0 \ + --hash=sha256:b0cabcb11063d21a0b261d557acb0a9d2126350e63b70cdf7db6347baea456dc \ + --hash=sha256:ca9ed98ce73076ba72e092b23d3c93ea6c4e186b3f1c3dad6edd98ff6ffcca2e + # via virtualenv +pre-commit==3.3.3 \ + --hash=sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb \ + --hash=sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023 + # via -r .gitpod_requirements.in +pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via pre-commit +virtualenv==20.23.1 \ + --hash=sha256:34da10f14fea9be20e0fd7f04aba9732f84e593dac291b757ce42e3368a39419 \ + --hash=sha256:8ff19a38c1021c742148edc4f81cb43d7f8c6816d2ede2ab72af5b84c749ade1 + # via pre-commit + +# WARNING: The following packages were not pinned, but pip requires them to be +# pinned when the requirements file includes hashes and the requirement is not +# satisfied by a package already installed. Consider using the --allow-unsafe flag. +# setuptools diff --git a/docs/Dockerfile b/docs/Dockerfile index 6f7fc7d26cb..50b8f6682c2 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -2,4 +2,4 @@ FROM squidfunk/mkdocs-material@sha256:a28ed811514d6c6cf15a4bcf7a2ce21d03fcb5c8cbdc4e1fec8ba179ef58fbb5 # pip-compile --generate-hashes --output-file=requirements.txt requirements.in COPY requirements.txt /tmp/ -RUN pip install -r /tmp/requirements.txt +RUN pip install --require-hashes -r /tmp/requirements.txt From 51a20a3417c616434630ed4cb8835b25caf28427 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 12:12:55 +0100 Subject: [PATCH 27/73] chore(deps-dev): bump ruff from 0.0.276 to 0.0.277 (#2682) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 38 +++++++++++++++++++------------------- pyproject.toml | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4e9f3cc437e..4fe708cc149 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2272,28 +2272,28 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.0.276" +version = "0.0.277" description = "An extremely fast Python linter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.0.276-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:c150912b8ebde843c10b33db90705d4fee48db6f05441e5d143be9f4c2f35df5"}, - {file = "ruff-0.0.276-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5e9cd7238d34f24d7ccfadcce4dc6807b8c5a390f547dd7236d06488d9d6f40f"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc7dc557cc3fa2a03a88e99425ceee91429cc7432e5a41087850c1629294faed"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13e5983836ae383c04de213954da731f14ea884aaf74467abc47e1d79d8cf1b7"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ac65df96be3e2f4b10bc97bbb624152281611b06ef1068d5bb064b7ad35d800"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d070a64de4affd17e006d6986ef25601dbbc6b373844ece5396c33900f8b8563"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2edcd6948a21fa7fb4594094da37a1aa1d205b7abaa718bd27d48ba1d7977348"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57c49b525d8ca3838d8b614f42e342077bed95aedd9fe6e6ec419f39320c214e"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5980960a748ada3ddfe4ea7ff3a01b9113c456a14cb1a39b4c30783012d4cba6"}, - {file = "ruff-0.0.276-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:12be4f007114cf5ed1242e522762651539521ec32ae0210cc4b8dfe434a872f0"}, - {file = "ruff-0.0.276-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6ed8fc729b3e7b9f20a4e2aa6f24c798b06912f8a94cb3e8fd590eba055780df"}, - {file = "ruff-0.0.276-py3-none-musllinux_1_2_i686.whl", hash = "sha256:735d724031212c2ab63fafdea49d4581ae866a1180d06c29b0b5481228ca6bb9"}, - {file = "ruff-0.0.276-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:100ad9055d50977c2b4ab3de0db62d6e525bcd4aafbb660a842733bdbf650be9"}, - {file = "ruff-0.0.276-py3-none-win32.whl", hash = "sha256:1b34a3673b2e5d97df8f7f04090c0b74e9ae6d3d172921d0e0781192954afddf"}, - {file = "ruff-0.0.276-py3-none-win_amd64.whl", hash = "sha256:02deadc0f6abead6cc2d38ddd7100a52aba27a0d90315facaa44b8b4acdba162"}, - {file = "ruff-0.0.276-py3-none-win_arm64.whl", hash = "sha256:a6bd5b53ac689a43c7afc45bd574a7b3efe0ceb192e26e95a055c770ef2045b9"}, - {file = "ruff-0.0.276.tar.gz", hash = "sha256:d456c86eb6ce9225507f24fcc7bf72fa031bb7cc750023310e62889bf4ad4b6a"}, + {file = "ruff-0.0.277-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:3250b24333ef419b7a232080d9724ccc4d2da1dbbe4ce85c4caa2290d83200f8"}, + {file = "ruff-0.0.277-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:3e60605e07482183ba1c1b7237eca827bd6cbd3535fe8a4ede28cbe2a323cb97"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7baa97c3d7186e5ed4d5d4f6834d759a27e56cf7d5874b98c507335f0ad5aadb"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74e4b206cb24f2e98a615f87dbe0bde18105217cbcc8eb785bb05a644855ba50"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:479864a3ccd8a6a20a37a6e7577bdc2406868ee80b1e65605478ad3b8eb2ba0b"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:468bfb0a7567443cec3d03cf408d6f562b52f30c3c29df19927f1e0e13a40cd7"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f32ec416c24542ca2f9cc8c8b65b84560530d338aaf247a4a78e74b99cd476b4"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:14a7b2f00f149c5a295f188a643ac25226ff8a4d08f7a62b1d4b0a1dc9f9b85c"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9879f59f763cc5628aa01c31ad256a0f4dc61a29355c7315b83c2a5aac932b5"}, + {file = "ruff-0.0.277-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f612e0a14b3d145d90eb6ead990064e22f6f27281d847237560b4e10bf2251f3"}, + {file = "ruff-0.0.277-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:323b674c98078be9aaded5b8b51c0d9c424486566fb6ec18439b496ce79e5998"}, + {file = "ruff-0.0.277-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3a43fbe026ca1a2a8c45aa0d600a0116bec4dfa6f8bf0c3b871ecda51ef2b5dd"}, + {file = "ruff-0.0.277-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:734165ea8feb81b0d53e3bf523adc2413fdb76f1264cde99555161dd5a725522"}, + {file = "ruff-0.0.277-py3-none-win32.whl", hash = "sha256:88d0f2afb2e0c26ac1120e7061ddda2a566196ec4007bd66d558f13b374b9efc"}, + {file = "ruff-0.0.277-py3-none-win_amd64.whl", hash = "sha256:6fe81732f788894a00f6ade1fe69e996cc9e485b7c35b0f53fb00284397284b2"}, + {file = "ruff-0.0.277-py3-none-win_arm64.whl", hash = "sha256:2d4444c60f2e705c14cd802b55cd2b561d25bf4311702c463a002392d3116b22"}, + {file = "ruff-0.0.277.tar.gz", hash = "sha256:2dab13cdedbf3af6d4427c07f47143746b6b95d9e4a254ac369a0edb9280a0d2"}, ] [[package]] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "a3a0d7c85cdb5e430e87c70c11844e0126d6ebf501fe439ca129469ef1ea6824" +content-hash = "6b78a2eaa84743416b8bbc62aae87607abaf52cb6e748f3529c3e3b3a43c00ac" diff --git a/pyproject.toml b/pyproject.toml index 7aca726401a..80ed1d28dba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" sentry-sdk = "^1.22.2" -ruff = ">=0.0.272,<0.0.277" +ruff = ">=0.0.272,<0.0.278" retry2 = "^0.9.5" [tool.coverage.run] From c1d87325914a9cd2d511e2d59ab78e4de3374f03 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Wed, 5 Jul 2023 17:49:54 +0200 Subject: [PATCH 28/73] docs(contributing): add code integration journey graph (#2685) --- CONTRIBUTING.md | 64 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 41928a18926..cc37371cb88 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,8 +18,9 @@ # Contributing Guidelines -Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional -documentation, we greatly value feedback and contributions from our community. + +Thank you for your interest in contributing to our project. Whether it's a [bug report](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=bug%2Ctriage&projects=&template=bug_report.yml&title=Bug%3A+TITLE), [new feature](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&projects=&template=feature_request.yml&title=Feature+request%3A+TITLE), [correction](https://github.com/aws-powertools/powertools-lambda-python/issues/new/choose), or [additional documentation](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=documentation%2Ctriage&projects=&template=documentation_improvements.yml&title=Docs%3A+TITLE), we greatly value feedback and contributions from our community. + Please read through this document before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution. @@ -28,8 +29,9 @@ information to effectively respond to your bug report or contribution. We welcome you to use the GitHub issue tracker to report bugs, suggest features, or documentation improvements. -When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already -reported the issue. Please try to include as much information as you can. + +[When filing an issue](https://github.com/aws-powertools/powertools-lambda-python/issues/new/choose), please check [existing open](https://github.com/aws-powertools/powertools-lambda-python/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc), or [recently closed](https://github.com/aws-powertools/powertools-lambda-python/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aclosed), issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. + ## Contributing via Pull Requests @@ -39,6 +41,56 @@ Contributions via pull requests are much appreciated. Before sending us a pull r 2. You check existing open, and recently merged pull requests to make sure someone else hasn't addressed the problem already. 3. You open an [issue](https://github.com/aws-powertools/powertools-lambda-python/issues/new/choose) before you begin any implementation. We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful. +At a high level, these are the steps to get code merged in the repository - don't worry, nearly all of them are automated. + +```mermaid +timeline + title Code integration journey (CI) + Project setup
(make dev) : Code checkout + : Virtual environment + : Dependencies + : Git pre-commit hooks + : Local branch + : Local changes + : Local tests + + Pre-commit checks
(git commit) : Merge conflict check + : Trailing whitespaces + : TOML checks + : Code linting (standards) + : Markdown linting + : CloudFormation linting + : GitHub Actions linting + : Terraform linting + : Secrets linting + + Pre-Pull Request
(make pr) : Code linting + : Docs linting + : Static typing analysis + : Tests (unit|functional|perf) + : Security baseline + : Complexity baseline + : +pre-commit checks + + Pull Request
(CI checks) : Semantic PR title check + : Related issue check + : Acknowledgment check + : Code coverage diff + : Contribution size check + : Contribution category check + : Dependency vulnerability check + : GitHub Actions security check + : +pre-pull request checks + + After merge
(CI checks) : End-to-end tests + : Longer SAST check + : Security posture check (scorecard) + : GitHub Actions security check + : Rebuild Changelog + : Deploy staging docs + : Update draft release +``` + ### Dev setup [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/from-referrer/) @@ -76,7 +128,7 @@ You might find useful to run both the documentation website and the API referenc | Category | Convention | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Docstring** | We use a slight variation of Numpy convention with markdown to help generate more readable API references. | -| **Style guide** | We use black as well as [Ruff](https://beta.ruff.rs/docs/) to enforce beyond good practices [PEP8](https://pep8.org/). We use type annotations and enforce static type checking at CI (mypy). | +| **Style guide** | We use black as well as [Ruff](https://beta.ruff.rs/docs/) to enforce beyond good practices [PEP8](https://pep8.org/). We use type annotations and enforce static type checking at CI (mypy). | | **Core utilities** | Core utilities use a Class, always accept `service` as a constructor parameter, can work in isolation, and are also available in other languages implementation. | | **Utilities** | Utilities are not as strict as core and focus on solving a developer experience problem while following the project [Tenets](https://docs.powertools.aws.dev/lambda/python/#tenets). | | **Exceptions** | Specific exceptions live within utilities themselves and use `Error` suffix e.g. `MetricUnitError`. | @@ -100,7 +152,7 @@ We group tests in different categories ## Finding contributions to work on -Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/help wanted/invalid/question/documentation), looking at any 'help wanted' issues is a great place to start. +Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/help wanted/invalid/question/documentation), [looking at any 'help wanted' issues is a great place to start](https://github.com/orgs/aws-powertools/projects/3/views/5?query=is%3Aopen+sort%3Aupdated-desc). ## Code of Conduct From 86179999994462e8a7922d14b171040de85957f5 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 5 Jul 2023 16:51:07 +0100 Subject: [PATCH 29/73] refactor(parser): convert functional tests to unit tests (#2656) Co-authored-by: Heitor Lessa --- tests/events/kinesisStreamEventOneRecord.json | 20 ++ tests/functional/parser/__init__.py | 0 tests/functional/parser/test_alb.py | 44 --- tests/functional/parser/test_apigw.py | 152 ---------- tests/functional/parser/test_apigwv2.py | 105 ------- tests/functional/parser/test_cloudwatch.py | 89 ------ tests/functional/parser/test_dynamodb.py | 73 ----- tests/functional/parser/test_eventbridge.py | 69 ----- tests/functional/parser/test_kafka.py | 93 ------ tests/functional/parser/test_kinesis.py | 153 ---------- .../parser/test_kinesis_firehose.py | 138 --------- .../parser/test_lambda_function_url.py | 128 -------- tests/functional/parser/test_s3.py | 155 ---------- tests/functional/parser/test_ses.py | 49 --- tests/functional/parser/test_sns.py | 128 -------- tests/{functional => unit}/parser/schemas.py | 0 tests/unit/parser/test_alb.py | 24 ++ tests/unit/parser/test_apigw.py | 148 +++++++++ tests/unit/parser/test_apigwv2.py | 106 +++++++ tests/unit/parser/test_cloudwatch.py | 95 ++++++ tests/unit/parser/test_dynamodb.py | 84 ++++++ tests/unit/parser/test_eventbridge.py | 53 ++++ tests/unit/parser/test_kafka.py | 82 +++++ tests/unit/parser/test_kinesis.py | 108 +++++++ tests/unit/parser/test_kinesis_firehose.py | 123 ++++++++ tests/unit/parser/test_lambda_function_url.py | 127 ++++++++ .../parser/test_s3 object_event.py | 35 +-- tests/unit/parser/test_s3.py | 280 +++++++++--------- tests/unit/parser/test_s3_notification.py | 145 +++++++++ tests/unit/parser/test_ses.py | 52 ++++ tests/unit/parser/test_sns.py | 118 ++++++++ tests/{functional => unit}/parser/test_sqs.py | 89 +++--- tests/unit/parser/test_vpc_lattice.py | 28 +- 33 files changed, 1495 insertions(+), 1598 deletions(-) create mode 100644 tests/events/kinesisStreamEventOneRecord.json delete mode 100644 tests/functional/parser/__init__.py delete mode 100644 tests/functional/parser/test_alb.py delete mode 100644 tests/functional/parser/test_apigw.py delete mode 100644 tests/functional/parser/test_apigwv2.py delete mode 100644 tests/functional/parser/test_cloudwatch.py delete mode 100644 tests/functional/parser/test_dynamodb.py delete mode 100644 tests/functional/parser/test_eventbridge.py delete mode 100644 tests/functional/parser/test_kafka.py delete mode 100644 tests/functional/parser/test_kinesis.py delete mode 100644 tests/functional/parser/test_kinesis_firehose.py delete mode 100644 tests/functional/parser/test_lambda_function_url.py delete mode 100644 tests/functional/parser/test_s3.py delete mode 100644 tests/functional/parser/test_ses.py delete mode 100644 tests/functional/parser/test_sns.py rename tests/{functional => unit}/parser/schemas.py (100%) create mode 100644 tests/unit/parser/test_alb.py create mode 100644 tests/unit/parser/test_apigw.py create mode 100644 tests/unit/parser/test_apigwv2.py create mode 100644 tests/unit/parser/test_cloudwatch.py create mode 100644 tests/unit/parser/test_dynamodb.py create mode 100644 tests/unit/parser/test_eventbridge.py create mode 100644 tests/unit/parser/test_kafka.py create mode 100644 tests/unit/parser/test_kinesis.py create mode 100644 tests/unit/parser/test_kinesis_firehose.py create mode 100644 tests/unit/parser/test_lambda_function_url.py rename tests/{functional => unit}/parser/test_s3 object_event.py (62%) create mode 100644 tests/unit/parser/test_s3_notification.py create mode 100644 tests/unit/parser/test_ses.py create mode 100644 tests/unit/parser/test_sns.py rename tests/{functional => unit}/parser/test_sqs.py (51%) diff --git a/tests/events/kinesisStreamEventOneRecord.json b/tests/events/kinesisStreamEventOneRecord.json new file mode 100644 index 00000000000..05fe2d297a9 --- /dev/null +++ b/tests/events/kinesisStreamEventOneRecord.json @@ -0,0 +1,20 @@ +{ + "Records": [ + { + "kinesis": { + "kinesisSchemaVersion": "1.0", + "partitionKey": "1", + "sequenceNumber": "49590338271490256608559692538361571095921575989136588898", + "data": "eyJtZXNzYWdlIjogInRlc3QgbWVzc2FnZSIsICJ1c2VybmFtZSI6ICJ0ZXN0In0=", + "approximateArrivalTimestamp": 1545084650.987 + }, + "eventSource": "aws:kinesis", + "eventVersion": "1.0", + "eventID": "shardId-000000000006:49590338271490256608559692538361571095921575989136588898", + "eventName": "aws:kinesis:record", + "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role", + "awsRegion": "us-east-2", + "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream" + } + ] +} diff --git a/tests/functional/parser/__init__.py b/tests/functional/parser/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/functional/parser/test_alb.py b/tests/functional/parser/test_alb.py deleted file mode 100644 index d48e39f1bab..00000000000 --- a/tests/functional/parser/test_alb.py +++ /dev/null @@ -1,44 +0,0 @@ -import pytest - -from aws_lambda_powertools.utilities.parser import ValidationError, event_parser -from aws_lambda_powertools.utilities.parser.models import AlbModel -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.utils import load_event - - -@event_parser(model=AlbModel) -def handle_alb(event: AlbModel, _: LambdaContext): - assert ( - event.requestContext.elb.targetGroupArn - == "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a" # noqa E501 - ) - assert event.httpMethod == "GET" - assert event.path == "/lambda" - assert event.queryStringParameters == {"query": "1234ABCD"} - assert event.headers == { - "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", - "accept-encoding": "gzip", - "accept-language": "en-US,en;q=0.9", - "connection": "keep-alive", - "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com", - "upgrade-insecure-requests": "1", - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", # noqa E501 - "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476", - "x-forwarded-for": "72.12.164.125", - "x-forwarded-port": "80", - "x-forwarded-proto": "http", - "x-imforwards": "20", - } - assert event.body == "Test" - assert not event.isBase64Encoded - - -def test_alb_trigger_event(): - event_dict = load_event("albEvent.json") - handle_alb(event_dict, LambdaContext()) - - -def test_validate_event_does_not_conform_with_model(): - event = {"invalid": "event"} - with pytest.raises(ValidationError): - handle_alb(event, LambdaContext()) diff --git a/tests/functional/parser/test_apigw.py b/tests/functional/parser/test_apigw.py deleted file mode 100644 index 35b2fdb1926..00000000000 --- a/tests/functional/parser/test_apigw.py +++ /dev/null @@ -1,152 +0,0 @@ -import pytest -from pydantic import ValidationError - -from aws_lambda_powertools.utilities.parser import envelopes, event_parser, parse -from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventModel -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyApiGatewayBusiness -from tests.functional.utils import load_event - - -@event_parser(model=MyApiGatewayBusiness, envelope=envelopes.ApiGatewayEnvelope) -def handle_apigw_with_envelope(event: MyApiGatewayBusiness, _: LambdaContext): - assert event.message == "Hello" - assert event.username == "Ran" - - -@event_parser(model=APIGatewayProxyEventModel) -def handle_apigw_event(event: APIGatewayProxyEventModel, _: LambdaContext): - assert event.body == "Hello from Lambda!" - return event - - -def test_apigw_event_with_envelope(): - event = load_event("apiGatewayProxyEvent.json") - event["body"] = '{"message": "Hello", "username": "Ran"}' - handle_apigw_with_envelope(event, LambdaContext()) - - -def test_apigw_event(): - event = load_event("apiGatewayProxyEvent.json") - parsed_event: APIGatewayProxyEventModel = handle_apigw_event(event, LambdaContext()) - assert parsed_event.version == event["version"] - assert parsed_event.resource == event["resource"] - assert parsed_event.path == event["path"] - assert parsed_event.headers == event["headers"] - assert parsed_event.multiValueHeaders == event["multiValueHeaders"] - assert parsed_event.queryStringParameters == event["queryStringParameters"] - assert parsed_event.multiValueQueryStringParameters == event["multiValueQueryStringParameters"] - - request_context = parsed_event.requestContext - assert request_context.accountId == event["requestContext"]["accountId"] - assert request_context.apiId == event["requestContext"]["apiId"] - - authorizer = request_context.authorizer - assert authorizer.claims is None - assert authorizer.scopes is None - - assert request_context.domainName == event["requestContext"]["domainName"] - assert request_context.domainPrefix == event["requestContext"]["domainPrefix"] - assert request_context.extendedRequestId == event["requestContext"]["extendedRequestId"] - assert request_context.httpMethod == event["requestContext"]["httpMethod"] - - identity = request_context.identity - assert identity.accessKey == event["requestContext"]["identity"]["accessKey"] - assert identity.accountId == event["requestContext"]["identity"]["accountId"] - assert identity.caller == event["requestContext"]["identity"]["caller"] - assert ( - identity.cognitoAuthenticationProvider == event["requestContext"]["identity"]["cognitoAuthenticationProvider"] - ) - assert identity.cognitoAuthenticationType == event["requestContext"]["identity"]["cognitoAuthenticationType"] - assert identity.cognitoIdentityId == event["requestContext"]["identity"]["cognitoIdentityId"] - assert identity.cognitoIdentityPoolId == event["requestContext"]["identity"]["cognitoIdentityPoolId"] - assert identity.principalOrgId == event["requestContext"]["identity"]["principalOrgId"] - assert str(identity.sourceIp) == event["requestContext"]["identity"]["sourceIp"] - assert identity.user == event["requestContext"]["identity"]["user"] - assert identity.userAgent == event["requestContext"]["identity"]["userAgent"] - assert identity.userArn == event["requestContext"]["identity"]["userArn"] - assert identity.clientCert is not None - assert identity.clientCert.clientCertPem == event["requestContext"]["identity"]["clientCert"]["clientCertPem"] - assert identity.clientCert.subjectDN == event["requestContext"]["identity"]["clientCert"]["subjectDN"] - assert identity.clientCert.issuerDN == event["requestContext"]["identity"]["clientCert"]["issuerDN"] - assert identity.clientCert.serialNumber == event["requestContext"]["identity"]["clientCert"]["serialNumber"] - assert ( - identity.clientCert.validity.notBefore - == event["requestContext"]["identity"]["clientCert"]["validity"]["notBefore"] - ) - assert ( - identity.clientCert.validity.notAfter - == event["requestContext"]["identity"]["clientCert"]["validity"]["notAfter"] - ) - - assert request_context.path == event["requestContext"]["path"] - assert request_context.protocol == event["requestContext"]["protocol"] - assert request_context.requestId == event["requestContext"]["requestId"] - assert request_context.requestTime == event["requestContext"]["requestTime"] - convert_time = int(round(request_context.requestTimeEpoch.timestamp() * 1000)) - assert convert_time == 1583349317135 - assert request_context.resourceId == event["requestContext"]["resourceId"] - assert request_context.resourcePath == event["requestContext"]["resourcePath"] - assert request_context.stage == event["requestContext"]["stage"] - - assert parsed_event.pathParameters == event["pathParameters"] - assert parsed_event.stageVariables == event["stageVariables"] - assert parsed_event.body == event["body"] - assert parsed_event.isBase64Encoded == event["isBase64Encoded"] - - assert request_context.connectedAt is None - assert request_context.connectionId is None - assert request_context.eventType is None - assert request_context.messageDirection is None - assert request_context.messageId is None - assert request_context.routeKey is None - assert request_context.operationName is None - assert identity.apiKey is None - assert identity.apiKeyId is None - - -def test_apigw_event_with_invalid_websocket_request(): - # GIVEN an event with an eventType != MESSAGE and has a messageId - event = { - "resource": "/", - "path": "/", - "httpMethod": "GET", - "headers": {}, - "multiValueHeaders": {}, - "isBase64Encoded": False, - "body": "Foo!", - "requestContext": { - "accountId": "1234", - "apiId": "myApi", - "httpMethod": "GET", - "identity": { - "sourceIp": "127.0.0.1", - }, - "path": "/", - "protocol": "Https", - "requestId": "1234", - "requestTime": "2018-09-07T16:20:46Z", - "requestTimeEpoch": 1536992496000, - "resourcePath": "/", - "stage": "test", - "eventType": "DISCONNECT", - "messageId": "messageId", - }, - } - - # WHEN calling event_parser with APIGatewayProxyEventModel - with pytest.raises(ValidationError) as err: - handle_apigw_event(event, LambdaContext()) - - # THEN raise TypeError for invalid event - errors = err.value.errors() - assert len(errors) == 1 - expected_msg = "messageId is available only when the `eventType` is `MESSAGE`" - assert errors[0]["msg"] == expected_msg - assert expected_msg in str(err.value) - - -def test_apigw_event_empty_body(): - event = load_event("apiGatewayProxyEvent.json") - event["body"] = None - parse(event=event, model=APIGatewayProxyEventModel) diff --git a/tests/functional/parser/test_apigwv2.py b/tests/functional/parser/test_apigwv2.py deleted file mode 100644 index d3510b185dd..00000000000 --- a/tests/functional/parser/test_apigwv2.py +++ /dev/null @@ -1,105 +0,0 @@ -from aws_lambda_powertools.utilities.parser import envelopes, event_parser, parse -from aws_lambda_powertools.utilities.parser.models import ( - APIGatewayProxyEventV2Model, - RequestContextV2, - RequestContextV2Authorizer, -) -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyApiGatewayBusiness -from tests.functional.utils import load_event - - -@event_parser(model=MyApiGatewayBusiness, envelope=envelopes.ApiGatewayV2Envelope) -def handle_apigw_with_envelope(event: MyApiGatewayBusiness, _: LambdaContext): - assert event.message == "Hello" - assert event.username == "Ran" - - -@event_parser(model=APIGatewayProxyEventV2Model) -def handle_apigw_event(event: APIGatewayProxyEventV2Model, _: LambdaContext): - return event - - -def test_apigw_v2_event_with_envelope(): - event = load_event("apiGatewayProxyV2Event.json") - event["body"] = '{"message": "Hello", "username": "Ran"}' - handle_apigw_with_envelope(event, LambdaContext()) - - -def test_apigw_v2_event_jwt_authorizer(): - event = load_event("apiGatewayProxyV2Event.json") - parsed_event: APIGatewayProxyEventV2Model = handle_apigw_event(event, LambdaContext()) - assert parsed_event.version == event["version"] - assert parsed_event.routeKey == event["routeKey"] - assert parsed_event.rawPath == event["rawPath"] - assert parsed_event.rawQueryString == event["rawQueryString"] - assert parsed_event.cookies == event["cookies"] - assert parsed_event.cookies[0] == "cookie1" - assert parsed_event.headers == event["headers"] - assert parsed_event.queryStringParameters == event["queryStringParameters"] - assert parsed_event.queryStringParameters["parameter2"] == "value" - - request_context = parsed_event.requestContext - assert request_context.accountId == event["requestContext"]["accountId"] - assert request_context.apiId == event["requestContext"]["apiId"] - assert request_context.authorizer.jwt.claims == event["requestContext"]["authorizer"]["jwt"]["claims"] - assert request_context.authorizer.jwt.scopes == event["requestContext"]["authorizer"]["jwt"]["scopes"] - assert request_context.domainName == event["requestContext"]["domainName"] - assert request_context.domainPrefix == event["requestContext"]["domainPrefix"] - - http = request_context.http - assert http.method == "POST" - assert http.path == "/my/path" - assert http.protocol == "HTTP/1.1" - assert str(http.sourceIp) == "192.168.0.1/32" - assert http.userAgent == "agent" - - assert request_context.requestId == event["requestContext"]["requestId"] - assert request_context.routeKey == event["requestContext"]["routeKey"] - assert request_context.stage == event["requestContext"]["stage"] - assert request_context.time == event["requestContext"]["time"] - convert_time = int(round(request_context.timeEpoch.timestamp() * 1000)) - assert convert_time == event["requestContext"]["timeEpoch"] - assert parsed_event.body == event["body"] - assert parsed_event.pathParameters == event["pathParameters"] - assert parsed_event.isBase64Encoded == event["isBase64Encoded"] - assert parsed_event.stageVariables == event["stageVariables"] - - -def test_api_gateway_proxy_v2_event_lambda_authorizer(): - event = load_event("apiGatewayProxyV2LambdaAuthorizerEvent.json") - parsed_event: APIGatewayProxyEventV2Model = handle_apigw_event(event, LambdaContext()) - request_context: RequestContextV2 = parsed_event.requestContext - assert request_context is not None - lambda_props: RequestContextV2Authorizer = request_context.authorizer.lambda_value - assert lambda_props is not None - assert lambda_props["key"] == "value" - - -def test_api_gateway_proxy_v2_event_iam_authorizer(): - event = load_event("apiGatewayProxyV2IamEvent.json") - parsed_event: APIGatewayProxyEventV2Model = handle_apigw_event(event, LambdaContext()) - iam = parsed_event.requestContext.authorizer.iam - assert iam is not None - assert iam.accessKey == "ARIA2ZJZYVUEREEIHAKY" - assert iam.accountId == "1234567890" - assert iam.callerId == "AROA7ZJZYVRE7C3DUXHH6:CognitoIdentityCredentials" - assert iam.cognitoIdentity.amr == ["foo"] - assert iam.cognitoIdentity.identityId == "us-east-1:3f291106-8703-466b-8f2b-3ecee1ca56ce" - assert iam.cognitoIdentity.identityPoolId == "us-east-1:4f291106-8703-466b-8f2b-3ecee1ca56ce" - assert iam.principalOrgId == "AwsOrgId" - assert iam.userArn == "arn:aws:iam::1234567890:user/Admin" - assert iam.userId == "AROA2ZJZYVRE7Y3TUXHH6" - - -def test_apigw_event_empty_body(): - event = load_event("apiGatewayProxyV2Event.json") - event.pop("body") # API GW v2 removes certain keys when no data is passed - parse(event=event, model=APIGatewayProxyEventV2Model) - - -def test_apigw_event_empty_query_strings(): - event = load_event("apiGatewayProxyV2Event.json") - event["rawQueryString"] = "" - event.pop("queryStringParameters") # API GW v2 removes certain keys when no data is passed - parse(event=event, model=APIGatewayProxyEventV2Model) diff --git a/tests/functional/parser/test_cloudwatch.py b/tests/functional/parser/test_cloudwatch.py deleted file mode 100644 index 5fa197bb792..00000000000 --- a/tests/functional/parser/test_cloudwatch.py +++ /dev/null @@ -1,89 +0,0 @@ -import base64 -import json -import zlib -from typing import Any, List - -import pytest - -from aws_lambda_powertools.utilities.parser import ( - ValidationError, - envelopes, - event_parser, -) -from aws_lambda_powertools.utilities.parser.models import ( - CloudWatchLogsLogEvent, - CloudWatchLogsModel, -) -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyCloudWatchBusiness -from tests.functional.utils import load_event - - -@event_parser(model=MyCloudWatchBusiness, envelope=envelopes.CloudWatchLogsEnvelope) -def handle_cloudwatch_logs(event: List[MyCloudWatchBusiness], _: LambdaContext): - assert len(event) == 1 - log: MyCloudWatchBusiness = event[0] - assert log.my_message == "hello" - assert log.user == "test" - - -@event_parser(model=CloudWatchLogsModel) -def handle_cloudwatch_logs_no_envelope(event: CloudWatchLogsModel, _: LambdaContext): - assert event.awslogs.decoded_data.owner == "123456789123" - assert event.awslogs.decoded_data.logGroup == "testLogGroup" - assert event.awslogs.decoded_data.logStream == "testLogStream" - assert event.awslogs.decoded_data.subscriptionFilters == ["testFilter"] - assert event.awslogs.decoded_data.messageType == "DATA_MESSAGE" - - assert len(event.awslogs.decoded_data.logEvents) == 2 - log_record: CloudWatchLogsLogEvent = event.awslogs.decoded_data.logEvents[0] - assert log_record.id == "eventId1" - convert_time = int(round(log_record.timestamp.timestamp() * 1000)) - assert convert_time == 1440442987000 - assert log_record.message == "[ERROR] First test message" - log_record: CloudWatchLogsLogEvent = event.awslogs.decoded_data.logEvents[1] - assert log_record.id == "eventId2" - convert_time = int(round(log_record.timestamp.timestamp() * 1000)) - assert convert_time == 1440442987001 - assert log_record.message == "[ERROR] Second test message" - - -def test_validate_event_user_model_with_envelope(): - my_log_message = {"my_message": "hello", "user": "test"} - inner_event_dict = { - "messageType": "DATA_MESSAGE", - "owner": "123456789123", - "logGroup": "testLogGroup", - "logStream": "testLogStream", - "subscriptionFilters": ["testFilter"], - "logEvents": [{"id": "eventId1", "timestamp": 1440442987000, "message": json.dumps(my_log_message)}], - } - dict_str = json.dumps(inner_event_dict) - compressesd_str = zlib.compress(str.encode(dict_str), -1) - event_dict = {"awslogs": {"data": base64.b64encode(compressesd_str)}} - - handle_cloudwatch_logs(event_dict, LambdaContext()) - - -def test_validate_event_does_not_conform_with_user_dict_model(): - event_dict = load_event("cloudWatchLogEvent.json") - with pytest.raises(ValidationError): - handle_cloudwatch_logs(event_dict, LambdaContext()) - - -def test_handle_cloudwatch_trigger_event_no_envelope(): - event_dict = load_event("cloudWatchLogEvent.json") - handle_cloudwatch_logs_no_envelope(event_dict, LambdaContext()) - - -def test_handle_invalid_cloudwatch_trigger_event_no_envelope(): - event_dict: Any = {"awslogs": {"data": "invalid_data"}} - with pytest.raises(ValidationError) as context: - handle_cloudwatch_logs_no_envelope(event_dict, LambdaContext()) - - assert context.value.errors()[0]["msg"] == "unable to decompress data" - - -def test_handle_invalid_event_with_envelope(): - with pytest.raises(ValidationError): - handle_cloudwatch_logs(event={}, context=LambdaContext()) diff --git a/tests/functional/parser/test_dynamodb.py b/tests/functional/parser/test_dynamodb.py deleted file mode 100644 index e6238b00b83..00000000000 --- a/tests/functional/parser/test_dynamodb.py +++ /dev/null @@ -1,73 +0,0 @@ -from typing import Any, Dict, List - -import pytest - -from aws_lambda_powertools.utilities.parser import ( - ValidationError, - envelopes, - event_parser, -) -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyAdvancedDynamoBusiness, MyDynamoBusiness -from tests.functional.utils import load_event - - -@event_parser(model=MyDynamoBusiness, envelope=envelopes.DynamoDBStreamEnvelope) -def handle_dynamodb(event: List[Dict[str, MyDynamoBusiness]], _: LambdaContext): - assert len(event) == 2 - assert event[0]["OldImage"] is None - assert event[0]["NewImage"].Message["S"] == "New item!" - assert event[0]["NewImage"].Id["N"] == 101 - assert event[1]["OldImage"].Message["S"] == "New item!" - assert event[1]["OldImage"].Id["N"] == 101 - assert event[1]["NewImage"].Message["S"] == "This item has changed" - assert event[1]["NewImage"].Id["N"] == 101 - - -@event_parser(model=MyAdvancedDynamoBusiness) -def handle_dynamodb_no_envelope(event: MyAdvancedDynamoBusiness, _: LambdaContext): - records = event.Records - record = records[0] - assert record.awsRegion == "us-west-2" - dynamodb = record.dynamodb - assert dynamodb is not None - assert dynamodb.ApproximateCreationDateTime is None - keys = dynamodb.Keys - assert keys is not None - id_key = keys["Id"] - assert id_key["N"] == "101" - message_key = dynamodb.NewImage.Message - assert message_key is not None - assert message_key["S"] == "New item!" - assert dynamodb.OldImage is None - assert dynamodb.SequenceNumber == "111" - assert dynamodb.SizeBytes == 26 - assert dynamodb.StreamViewType == "NEW_AND_OLD_IMAGES" - assert record.eventID == "1" - assert record.eventName == "INSERT" - assert record.eventSource == "aws:dynamodb" - assert record.eventSourceARN == "eventsource_arn" - assert record.eventVersion == 1.0 - assert record.userIdentity is None - - -def test_dynamo_db_stream_trigger_event(): - event_dict = load_event("dynamoStreamEvent.json") - handle_dynamodb(event_dict, LambdaContext()) - - -def test_dynamo_db_stream_trigger_event_no_envelope(): - event_dict = load_event("dynamoStreamEvent.json") - handle_dynamodb_no_envelope(event_dict, LambdaContext()) - - -def test_validate_event_does_not_conform_with_model_no_envelope(): - event_dict: Any = {"hello": "s"} - with pytest.raises(ValidationError): - handle_dynamodb_no_envelope(event_dict, LambdaContext()) - - -def test_validate_event_does_not_conform_with_model(): - event_dict: Any = {"hello": "s"} - with pytest.raises(ValidationError): - handle_dynamodb(event_dict, LambdaContext()) diff --git a/tests/functional/parser/test_eventbridge.py b/tests/functional/parser/test_eventbridge.py deleted file mode 100644 index ca41e1a4bc5..00000000000 --- a/tests/functional/parser/test_eventbridge.py +++ /dev/null @@ -1,69 +0,0 @@ -from typing import Any - -import pytest - -from aws_lambda_powertools.utilities.parser import ( - ValidationError, - envelopes, - event_parser, -) -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import ( - MyAdvancedEventbridgeBusiness, - MyEventbridgeBusiness, -) -from tests.functional.utils import load_event - - -@event_parser(model=MyEventbridgeBusiness, envelope=envelopes.EventBridgeEnvelope) -def handle_eventbridge(event: MyEventbridgeBusiness, _: LambdaContext): - assert event.instance_id == "i-1234567890abcdef0" - assert event.state == "terminated" - - -@event_parser(model=MyAdvancedEventbridgeBusiness) -def handle_eventbridge_no_envelope(event: MyAdvancedEventbridgeBusiness, _: LambdaContext): - assert event.detail.instance_id == "i-1234567890abcdef0" - assert event.detail.state == "terminated" - assert event.id == "6a7e8feb-b491-4cf7-a9f1-bf3703467718" - assert event.version == "0" - assert event.account == "111122223333" - time_str = event.time.strftime("%Y-%m-%dT%H:%M:%SZ") - assert time_str == "2017-12-22T18:43:48Z" - assert event.region == "us-west-1" - assert event.resources == ["arn:aws:ec2:us-west-1:123456789012:instance/i-1234567890abcdef0"] - assert event.source == "aws.ec2" - assert event.detail_type == "EC2 Instance State-change Notification" - assert event.replay_name == "replay_archive" - - -def test_handle_eventbridge_trigger_event(): - event_dict = load_event("eventBridgeEvent.json") - handle_eventbridge(event_dict, LambdaContext()) - - -def test_validate_event_does_not_conform_with_user_dict_model(): - event_dict: Any = { - "version": "0", - "id": "6a7e8feb-b491-4cf7-a9f1-bf3703467718", - "detail-type": "EC2 Instance State-change Notification", - "source": "aws.ec2", - "account": "111122223333", - "time": "2017-12-22T18:43:48Z", - "region": "us-west-1", - "resources": ["arn:aws:ec2:us-west-1:123456789012:instance/i-1234567890abcdef0"], - "detail": {}, - } - with pytest.raises(ValidationError) as e: - handle_eventbridge(event_dict, LambdaContext()) - print(e.exconly()) - - -def test_handle_eventbridge_trigger_event_no_envelope(): - event_dict = load_event("eventBridgeEvent.json") - handle_eventbridge_no_envelope(event_dict, LambdaContext()) - - -def test_handle_invalid_event_with_eventbridge_envelope(): - with pytest.raises(ValidationError): - handle_eventbridge(event={}, context=LambdaContext()) diff --git a/tests/functional/parser/test_kafka.py b/tests/functional/parser/test_kafka.py deleted file mode 100644 index f764106add4..00000000000 --- a/tests/functional/parser/test_kafka.py +++ /dev/null @@ -1,93 +0,0 @@ -from typing import List - -from aws_lambda_powertools.utilities.parser import envelopes, event_parser -from aws_lambda_powertools.utilities.parser.models import ( - KafkaMskEventModel, - KafkaRecordModel, - KafkaSelfManagedEventModel, -) -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyLambdaKafkaBusiness -from tests.functional.utils import load_event - - -@event_parser(model=MyLambdaKafkaBusiness, envelope=envelopes.KafkaEnvelope) -def handle_lambda_kafka_with_envelope(event: List[MyLambdaKafkaBusiness], _: LambdaContext): - assert event[0].key == "value" - assert len(event) == 1 - - -@event_parser(model=KafkaSelfManagedEventModel) -def handle_kafka_event(event: KafkaSelfManagedEventModel, _: LambdaContext): - return event - - -def test_kafka_msk_event_with_envelope(): - event = load_event("kafkaEventMsk.json") - handle_lambda_kafka_with_envelope(event, LambdaContext()) - - -def test_kafka_self_managed_event_with_envelope(): - event = load_event("kafkaEventSelfManaged.json") - handle_lambda_kafka_with_envelope(event, LambdaContext()) - - -def test_self_managed_kafka_event(): - json_event = load_event("kafkaEventSelfManaged.json") - event: KafkaSelfManagedEventModel = handle_kafka_event(json_event, LambdaContext()) - assert event.eventSource == "aws:SelfManagedKafka" - bootstrap_servers = [ - "b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092", - "b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092", - ] - assert event.bootstrapServers == bootstrap_servers - - records = list(event.records["mytopic-0"]) - assert len(records) == 1 - record: KafkaRecordModel = records[0] - assert record.topic == "mytopic" - assert record.partition == 0 - assert record.offset == 15 - assert record.timestamp is not None - convert_time = int(round(record.timestamp.timestamp() * 1000)) - assert convert_time == 1545084650987 - assert record.timestampType == "CREATE_TIME" - assert record.key == b"recordKey" - assert record.value == '{"key":"value"}' - assert len(record.headers) == 1 - assert record.headers[0]["headerKey"] == b"headerValue" - - -@event_parser(model=KafkaMskEventModel) -def handle_msk_event(event: KafkaMskEventModel, _: LambdaContext): - return event - - -def test_kafka_msk_event(): - json_event = load_event("kafkaEventMsk.json") - event: KafkaMskEventModel = handle_msk_event(json_event, LambdaContext()) - assert event.eventSource == "aws:kafka" - bootstrap_servers = [ - "b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092", - "b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092", - ] - assert event.bootstrapServers == bootstrap_servers - assert ( - event.eventSourceArn - == "arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4" - ) - - records = list(event.records["mytopic-0"]) - assert len(records) == 1 - record: KafkaRecordModel = records[0] - assert record.topic == "mytopic" - assert record.partition == 0 - assert record.offset == 15 - assert record.timestamp is not None - convert_time = int(round(record.timestamp.timestamp() * 1000)) - assert convert_time == 1545084650987 - assert record.timestampType == "CREATE_TIME" - assert record.key == b"recordKey" - assert record.value == '{"key":"value"}' - assert len(record.headers) == 1 - assert record.headers[0]["headerKey"] == b"headerValue" diff --git a/tests/functional/parser/test_kinesis.py b/tests/functional/parser/test_kinesis.py deleted file mode 100644 index 151102c34c8..00000000000 --- a/tests/functional/parser/test_kinesis.py +++ /dev/null @@ -1,153 +0,0 @@ -from typing import Any, List - -import pytest - -from aws_lambda_powertools.utilities.parser import ( - BaseModel, - ValidationError, - envelopes, - event_parser, -) -from aws_lambda_powertools.utilities.parser.models import ( - KinesisDataStreamModel, - KinesisDataStreamRecordPayload, -) -from aws_lambda_powertools.utilities.parser.models.cloudwatch import ( - CloudWatchLogsDecode, -) -from aws_lambda_powertools.utilities.parser.models.kinesis import ( - extract_cloudwatch_logs_from_event, - extract_cloudwatch_logs_from_record, -) -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyKinesisBusiness -from tests.functional.utils import load_event - - -@event_parser(model=MyKinesisBusiness, envelope=envelopes.KinesisDataStreamEnvelope) -def handle_kinesis(event: List[MyKinesisBusiness], _: LambdaContext): - assert len(event) == 1 - record: KinesisDataStreamModel = event[0] - assert record.message == "test message" - assert record.username == "test" - - -@event_parser(model=KinesisDataStreamModel) -def handle_kinesis_no_envelope(event: KinesisDataStreamModel, _: LambdaContext): - records = event.Records - assert len(records) == 2 - record: KinesisDataStreamModel = records[0] - - assert record.awsRegion == "us-east-2" - assert record.eventID == "shardId-000000000006:49590338271490256608559692538361571095921575989136588898" - assert record.eventName == "aws:kinesis:record" - assert record.eventSource == "aws:kinesis" - assert record.eventSourceARN == "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream" - assert record.eventVersion == "1.0" - assert record.invokeIdentityArn == "arn:aws:iam::123456789012:role/lambda-role" - - kinesis: KinesisDataStreamRecordPayload = record.kinesis - assert kinesis.approximateArrivalTimestamp == 1545084650.987 - assert kinesis.kinesisSchemaVersion == "1.0" - assert kinesis.partitionKey == "1" - assert kinesis.sequenceNumber == "49590338271490256608559692538361571095921575989136588898" - assert kinesis.data == b"Hello, this is a test." - - -def test_kinesis_trigger_event(): - event_dict = { - "Records": [ - { - "kinesis": { - "kinesisSchemaVersion": "1.0", - "partitionKey": "1", - "sequenceNumber": "49590338271490256608559692538361571095921575989136588898", - "data": "eyJtZXNzYWdlIjogInRlc3QgbWVzc2FnZSIsICJ1c2VybmFtZSI6ICJ0ZXN0In0=", - "approximateArrivalTimestamp": 1545084650.987, - }, - "eventSource": "aws:kinesis", - "eventVersion": "1.0", - "eventID": "shardId-000000000006:49590338271490256608559692538361571095921575989136588898", - "eventName": "aws:kinesis:record", - "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role", - "awsRegion": "us-east-2", - "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream", - }, - ], - } - - handle_kinesis(event_dict, LambdaContext()) - - -def test_kinesis_trigger_bad_base64_event(): - event_dict = { - "Records": [ - { - "kinesis": { - "kinesisSchemaVersion": "1.0", - "partitionKey": "1", - "sequenceNumber": "49590338271490256608559692538361571095921575989136588898", - "data": "bad", - "approximateArrivalTimestamp": 1545084650.987, - }, - "eventSource": "aws:kinesis", - "eventVersion": "1.0", - "eventID": "shardId-000000000006:49590338271490256608559692538361571095921575989136588898", - "eventName": "aws:kinesis:record", - "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role", - "awsRegion": "us-east-2", - "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream", - }, - ], - } - with pytest.raises(ValidationError): - handle_kinesis_no_envelope(event_dict, LambdaContext()) - - -def test_kinesis_trigger_event_no_envelope(): - event_dict = load_event("kinesisStreamEvent.json") - handle_kinesis_no_envelope(event_dict, LambdaContext()) - - -def test_validate_event_does_not_conform_with_model_no_envelope(): - event_dict: Any = {"hello": "s"} - with pytest.raises(ValidationError): - handle_kinesis_no_envelope(event_dict, LambdaContext()) - - -def test_validate_event_does_not_conform_with_model(): - event_dict: Any = {"hello": "s"} - with pytest.raises(ValidationError): - handle_kinesis(event_dict, LambdaContext()) - - -def test_kinesis_stream_event_cloudwatch_logs_data_extraction(): - # GIVEN a KinesisDataStreamModel is instantiated with CloudWatch Logs compressed data - event_dict = load_event("kinesisStreamCloudWatchLogsEvent.json") - stream_data = KinesisDataStreamModel(**event_dict) - single_record = stream_data.Records[0] - - # WHEN we try to extract CloudWatch Logs from KinesisDataStreamRecordPayload model - extracted_logs = extract_cloudwatch_logs_from_event(stream_data) - individual_logs = [extract_cloudwatch_logs_from_record(record) for record in stream_data.Records] - single_log = extract_cloudwatch_logs_from_record(single_record) - - # THEN we should have extracted any potential logs as CloudWatchLogsDecode models - assert len(extracted_logs) == len(individual_logs) - assert isinstance(single_log, CloudWatchLogsDecode) - - -def test_kinesis_stream_event_cloudwatch_logs_data_extraction_fails_with_custom_model(): - # GIVEN a custom model replaces Kinesis Record Data bytes - class DummyModel(BaseModel): - ... - - event_dict = load_event("kinesisStreamCloudWatchLogsEvent.json") - stream_data = KinesisDataStreamModel(**event_dict) - - # WHEN decompress_zlib_record_data_as_json is used - # THEN ValueError should be raised - with pytest.raises(ValueError, match="We can only decompress bytes data"): - for record in stream_data.Records: - record.kinesis.data = DummyModel() - record.decompress_zlib_record_data_as_json() diff --git a/tests/functional/parser/test_kinesis_firehose.py b/tests/functional/parser/test_kinesis_firehose.py deleted file mode 100644 index c0b71f80540..00000000000 --- a/tests/functional/parser/test_kinesis_firehose.py +++ /dev/null @@ -1,138 +0,0 @@ -from typing import List - -import pytest - -from aws_lambda_powertools.utilities.parser import ( - ValidationError, - envelopes, - event_parser, -) -from aws_lambda_powertools.utilities.parser.models import ( - KinesisFirehoseModel, - KinesisFirehoseRecord, - KinesisFirehoseRecordMetadata, - KinesisFirehoseSqsModel, - KinesisFirehoseSqsRecord, -) -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyKinesisFirehoseBusiness -from tests.functional.utils import load_event - - -@event_parser(model=MyKinesisFirehoseBusiness, envelope=envelopes.KinesisFirehoseEnvelope) -def handle_firehose(event: List[MyKinesisFirehoseBusiness], _: LambdaContext): - assert len(event) == 1 - assert event[0].Hello == "World" - - -@event_parser(model=KinesisFirehoseModel) -def handle_firehose_no_envelope_kinesis(event: KinesisFirehoseModel, _: LambdaContext): - assert event.region == "us-east-2" - assert event.invocationId == "2b4d1ad9-2f48-94bd-a088-767c317e994a" - assert event.deliveryStreamArn == "arn:aws:firehose:us-east-2:123456789012:deliverystream/delivery-stream-name" - assert event.sourceKinesisStreamArn == "arn:aws:kinesis:us-east-1:123456789012:stream/kinesis-source" - - records = list(event.records) - assert len(records) == 2 - record_01: KinesisFirehoseRecord = records[0] - assert record_01.approximateArrivalTimestamp == 1664028820148 - assert record_01.recordId == "record1" - assert record_01.data == b"Hello World" - - metadata_01: KinesisFirehoseRecordMetadata = record_01.kinesisRecordMetadata - assert metadata_01.partitionKey == "4d1ad2b9-24f8-4b9d-a088-76e9947c317a" - assert metadata_01.subsequenceNumber == "" - assert metadata_01.shardId == "shardId-000000000000" - assert metadata_01.approximateArrivalTimestamp == 1664028820148 - assert metadata_01.sequenceNumber == "49546986683135544286507457936321625675700192471156785154" - - record_02: KinesisFirehoseRecord = records[1] - assert record_02.approximateArrivalTimestamp == 1664028793294 - assert record_02.recordId == "record2" - assert record_02.data == b'{"Hello": "World"}' - - metadata_02: KinesisFirehoseRecordMetadata = record_02.kinesisRecordMetadata - assert metadata_02.partitionKey == "4d1ad2b9-24f8-4b9d-a088-76e9947c318a" - assert metadata_02.subsequenceNumber == "" - assert metadata_02.shardId == "shardId-000000000001" - assert metadata_02.approximateArrivalTimestamp == 1664028793294 - assert metadata_02.sequenceNumber == "49546986683135544286507457936321625675700192471156785155" - - -@event_parser(model=KinesisFirehoseModel) -def handle_firehose_no_envelope_put(event: KinesisFirehoseModel, _: LambdaContext): - assert event.region == "us-east-2" - assert event.invocationId == "2b4d1ad9-2f48-94bd-a088-767c317e994a" - assert event.deliveryStreamArn == "arn:aws:firehose:us-east-2:123456789012:deliverystream/delivery-stream-name" - - records = list(event.records) - assert len(records) == 2 - - record_01: KinesisFirehoseRecord = records[0] - assert record_01.approximateArrivalTimestamp == 1664029185290 - assert record_01.recordId == "record1" - assert record_01.data == b"Hello World" - - record_02: KinesisFirehoseRecord = records[1] - assert record_02.approximateArrivalTimestamp == 1664029186945 - assert record_02.recordId == "record2" - assert record_02.data == b'{"Hello": "World"}' - - -@event_parser(model=KinesisFirehoseSqsModel) -def handle_firehose_sqs_wrapped_message(event: KinesisFirehoseSqsModel, _: LambdaContext): - assert event.region == "us-east-1" - assert event.invocationId == "556b67a3-48fc-4385-af49-e133aade9cb9" - assert event.deliveryStreamArn == "arn:aws:firehose:us-east-1:123456789012:deliverystream/PUT-S3-tdyyE" - - records = list(event.records) - assert len(records) == 1 - - record_01: KinesisFirehoseSqsRecord = records[0] - assert record_01.data.messageId == "5ab807d4-5644-4c55-97a3-47396635ac74" - assert record_01.data.receiptHandle == "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a..." - assert record_01.data.body == "Test message." - assert record_01.data.attributes.ApproximateReceiveCount == "1" - assert record_01.data.attributes.SenderId == "AIDAIENQZJOLO23YVJ4VO" - - -def test_firehose_sqs_wrapped_message_event(): - event_dict = load_event("kinesisFirehoseSQSEvent.json") - handle_firehose_sqs_wrapped_message(event_dict, LambdaContext()) - - -def test_firehose_trigger_event(): - event_dict = load_event("kinesisFirehoseKinesisEvent.json") - event_dict["records"].pop(0) # remove first item since the payload is bytes and we want to test payload json class - handle_firehose(event_dict, LambdaContext()) - - -def test_firehose_trigger_event_kinesis_no_envelope(): - event_dict = load_event("kinesisFirehoseKinesisEvent.json") - handle_firehose_no_envelope_kinesis(event_dict, LambdaContext()) - - -def test_firehose_trigger_event_put_no_envelope(): - event_dict = load_event("kinesisFirehosePutEvent.json") - handle_firehose_no_envelope_put(event_dict, LambdaContext()) - - -def test_kinesis_trigger_bad_base64_event(): - event_dict = load_event("kinesisFirehoseKinesisEvent.json") - event_dict["records"][0]["data"] = {"bad base64"} - with pytest.raises(ValidationError): - handle_firehose_no_envelope_kinesis(event_dict, LambdaContext()) - - -def test_kinesis_trigger_bad_timestamp_event(): - event_dict = load_event("kinesisFirehoseKinesisEvent.json") - event_dict["records"][0]["approximateArrivalTimestamp"] = -1 - with pytest.raises(ValidationError): - handle_firehose_no_envelope_kinesis(event_dict, LambdaContext()) - - -def test_kinesis_trigger_bad_metadata_timestamp_event(): - event_dict = load_event("kinesisFirehoseKinesisEvent.json") - event_dict["records"][0]["kinesisRecordMetadata"]["approximateArrivalTimestamp"] = "-1" - with pytest.raises(ValidationError): - handle_firehose_no_envelope_kinesis(event_dict, LambdaContext()) diff --git a/tests/functional/parser/test_lambda_function_url.py b/tests/functional/parser/test_lambda_function_url.py deleted file mode 100644 index a63a4e25884..00000000000 --- a/tests/functional/parser/test_lambda_function_url.py +++ /dev/null @@ -1,128 +0,0 @@ -from aws_lambda_powertools.utilities.parser import envelopes, event_parser -from aws_lambda_powertools.utilities.parser.models import LambdaFunctionUrlModel -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyALambdaFuncUrlBusiness -from tests.functional.utils import load_event - - -@event_parser(model=MyALambdaFuncUrlBusiness, envelope=envelopes.LambdaFunctionUrlEnvelope) -def handle_lambda_func_url_with_envelope(event: MyALambdaFuncUrlBusiness, _: LambdaContext): - assert event.message == "Hello" - assert event.username == "Ran" - - -@event_parser(model=LambdaFunctionUrlModel) -def handle_lambda_func_url_event(event: LambdaFunctionUrlModel, _: LambdaContext): - return event - - -def test_lambda_func_url_event_with_envelope(): - event = load_event("lambdaFunctionUrlEvent.json") - event["body"] = '{"message": "Hello", "username": "Ran"}' - handle_lambda_func_url_with_envelope(event, LambdaContext()) - - -def test_lambda_function_url_event(): - json_event = load_event("lambdaFunctionUrlEvent.json") - event: LambdaFunctionUrlModel = handle_lambda_func_url_event(json_event, LambdaContext()) - - assert event.version == "2.0" - assert event.routeKey == "$default" - - assert event.rawQueryString == "" - - assert event.cookies is None - - headers = event.headers - assert len(headers) == 20 - - assert event.queryStringParameters is None - - assert event.isBase64Encoded is False - assert event.body is None - assert event.pathParameters is None - assert event.stageVariables is None - - request_context = event.requestContext - - assert request_context.accountId == "anonymous" - assert request_context.apiId is not None - assert request_context.domainName == ".lambda-url.us-east-1.on.aws" - assert request_context.domainPrefix == "" - assert request_context.requestId == "id" - assert request_context.routeKey == "$default" - assert request_context.stage == "$default" - assert request_context.time is not None - convert_time = int(round(request_context.timeEpoch.timestamp() * 1000)) - assert convert_time == 1659687279885 - assert request_context.authorizer is None - - http = request_context.http - assert http.method == "GET" - assert http.path == "/" - assert http.protocol == "HTTP/1.1" - assert str(http.sourceIp) == "123.123.123.123/32" - assert http.userAgent == "agent" - - assert request_context.authorizer is None - - -def test_lambda_function_url_event_iam(): - json_event = load_event("lambdaFunctionUrlIAMEvent.json") - event: LambdaFunctionUrlModel = handle_lambda_func_url_event(json_event, LambdaContext()) - - assert event.version == "2.0" - assert event.routeKey == "$default" - - assert event.rawQueryString == "parameter1=value1¶meter1=value2¶meter2=value" - - cookies = event.cookies - assert len(cookies) == 2 - assert cookies[0] == "cookie1" - - headers = event.headers - assert len(headers) == 2 - - query_string_parameters = event.queryStringParameters - assert len(query_string_parameters) == 2 - assert query_string_parameters.get("parameter2") == "value" - - assert event.isBase64Encoded is False - assert event.body == "Hello from client!" - assert event.pathParameters is None - assert event.stageVariables is None - - request_context = event.requestContext - - assert request_context.accountId == "123456789012" - assert request_context.apiId is not None - assert request_context.domainName == ".lambda-url.us-west-2.on.aws" - assert request_context.domainPrefix == "" - assert request_context.requestId == "id" - assert request_context.routeKey == "$default" - assert request_context.stage == "$default" - assert request_context.time is not None - convert_time = int(round(request_context.timeEpoch.timestamp() * 1000)) - assert convert_time == 1583348638390 - - http = request_context.http - assert http.method == "POST" - assert http.path == "/my/path" - assert http.protocol == "HTTP/1.1" - assert str(http.sourceIp) == "123.123.123.123/32" - assert http.userAgent == "agent" - - authorizer = request_context.authorizer - assert authorizer is not None - assert authorizer.jwt is None - assert authorizer.lambda_value is None - - iam = authorizer.iam - assert iam is not None - assert iam.accessKey == "AKIA..." - assert iam.accountId == "111122223333" - assert iam.callerId == "AIDA..." - assert iam.cognitoIdentity is None - assert iam.principalOrgId is None - assert iam.userId == "AIDA..." - assert iam.userArn == "arn:aws:iam::111122223333:user/example-user" diff --git a/tests/functional/parser/test_s3.py b/tests/functional/parser/test_s3.py deleted file mode 100644 index 4037790efc5..00000000000 --- a/tests/functional/parser/test_s3.py +++ /dev/null @@ -1,155 +0,0 @@ -import pytest - -from aws_lambda_powertools.utilities.parser import ValidationError, event_parser, parse -from aws_lambda_powertools.utilities.parser.models import S3Model, S3RecordModel -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.utils import load_event - - -def assert_s3(event: S3Model): - records = list(event.Records) - assert len(records) == 1 - record: S3RecordModel = records[0] - assert record.eventVersion == "2.1" - assert record.eventSource == "aws:s3" - assert record.awsRegion == "us-east-2" - convert_time = int(round(record.eventTime.timestamp() * 1000)) - assert convert_time == 1567539447192 - assert record.eventName == "ObjectCreated:Put" - user_identity = record.userIdentity - assert user_identity.principalId == "AWS:AIDAINPONIXQXHT3IKHL2" - request_parameters = record.requestParameters - assert str(request_parameters.sourceIPAddress) == "205.255.255.255/32" - assert record.responseElements.x_amz_request_id == "D82B88E5F771F645" - assert ( - record.responseElements.x_amz_id_2 - == "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo=" - ) - s3 = record.s3 - assert s3.s3SchemaVersion == "1.0" - assert s3.configurationId == "828aa6fc-f7b5-4305-8584-487c791949c1" - bucket = s3.bucket - assert bucket.name == "lambda-artifacts-deafc19498e3f2df" - assert bucket.ownerIdentity.principalId == "A3I5XTEXAMAI3E" - assert bucket.arn == "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df" - assert s3.object.key == "b21b84d653bb07b05b1e6b33684dc11b" - assert s3.object.size == 1305107 - assert s3.object.eTag == "b21b84d653bb07b05b1e6b33684dc11b" - assert s3.object.versionId is None - assert s3.object.sequencer == "0C0F6F405D6ED209E1" - assert record.glacierEventData is None - - -@event_parser(model=S3Model) -def handle_s3(event: S3Model, _: LambdaContext): - assert_s3(event) - - -@event_parser(model=S3Model) -def handle_s3_glacier(event: S3Model, _: LambdaContext): - records = list(event.Records) - assert len(records) == 1 - record: S3RecordModel = records[0] - assert record.eventVersion == "2.1" - assert record.eventSource == "aws:s3" - assert record.awsRegion == "us-east-2" - convert_time = int(round(record.eventTime.timestamp() * 1000)) - assert convert_time == 1567539447192 - assert record.eventName == "ObjectCreated:Put" - user_identity = record.userIdentity - assert user_identity.principalId == "AWS:AIDAINPONIXQXHT3IKHL2" - request_parameters = record.requestParameters - assert str(request_parameters.sourceIPAddress) == "205.255.255.255/32" - assert record.responseElements.x_amz_request_id == "D82B88E5F771F645" - assert ( - record.responseElements.x_amz_id_2 - == "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo=" - ) - s3 = record.s3 - assert s3.s3SchemaVersion == "1.0" - assert s3.configurationId == "828aa6fc-f7b5-4305-8584-487c791949c1" - bucket = s3.bucket - assert bucket.name == "lambda-artifacts-deafc19498e3f2df" - assert bucket.ownerIdentity.principalId == "A3I5XTEXAMAI3E" - assert bucket.arn == "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df" - assert s3.object.key == "b21b84d653bb07b05b1e6b33684dc11b" - assert s3.object.size == 1305107 - assert s3.object.eTag == "b21b84d653bb07b05b1e6b33684dc11b" - assert s3.object.versionId is None - assert s3.object.sequencer == "0C0F6F405D6ED209E1" - assert record.glacierEventData is not None - convert_time = int( - round(record.glacierEventData.restoreEventData.lifecycleRestorationExpiryTime.timestamp() * 1000), - ) - assert convert_time == 60000 - assert record.glacierEventData.restoreEventData.lifecycleRestoreStorageClass == "standard" - - -def test_s3_trigger_event(): - event_dict = load_event("s3Event.json") - handle_s3(event_dict, LambdaContext()) - - -def test_s3_glacier_trigger_event(): - event_dict = load_event("s3EventGlacier.json") - handle_s3_glacier(event_dict, LambdaContext()) - - -def test_s3_empty_object(): - event_dict = load_event("s3Event.json") - event_dict["Records"][0]["s3"]["object"]["size"] = 0 - parse(event=event_dict, model=S3Model) - - -def test_s3_none_object_size_failed_validation(): - event_dict = load_event("s3Event.json") - event_dict["Records"][0]["s3"]["object"]["size"] = None - with pytest.raises(ValidationError): - parse(event=event_dict, model=S3Model) - - -def test_s3_none_etag_value_failed_validation(): - event_dict = load_event("s3Event.json") - event_dict["Records"][0]["s3"]["object"]["eTag"] = None - with pytest.raises(ValidationError): - parse(event=event_dict, model=S3Model) - - -@event_parser(model=S3Model) -def handle_s3_delete_object(event: S3Model, _: LambdaContext): - records = list(event.Records) - assert len(records) == 1 - record: S3RecordModel = records[0] - assert record.eventVersion == "2.1" - assert record.eventSource == "aws:s3" - assert record.awsRegion == "us-east-2" - convert_time = int(round(record.eventTime.timestamp() * 1000)) - assert convert_time == 1567539447192 - assert record.eventName == "ObjectRemoved:Delete" - user_identity = record.userIdentity - assert user_identity.principalId == "AWS:AIDAINPONIXQXHT3IKHL2" - request_parameters = record.requestParameters - assert str(request_parameters.sourceIPAddress) == "205.255.255.255/32" - assert record.responseElements.x_amz_request_id == "D82B88E5F771F645" - assert ( - record.responseElements.x_amz_id_2 - == "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo=" - ) - s3 = record.s3 - assert s3.s3SchemaVersion == "1.0" - assert s3.configurationId == "828aa6fc-f7b5-4305-8584-487c791949c1" - bucket = s3.bucket - assert bucket.name == "lambda-artifacts-deafc19498e3f2df" - assert bucket.ownerIdentity.principalId == "A3I5XTEXAMAI3E" - assert bucket.arn == "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df" - assert s3.object.key == "b21b84d653bb07b05b1e6b33684dc11b" - assert s3.object.size is None - assert s3.object.eTag is None - assert s3.object.versionId is None - assert s3.object.sequencer == "0C0F6F405D6ED209E1" - assert record.glacierEventData is None - - -def test_s3_trigger_event_delete_object(): - event_dict = load_event("s3EventDeleteObject.json") - handle_s3_delete_object(event_dict, LambdaContext()) diff --git a/tests/functional/parser/test_ses.py b/tests/functional/parser/test_ses.py deleted file mode 100644 index d434e2350f8..00000000000 --- a/tests/functional/parser/test_ses.py +++ /dev/null @@ -1,49 +0,0 @@ -from aws_lambda_powertools.utilities.parser import event_parser -from aws_lambda_powertools.utilities.parser.models import SesModel, SesRecordModel -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.utils import load_event - - -@event_parser(model=SesModel) -def handle_ses(event: SesModel, _: LambdaContext): - expected_address = "johndoe@example.com" - records = event.Records - record: SesRecordModel = records[0] - assert record.eventSource == "aws:ses" - assert record.eventVersion == "1.0" - mail = record.ses.mail - convert_time = int(round(mail.timestamp.timestamp() * 1000)) - assert convert_time == 0 - assert mail.source == "janedoe@example.com" - assert mail.messageId == "o3vrnil0e2ic28tr" - assert mail.destination == [expected_address] - assert mail.headersTruncated is False - headers = list(mail.headers) - assert len(headers) == 10 - assert headers[0].name == "Return-Path" - assert headers[0].value == "" - common_headers = mail.commonHeaders - assert common_headers.returnPath == "janedoe@example.com" - assert common_headers.header_from == ["Jane Doe "] - assert common_headers.date == "Wed, 7 Oct 2015 12:34:56 -0700" - assert common_headers.to == [expected_address] - assert common_headers.messageId == "<0123456789example.com>" - assert common_headers.subject == "Test Subject" - receipt = record.ses.receipt - convert_time = int(round(receipt.timestamp.timestamp() * 1000)) - assert convert_time == 0 - assert receipt.processingTimeMillis == 574 - assert receipt.recipients == [expected_address] - assert receipt.spamVerdict.status == "PASS" - assert receipt.virusVerdict.status == "PASS" - assert receipt.spfVerdict.status == "PASS" - assert receipt.dmarcVerdict.status == "PASS" - action = receipt.action - assert action.type == "Lambda" - assert action.functionArn == "arn:aws:lambda:us-west-2:012345678912:function:Example" - assert action.invocationType == "Event" - - -def test_ses_trigger_event(): - event_dict = load_event("sesEvent.json") - handle_ses(event_dict, LambdaContext()) diff --git a/tests/functional/parser/test_sns.py b/tests/functional/parser/test_sns.py deleted file mode 100644 index 617de487748..00000000000 --- a/tests/functional/parser/test_sns.py +++ /dev/null @@ -1,128 +0,0 @@ -import json -from typing import Any, List - -import pytest - -from aws_lambda_powertools.utilities.parser import ( - ValidationError, - envelopes, - event_parser, -) -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyAdvancedSnsBusiness, MySnsBusiness -from tests.functional.utils import load_event -from tests.functional.validator.conftest import sns_event # noqa: F401 - - -@event_parser(model=MySnsBusiness, envelope=envelopes.SnsEnvelope) -def handle_sns_json_body(event: List[MySnsBusiness], _: LambdaContext): - assert len(event) == 1 - assert event[0].message == "hello world" - assert event[0].username == "lessa" - - -def test_handle_sns_trigger_event_json_body(sns_event): # noqa: F811 - handle_sns_json_body(sns_event, LambdaContext()) - - -def test_validate_event_does_not_conform_with_model(): - event: Any = {"invalid": "event"} - - with pytest.raises(ValidationError): - handle_sns_json_body(event, LambdaContext()) - - -def test_validate_event_does_not_conform_user_json_string_with_model(): - event: Any = { - "Records": [ - { - "EventVersion": "1.0", - "EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:sns-la ...", - "EventSource": "aws:sns", - "Sns": { - "SignatureVersion": "1", - "Timestamp": "2019-01-02T12:45:07.000Z", - "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==", - "SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificat ...", - "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e", - "Message": "not a valid JSON!", - "MessageAttributes": {"Test": {"Type": "String", "Value": "TestString"}}, - "Type": "Notification", - "UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscri ...", - "TopicArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda", - "Subject": "TestInvoke", - }, - }, - ], - } - - with pytest.raises(ValidationError): - handle_sns_json_body(event, LambdaContext()) - - -@event_parser(model=MyAdvancedSnsBusiness) -def handle_sns_no_envelope(event: MyAdvancedSnsBusiness, _: LambdaContext): - records = event.Records - record = records[0] - - assert len(records) == 1 - assert record.EventVersion == "1.0" - assert record.EventSubscriptionArn == "arn:aws:sns:us-east-2:123456789012:sns-la ..." - assert record.EventSource == "aws:sns" - assert record.Sns.Type == "Notification" - assert record.Sns.UnsubscribeUrl.scheme == "https" - assert record.Sns.UnsubscribeUrl.host == "sns.us-east-2.amazonaws.com" - assert record.Sns.UnsubscribeUrl.query == "Action=Unsubscribe" - assert record.Sns.TopicArn == "arn:aws:sns:us-east-2:123456789012:sns-lambda" - assert record.Sns.Subject == "TestInvoke" - assert record.Sns.SignatureVersion == "1" - convert_time = int(round(record.Sns.Timestamp.timestamp() * 1000)) - assert convert_time == 1546433107000 - assert record.Sns.Signature == "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==" - assert record.Sns.SigningCertUrl.host == "sns.us-east-2.amazonaws.com" - assert record.Sns.SigningCertUrl.scheme == "https" - assert record.Sns.SigningCertUrl.host == "sns.us-east-2.amazonaws.com" - assert record.Sns.SigningCertUrl.path == "/SimpleNotification" - assert record.Sns.MessageId == "95df01b4-ee98-5cb9-9903-4c221d41eb5e" - assert record.Sns.Message == "Hello from SNS!" - attrib_dict = record.Sns.MessageAttributes - assert len(attrib_dict) == 2 - assert attrib_dict["Test"].Type == "String" - assert attrib_dict["Test"].Value == "TestString" - assert attrib_dict["TestBinary"].Type == "Binary" - assert attrib_dict["TestBinary"].Value == "TestBinary" - - -def test_handle_sns_trigger_event_no_envelope(): - event_dict = load_event("snsEvent.json") - handle_sns_no_envelope(event_dict, LambdaContext()) - - -@event_parser(model=MySnsBusiness, envelope=envelopes.SnsSqsEnvelope) -def handle_sns_sqs_json_body(event: List[MySnsBusiness], _: LambdaContext): - assert len(event) == 1 - assert event[0].message == "hello world" - assert event[0].username == "lessa" - - -def test_handle_sns_sqs_trigger_event_json_body(): # noqa: F811 - event_dict = load_event("snsSqsEvent.json") - handle_sns_sqs_json_body(event_dict, LambdaContext()) - - -def test_handle_sns_sqs_trigger_event_json_body_missing_unsubscribe_url(): - # GIVEN an event is tampered with a missing UnsubscribeURL - event_dict = load_event("snsSqsEvent.json") - payload = json.loads(event_dict["Records"][0]["body"]) - payload.pop("UnsubscribeURL") - event_dict["Records"][0]["body"] = json.dumps(payload) - - # WHEN parsing the payload - # THEN raise a ValidationError error - with pytest.raises(ValidationError): - handle_sns_sqs_json_body(event_dict, LambdaContext()) - - -def test_handle_sns_sqs_fifo_trigger_event_json_body(): - event_dict = load_event("snsSqsFifoEvent.json") - handle_sns_sqs_json_body(event_dict, LambdaContext()) diff --git a/tests/functional/parser/schemas.py b/tests/unit/parser/schemas.py similarity index 100% rename from tests/functional/parser/schemas.py rename to tests/unit/parser/schemas.py diff --git a/tests/unit/parser/test_alb.py b/tests/unit/parser/test_alb.py new file mode 100644 index 00000000000..6cd109941e9 --- /dev/null +++ b/tests/unit/parser/test_alb.py @@ -0,0 +1,24 @@ +import pytest + +from aws_lambda_powertools.utilities.parser import ValidationError +from aws_lambda_powertools.utilities.parser.models import AlbModel +from tests.functional.utils import load_event + + +def test_alb_trigger_event(): + raw_event = load_event("albEvent.json") + parsed_event: AlbModel = AlbModel(**raw_event) + + assert parsed_event.requestContext.elb.targetGroupArn == raw_event["requestContext"]["elb"]["targetGroupArn"] + assert parsed_event.httpMethod == raw_event["httpMethod"] + assert parsed_event.path == raw_event["path"] + assert parsed_event.queryStringParameters == raw_event["queryStringParameters"] + assert parsed_event.headers == raw_event["headers"] + assert parsed_event.body == raw_event["body"] + assert not parsed_event.isBase64Encoded + + +def test_validate_event_does_not_conform_with_model(): + event = {"invalid": "event"} + with pytest.raises(ValidationError): + AlbModel(**event) diff --git a/tests/unit/parser/test_apigw.py b/tests/unit/parser/test_apigw.py new file mode 100644 index 00000000000..a65d181cc54 --- /dev/null +++ b/tests/unit/parser/test_apigw.py @@ -0,0 +1,148 @@ +import pytest +from pydantic import ValidationError + +from aws_lambda_powertools.utilities.parser import envelopes, parse +from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventModel +from tests.functional.utils import load_event +from tests.unit.parser.schemas import MyApiGatewayBusiness + + +def test_apigw_event_with_envelope(): + raw_event = load_event("apiGatewayProxyEvent.json") + raw_event["body"] = '{"message": "Hello", "username": "Ran"}' + parsed_event: MyApiGatewayBusiness = parse( + event=raw_event, + model=MyApiGatewayBusiness, + envelope=envelopes.ApiGatewayEnvelope, + ) + + assert parsed_event.message == "Hello" + assert parsed_event.username == "Ran" + + +def test_apigw_event(): + raw_event = load_event("apiGatewayProxyEvent.json") + parsed_event: APIGatewayProxyEventModel = APIGatewayProxyEventModel(**raw_event) + + assert parsed_event.version == raw_event["version"] + assert parsed_event.resource == raw_event["resource"] + assert parsed_event.path == raw_event["path"] + assert parsed_event.headers == raw_event["headers"] + assert parsed_event.multiValueHeaders == raw_event["multiValueHeaders"] + assert parsed_event.queryStringParameters == raw_event["queryStringParameters"] + assert parsed_event.multiValueQueryStringParameters == raw_event["multiValueQueryStringParameters"] + + request_context = parsed_event.requestContext + assert request_context.accountId == raw_event["requestContext"]["accountId"] + assert request_context.apiId == raw_event["requestContext"]["apiId"] + + authorizer = request_context.authorizer + assert authorizer.claims is None + assert authorizer.scopes is None + + assert request_context.domainName == raw_event["requestContext"]["domainName"] + assert request_context.domainPrefix == raw_event["requestContext"]["domainPrefix"] + assert request_context.extendedRequestId == raw_event["requestContext"]["extendedRequestId"] + assert request_context.httpMethod == raw_event["requestContext"]["httpMethod"] + + identity = request_context.identity + assert identity.accessKey == raw_event["requestContext"]["identity"]["accessKey"] + assert identity.accountId == raw_event["requestContext"]["identity"]["accountId"] + assert identity.caller == raw_event["requestContext"]["identity"]["caller"] + assert ( + identity.cognitoAuthenticationProvider + == raw_event["requestContext"]["identity"]["cognitoAuthenticationProvider"] + ) + assert identity.cognitoAuthenticationType == raw_event["requestContext"]["identity"]["cognitoAuthenticationType"] + assert identity.cognitoIdentityId == raw_event["requestContext"]["identity"]["cognitoIdentityId"] + assert identity.cognitoIdentityPoolId == raw_event["requestContext"]["identity"]["cognitoIdentityPoolId"] + assert identity.principalOrgId == raw_event["requestContext"]["identity"]["principalOrgId"] + assert str(identity.sourceIp) == raw_event["requestContext"]["identity"]["sourceIp"] + assert identity.user == raw_event["requestContext"]["identity"]["user"] + assert identity.userAgent == raw_event["requestContext"]["identity"]["userAgent"] + assert identity.userArn == raw_event["requestContext"]["identity"]["userArn"] + assert identity.clientCert is not None + assert identity.clientCert.clientCertPem == raw_event["requestContext"]["identity"]["clientCert"]["clientCertPem"] + assert identity.clientCert.subjectDN == raw_event["requestContext"]["identity"]["clientCert"]["subjectDN"] + assert identity.clientCert.issuerDN == raw_event["requestContext"]["identity"]["clientCert"]["issuerDN"] + assert identity.clientCert.serialNumber == raw_event["requestContext"]["identity"]["clientCert"]["serialNumber"] + assert ( + identity.clientCert.validity.notBefore + == raw_event["requestContext"]["identity"]["clientCert"]["validity"]["notBefore"] + ) + assert ( + identity.clientCert.validity.notAfter + == raw_event["requestContext"]["identity"]["clientCert"]["validity"]["notAfter"] + ) + + assert request_context.path == raw_event["requestContext"]["path"] + assert request_context.protocol == raw_event["requestContext"]["protocol"] + assert request_context.requestId == raw_event["requestContext"]["requestId"] + assert request_context.requestTime == raw_event["requestContext"]["requestTime"] + convert_time = int(round(request_context.requestTimeEpoch.timestamp() * 1000)) + assert convert_time == 1583349317135 + assert request_context.resourceId == raw_event["requestContext"]["resourceId"] + assert request_context.resourcePath == raw_event["requestContext"]["resourcePath"] + assert request_context.stage == raw_event["requestContext"]["stage"] + + assert parsed_event.pathParameters == raw_event["pathParameters"] + assert parsed_event.stageVariables == raw_event["stageVariables"] + assert parsed_event.body == raw_event["body"] + assert parsed_event.isBase64Encoded == raw_event["isBase64Encoded"] + + assert request_context.connectedAt is None + assert request_context.connectionId is None + assert request_context.eventType is None + assert request_context.messageDirection is None + assert request_context.messageId is None + assert request_context.routeKey is None + assert request_context.operationName is None + assert identity.apiKey is None + assert identity.apiKeyId is None + + +def test_apigw_event_with_invalid_websocket_request(): + # GIVEN an event with an eventType != MESSAGE and has a messageId + event = { + "resource": "/", + "path": "/", + "httpMethod": "GET", + "headers": {}, + "multiValueHeaders": {}, + "isBase64Encoded": False, + "body": "Foo!", + "requestContext": { + "accountId": "1234", + "apiId": "myApi", + "httpMethod": "GET", + "identity": { + "sourceIp": "127.0.0.1", + }, + "path": "/", + "protocol": "Https", + "requestId": "1234", + "requestTime": "2018-09-07T16:20:46Z", + "requestTimeEpoch": 1536992496000, + "resourcePath": "/", + "stage": "test", + "eventType": "DISCONNECT", + "messageId": "messageId", + }, + } + + # WHEN calling event_parser with APIGatewayProxyEventModel + with pytest.raises(ValidationError) as err: + APIGatewayProxyEventModel(**event) + + # THEN raise TypeError for invalid event + errors = err.value.errors() + assert len(errors) == 1 + expected_msg = "messageId is available only when the `eventType` is `MESSAGE`" + assert errors[0]["msg"] == expected_msg + assert expected_msg in str(err.value) + + +def test_apigw_event_empty_body(): + event = load_event("apiGatewayProxyEvent.json") + event["body"] = None + parse(event=event, model=APIGatewayProxyEventModel) diff --git a/tests/unit/parser/test_apigwv2.py b/tests/unit/parser/test_apigwv2.py new file mode 100644 index 00000000000..9ffc7f525bc --- /dev/null +++ b/tests/unit/parser/test_apigwv2.py @@ -0,0 +1,106 @@ +from aws_lambda_powertools.utilities.parser import envelopes, parse +from aws_lambda_powertools.utilities.parser.models import ( + APIGatewayProxyEventV2Model, + RequestContextV2, + RequestContextV2Authorizer, +) +from tests.functional.utils import load_event +from tests.unit.parser.schemas import MyApiGatewayBusiness + + +def test_apigw_v2_event_with_envelope(): + raw_event = load_event("apiGatewayProxyV2Event.json") + raw_event["body"] = '{"message": "Hello", "username": "Ran"}' + parsed_event: MyApiGatewayBusiness = parse( + event=raw_event, + model=MyApiGatewayBusiness, + envelope=envelopes.ApiGatewayV2Envelope, + ) + + assert parsed_event.message == "Hello" + assert parsed_event.username == "Ran" + + +def test_apigw_v2_event_jwt_authorizer(): + raw_event = load_event("apiGatewayProxyV2Event.json") + parsed_event: APIGatewayProxyEventV2Model = APIGatewayProxyEventV2Model(**raw_event) + + assert parsed_event.version == raw_event["version"] + assert parsed_event.routeKey == raw_event["routeKey"] + assert parsed_event.rawPath == raw_event["rawPath"] + assert parsed_event.rawQueryString == raw_event["rawQueryString"] + assert parsed_event.cookies == raw_event["cookies"] + assert parsed_event.cookies[0] == "cookie1" + assert parsed_event.headers == raw_event["headers"] + assert parsed_event.queryStringParameters == raw_event["queryStringParameters"] + assert parsed_event.queryStringParameters.get("parameter2") == raw_event["queryStringParameters"]["parameter2"] + + request_context = parsed_event.requestContext + assert request_context.accountId == raw_event["requestContext"]["accountId"] + assert request_context.apiId == raw_event["requestContext"]["apiId"] + assert request_context.authorizer.jwt.claims == raw_event["requestContext"]["authorizer"]["jwt"]["claims"] + assert request_context.authorizer.jwt.scopes == raw_event["requestContext"]["authorizer"]["jwt"]["scopes"] + assert request_context.domainName == raw_event["requestContext"]["domainName"] + assert request_context.domainPrefix == raw_event["requestContext"]["domainPrefix"] + + http = request_context.http + raw_http = raw_event["requestContext"]["http"] + assert http.method == raw_http["method"] + assert http.path == raw_http["path"] + assert http.protocol == raw_http["protocol"] + assert str(http.sourceIp) == raw_http["sourceIp"] + assert http.userAgent == raw_http["userAgent"] + + assert request_context.requestId == raw_event["requestContext"]["requestId"] + assert request_context.routeKey == raw_event["requestContext"]["routeKey"] + assert request_context.stage == raw_event["requestContext"]["stage"] + assert request_context.time == raw_event["requestContext"]["time"] + convert_time = int(round(request_context.timeEpoch.timestamp() * 1000)) + assert convert_time == raw_event["requestContext"]["timeEpoch"] + assert parsed_event.body == raw_event["body"] + assert parsed_event.pathParameters == raw_event["pathParameters"] + assert parsed_event.isBase64Encoded == raw_event["isBase64Encoded"] + assert parsed_event.stageVariables == raw_event["stageVariables"] + + +def test_api_gateway_proxy_v2_event_lambda_authorizer(): + raw_event = load_event("apiGatewayProxyV2LambdaAuthorizerEvent.json") + parsed_event: APIGatewayProxyEventV2Model = APIGatewayProxyEventV2Model(**raw_event) + + request_context: RequestContextV2 = parsed_event.requestContext + assert request_context is not None + + lambda_props: RequestContextV2Authorizer = request_context.authorizer.lambda_value + assert lambda_props is not None + assert lambda_props["key"] == raw_event["requestContext"]["authorizer"]["lambda"]["key"] + + +def test_api_gateway_proxy_v2_event_iam_authorizer(): + raw_event = load_event("apiGatewayProxyV2IamEvent.json") + parsed_event: APIGatewayProxyEventV2Model = APIGatewayProxyEventV2Model(**raw_event) + + iam = parsed_event.requestContext.authorizer.iam + raw_iam = raw_event["requestContext"]["authorizer"]["iam"] + assert iam is not None + assert iam.accessKey == raw_iam["accessKey"] + assert iam.accountId == raw_iam["accountId"] + assert iam.callerId == raw_iam["callerId"] + assert iam.cognitoIdentity.amr == raw_iam["cognitoIdentity"]["amr"] + assert iam.cognitoIdentity.identityId == raw_iam["cognitoIdentity"]["identityId"] + assert iam.cognitoIdentity.identityPoolId == raw_iam["cognitoIdentity"]["identityPoolId"] + assert iam.principalOrgId == raw_iam["principalOrgId"] + assert iam.userArn == raw_iam["userArn"] + assert iam.userId == raw_iam["userId"] + + +def test_apigw_event_empty_body(): + raw_event = load_event("apiGatewayProxyV2Event.json") + raw_event.pop("body") # API GW v2 removes certain keys when no data is passed + parse(event=raw_event, model=APIGatewayProxyEventV2Model) + + +def test_apigw_event_empty_query_strings(): + raw_event = load_event("apiGatewayProxyV2Event.json") + raw_event["rawQueryString"] = "" + raw_event.pop("queryStringParameters") # API GW v2 removes certain keys when no data is passed + parse(event=raw_event, model=APIGatewayProxyEventV2Model) diff --git a/tests/unit/parser/test_cloudwatch.py b/tests/unit/parser/test_cloudwatch.py new file mode 100644 index 00000000000..bc8bf0776f9 --- /dev/null +++ b/tests/unit/parser/test_cloudwatch.py @@ -0,0 +1,95 @@ +import base64 +import json +import zlib +from typing import Any + +import pytest + +from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, parse +from aws_lambda_powertools.utilities.parser.models import ( + CloudWatchLogsLogEvent, + CloudWatchLogsModel, +) +from tests.functional.utils import load_event +from tests.unit.parser.schemas import MyCloudWatchBusiness + + +def decode_cloudwatch_raw_event(event: dict): + payload = base64.b64decode(event) + uncompressed = zlib.decompress(payload, zlib.MAX_WBITS | 32) + return json.loads(uncompressed.decode("utf-8")) + + +def test_validate_event_user_model_with_envelope(): + my_log_message = {"my_message": "hello", "user": "test"} + inner_event_dict = { + "messageType": "DATA_MESSAGE", + "owner": "123456789123", + "logGroup": "testLogGroup", + "logStream": "testLogStream", + "subscriptionFilters": ["testFilter"], + "logEvents": [{"id": "eventId1", "timestamp": 1440442987000, "message": json.dumps(my_log_message)}], + } + dict_str = json.dumps(inner_event_dict) + compressesd_str = zlib.compress(str.encode(dict_str), -1) + raw_event = {"awslogs": {"data": base64.b64encode(compressesd_str)}} + + parsed_event: MyCloudWatchBusiness = parse( + event=raw_event, + model=MyCloudWatchBusiness, + envelope=envelopes.CloudWatchLogsEnvelope, + ) + + assert len(parsed_event) == 1 + log: MyCloudWatchBusiness = parsed_event[0] + assert log.my_message == "hello" + assert log.user == "test" + + +def test_validate_event_does_not_conform_with_user_dict_model(): + event_dict = load_event("cloudWatchLogEvent.json") + with pytest.raises(ValidationError): + MyCloudWatchBusiness(**event_dict) + + +def test_handle_cloudwatch_trigger_event_no_envelope(): + raw_event = load_event("cloudWatchLogEvent.json") + parsed_event: CloudWatchLogsModel = CloudWatchLogsModel(**raw_event) + + raw_event_decoded = decode_cloudwatch_raw_event(raw_event["awslogs"]["data"]) + + assert parsed_event.awslogs.decoded_data.owner == raw_event_decoded["owner"] + assert parsed_event.awslogs.decoded_data.logGroup == raw_event_decoded["logGroup"] + assert parsed_event.awslogs.decoded_data.logStream == raw_event_decoded["logStream"] + assert parsed_event.awslogs.decoded_data.subscriptionFilters == raw_event_decoded["subscriptionFilters"] + assert parsed_event.awslogs.decoded_data.messageType == raw_event_decoded["messageType"] + + assert len(parsed_event.awslogs.decoded_data.logEvents) == 2 + + log_record: CloudWatchLogsLogEvent = parsed_event.awslogs.decoded_data.logEvents[0] + raw_log_record = raw_event_decoded["logEvents"][0] + assert log_record.id == raw_log_record["id"] + convert_time = int(round(log_record.timestamp.timestamp() * 1000)) + assert convert_time == raw_log_record["timestamp"] + assert log_record.message == raw_log_record["message"] + + log_record: CloudWatchLogsLogEvent = parsed_event.awslogs.decoded_data.logEvents[1] + raw_log_record = raw_event_decoded["logEvents"][1] + assert log_record.id == raw_log_record["id"] + convert_time = int(round(log_record.timestamp.timestamp() * 1000)) + assert convert_time == raw_log_record["timestamp"] + assert log_record.message == raw_log_record["message"] + + +def test_handle_invalid_cloudwatch_trigger_event_no_envelope(): + raw_event: Any = {"awslogs": {"data": "invalid_data"}} + with pytest.raises(ValidationError) as context: + CloudWatchLogsModel(**raw_event) + + assert context.value.errors()[0]["msg"] == "unable to decompress data" + + +def test_handle_invalid_event_with_envelope(): + empty_dict = {} + with pytest.raises(ValidationError): + CloudWatchLogsModel(**empty_dict) diff --git a/tests/unit/parser/test_dynamodb.py b/tests/unit/parser/test_dynamodb.py new file mode 100644 index 00000000000..57bd2be5f0a --- /dev/null +++ b/tests/unit/parser/test_dynamodb.py @@ -0,0 +1,84 @@ +import pytest + +from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, parse +from tests.functional.utils import load_event +from tests.unit.parser.schemas import MyAdvancedDynamoBusiness, MyDynamoBusiness + + +def test_dynamo_db_stream_trigger_event(): + raw_event = load_event("dynamoStreamEvent.json") + parserd_event: MyDynamoBusiness = parse( + event=raw_event, + model=MyDynamoBusiness, + envelope=envelopes.DynamoDBStreamEnvelope, + ) + + assert len(parserd_event) == 2 + + # record index 0 + old_image = parserd_event[0]["OldImage"] + assert old_image is None + + new_image = parserd_event[0]["NewImage"] + new_image_raw = raw_event["Records"][0]["dynamodb"]["NewImage"] + assert new_image.Message["S"] == new_image_raw["Message"]["S"] + assert new_image.Id["N"] == float(new_image_raw["Id"]["N"]) + + # record index 1 + old_image = parserd_event[1]["OldImage"] + old_image_raw = raw_event["Records"][1]["dynamodb"]["OldImage"] + assert old_image.Message["S"] == old_image_raw["Message"]["S"] + assert old_image.Id["N"] == float(old_image_raw["Id"]["N"]) + + new_image = parserd_event[1]["NewImage"] + new_image_raw = raw_event["Records"][1]["dynamodb"]["NewImage"] + assert new_image.Message["S"] == new_image_raw["Message"]["S"] + assert new_image.Id["N"] == float(new_image_raw["Id"]["N"]) + + +def test_dynamo_db_stream_trigger_event_no_envelope(): + raw_event = load_event("dynamoStreamEvent.json") + parserd_event: MyAdvancedDynamoBusiness = MyAdvancedDynamoBusiness(**raw_event) + + records = parserd_event.Records + record = records[0] + raw_record = raw_event["Records"][0] + + assert record.awsRegion == raw_record["awsRegion"] + assert record.eventID == raw_record["eventID"] + assert record.eventName == raw_record["eventName"] + assert record.eventSource == raw_record["eventSource"] + assert record.eventSourceARN == raw_record["eventSourceARN"] + assert record.eventVersion == float(raw_record["eventVersion"]) + assert record.userIdentity is None + + dynamodb = record.dynamodb + raw_dynamodb = raw_record["dynamodb"] + assert dynamodb is not None + assert dynamodb.ApproximateCreationDateTime is None + assert dynamodb.OldImage is None + assert dynamodb.SequenceNumber == raw_dynamodb["SequenceNumber"] + assert dynamodb.SizeBytes == raw_dynamodb["SizeBytes"] + assert dynamodb.StreamViewType == raw_dynamodb["StreamViewType"] + + keys = dynamodb.Keys + raw_keys = raw_dynamodb["Keys"] + assert keys is not None + id_key = keys["Id"] + assert id_key["N"] == raw_keys["Id"]["N"] + + message_key = dynamodb.NewImage.Message + assert message_key is not None + assert message_key["S"] == "New item!" + + +def test_validate_event_does_not_conform_with_model_no_envelope(): + raw_event: dict = {"hello": "s"} + with pytest.raises(ValidationError): + MyAdvancedDynamoBusiness(**raw_event) + + +def test_validate_event_does_not_conform_with_model(): + raw_event: dict = {"hello": "s"} + with pytest.raises(ValidationError): + parse(event=raw_event, model=MyDynamoBusiness, envelope=envelopes.DynamoDBStreamEnvelope) diff --git a/tests/unit/parser/test_eventbridge.py b/tests/unit/parser/test_eventbridge.py new file mode 100644 index 00000000000..7f250ecdb83 --- /dev/null +++ b/tests/unit/parser/test_eventbridge.py @@ -0,0 +1,53 @@ +import pytest + +from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, parse +from tests.functional.utils import load_event +from tests.unit.parser.schemas import ( + MyAdvancedEventbridgeBusiness, + MyEventbridgeBusiness, +) + + +def test_handle_eventbridge_trigger_event(): + raw_event = load_event("eventBridgeEvent.json") + parsed_event: MyEventbridgeBusiness = parse( + event=raw_event, + model=MyEventbridgeBusiness, + envelope=envelopes.EventBridgeEnvelope, + ) + + assert parsed_event.instance_id == raw_event["detail"]["instance_id"] + assert parsed_event.state == raw_event["detail"]["state"] + + +def test_validate_event_does_not_conform_with_user_dict_model(): + raw_event = load_event("eventBridgeEvent.json") + + raw_event.pop("version") + + with pytest.raises(ValidationError): + parse(event=raw_event, model=MyEventbridgeBusiness, envelope=envelopes.EventBridgeEnvelope) + + +def test_handle_eventbridge_trigger_event_no_envelope(): + raw_event = load_event("eventBridgeEvent.json") + parsed_event: MyAdvancedEventbridgeBusiness = MyAdvancedEventbridgeBusiness(**raw_event) + + assert parsed_event.detail.instance_id == raw_event["detail"]["instance_id"] + assert parsed_event.detail.state == raw_event["detail"]["state"] + assert parsed_event.id == raw_event["id"] + assert parsed_event.version == raw_event["version"] + assert parsed_event.account == raw_event["account"] + time_str = parsed_event.time.strftime("%Y-%m-%dT%H:%M:%SZ") + assert time_str == raw_event["time"] + assert parsed_event.region == raw_event["region"] + assert parsed_event.resources == raw_event["resources"] + assert parsed_event.source == raw_event["source"] + assert parsed_event.detail_type == raw_event["detail-type"] + assert parsed_event.replay_name == raw_event["replay-name"] + + +def test_handle_invalid_event_with_eventbridge_envelope(): + empty_event = {} + with pytest.raises(ValidationError): + parse(event=empty_event, model=MyEventbridgeBusiness, envelope=envelopes.EventBridgeEnvelope) diff --git a/tests/unit/parser/test_kafka.py b/tests/unit/parser/test_kafka.py new file mode 100644 index 00000000000..1f229c1db6e --- /dev/null +++ b/tests/unit/parser/test_kafka.py @@ -0,0 +1,82 @@ +from aws_lambda_powertools.utilities.parser import envelopes, parse +from aws_lambda_powertools.utilities.parser.models import ( + KafkaMskEventModel, + KafkaRecordModel, + KafkaSelfManagedEventModel, +) +from tests.functional.utils import load_event +from tests.unit.parser.schemas import MyLambdaKafkaBusiness + + +def test_kafka_msk_event_with_envelope(): + raw_event = load_event("kafkaEventMsk.json") + parsed_event: MyLambdaKafkaBusiness = parse( + event=raw_event, + model=MyLambdaKafkaBusiness, + envelope=envelopes.KafkaEnvelope, + ) + + assert parsed_event[0].key == "value" + assert len(parsed_event) == 1 + + +def test_kafka_self_managed_event_with_envelope(): + raw_event = load_event("kafkaEventSelfManaged.json") + parsed_event: MyLambdaKafkaBusiness = parse( + event=raw_event, + model=MyLambdaKafkaBusiness, + envelope=envelopes.KafkaEnvelope, + ) + + assert parsed_event[0].key == "value" + assert len(parsed_event) == 1 + + +def test_self_managed_kafka_event(): + raw_event = load_event("kafkaEventSelfManaged.json") + parsed_event: KafkaSelfManagedEventModel = KafkaSelfManagedEventModel(**raw_event) + + assert parsed_event.eventSource == raw_event["eventSource"] + + assert parsed_event.bootstrapServers == raw_event["bootstrapServers"].split(",") + + records = list(parsed_event.records["mytopic-0"]) + assert len(records) == 1 + record: KafkaRecordModel = records[0] + raw_record = raw_event["records"]["mytopic-0"][0] + assert record.topic == raw_record["topic"] + assert record.partition == raw_record["partition"] + assert record.offset == raw_record["offset"] + assert record.timestamp is not None + convert_time = int(round(record.timestamp.timestamp() * 1000)) + assert convert_time == raw_record["timestamp"] + assert record.timestampType == raw_record["timestampType"] + assert record.key == b"recordKey" + assert record.value == '{"key":"value"}' + assert len(record.headers) == 1 + assert record.headers[0]["headerKey"] == b"headerValue" + + +def test_kafka_msk_event(): + raw_event = load_event("kafkaEventMsk.json") + parsed_event: KafkaMskEventModel = KafkaMskEventModel(**raw_event) + + assert parsed_event.eventSource == raw_event["eventSource"] + assert parsed_event.bootstrapServers == raw_event["bootstrapServers"].split(",") + assert parsed_event.eventSourceArn == raw_event["eventSourceArn"] + + records = list(parsed_event.records["mytopic-0"]) + assert len(records) == 1 + record: KafkaRecordModel = records[0] + raw_record = raw_event["records"]["mytopic-0"][0] + assert record.topic == raw_record["topic"] + assert record.partition == raw_record["partition"] + assert record.offset == raw_record["offset"] + assert record.timestamp is not None + convert_time = int(round(record.timestamp.timestamp() * 1000)) + assert convert_time == raw_record["timestamp"] + assert record.timestampType == raw_record["timestampType"] + assert record.key == b"recordKey" + assert record.value == '{"key":"value"}' + assert len(record.headers) == 1 + assert record.headers[0]["headerKey"] == b"headerValue" diff --git a/tests/unit/parser/test_kinesis.py b/tests/unit/parser/test_kinesis.py new file mode 100644 index 00000000000..e8b1ae87378 --- /dev/null +++ b/tests/unit/parser/test_kinesis.py @@ -0,0 +1,108 @@ +import pytest + +from aws_lambda_powertools.utilities.parser import BaseModel, ValidationError, envelopes, parse +from aws_lambda_powertools.utilities.parser.models import ( + KinesisDataStreamModel, + KinesisDataStreamRecordPayload, +) +from aws_lambda_powertools.utilities.parser.models.cloudwatch import ( + CloudWatchLogsDecode, +) +from aws_lambda_powertools.utilities.parser.models.kinesis import ( + extract_cloudwatch_logs_from_event, + extract_cloudwatch_logs_from_record, +) +from tests.functional.utils import load_event +from tests.unit.parser.schemas import MyKinesisBusiness + + +def test_kinesis_trigger_bad_base64_event(): + raw_event = load_event("kinesisStreamEvent.json") + + raw_event["Records"][0]["kinesis"]["data"] = "bad" + + with pytest.raises(ValidationError): + KinesisDataStreamModel(**raw_event) + + +def test_kinesis_trigger_event(): + raw_event = load_event("kinesisStreamEventOneRecord.json") + parsed_event: MyKinesisBusiness = parse( + event=raw_event, + model=MyKinesisBusiness, + envelope=envelopes.KinesisDataStreamEnvelope, + ) + + assert len(parsed_event) == 1 + record: KinesisDataStreamModel = parsed_event[0] + assert record.message == "test message" + assert record.username == "test" + + +def test_kinesis_trigger_event_no_envelope(): + raw_event = load_event("kinesisStreamEvent.json") + parsed_event: KinesisDataStreamModel = KinesisDataStreamModel(**raw_event) + + records = parsed_event.Records + assert len(records) == 2 + record: KinesisDataStreamModel = records[0] + raw_record = raw_event["Records"][0] + + assert record.awsRegion == raw_record["awsRegion"] + assert record.eventID == raw_record["eventID"] + assert record.eventName == raw_record["eventName"] + assert record.eventSource == raw_record["eventSource"] + assert record.eventSourceARN == raw_record["eventSourceARN"] + assert record.eventVersion == raw_record["eventVersion"] + assert record.invokeIdentityArn == raw_record["invokeIdentityArn"] + + kinesis: KinesisDataStreamRecordPayload = record.kinesis + assert kinesis.approximateArrivalTimestamp == raw_record["kinesis"]["approximateArrivalTimestamp"] + assert kinesis.kinesisSchemaVersion == raw_record["kinesis"]["kinesisSchemaVersion"] + assert kinesis.partitionKey == raw_record["kinesis"]["partitionKey"] + assert kinesis.sequenceNumber == raw_record["kinesis"]["sequenceNumber"] + assert kinesis.data == b"Hello, this is a test." + + +def test_validate_event_does_not_conform_with_model_no_envelope(): + raw_event: dict = {"hello": "s"} + with pytest.raises(ValidationError): + KinesisDataStreamModel(**raw_event) + + +def test_validate_event_does_not_conform_with_model(): + raw_event: dict = {"hello": "s"} + with pytest.raises(ValidationError): + parse(event=raw_event, model=MyKinesisBusiness, envelope=envelopes.KinesisDataStreamEnvelope) + + +def test_kinesis_stream_event_cloudwatch_logs_data_extraction(): + # GIVEN a KinesisDataStreamModel is instantiated with CloudWatch Logs compressed data + raw_event = load_event("kinesisStreamCloudWatchLogsEvent.json") + stream_data = KinesisDataStreamModel(**raw_event) + single_record = stream_data.Records[0] + + # WHEN we try to extract CloudWatch Logs from KinesisDataStreamRecordPayload model + extracted_logs = extract_cloudwatch_logs_from_event(stream_data) + individual_logs = [extract_cloudwatch_logs_from_record(record) for record in stream_data.Records] + single_log = extract_cloudwatch_logs_from_record(single_record) + + # THEN we should have extracted any potential logs as CloudWatchLogsDecode models + assert len(extracted_logs) == len(individual_logs) + assert isinstance(single_log, CloudWatchLogsDecode) + + +def test_kinesis_stream_event_cloudwatch_logs_data_extraction_fails_with_custom_model(): + # GIVEN a custom model replaces Kinesis Record Data bytes + class DummyModel(BaseModel): + ... + + raw_event = load_event("kinesisStreamCloudWatchLogsEvent.json") + stream_data = KinesisDataStreamModel(**raw_event) + + # WHEN decompress_zlib_record_data_as_json is used + # THEN ValueError should be raised + with pytest.raises(ValueError, match="We can only decompress bytes data"): + for record in stream_data.Records: + record.kinesis.data = DummyModel() + record.decompress_zlib_record_data_as_json() diff --git a/tests/unit/parser/test_kinesis_firehose.py b/tests/unit/parser/test_kinesis_firehose.py new file mode 100644 index 00000000000..87eaef7ca9d --- /dev/null +++ b/tests/unit/parser/test_kinesis_firehose.py @@ -0,0 +1,123 @@ +import pytest + +from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, parse +from aws_lambda_powertools.utilities.parser.models import ( + KinesisFirehoseModel, + KinesisFirehoseRecord, + KinesisFirehoseRecordMetadata, + KinesisFirehoseSqsModel, + KinesisFirehoseSqsRecord, +) +from tests.functional.utils import load_event +from tests.unit.parser.schemas import MyKinesisFirehoseBusiness + + +def test_firehose_sqs_wrapped_message_event(): + raw_event = load_event("kinesisFirehoseSQSEvent.json") + parsed_event: KinesisFirehoseSqsModel = KinesisFirehoseSqsModel(**raw_event) + + assert parsed_event.region == raw_event["region"] + assert parsed_event.invocationId == raw_event["invocationId"] + assert parsed_event.deliveryStreamArn == raw_event["deliveryStreamArn"] + + records = list(parsed_event.records) + assert len(records) == 1 + + record_01: KinesisFirehoseSqsRecord = records[0] + assert record_01.data.messageId == "5ab807d4-5644-4c55-97a3-47396635ac74" + assert record_01.data.receiptHandle == "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a..." + assert record_01.data.body == "Test message." + assert record_01.data.attributes.ApproximateReceiveCount == "1" + assert record_01.data.attributes.SenderId == "AIDAIENQZJOLO23YVJ4VO" + + +def test_firehose_trigger_event(): + raw_event = load_event("kinesisFirehoseKinesisEvent.json") + raw_event["records"].pop(0) # remove first item since the payload is bytes and we want to test payload json class + parsed_event: MyKinesisFirehoseBusiness = parse( + event=raw_event, + model=MyKinesisFirehoseBusiness, + envelope=envelopes.KinesisFirehoseEnvelope, + ) + + assert len(parsed_event) == 1 + assert parsed_event[0].Hello == "World" + + +def test_firehose_trigger_event_kinesis_no_envelope(): + raw_event = load_event("kinesisFirehoseKinesisEvent.json") + parsed_event: KinesisFirehoseModel = KinesisFirehoseModel(**raw_event) + + assert parsed_event.region == raw_event["region"] + assert parsed_event.invocationId == raw_event["invocationId"] + assert parsed_event.deliveryStreamArn == raw_event["deliveryStreamArn"] + assert parsed_event.sourceKinesisStreamArn == raw_event["sourceKinesisStreamArn"] + + records = list(parsed_event.records) + assert len(records) == 2 + record_01: KinesisFirehoseRecord = records[0] + assert record_01.approximateArrivalTimestamp == 1664028820148 + assert record_01.recordId == "record1" + assert record_01.data == b"Hello World" + + metadata_01: KinesisFirehoseRecordMetadata = record_01.kinesisRecordMetadata + assert metadata_01.partitionKey == "4d1ad2b9-24f8-4b9d-a088-76e9947c317a" + assert metadata_01.subsequenceNumber == "" + assert metadata_01.shardId == "shardId-000000000000" + assert metadata_01.approximateArrivalTimestamp == 1664028820148 + assert metadata_01.sequenceNumber == "49546986683135544286507457936321625675700192471156785154" + + record_02: KinesisFirehoseRecord = records[1] + assert record_02.approximateArrivalTimestamp == 1664028793294 + assert record_02.recordId == "record2" + assert record_02.data == b'{"Hello": "World"}' + + metadata_02: KinesisFirehoseRecordMetadata = record_02.kinesisRecordMetadata + assert metadata_02.partitionKey == "4d1ad2b9-24f8-4b9d-a088-76e9947c318a" + assert metadata_02.subsequenceNumber == "" + assert metadata_02.shardId == "shardId-000000000001" + assert metadata_02.approximateArrivalTimestamp == 1664028793294 + assert metadata_02.sequenceNumber == "49546986683135544286507457936321625675700192471156785155" + + +def test_firehose_trigger_event_put_no_envelope(): + raw_event = load_event("kinesisFirehosePutEvent.json") + parsed_event: KinesisFirehoseModel = KinesisFirehoseModel(**raw_event) + + assert parsed_event.region == raw_event["region"] + assert parsed_event.invocationId == raw_event["invocationId"] + assert parsed_event.deliveryStreamArn == raw_event["deliveryStreamArn"] + + records = list(parsed_event.records) + assert len(records) == 2 + + record_01: KinesisFirehoseRecord = records[0] + assert record_01.approximateArrivalTimestamp == 1664029185290 + assert record_01.recordId == "record1" + assert record_01.data == b"Hello World" + + record_02: KinesisFirehoseRecord = records[1] + assert record_02.approximateArrivalTimestamp == 1664029186945 + assert record_02.recordId == "record2" + assert record_02.data == b'{"Hello": "World"}' + + +def test_kinesis_trigger_bad_base64_event(): + raw_event = load_event("kinesisFirehoseKinesisEvent.json") + raw_event["records"][0]["data"] = {"bad base64"} + with pytest.raises(ValidationError): + KinesisFirehoseModel(**raw_event) + + +def test_kinesis_trigger_bad_timestamp_event(): + raw_event = load_event("kinesisFirehoseKinesisEvent.json") + raw_event["records"][0]["approximateArrivalTimestamp"] = -1 + with pytest.raises(ValidationError): + KinesisFirehoseModel(**raw_event) + + +def test_kinesis_trigger_bad_metadata_timestamp_event(): + raw_event = load_event("kinesisFirehoseKinesisEvent.json") + raw_event["records"][0]["kinesisRecordMetadata"]["approximateArrivalTimestamp"] = "-1" + with pytest.raises(ValidationError): + KinesisFirehoseModel(**raw_event) diff --git a/tests/unit/parser/test_lambda_function_url.py b/tests/unit/parser/test_lambda_function_url.py new file mode 100644 index 00000000000..3b1a7f259ec --- /dev/null +++ b/tests/unit/parser/test_lambda_function_url.py @@ -0,0 +1,127 @@ +from aws_lambda_powertools.utilities.parser import envelopes, parse +from aws_lambda_powertools.utilities.parser.models import LambdaFunctionUrlModel +from tests.functional.utils import load_event +from tests.unit.parser.schemas import MyALambdaFuncUrlBusiness + + +def test_lambda_func_url_event_with_envelope(): + raw_event = load_event("lambdaFunctionUrlEvent.json") + raw_event["body"] = '{"message": "Hello", "username": "Ran"}' + + parsed_event: MyALambdaFuncUrlBusiness = parse( + event=raw_event, + model=MyALambdaFuncUrlBusiness, + envelope=envelopes.LambdaFunctionUrlEnvelope, + ) + + assert parsed_event.message == "Hello" + assert parsed_event.username == "Ran" + + +def test_lambda_function_url_event(): + raw_event = load_event("lambdaFunctionUrlEvent.json") + parsed_event: LambdaFunctionUrlModel = LambdaFunctionUrlModel(**raw_event) + + assert parsed_event.version == raw_event["version"] + assert parsed_event.routeKey == raw_event["routeKey"] + + assert parsed_event.rawQueryString == raw_event["rawQueryString"] + + assert parsed_event.cookies is None + + headers = parsed_event.headers + assert len(headers) == 20 + + assert parsed_event.queryStringParameters is None + + assert parsed_event.isBase64Encoded is False + assert parsed_event.body is None + assert parsed_event.pathParameters is None + assert parsed_event.stageVariables is None + + request_context = parsed_event.requestContext + raw_request_context = raw_event["requestContext"] + + assert request_context.accountId == raw_request_context["accountId"] + assert request_context.apiId == raw_request_context["apiId"] + assert request_context.domainName == raw_request_context["domainName"] + assert request_context.domainPrefix == raw_request_context["domainPrefix"] + assert request_context.requestId == raw_request_context["requestId"] + assert request_context.routeKey == raw_request_context["routeKey"] + assert request_context.stage == raw_request_context["stage"] + assert request_context.time == raw_request_context["time"] + convert_time = int(round(request_context.timeEpoch.timestamp() * 1000)) + assert convert_time == raw_request_context["timeEpoch"] + assert request_context.authorizer is None + + http = request_context.http + assert http.method == raw_request_context["http"]["method"] + assert http.path == raw_request_context["http"]["path"] + assert http.protocol == raw_request_context["http"]["protocol"] + assert str(http.sourceIp) == "123.123.123.123/32" + assert http.userAgent == raw_request_context["http"]["userAgent"] + + assert request_context.authorizer is None + + +def test_lambda_function_url_event_iam(): + raw_event = load_event("lambdaFunctionUrlIAMEvent.json") + parsed_event: LambdaFunctionUrlModel = LambdaFunctionUrlModel(**raw_event) + + assert parsed_event.version == raw_event["version"] + assert parsed_event.routeKey == raw_event["routeKey"] + + assert parsed_event.rawQueryString == raw_event["rawQueryString"] + + cookies = parsed_event.cookies + assert len(cookies) == 2 + assert cookies[0] == raw_event["cookies"][0] + + headers = parsed_event.headers + assert len(headers) == 2 + + query_string_parameters = parsed_event.queryStringParameters + assert len(query_string_parameters) == 2 + assert query_string_parameters.get("parameter2") == raw_event["queryStringParameters"]["parameter2"] + + assert parsed_event.isBase64Encoded is False + assert parsed_event.body == raw_event["body"] + assert parsed_event.pathParameters is None + assert parsed_event.stageVariables is None + + request_context = parsed_event.requestContext + raw_request_context = raw_event["requestContext"] + assert request_context.accountId == raw_request_context["accountId"] + assert request_context.apiId == raw_request_context["apiId"] + assert request_context.domainName == raw_request_context["domainName"] + assert request_context.domainPrefix == raw_request_context["domainPrefix"] + assert request_context.requestId == raw_request_context["requestId"] + assert request_context.routeKey == raw_request_context["routeKey"] + assert request_context.stage == raw_request_context["stage"] + assert request_context.time == raw_request_context["time"] + convert_time = int(round(request_context.timeEpoch.timestamp() * 1000)) + assert convert_time == raw_request_context["timeEpoch"] + assert request_context.authorizer is not None + + http = request_context.http + assert http.method == raw_request_context["http"]["method"] + assert http.path == raw_request_context["http"]["path"] + assert http.protocol == raw_request_context["http"]["protocol"] + assert str(http.sourceIp) == "123.123.123.123/32" + assert http.userAgent == raw_request_context["http"]["userAgent"] + + authorizer = request_context.authorizer + assert authorizer is not None + assert authorizer.jwt is None + assert authorizer.lambda_value is None + + iam = authorizer.iam + iam_raw = raw_event["requestContext"]["authorizer"]["iam"] + assert iam is not None + assert iam.accessKey == iam_raw["accessKey"] + assert iam.accountId == iam_raw["accountId"] + assert iam.callerId == iam_raw["callerId"] + assert iam.cognitoIdentity is None + assert iam.principalOrgId is None + assert iam.userId == iam_raw["userId"] + assert iam.userArn == iam_raw["userArn"] diff --git a/tests/functional/parser/test_s3 object_event.py b/tests/unit/parser/test_s3 object_event.py similarity index 62% rename from tests/functional/parser/test_s3 object_event.py rename to tests/unit/parser/test_s3 object_event.py index 90c2555360d..c106a66c2a9 100644 --- a/tests/functional/parser/test_s3 object_event.py +++ b/tests/unit/parser/test_s3 object_event.py @@ -1,17 +1,10 @@ -from aws_lambda_powertools.utilities.parser import event_parser from aws_lambda_powertools.utilities.parser.models import S3ObjectLambdaEvent -from aws_lambda_powertools.utilities.typing import LambdaContext from tests.functional.utils import load_event -@event_parser(model=S3ObjectLambdaEvent) -def handle_s3_object_event_iam(event: S3ObjectLambdaEvent, _: LambdaContext): - return event - - def test_s3_object_event(): event = load_event("s3ObjectEventIAMUser.json") - parsed_event: S3ObjectLambdaEvent = handle_s3_object_event_iam(event, LambdaContext()) + parsed_event: S3ObjectLambdaEvent = S3ObjectLambdaEvent(**event) assert parsed_event.xAmzRequestId == event["xAmzRequestId"] assert parsed_event.getObjectContext is not None object_context = parsed_event.getObjectContext @@ -40,28 +33,22 @@ def test_s3_object_event(): assert parsed_event.protocolVersion == event["protocolVersion"] -@event_parser(model=S3ObjectLambdaEvent) -def handle_s3_object_event_temp_creds(event: S3ObjectLambdaEvent, _: LambdaContext): - return event - - def test_s3_object_event_temp_credentials(): event = load_event("s3ObjectEventTempCredentials.json") - parsed_event: S3ObjectLambdaEvent = handle_s3_object_event_temp_creds(event, LambdaContext()) + parsed_event: S3ObjectLambdaEvent = S3ObjectLambdaEvent(**event) assert parsed_event.xAmzRequestId == event["xAmzRequestId"] session_context = parsed_event.userIdentity.sessionContext assert session_context is not None session_issuer = session_context.sessionIssuer + session_issuer_raw = event["userIdentity"]["sessionContext"]["sessionIssuer"] assert session_issuer is not None - assert session_issuer.type == event["userIdentity"]["sessionContext"]["sessionIssuer"]["type"] - assert session_issuer.userName == event["userIdentity"]["sessionContext"]["sessionIssuer"]["userName"] - assert session_issuer.principalId == event["userIdentity"]["sessionContext"]["sessionIssuer"]["principalId"] - assert session_issuer.arn == event["userIdentity"]["sessionContext"]["sessionIssuer"]["arn"] - assert session_issuer.accountId == event["userIdentity"]["sessionContext"]["sessionIssuer"]["accountId"] + assert session_issuer.type == session_issuer_raw["type"] + assert session_issuer.userName == session_issuer_raw["userName"] + assert session_issuer.principalId == session_issuer_raw["principalId"] + assert session_issuer.arn == session_issuer_raw["arn"] + assert session_issuer.accountId == session_issuer_raw["accountId"] session_attributes = session_context.attributes + session_attributes_raw = event["userIdentity"]["sessionContext"]["attributes"] assert session_attributes is not None - assert ( - str(session_attributes.mfaAuthenticated).lower() - == event["userIdentity"]["sessionContext"]["attributes"]["mfaAuthenticated"] - ) - assert session_attributes.creationDate == event["userIdentity"]["sessionContext"]["attributes"]["creationDate"] + assert str(session_attributes.mfaAuthenticated).lower() == session_attributes_raw["mfaAuthenticated"] + assert session_attributes.creationDate == session_attributes_raw["creationDate"] diff --git a/tests/unit/parser/test_s3.py b/tests/unit/parser/test_s3.py index c77c70095a3..1586f32d28e 100644 --- a/tests/unit/parser/test_s3.py +++ b/tests/unit/parser/test_s3.py @@ -1,145 +1,159 @@ -import json -from datetime import datetime - import pytest from aws_lambda_powertools.utilities.parser import ValidationError -from aws_lambda_powertools.utilities.parser.models import ( - S3EventNotificationEventBridgeModel, - S3SqsEventNotificationModel, -) +from aws_lambda_powertools.utilities.parser.models import S3Model, S3RecordModel from tests.functional.utils import load_event -def test_s3_eventbridge_notification_object_created_event(): - raw_event = load_event("s3EventBridgeNotificationObjectCreatedEvent.json") - model = S3EventNotificationEventBridgeModel(**raw_event) - - assert model.version == raw_event["version"] - assert model.id == raw_event["id"] - assert model.detail_type == raw_event["detail-type"] - assert model.source == raw_event["source"] - assert model.account == raw_event["account"] - assert model.time == datetime.fromisoformat(raw_event["time"].replace("Z", "+00:00")) - assert model.region == raw_event["region"] - assert model.resources == raw_event["resources"] - - assert model.detail.version == raw_event["detail"]["version"] - assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"] - assert model.detail.object.key == raw_event["detail"]["object"]["key"] - assert model.detail.object.size == raw_event["detail"]["object"]["size"] - assert model.detail.object.etag == raw_event["detail"]["object"]["etag"] - assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] - assert model.detail.request_id == raw_event["detail"]["request-id"] - assert model.detail.requester == raw_event["detail"]["requester"] - assert model.detail.source_ip_address == raw_event["detail"]["source-ip-address"] - assert model.detail.reason == raw_event["detail"]["reason"] - - -def test_s3_eventbridge_notification_object_deleted_event(): - raw_event = load_event("s3EventBridgeNotificationObjectDeletedEvent.json") - model = S3EventNotificationEventBridgeModel(**raw_event) - - assert model.version == raw_event["version"] - assert model.id == raw_event["id"] - assert model.detail_type == raw_event["detail-type"] - assert model.source == raw_event["source"] - assert model.account == raw_event["account"] - assert model.time == datetime.fromisoformat(raw_event["time"].replace("Z", "+00:00")) - assert model.region == raw_event["region"] - assert model.resources == raw_event["resources"] - - assert model.detail.version == raw_event["detail"]["version"] - assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"] - assert model.detail.object.key == raw_event["detail"]["object"]["key"] - assert model.detail.object.size == raw_event["detail"]["object"]["size"] - assert model.detail.object.etag == raw_event["detail"]["object"]["etag"] - assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] - assert model.detail.request_id == raw_event["detail"]["request-id"] - assert model.detail.requester == raw_event["detail"]["requester"] - assert model.detail.source_ip_address == raw_event["detail"]["source-ip-address"] - assert model.detail.reason == raw_event["detail"]["reason"] - assert model.detail.deletion_type == raw_event["detail"]["deletion-type"] - - -def test_s3_eventbridge_notification_object_expired_event(): - raw_event = load_event("s3EventBridgeNotificationObjectExpiredEvent.json") - model = S3EventNotificationEventBridgeModel(**raw_event) - - assert model.version == raw_event["version"] - assert model.id == raw_event["id"] - assert model.detail_type == raw_event["detail-type"] - assert model.source == raw_event["source"] - assert model.account == raw_event["account"] - assert model.time == datetime.fromisoformat(raw_event["time"].replace("Z", "+00:00")) - assert model.region == raw_event["region"] - assert model.resources == raw_event["resources"] - - assert model.detail.version == raw_event["detail"]["version"] - assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"] - assert model.detail.object.key == raw_event["detail"]["object"]["key"] - assert model.detail.object.size == raw_event["detail"]["object"]["size"] - assert model.detail.object.etag == raw_event["detail"]["object"]["etag"] - assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] - assert model.detail.request_id == raw_event["detail"]["request-id"] - assert model.detail.requester == raw_event["detail"]["requester"] - assert model.detail.reason == raw_event["detail"]["reason"] - assert model.detail.deletion_type == raw_event["detail"]["deletion-type"] - - -def test_s3_eventbridge_notification_object_restore_completed_event(): - raw_event = load_event("s3EventBridgeNotificationObjectRestoreCompletedEvent.json") - model = S3EventNotificationEventBridgeModel(**raw_event) - - assert model.version == raw_event["version"] - assert model.id == raw_event["id"] - assert model.detail_type == raw_event["detail-type"] - assert model.source == raw_event["source"] - assert model.account == raw_event["account"] - assert model.time == datetime.fromisoformat(raw_event["time"].replace("Z", "+00:00")) - assert model.region == raw_event["region"] - assert model.resources == raw_event["resources"] - - assert model.detail.version == raw_event["detail"]["version"] - assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"] - assert model.detail.object.key == raw_event["detail"]["object"]["key"] - assert model.detail.object.size == raw_event["detail"]["object"]["size"] - assert model.detail.object.etag == raw_event["detail"]["object"]["etag"] - assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] - assert model.detail.request_id == raw_event["detail"]["request-id"] - assert model.detail.requester == raw_event["detail"]["requester"] - assert model.detail.restore_expiry_time == raw_event["detail"]["restore-expiry-time"] - assert model.detail.source_storage_class == raw_event["detail"]["source-storage-class"] - - -def test_s3_sqs_event_notification(): - raw_event = load_event("s3SqsEvent.json") - model = S3SqsEventNotificationModel(**raw_event) - - body = json.loads(raw_event["Records"][0]["body"]) - - assert model.Records[0].body.Records[0].eventVersion == body["Records"][0]["eventVersion"] - assert model.Records[0].body.Records[0].eventSource == body["Records"][0]["eventSource"] - assert model.Records[0].body.Records[0].eventTime == datetime.fromisoformat( - body["Records"][0]["eventTime"].replace("Z", "+00:00"), +def test_s3_trigger_event(): + raw_event = load_event("s3Event.json") + parsed_event: S3Model = S3Model(**raw_event) + + records = list(parsed_event.Records) + assert len(records) == 1 + + record: S3RecordModel = records[0] + raw_record = raw_event["Records"][0] + assert record.eventVersion == raw_record["eventVersion"] + assert record.eventSource == raw_record["eventSource"] + assert record.awsRegion == raw_record["awsRegion"] + convert_time = int(round(record.eventTime.timestamp() * 1000)) + assert convert_time == 1567539447192 + assert record.eventName == raw_record["eventName"] + assert record.glacierEventData is None + + user_identity = record.userIdentity + assert user_identity.principalId == raw_record["userIdentity"]["principalId"] + + request_parameters = record.requestParameters + assert str(request_parameters.sourceIPAddress) == "205.255.255.255/32" + assert record.responseElements.x_amz_request_id == raw_record["responseElements"]["x-amz-request-id"] + assert record.responseElements.x_amz_id_2 == raw_record["responseElements"]["x-amz-id-2"] + + s3 = record.s3 + raw_s3 = raw_event["Records"][0]["s3"] + assert s3.s3SchemaVersion == raw_record["s3"]["s3SchemaVersion"] + assert s3.configurationId == raw_record["s3"]["configurationId"] + assert s3.object.key == raw_s3["object"]["key"] + assert s3.object.size == raw_s3["object"]["size"] + assert s3.object.eTag == raw_s3["object"]["eTag"] + assert s3.object.versionId is None + assert s3.object.sequencer == raw_s3["object"]["sequencer"] + + bucket = s3.bucket + raw_bucket = raw_record["s3"]["bucket"] + assert bucket.name == raw_bucket["name"] + assert bucket.ownerIdentity.principalId == raw_bucket["ownerIdentity"]["principalId"] + assert bucket.arn == raw_bucket["arn"] + + +def test_s3_glacier_trigger_event(): + raw_event = load_event("s3EventGlacier.json") + parsed_event: S3Model = S3Model(**raw_event) + + records = list(parsed_event.Records) + assert len(records) == 1 + + record: S3RecordModel = records[0] + raw_record = raw_event["Records"][0] + assert record.eventVersion == raw_record["eventVersion"] + assert record.eventSource == raw_record["eventSource"] + assert record.awsRegion == raw_record["awsRegion"] + convert_time = int(round(record.eventTime.timestamp() * 1000)) + assert convert_time == 1567539447192 + assert record.eventName == raw_record["eventName"] + assert record.glacierEventData is not None + convert_time = int( + round(record.glacierEventData.restoreEventData.lifecycleRestorationExpiryTime.timestamp() * 1000), + ) + assert convert_time == 60000 + assert ( + record.glacierEventData.restoreEventData.lifecycleRestoreStorageClass + == raw_record["glacierEventData"]["restoreEventData"]["lifecycleRestoreStorageClass"] ) - assert model.Records[0].body.Records[0].eventName == body["Records"][0]["eventName"] - - -def test_s3_sqs_event_notification_body_invalid_json(): - raw_event = load_event("s3SqsEvent.json") - - for record in raw_event["Records"]: - record["body"] = "invalid body" + user_identity = record.userIdentity + assert user_identity.principalId == raw_record["userIdentity"]["principalId"] + + request_parameters = record.requestParameters + assert str(request_parameters.sourceIPAddress) == "205.255.255.255/32" + assert record.responseElements.x_amz_request_id == raw_record["responseElements"]["x-amz-request-id"] + assert record.responseElements.x_amz_id_2 == raw_record["responseElements"]["x-amz-id-2"] + + s3 = record.s3 + raw_s3 = raw_event["Records"][0]["s3"] + assert s3.s3SchemaVersion == raw_record["s3"]["s3SchemaVersion"] + assert s3.configurationId == raw_record["s3"]["configurationId"] + assert s3.object.key == raw_s3["object"]["key"] + assert s3.object.size == raw_s3["object"]["size"] + assert s3.object.eTag == raw_s3["object"]["eTag"] + assert s3.object.versionId is None + assert s3.object.sequencer == raw_s3["object"]["sequencer"] + + bucket = s3.bucket + raw_bucket = raw_record["s3"]["bucket"] + assert bucket.name == raw_bucket["name"] + assert bucket.ownerIdentity.principalId == raw_bucket["ownerIdentity"]["principalId"] + assert bucket.arn == raw_bucket["arn"] + + +def test_s3_trigger_event_delete_object(): + raw_event = load_event("s3EventDeleteObject.json") + parsed_event: S3Model = S3Model(**raw_event) + + records = list(parsed_event.Records) + assert len(records) == 1 + + record: S3RecordModel = records[0] + raw_record = raw_event["Records"][0] + assert record.eventVersion == raw_record["eventVersion"] + assert record.eventSource == raw_record["eventSource"] + assert record.awsRegion == raw_record["awsRegion"] + convert_time = int(round(record.eventTime.timestamp() * 1000)) + assert convert_time == 1567539447192 + assert record.eventName == raw_record["eventName"] + assert record.glacierEventData is None + + user_identity = record.userIdentity + assert user_identity.principalId == raw_record["userIdentity"]["principalId"] + + request_parameters = record.requestParameters + assert str(request_parameters.sourceIPAddress) == "205.255.255.255/32" + assert record.responseElements.x_amz_request_id == raw_record["responseElements"]["x-amz-request-id"] + assert record.responseElements.x_amz_id_2 == raw_record["responseElements"]["x-amz-id-2"] + + s3 = record.s3 + raw_s3 = raw_event["Records"][0]["s3"] + assert s3.s3SchemaVersion == raw_record["s3"]["s3SchemaVersion"] + assert s3.configurationId == raw_record["s3"]["configurationId"] + assert s3.object.key == raw_s3["object"]["key"] + assert s3.object.size is None + assert s3.object.eTag is None + assert s3.object.versionId is None + assert s3.object.sequencer == raw_s3["object"]["sequencer"] + + bucket = s3.bucket + raw_bucket = raw_record["s3"]["bucket"] + assert bucket.name == raw_bucket["name"] + assert bucket.ownerIdentity.principalId == raw_bucket["ownerIdentity"]["principalId"] + assert bucket.arn == raw_bucket["arn"] + + +def test_s3_empty_object(): + raw_event = load_event("s3Event.json") + raw_event["Records"][0]["s3"]["object"]["size"] = 0 + S3Model(**raw_event) + + +def test_s3_none_object_size_failed_validation(): + raw_event = load_event("s3Event.json") + raw_event["Records"][0]["s3"]["object"]["size"] = None with pytest.raises(ValidationError): - S3SqsEventNotificationModel(**raw_event) - + S3Model(**raw_event) -def test_s3_sqs_event_notification_body_containing_arbitrary_json(): - raw_event = load_event("s3SqsEvent.json") - for record in raw_event["Records"]: - record["body"] = {"foo": "bar"} +def test_s3_none_etag_value_failed_validation(): + raw_event = load_event("s3Event.json") + raw_event["Records"][0]["s3"]["object"]["eTag"] = None with pytest.raises(ValidationError): - S3SqsEventNotificationModel(**raw_event) + S3Model(**raw_event) diff --git a/tests/unit/parser/test_s3_notification.py b/tests/unit/parser/test_s3_notification.py new file mode 100644 index 00000000000..c77c70095a3 --- /dev/null +++ b/tests/unit/parser/test_s3_notification.py @@ -0,0 +1,145 @@ +import json +from datetime import datetime + +import pytest + +from aws_lambda_powertools.utilities.parser import ValidationError +from aws_lambda_powertools.utilities.parser.models import ( + S3EventNotificationEventBridgeModel, + S3SqsEventNotificationModel, +) +from tests.functional.utils import load_event + + +def test_s3_eventbridge_notification_object_created_event(): + raw_event = load_event("s3EventBridgeNotificationObjectCreatedEvent.json") + model = S3EventNotificationEventBridgeModel(**raw_event) + + assert model.version == raw_event["version"] + assert model.id == raw_event["id"] + assert model.detail_type == raw_event["detail-type"] + assert model.source == raw_event["source"] + assert model.account == raw_event["account"] + assert model.time == datetime.fromisoformat(raw_event["time"].replace("Z", "+00:00")) + assert model.region == raw_event["region"] + assert model.resources == raw_event["resources"] + + assert model.detail.version == raw_event["detail"]["version"] + assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"] + assert model.detail.object.key == raw_event["detail"]["object"]["key"] + assert model.detail.object.size == raw_event["detail"]["object"]["size"] + assert model.detail.object.etag == raw_event["detail"]["object"]["etag"] + assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] + assert model.detail.request_id == raw_event["detail"]["request-id"] + assert model.detail.requester == raw_event["detail"]["requester"] + assert model.detail.source_ip_address == raw_event["detail"]["source-ip-address"] + assert model.detail.reason == raw_event["detail"]["reason"] + + +def test_s3_eventbridge_notification_object_deleted_event(): + raw_event = load_event("s3EventBridgeNotificationObjectDeletedEvent.json") + model = S3EventNotificationEventBridgeModel(**raw_event) + + assert model.version == raw_event["version"] + assert model.id == raw_event["id"] + assert model.detail_type == raw_event["detail-type"] + assert model.source == raw_event["source"] + assert model.account == raw_event["account"] + assert model.time == datetime.fromisoformat(raw_event["time"].replace("Z", "+00:00")) + assert model.region == raw_event["region"] + assert model.resources == raw_event["resources"] + + assert model.detail.version == raw_event["detail"]["version"] + assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"] + assert model.detail.object.key == raw_event["detail"]["object"]["key"] + assert model.detail.object.size == raw_event["detail"]["object"]["size"] + assert model.detail.object.etag == raw_event["detail"]["object"]["etag"] + assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] + assert model.detail.request_id == raw_event["detail"]["request-id"] + assert model.detail.requester == raw_event["detail"]["requester"] + assert model.detail.source_ip_address == raw_event["detail"]["source-ip-address"] + assert model.detail.reason == raw_event["detail"]["reason"] + assert model.detail.deletion_type == raw_event["detail"]["deletion-type"] + + +def test_s3_eventbridge_notification_object_expired_event(): + raw_event = load_event("s3EventBridgeNotificationObjectExpiredEvent.json") + model = S3EventNotificationEventBridgeModel(**raw_event) + + assert model.version == raw_event["version"] + assert model.id == raw_event["id"] + assert model.detail_type == raw_event["detail-type"] + assert model.source == raw_event["source"] + assert model.account == raw_event["account"] + assert model.time == datetime.fromisoformat(raw_event["time"].replace("Z", "+00:00")) + assert model.region == raw_event["region"] + assert model.resources == raw_event["resources"] + + assert model.detail.version == raw_event["detail"]["version"] + assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"] + assert model.detail.object.key == raw_event["detail"]["object"]["key"] + assert model.detail.object.size == raw_event["detail"]["object"]["size"] + assert model.detail.object.etag == raw_event["detail"]["object"]["etag"] + assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] + assert model.detail.request_id == raw_event["detail"]["request-id"] + assert model.detail.requester == raw_event["detail"]["requester"] + assert model.detail.reason == raw_event["detail"]["reason"] + assert model.detail.deletion_type == raw_event["detail"]["deletion-type"] + + +def test_s3_eventbridge_notification_object_restore_completed_event(): + raw_event = load_event("s3EventBridgeNotificationObjectRestoreCompletedEvent.json") + model = S3EventNotificationEventBridgeModel(**raw_event) + + assert model.version == raw_event["version"] + assert model.id == raw_event["id"] + assert model.detail_type == raw_event["detail-type"] + assert model.source == raw_event["source"] + assert model.account == raw_event["account"] + assert model.time == datetime.fromisoformat(raw_event["time"].replace("Z", "+00:00")) + assert model.region == raw_event["region"] + assert model.resources == raw_event["resources"] + + assert model.detail.version == raw_event["detail"]["version"] + assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"] + assert model.detail.object.key == raw_event["detail"]["object"]["key"] + assert model.detail.object.size == raw_event["detail"]["object"]["size"] + assert model.detail.object.etag == raw_event["detail"]["object"]["etag"] + assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] + assert model.detail.request_id == raw_event["detail"]["request-id"] + assert model.detail.requester == raw_event["detail"]["requester"] + assert model.detail.restore_expiry_time == raw_event["detail"]["restore-expiry-time"] + assert model.detail.source_storage_class == raw_event["detail"]["source-storage-class"] + + +def test_s3_sqs_event_notification(): + raw_event = load_event("s3SqsEvent.json") + model = S3SqsEventNotificationModel(**raw_event) + + body = json.loads(raw_event["Records"][0]["body"]) + + assert model.Records[0].body.Records[0].eventVersion == body["Records"][0]["eventVersion"] + assert model.Records[0].body.Records[0].eventSource == body["Records"][0]["eventSource"] + assert model.Records[0].body.Records[0].eventTime == datetime.fromisoformat( + body["Records"][0]["eventTime"].replace("Z", "+00:00"), + ) + assert model.Records[0].body.Records[0].eventName == body["Records"][0]["eventName"] + + +def test_s3_sqs_event_notification_body_invalid_json(): + raw_event = load_event("s3SqsEvent.json") + + for record in raw_event["Records"]: + record["body"] = "invalid body" + + with pytest.raises(ValidationError): + S3SqsEventNotificationModel(**raw_event) + + +def test_s3_sqs_event_notification_body_containing_arbitrary_json(): + raw_event = load_event("s3SqsEvent.json") + for record in raw_event["Records"]: + record["body"] = {"foo": "bar"} + + with pytest.raises(ValidationError): + S3SqsEventNotificationModel(**raw_event) diff --git a/tests/unit/parser/test_ses.py b/tests/unit/parser/test_ses.py new file mode 100644 index 00000000000..34eb43bf5eb --- /dev/null +++ b/tests/unit/parser/test_ses.py @@ -0,0 +1,52 @@ +from aws_lambda_powertools.utilities.parser.models import SesModel, SesRecordModel +from tests.functional.utils import load_event + + +def test_ses_trigger_event(): + raw_event = load_event("sesEvent.json") + parsed_event: SesModel = SesModel(**raw_event) + + records = parsed_event.Records + record: SesRecordModel = records[0] + raw_record = raw_event["Records"][0] + + assert record.eventSource == raw_record["eventSource"] + assert record.eventVersion == raw_record["eventVersion"] + + mail = record.ses.mail + raw_mail = raw_record["ses"]["mail"] + assert mail.source == raw_mail["source"] + assert mail.messageId == raw_mail["messageId"] + assert mail.destination == raw_mail["destination"] + assert mail.headersTruncated is False + convert_time = int(round(mail.timestamp.timestamp() * 1000)) + assert convert_time == 0 + + headers = list(mail.headers) + assert len(headers) == 10 + assert headers[0].name == raw_mail["headers"][0]["name"] + assert headers[0].value == raw_mail["headers"][0]["value"] + + common_headers = mail.commonHeaders + assert common_headers.returnPath == raw_mail["commonHeaders"]["returnPath"] + assert common_headers.header_from == raw_mail["commonHeaders"]["from"] + assert common_headers.date == raw_mail["commonHeaders"]["date"] + assert common_headers.to == raw_mail["commonHeaders"]["to"] + assert common_headers.messageId == raw_mail["commonHeaders"]["messageId"] + assert common_headers.subject == raw_mail["commonHeaders"]["subject"] + + receipt = record.ses.receipt + raw_receipt = raw_record["ses"]["receipt"] + convert_time = int(round(receipt.timestamp.timestamp() * 1000)) + assert convert_time == 0 + assert receipt.processingTimeMillis == raw_receipt["processingTimeMillis"] + assert receipt.recipients == raw_receipt["recipients"] + assert receipt.spamVerdict.status == raw_receipt["spamVerdict"]["status"] + assert receipt.virusVerdict.status == raw_receipt["virusVerdict"]["status"] + assert receipt.spfVerdict.status == raw_receipt["spfVerdict"]["status"] + assert receipt.dmarcVerdict.status == raw_receipt["dmarcVerdict"]["status"] + + action = receipt.action + assert action.type == raw_receipt["action"]["type"] + assert action.functionArn == raw_receipt["action"]["functionArn"] + assert action.invocationType == raw_receipt["action"]["invocationType"] diff --git a/tests/unit/parser/test_sns.py b/tests/unit/parser/test_sns.py new file mode 100644 index 00000000000..9b925d5fa76 --- /dev/null +++ b/tests/unit/parser/test_sns.py @@ -0,0 +1,118 @@ +import json + +import pytest + +from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, parse +from tests.functional.utils import load_event +from tests.functional.validator.conftest import sns_event # noqa: F401 +from tests.unit.parser.schemas import MyAdvancedSnsBusiness, MySnsBusiness + + +def test_handle_sns_trigger_event_json_body(sns_event): # noqa: F811 + parse(event=sns_event, model=MySnsBusiness, envelope=envelopes.SnsEnvelope) + + +def test_validate_event_does_not_conform_with_model(): + raw_event: dict = {"invalid": "event"} + + with pytest.raises(ValidationError): + parse(event=raw_event, model=MySnsBusiness, envelope=envelopes.SnsEnvelope) + + +def test_validate_event_does_not_conform_user_json_string_with_model(): + raw_event: dict = { + "Records": [ + { + "EventVersion": "1.0", + "EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:sns-la ...", + "EventSource": "aws:sns", + "Sns": { + "SignatureVersion": "1", + "Timestamp": "2019-01-02T12:45:07.000Z", + "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==", + "SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificat ...", + "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e", + "Message": "not a valid JSON!", + "MessageAttributes": {"Test": {"Type": "String", "Value": "TestString"}}, + "Type": "Notification", + "UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscri ...", + "TopicArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda", + "Subject": "TestInvoke", + }, + }, + ], + } + + with pytest.raises(ValidationError): + parse(event=raw_event, model=MySnsBusiness, envelope=envelopes.SnsEnvelope) + + +def test_handle_sns_trigger_event_no_envelope(): + raw_event = load_event("snsEvent.json") + parsed_event: MyAdvancedSnsBusiness = MyAdvancedSnsBusiness(**raw_event) + + records = parsed_event.Records + record = records[0] + raw_record = raw_event["Records"][0] + + assert len(records) == 1 + assert record.EventVersion == raw_record["EventVersion"] + assert record.EventSubscriptionArn == raw_record["EventSubscriptionArn"] + assert record.EventSource == raw_record["EventSource"] + + sns = record.Sns + raw_sns = raw_record["Sns"] + assert sns.Type == raw_sns["Type"] + assert sns.UnsubscribeUrl.scheme == "https" + assert sns.UnsubscribeUrl.host == "sns.us-east-2.amazonaws.com" + assert sns.UnsubscribeUrl.query == "Action=Unsubscribe" + assert sns.TopicArn == raw_sns["TopicArn"] + assert sns.Subject == raw_sns["Subject"] + assert sns.SignatureVersion == raw_sns["SignatureVersion"] + convert_time = int(round(sns.Timestamp.timestamp() * 1000)) + assert convert_time == 1546433107000 + assert sns.Signature == raw_sns["Signature"] + assert sns.SigningCertUrl.host == "sns.us-east-2.amazonaws.com" + assert sns.SigningCertUrl.scheme == "https" + assert sns.SigningCertUrl.host == "sns.us-east-2.amazonaws.com" + assert sns.SigningCertUrl.path == "/SimpleNotification" + assert sns.MessageId == raw_sns["MessageId"] + assert sns.Message == raw_sns["Message"] + + attrib_dict = sns.MessageAttributes + assert len(attrib_dict) == 2 + assert attrib_dict["Test"].Type == raw_sns["MessageAttributes"]["Test"]["Type"] + assert attrib_dict["Test"].Value == raw_sns["MessageAttributes"]["Test"]["Value"] + assert attrib_dict["TestBinary"].Type == raw_sns["MessageAttributes"]["TestBinary"]["Type"] + assert attrib_dict["TestBinary"].Value == raw_sns["MessageAttributes"]["TestBinary"]["Value"] + + +def test_handle_sns_sqs_trigger_event_json_body(): # noqa: F811 + raw_event = load_event("snsSqsEvent.json") + parsed_event: MySnsBusiness = parse(event=raw_event, model=MySnsBusiness, envelope=envelopes.SnsSqsEnvelope) + + assert len(parsed_event) == 1 + assert parsed_event[0].message == "hello world" + assert parsed_event[0].username == "lessa" + + +def test_handle_sns_sqs_trigger_event_json_body_missing_unsubscribe_url(): + # GIVEN an event is tampered with a missing UnsubscribeURL + raw_event = load_event("snsSqsEvent.json") + payload = json.loads(raw_event["Records"][0]["body"]) + payload.pop("UnsubscribeURL") + raw_event["Records"][0]["body"] = json.dumps(payload) + + # WHEN parsing the payload + # THEN raise a ValidationError error + with pytest.raises(ValidationError): + parse(event=raw_event, model=MySnsBusiness, envelope=envelopes.SnsSqsEnvelope) + + +def test_handle_sns_sqs_fifo_trigger_event_json_body(): + raw_event = load_event("snsSqsFifoEvent.json") + parsed_event: MySnsBusiness = parse(event=raw_event, model=MySnsBusiness, envelope=envelopes.SnsSqsEnvelope) + + assert len(parsed_event) == 1 + assert parsed_event[0].message == "hello world" + assert parsed_event[0].username == "lessa" diff --git a/tests/functional/parser/test_sqs.py b/tests/unit/parser/test_sqs.py similarity index 51% rename from tests/functional/parser/test_sqs.py rename to tests/unit/parser/test_sqs.py index 4f547ad4bcc..0d948acb39d 100644 --- a/tests/functional/parser/test_sqs.py +++ b/tests/unit/parser/test_sqs.py @@ -1,38 +1,28 @@ -from typing import Any, List - import pytest -from aws_lambda_powertools.utilities.parser import ( - ValidationError, - envelopes, - event_parser, -) -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyAdvancedSqsBusiness, MySqsBusiness +from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, parse from tests.functional.utils import load_event from tests.functional.validator.conftest import sqs_event # noqa: F401 - - -@event_parser(model=MySqsBusiness, envelope=envelopes.SqsEnvelope) -def handle_sqs_json_body(event: List[MySqsBusiness], _: LambdaContext): - assert len(event) == 1 - assert event[0].message == "hello world" - assert event[0].username == "lessa" +from tests.unit.parser.schemas import MyAdvancedSqsBusiness, MySqsBusiness def test_handle_sqs_trigger_event_json_body(sqs_event): # noqa: F811 - handle_sqs_json_body(sqs_event, LambdaContext()) + parsed_event: MySqsBusiness = parse(event=sqs_event, model=MySqsBusiness, envelope=envelopes.SqsEnvelope) + + assert len(parsed_event) == 1 + assert parsed_event[0].message == "hello world" + assert parsed_event[0].username == "lessa" def test_validate_event_does_not_conform_with_model(): - event: Any = {"invalid": "event"} + raw_event: dict = {"invalid": "event"} with pytest.raises(ValidationError): - handle_sqs_json_body(event, LambdaContext()) + parse(event=raw_event, model=MySqsBusiness, envelope=envelopes.SqsEnvelope) def test_validate_event_does_not_conform_user_json_string_with_model(): - event: Any = { + raw_event: dict = { "Records": [ { "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", @@ -56,41 +46,42 @@ def test_validate_event_does_not_conform_user_json_string_with_model(): } with pytest.raises(ValidationError): - handle_sqs_json_body(event, LambdaContext()) + parse(event=raw_event, model=MySqsBusiness, envelope=envelopes.SqsEnvelope) -@event_parser(model=MyAdvancedSqsBusiness) -def handle_sqs_no_envelope(event: MyAdvancedSqsBusiness, _: LambdaContext): - records = event.Records - record = records[0] - attributes = record.attributes - message_attributes = record.messageAttributes - test_attr = message_attributes["testAttr"] +def test_handle_sqs_trigger_event_no_envelope(): + raw_event = load_event("sqsEvent.json") + parsed_event: MyAdvancedSqsBusiness = MyAdvancedSqsBusiness(**raw_event) + records = parsed_event.Records + record = records[0] + raw_record = raw_event["Records"][0] assert len(records) == 2 - assert record.messageId == "059f36b4-87a3-44ab-83d2-661975830a7d" - assert record.receiptHandle == "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a..." - assert record.body == "Test message." + + assert record.messageId == raw_record["messageId"] + assert record.receiptHandle == raw_record["receiptHandle"] + assert record.body == raw_record["body"] + assert record.eventSource == raw_record["eventSource"] + assert record.eventSourceARN == raw_record["eventSourceARN"] + assert record.awsRegion == raw_record["awsRegion"] + assert record.md5OfBody == raw_record["md5OfBody"] + + attributes = record.attributes assert attributes.AWSTraceHeader is None - assert attributes.ApproximateReceiveCount == "1" - convert_time = int(round(attributes.SentTimestamp.timestamp() * 1000)) - assert convert_time == 1545082649183 - assert attributes.SenderId == "AIDAIENQZJOLO23YVJ4VO" - convert_time = int(round(attributes.ApproximateFirstReceiveTimestamp.timestamp() * 1000)) - assert convert_time == 1545082649185 + assert attributes.ApproximateReceiveCount == raw_record["attributes"]["ApproximateReceiveCount"] assert attributes.SequenceNumber is None assert attributes.MessageGroupId is None assert attributes.MessageDeduplicationId is None - assert message_attributes.get("NotFound") is None - assert test_attr.stringValue == "100" - assert test_attr.binaryValue == "base64Str" - assert test_attr.dataType == "Number" - assert record.md5OfBody == "e4e68fb7bd0e697a0ae8f1bb342846b3" - assert record.eventSource == "aws:sqs" - assert record.eventSourceARN == "arn:aws:sqs:us-east-2:123456789012:my-queue" - assert record.awsRegion == "us-east-2" - + assert attributes.SenderId == raw_record["attributes"]["SenderId"] + convert_time = int(round(attributes.ApproximateFirstReceiveTimestamp.timestamp() * 1000)) + assert convert_time == int(raw_record["attributes"]["ApproximateFirstReceiveTimestamp"]) + convert_time = int(round(attributes.SentTimestamp.timestamp() * 1000)) + assert convert_time == int(raw_record["attributes"]["SentTimestamp"]) -def test_handle_sqs_trigger_event_no_envelope(): - event_dict = load_event("sqsEvent.json") - handle_sqs_no_envelope(event_dict, LambdaContext()) + message_attributes = record.messageAttributes + message_attributes_raw = raw_record["messageAttributes"]["testAttr"] + test_attr = message_attributes["testAttr"] + assert message_attributes.get("NotFound") is None + assert test_attr.stringValue == message_attributes_raw["stringValue"] + assert test_attr.binaryValue == message_attributes_raw["binaryValue"] + assert test_attr.dataType == message_attributes_raw["dataType"] diff --git a/tests/unit/parser/test_vpc_lattice.py b/tests/unit/parser/test_vpc_lattice.py index f0476509cea..e5dfedfb445 100644 --- a/tests/unit/parser/test_vpc_lattice.py +++ b/tests/unit/parser/test_vpc_lattice.py @@ -1,26 +1,22 @@ import pytest -from aws_lambda_powertools.utilities.parser import ( - ValidationError, - envelopes, - event_parser, -) +from aws_lambda_powertools.utilities.parser import ValidationError, envelopes, parse from aws_lambda_powertools.utilities.parser.models import VpcLatticeModel -from aws_lambda_powertools.utilities.typing import LambdaContext -from tests.functional.parser.schemas import MyVpcLatticeBusiness from tests.functional.utils import load_event - - -@event_parser(model=MyVpcLatticeBusiness, envelope=envelopes.VpcLatticeEnvelope) -def handle_lambda_vpclattice_with_envelope(event: MyVpcLatticeBusiness, context: LambdaContext): - assert event.username == "Leandro" - assert event.name == "Damascena" +from tests.unit.parser.schemas import MyVpcLatticeBusiness def test_vpc_lattice_event_with_envelope(): - event = load_event("vpcLatticeEvent.json") - event["body"] = '{"username": "Leandro", "name": "Damascena"}' - handle_lambda_vpclattice_with_envelope(event, LambdaContext()) + raw_event = load_event("vpcLatticeEvent.json") + raw_event["body"] = '{"username": "Leandro", "name": "Damascena"}' + parsed_event: MyVpcLatticeBusiness = parse( + event=raw_event, + model=MyVpcLatticeBusiness, + envelope=envelopes.VpcLatticeEnvelope, + ) + + assert parsed_event.username == "Leandro" + assert parsed_event.name == "Damascena" def test_vpc_lattice_event(): From 0294d8db6505161473f7b6232a32f4ef2132142d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 01:16:51 +0100 Subject: [PATCH 30/73] chore(deps): bump actions/setup-node from 3.6.0 to 3.7.0 (#2689) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish_v2_layer.yml | 2 +- .github/workflows/reusable_deploy_v2_layer_stack.yml | 2 +- .github/workflows/reusable_deploy_v2_sar.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index 864fc74241a..d92034076f0 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -72,7 +72,7 @@ jobs: - name: Install poetry run: pipx install poetry - name: Setup Node.js - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: node-version: "16.12" - name: Setup python diff --git a/.github/workflows/reusable_deploy_v2_layer_stack.yml b/.github/workflows/reusable_deploy_v2_layer_stack.yml index 76b6950267c..8b255218827 100644 --- a/.github/workflows/reusable_deploy_v2_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v2_layer_stack.yml @@ -134,7 +134,7 @@ jobs: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} - name: Setup Node.js - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: node-version: "16.12" - name: Setup python diff --git a/.github/workflows/reusable_deploy_v2_sar.yml b/.github/workflows/reusable_deploy_v2_sar.yml index 3fd83681e6a..1ca76a2a706 100644 --- a/.github/workflows/reusable_deploy_v2_sar.yml +++ b/.github/workflows/reusable_deploy_v2_sar.yml @@ -85,7 +85,7 @@ jobs: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.AWS_SAR_V2_ROLE_ARN }} - name: Setup Node.js - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: node-version: ${{ env.NODE_VERSION }} - name: Download artifact diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 8173596769f..21484d34a6c 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -61,7 +61,7 @@ jobs: architecture: "x64" cache: "poetry" - name: Setup Node.js - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: node-version: "16.12" - name: Install CDK CLI From e8399c3f331444ad9b5243ab296d28d5f74198a6 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Thu, 6 Jul 2023 14:12:13 +0200 Subject: [PATCH 31/73] docs(maintainers): add cicd pipeline diagram (#2692) --- .github/workflows/dispatch_analytics.yml | 29 ++++--- .github/workflows/ossf_scorecard.yml | 3 +- MAINTAINERS.md | 102 ++++++++++++++++++++++- 3 files changed, 119 insertions(+), 15 deletions(-) diff --git a/.github/workflows/dispatch_analytics.yml b/.github/workflows/dispatch_analytics.yml index f7eac5a2f49..b94c7439f7b 100644 --- a/.github/workflows/dispatch_analytics.yml +++ b/.github/workflows/dispatch_analytics.yml @@ -17,19 +17,8 @@ on: - cron: "0 * * * *" permissions: - id-token: write - actions: read - checks: read - contents: write - deployments: read - issues: read - discussions: read - packages: read - pages: read - pull-requests: read - repository-projects: read - security-events: read - statuses: read + contents: read + jobs: dispatch_token: @@ -38,6 +27,20 @@ jobs: group: analytics runs-on: ubuntu-latest environment: analytics + permissions: + id-token: write + actions: read + checks: read + contents: read # previously we needed `write` to use GH_TOKEN in our dispatcher (Lambda) + deployments: read + issues: read + discussions: read + packages: read + pages: read + pull-requests: read + repository-projects: read + security-events: read + statuses: read steps: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml index 10e53f164ec..4d7d2b6fbe4 100644 --- a/.github/workflows/ossf_scorecard.yml +++ b/.github/workflows/ossf_scorecard.yml @@ -6,7 +6,8 @@ on: schedule: - cron: "0 9 * * *" push: - branches: [$default-branch] + branches: [develop] + workflow_dispatch: permissions: read-all diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 2a2631e91fc..3a008e9509a 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -198,7 +198,7 @@ Once complete, you can start drafting the release notes to let customers know ** Every release makes hundreds of checks, security scans, canaries and deployments - all of these are automated. -This is a close visual representation of the main steps (GitHub Actions UI should be the source of truth). +This is a close visual representation of the main steps (GitHub Actions UI should be the source of truth), along with the approximate time it takes for each key step to complete. @@ -258,6 +258,106 @@ section Post-release Release complete : milestone, m6, 10:31,2m ``` +If we combine our CI and CD pipelines into a single diagram, it looks like this: + +```mermaid +timeline + title Powertools for AWS Lambda (Python) CI/CD pipeline + + section Continuous Integration + Project setup
(make dev) : Code checkout + : Virtual environment + : Dependencies + : Git pre-commit hooks + : Local branch + : Local changes + : Local tests + + Pre-commit checks
(git commit) : Merge conflict check + : Trailing whitespaces + : TOML checks + : Code linting (standards) + : Markdown linting + : CloudFormation linting + : GitHub Actions linting + : Terraform linting + : Secrets linting + + Pre-Pull Request
(make pr) : Code linting + : Docs linting + : Static typing analysis + : Tests (unit|functional|perf) + : Security baseline + : Complexity baseline + : +pre-commit checks + + Pull Request
(CI checks) : Semantic PR title check + : Related issue check + : Acknowledgment check + : Code coverage diff + : Contribution size check + : Contribution category check + : Dependency vulnerability check + : GitHub Actions security check + : +pre-pull request checks + + After merge
(CI checks) : End-to-end tests + : Longer SAST check + : Security posture check (scorecard) + : GitHub Actions security check + : Rebuild Changelog + : Deploy staging docs + : Update draft release + + section Continuous Delivery + + Source code anti-tampering : Checkout release commit code + : Bump release version + : Seal and upload artifact + + Quality Assurance : Restore sealed code + : +Continuous Integration checks + + Build : Restore sealed code + : Integrity check + : Build release artifact + : Seal and upload artifact + + Release : Restore sealed build + : Integrity check + : PyPi ephemeral credentials + : Publish PyPi + : Baking time + + Git tagging : Restore sealed code + : Integrity check + : Bump git tag + : Create temporary branch + : Create PR + + Lambda Layers : Fetch PyPi release + : Build x86 architecture + : Build ARM architecture + : Deploy Beta + : Canary testing + : Deploy Prod + + Lambda Layers SAR : Deploy Beta + : Deploy Prod + + Documentation : Update Lambda Layer ARNs + : Build User Guide + : Build API Guide + : Rebuild Changelog + : Release new version + : Update latest alias + : Create temporary branch + : Create PR + + Post-release : Close pending-release issues + : Notify customers +``` + #### Drafting release notes Visit the [Releases page](https://github.com/aws-powertools/powertools-lambda-python/releases) and choose the edit pencil button. From 1d53b840777ee1dddc70ea1f9e9de95c67f37d93 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Thu, 6 Jul 2023 14:34:15 +0200 Subject: [PATCH 32/73] chore(ci): address ossf scorecard findings on npm, pip, and top-level permission leftover (#2694) --- .github/workflows/publish_v2_layer.yml | 4 ++-- .../workflows/reusable_deploy_v2_layer_stack.yml | 4 ++-- .github/workflows/reusable_publish_docs.yml | 10 ++++++---- .github/workflows/run-e2e-tests.yml | 2 +- package-lock.json | 13 +++++++++++++ package.json | 3 +++ 6 files changed, 27 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index d92034076f0..ba3e99a81f5 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -85,7 +85,7 @@ jobs: # therefore it ignores both activated virtual env and cached interpreter by GH run: | poetry export --format requirements.txt --output requirements.txt - pip install -r requirements.txt + pip install --require-hashes -r requirements.txt - name: Set up QEMU uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.0.0 with: @@ -101,7 +101,7 @@ jobs: - name: install cdk and deps working-directory: ./ run: | - npm install + npm ci npx cdk --version - name: CDK build run: npx cdk synth --verbose --context version="${{ inputs.latest_published_version }}" -o cdk.out diff --git a/.github/workflows/reusable_deploy_v2_layer_stack.yml b/.github/workflows/reusable_deploy_v2_layer_stack.yml index 8b255218827..3186009493e 100644 --- a/.github/workflows/reusable_deploy_v2_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v2_layer_stack.yml @@ -147,11 +147,11 @@ jobs: # therefore it ignores both activated virtual env and cached interpreter by GH run: | poetry export --format requirements.txt --output requirements.txt - pip install -r requirements.txt + pip install --require-hashes -r requirements.txt - name: install cdk and deps working-directory: ./ run: | - npm install + npm ci npx cdk --version - name: install deps run: poetry install diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index 3ca16a25b5a..8dfc45973ad 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -28,9 +28,7 @@ on: default: develop permissions: - id-token: write # trade JWT token for AWS credentials in AWS Docs account - contents: write # push to gh-pages - pages: write # deploy gh-pages website + contents: read jobs: publish_docs: @@ -40,6 +38,10 @@ jobs: group: on-docs-rebuild runs-on: ubuntu-latest environment: "Docs" + permissions: + contents: write # push to gh-pages + id-token: write # trade JWT token for AWS credentials in AWS Docs account + pages: write # uncomment if mike fails as we migrated to S3 hosting steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 with: @@ -110,7 +112,7 @@ jobs: # 1. Download the versions.json file from S3 # 2. Find any reference to the alias and delete it from the versions file # 3. This is voodoo (don't use JQ): - # - we assign the input as $o and the new version/alias as $n, + # - we assign the input as $o and the new version/alias as $n, # - we check if the version number exists in the file already (for republishing docs) # - if it's an alias (stage/latest/*) or old version, we do nothing and output $o (original input) # - if it's a new version number, we add it at position 0 in the array. diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 21484d34a6c..658be430d28 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -66,7 +66,7 @@ jobs: node-version: "16.12" - name: Install CDK CLI run: | - npm install + npm ci npx cdk --version - name: Install dependencies run: make dev diff --git a/package-lock.json b/package-lock.json index 3792d91ea89..0cec24720b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,9 @@ "": { "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", + "dependencies": { + "package-lock.json": "^1.0.0" + }, "devDependencies": { "aws-cdk": "^2.86.0" } @@ -39,6 +42,11 @@ "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } + }, + "node_modules/package-lock.json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-lock.json/-/package-lock.json-1.0.0.tgz", + "integrity": "sha512-+yEXtNdlCs5N0Zy/9uvkifgf/RqnGu0WqP4j9Wu1Us4YReFe1YNBh2Krmf8B1xGxjpYnta63K55QP8bkafnOzA==" } }, "dependencies": { @@ -57,6 +65,11 @@ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true + }, + "package-lock.json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-lock.json/-/package-lock.json-1.0.0.tgz", + "integrity": "sha512-+yEXtNdlCs5N0Zy/9uvkifgf/RqnGu0WqP4j9Wu1Us4YReFe1YNBh2Krmf8B1xGxjpYnta63K55QP8bkafnOzA==" } } } diff --git a/package.json b/package.json index 376c3766cc6..2a556b13098 100644 --- a/package.json +++ b/package.json @@ -3,5 +3,8 @@ "version": "1.0.0", "devDependencies": { "aws-cdk": "^2.86.0" + }, + "dependencies": { + "package-lock.json": "^1.0.0" } } From 313f65f509a0e0a4bbd4e0a33ba402c0853d08e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 05:53:36 +0200 Subject: [PATCH 33/73] chore(deps-dev): bump sentry-sdk from 1.27.0 to 1.27.1 (#2701) --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4fe708cc149..9458b109352 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2330,13 +2330,13 @@ pbr = "*" [[package]] name = "sentry-sdk" -version = "1.27.0" +version = "1.27.1" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = "*" files = [ - {file = "sentry-sdk-1.27.0.tar.gz", hash = "sha256:eb2a5080912dc9b397925657669e3761d95d62c8aa4c0c6d6a73d5a31edaafe9"}, - {file = "sentry_sdk-1.27.0-py2.py3-none-any.whl", hash = "sha256:8c0ba7a0ed4e39635d335fdac7c00840b14ce4319bb8629b934243d6306fee7d"}, + {file = "sentry-sdk-1.27.1.tar.gz", hash = "sha256:53f36293a0da271a22f476259d2fda76c0b8a1cb96b16d6e6e6aca490d7f3451"}, + {file = "sentry_sdk-1.27.1-py2.py3-none-any.whl", hash = "sha256:24308bd05a1f7d65e40acc68a768b4e5c35462039bfd6ae2ca116b92a7b53c78"}, ] [package.dependencies] From 22a097800fe7f5fca687d8e873d9260038b1718e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 05:54:45 +0200 Subject: [PATCH 34/73] chore(deps-dev): bump mypy-boto3-cloudformation from 1.27.0 to 1.28.0 (#2700) --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9458b109352..4e24e0b5bc7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1456,13 +1456,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudformation" -version = "1.27.0" -description = "Type annotations for boto3.CloudFormation 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.CloudFormation 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudformation-1.27.0.tar.gz", hash = "sha256:9a9395d79d86f9ed2b18cf796eb9906a47f76bac30fe60c20fd22e082e4b1d5c"}, - {file = "mypy_boto3_cloudformation-1.27.0-py3-none-any.whl", hash = "sha256:979f61f7466ed3fad239e79f54227b1927a2683a7cfe44993d146279cfba2980"}, + {file = "mypy-boto3-cloudformation-1.28.0.tar.gz", hash = "sha256:0d2ead02c352bc97ae59b65ae8b00d5ce186435b7cf5736213a52f58df192511"}, + {file = "mypy_boto3_cloudformation-1.28.0-py3-none-any.whl", hash = "sha256:99d5db7d6b220ba016757670a917bdfdab1c475593153833ed6c5cdd9a9aa9ba"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "6b78a2eaa84743416b8bbc62aae87607abaf52cb6e748f3529c3e3b3a43c00ac" +content-hash = "e99b00a4b211a7c671ff96c5d85c82ab94c125fc47e7a569eb6bbcbac347d7d0" diff --git a/pyproject.toml b/pyproject.toml index 80ed1d28dba..f6fb42ca8ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,7 @@ aws-cdk-lib = "^2.75.0" pytest-benchmark = "^4.0.0" python-snappy = "^0.6.1" mypy-boto3-appconfig = "^1.26.71" -mypy-boto3-cloudformation = "^1.26.156" +mypy-boto3-cloudformation = "^1.28.0" mypy-boto3-cloudwatch = "^1.26.127" mypy-boto3-dynamodb = "^1.26.164" mypy-boto3-lambda = "^1.26.163" From 65e32d86f793e45ee81fdb24232181086eed4ac5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 06:10:35 +0200 Subject: [PATCH 35/73] chore(deps-dev): bump mypy-boto3-appconfigdata from 1.27.0 to 1.28.0 (#2699) --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4e24e0b5bc7..de2c7b9ae7a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1442,13 +1442,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-appconfigdata" -version = "1.27.0" -description = "Type annotations for boto3.AppConfigData 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.AppConfigData 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-appconfigdata-1.27.0.tar.gz", hash = "sha256:a240f3c7b4f8b559d2b9a572c756884fe8247643fbc8c609d22f7414a79aa462"}, - {file = "mypy_boto3_appconfigdata-1.27.0-py3-none-any.whl", hash = "sha256:cfe864dab8557b66654d903104ac5a259079e24d43edd06469bd4715f5173a42"}, + {file = "mypy-boto3-appconfigdata-1.28.0.tar.gz", hash = "sha256:1f0331fcb6642c44d335d08250ee5abcd840030304d480adf85ea017ba941bb4"}, + {file = "mypy_boto3_appconfigdata-1.28.0-py3-none-any.whl", hash = "sha256:c01ecbbda949497dbb650cc761915a7e14b621db5bc20cc1fd3f49620e74c9bc"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "e99b00a4b211a7c671ff96c5d85c82ab94c125fc47e7a569eb6bbcbac347d7d0" +content-hash = "6081d9fba40d76564b0b9d840f9031493878cd775f207ddf6c09b85bdb9dbbad" diff --git a/pyproject.toml b/pyproject.toml index f6fb42ca8ab..c54e8f6b6b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ typing-extensions = "^4.6.2" mkdocs-material = "^9.1.17" filelock = "^3.12.2" checksumdir = "^1.2.0" -mypy-boto3-appconfigdata = "^1.27.0" +mypy-boto3-appconfigdata = "^1.28.0" ijson = "^3.2.2" typed-ast = { version = "^1.5.5", python = "< 3.8"} hvac = "^1.1.1" From af0075a7cd3b8536491adf93912895970a3777eb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 06:11:37 +0200 Subject: [PATCH 36/73] chore(ci): changelog rebuild (#2704) --- CHANGELOG.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18b751450f1..5ffb06e5dbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,51 @@ # Unreleased +## Bug Fixes + +* **docs:** ensure alias is applied to versioned releases ([#2644](https://github.com/aws-powertools/powertools-lambda-python/issues/2644)) +* **docs:** ensure version alias is in an array to prevent "you're not viewing the latest version" incorrect message ([#2629](https://github.com/aws-powertools/powertools-lambda-python/issues/2629)) + +## Code Refactoring + +* **parser:** convert functional tests to unit tests ([#2656](https://github.com/aws-powertools/powertools-lambda-python/issues/2656)) + +## Documentation + +* **contributing:** add code integration journey graph ([#2685](https://github.com/aws-powertools/powertools-lambda-python/issues/2685)) +* **maintainers:** add cicd pipeline diagram ([#2692](https://github.com/aws-powertools/powertools-lambda-python/issues/2692)) + +## Maintenance + +* **ci:** use sast on every commit on any supported language ([#2646](https://github.com/aws-powertools/powertools-lambda-python/issues/2646)) +* **ci:** prevent merging PRs that do not meet minimum requirements ([#2639](https://github.com/aws-powertools/powertools-lambda-python/issues/2639)) +* **ci:** address ossf scorecard findings on npm, pip, and top-level permission leftover ([#2694](https://github.com/aws-powertools/powertools-lambda-python/issues/2694)) +* **ci:** enforce top-level permission to minimum fail-safe permission as per openssf ([#2638](https://github.com/aws-powertools/powertools-lambda-python/issues/2638)) +* **ci:** propagate checkout permission to nested workflows ([#2642](https://github.com/aws-powertools/powertools-lambda-python/issues/2642)) +* **ci:** enforce pip --require-hashes to maybe satistify scorecard ([#2679](https://github.com/aws-powertools/powertools-lambda-python/issues/2679)) +* **ci:** add gitleaks in pre-commit hooks as an extra safety measure ([#2677](https://github.com/aws-powertools/powertools-lambda-python/issues/2677)) +* **ci:** improves dependabot based on ossf scorecard recommendations ([#2647](https://github.com/aws-powertools/powertools-lambda-python/issues/2647)) +* **ci:** use deps sha for docs and gitpod images based on ossf findings ([#2662](https://github.com/aws-powertools/powertools-lambda-python/issues/2662)) +* **deps:** bump pydantic from 1.10.10 to 1.10.11 ([#2671](https://github.com/aws-powertools/powertools-lambda-python/issues/2671)) +* **deps:** bump pydantic from 1.10.9 to 1.10.10 ([#2624](https://github.com/aws-powertools/powertools-lambda-python/issues/2624)) +* **deps:** migrate from retry to retry2 to address CVE-2022-42969 ([#2665](https://github.com/aws-powertools/powertools-lambda-python/issues/2665)) +* **deps:** bump squidfunk/mkdocs-material from `3837c0f` to `a28ed81` in /docs ([#2669](https://github.com/aws-powertools/powertools-lambda-python/issues/2669)) +* **deps:** bump actions/setup-node from 3.6.0 to 3.7.0 ([#2689](https://github.com/aws-powertools/powertools-lambda-python/issues/2689)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.17.8 to 1.18.27 in /layer/scripts/layer-balancer ([#2651](https://github.com/aws-powertools/powertools-lambda-python/issues/2651)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.24.6 to 1.37.0 in /layer/scripts/layer-balancer ([#2653](https://github.com/aws-powertools/powertools-lambda-python/issues/2653)) +* **deps:** bump golang.org/x/sync from 0.1.0 to 0.3.0 in /layer/scripts/layer-balancer ([#2649](https://github.com/aws-powertools/powertools-lambda-python/issues/2649)) +* **deps:** bump actions/dependency-review-action from 2.5.1 to 3.0.6 ([#2650](https://github.com/aws-powertools/powertools-lambda-python/issues/2650)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.16.16 to 1.18.1 in /layer/scripts/layer-balancer ([#2654](https://github.com/aws-powertools/powertools-lambda-python/issues/2654)) +* **deps-dev:** bump ruff from 0.0.275 to 0.0.276 ([#2655](https://github.com/aws-powertools/powertools-lambda-python/issues/2655)) +* **deps-dev:** bump ruff from 0.0.276 to 0.0.277 ([#2682](https://github.com/aws-powertools/powertools-lambda-python/issues/2682)) +* **deps-dev:** bump typed-ast from 1.5.4 to 1.5.5 ([#2670](https://github.com/aws-powertools/powertools-lambda-python/issues/2670)) +* **deps-dev:** bump sentry-sdk from 1.27.0 to 1.27.1 ([#2701](https://github.com/aws-powertools/powertools-lambda-python/issues/2701)) +* **deps-dev:** bump mypy-boto3-appconfigdata from 1.26.70 to 1.27.0 ([#2636](https://github.com/aws-powertools/powertools-lambda-python/issues/2636)) +* **deps-dev:** bump sentry-sdk from 1.26.0 to 1.27.0 ([#2652](https://github.com/aws-powertools/powertools-lambda-python/issues/2652)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.26.158 to 1.26.164 ([#2622](https://github.com/aws-powertools/powertools-lambda-python/issues/2622)) +* **deps-dev:** bump mypy-boto3-cloudformation from 1.27.0 to 1.28.0 ([#2700](https://github.com/aws-powertools/powertools-lambda-python/issues/2700)) +* **deps-dev:** bump mypy-boto3-appconfigdata from 1.27.0 to 1.28.0 ([#2699](https://github.com/aws-powertools/powertools-lambda-python/issues/2699)) + ## [v2.19.0] - 2023-06-30 From 75926dc3b2ada571d2b768f9321ca6199f1d2a1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 06:20:36 +0200 Subject: [PATCH 37/73] chore(deps-dev): bump mypy-boto3-lambda from 1.27.0 to 1.28.0 (#2698) --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index de2c7b9ae7a..5ebfa560f48 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1498,13 +1498,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-lambda" -version = "1.27.0" -description = "Type annotations for boto3.Lambda 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.Lambda 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-lambda-1.27.0.tar.gz", hash = "sha256:40c8f9b102ff1a341d5fcbeff601c73c06727e0aa4a29bc7e862c18e52fc69e5"}, - {file = "mypy_boto3_lambda-1.27.0-py3-none-any.whl", hash = "sha256:5e0a19c919ef1bcc9519d95209a715208af965e12ecf349815a3d69ecf65238e"}, + {file = "mypy-boto3-lambda-1.28.0.tar.gz", hash = "sha256:a3abaf98e514f2cabed2cf0b1e77c94c81f0fbbba8a549b3c073577a9f9ac196"}, + {file = "mypy_boto3_lambda-1.28.0-py3-none-any.whl", hash = "sha256:5fd38df6418829b2f3a184918fc8ad1d49b6738509f1832cdc71f33588efbdfb"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "6081d9fba40d76564b0b9d840f9031493878cd775f207ddf6c09b85bdb9dbbad" +content-hash = "85c52d77a4be2b53c39ca5291bf24b6553b43d4fbc70887d8b44dcb0b6dc867d" diff --git a/pyproject.toml b/pyproject.toml index c54e8f6b6b7..ceec85cece0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ mypy-boto3-appconfig = "^1.26.71" mypy-boto3-cloudformation = "^1.28.0" mypy-boto3-cloudwatch = "^1.26.127" mypy-boto3-dynamodb = "^1.26.164" -mypy-boto3-lambda = "^1.26.163" +mypy-boto3-lambda = "^1.28.0" mypy-boto3-logs = "^1.26.149" mypy-boto3-secretsmanager = "^1.26.135" mypy-boto3-ssm = "^1.26.162" From f441938323a28c379f80b73e1710ce0486834e4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 06:21:55 +0200 Subject: [PATCH 38/73] chore(deps-dev): bump aws-cdk from 2.86.0 to 2.87.0 (#2696) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0cec24720b2..8921e96a70a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,13 +11,13 @@ "package-lock.json": "^1.0.0" }, "devDependencies": { - "aws-cdk": "^2.86.0" + "aws-cdk": "^2.87.0" } }, "node_modules/aws-cdk": { - "version": "2.86.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.86.0.tgz", - "integrity": "sha512-GRcdU6p00Zu3fIZYPG+EbpDYppYMtzebuf0jrmCfKhCytRGaPWDHHfu3hrv0de4d0zbUD/+AmiODPMu3J6nXbQ==", + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.87.0.tgz", + "integrity": "sha512-dBm74nl3dMUxoAzgjcfKnzJyoVNIV//B1sqDN11cC3LXEflYapcBxPxZHAyGcRXg5dW3m14dMdKVQfmt4N970g==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -51,9 +51,9 @@ }, "dependencies": { "aws-cdk": { - "version": "2.86.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.86.0.tgz", - "integrity": "sha512-GRcdU6p00Zu3fIZYPG+EbpDYppYMtzebuf0jrmCfKhCytRGaPWDHHfu3hrv0de4d0zbUD/+AmiODPMu3J6nXbQ==", + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.87.0.tgz", + "integrity": "sha512-dBm74nl3dMUxoAzgjcfKnzJyoVNIV//B1sqDN11cC3LXEflYapcBxPxZHAyGcRXg5dW3m14dMdKVQfmt4N970g==", "dev": true, "requires": { "fsevents": "2.3.2" diff --git a/package.json b/package.json index 2a556b13098..643bec22883 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.86.0" + "aws-cdk": "^2.87.0" }, "dependencies": { "package-lock.json": "^1.0.0" From 7bb935e3cb4d51a9831f408f1ee9922f61b48e0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 06:30:24 +0200 Subject: [PATCH 39/73] chore(deps-dev): bump mypy-boto3-cloudwatch from 1.27.0 to 1.28.0 (#2697) --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5ebfa560f48..d4d09ef1c24 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1470,13 +1470,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudwatch" -version = "1.27.0" -description = "Type annotations for boto3.CloudWatch 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.CloudWatch 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudwatch-1.27.0.tar.gz", hash = "sha256:802f7cd086c67fdf23bce9e8b6fe558258c98cc9cfe926d5c19774359ad984d9"}, - {file = "mypy_boto3_cloudwatch-1.27.0-py3-none-any.whl", hash = "sha256:d5f97615e903ebc774a1ef4335c11cd7b965acbd238a295ee1254f0cfe4c443b"}, + {file = "mypy-boto3-cloudwatch-1.28.0.tar.gz", hash = "sha256:c34cc45c8a57702e11cf38de590af447d90cd3ea68328ea2908452d8a09d471a"}, + {file = "mypy_boto3_cloudwatch-1.28.0-py3-none-any.whl", hash = "sha256:8812c6120111798f84b2e1fe5808aae1f5766c183746ea336dec14f9bdf3308b"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "85c52d77a4be2b53c39ca5291bf24b6553b43d4fbc70887d8b44dcb0b6dc867d" +content-hash = "b4d202782b00785f2337b6950d37f1167e8e913e2c40fc95ec24dc8f9eb9d98e" diff --git a/pyproject.toml b/pyproject.toml index ceec85cece0..71ac772d4d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,7 @@ pytest-benchmark = "^4.0.0" python-snappy = "^0.6.1" mypy-boto3-appconfig = "^1.26.71" mypy-boto3-cloudformation = "^1.28.0" -mypy-boto3-cloudwatch = "^1.26.127" +mypy-boto3-cloudwatch = "^1.28.0" mypy-boto3-dynamodb = "^1.26.164" mypy-boto3-lambda = "^1.28.0" mypy-boto3-logs = "^1.26.149" From ec9c45148a4228ddfb4717259246881c35d7261e Mon Sep 17 00:00:00 2001 From: Roger Zhang Date: Thu, 6 Jul 2023 22:09:25 -0700 Subject: [PATCH 40/73] chore(user-agent): support patching botocore session (#2614) --- aws_lambda_powertools/shared/user_agent.py | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/aws_lambda_powertools/shared/user_agent.py b/aws_lambda_powertools/shared/user_agent.py index 21818bca2b8..098be7a503a 100644 --- a/aws_lambda_powertools/shared/user_agent.py +++ b/aws_lambda_powertools/shared/user_agent.py @@ -108,6 +108,45 @@ def register_feature_to_session(session, feature): logger.debug(f"session passed in doesn't have a event system:{e}") +# Add feature user-agent to given sdk botocore.session.Session +def register_feature_to_botocore_session(botocore_session, feature): + """ + Register the given feature string to the event system of the provided botocore session + + Please notice this function is for patching botocore session and is different from + previous one which is for patching boto3 session + + Parameters + ---------- + botocore_session : botocore.session.Session + The botocore session to which the feature will be registered. + feature : str + The feature string to be appended to the User-Agent header, e.g., "data-masking" in Powertools. + + Raises + ------ + AttributeError + If the provided session does not have an event system. + + Examples + -------- + **register data-masking user-agent to botocore session** + + >>> from aws_lambda_powertools.shared.user_agent import ( + >>> register_feature_to_botocore_session + >>> ) + >>> + >>> session = botocore.session.Session() + >>> register_feature_to_botocore_session(botocore_session=session, feature="data-masking") + >>> key_provider = StrictAwsKmsMasterKeyProvider(key_ids=self.keys, botocore_session=session) + + """ + try: + botocore_session.register(TARGET_SDK_EVENT, _create_feature_function(feature)) + except AttributeError as e: + logger.debug(f"botocore session passed in doesn't have a event system:{e}") + + # Add feature user-agent to given sdk boto3.client def register_feature_to_client(client, feature): """ From 50949b2d0af3933e88fb6f8623926edab7a39ee1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 07:14:23 +0200 Subject: [PATCH 41/73] chore(ci): changelog rebuild (#2709) --- CHANGELOG.md | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ffb06e5dbd..b59a4d6368e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,34 +20,38 @@ ## Maintenance -* **ci:** use sast on every commit on any supported language ([#2646](https://github.com/aws-powertools/powertools-lambda-python/issues/2646)) +* **ci:** add gitleaks in pre-commit hooks as an extra safety measure ([#2677](https://github.com/aws-powertools/powertools-lambda-python/issues/2677)) +* **ci:** use deps sha for docs and gitpod images based on ossf findings ([#2662](https://github.com/aws-powertools/powertools-lambda-python/issues/2662)) * **ci:** prevent merging PRs that do not meet minimum requirements ([#2639](https://github.com/aws-powertools/powertools-lambda-python/issues/2639)) -* **ci:** address ossf scorecard findings on npm, pip, and top-level permission leftover ([#2694](https://github.com/aws-powertools/powertools-lambda-python/issues/2694)) * **ci:** enforce top-level permission to minimum fail-safe permission as per openssf ([#2638](https://github.com/aws-powertools/powertools-lambda-python/issues/2638)) * **ci:** propagate checkout permission to nested workflows ([#2642](https://github.com/aws-powertools/powertools-lambda-python/issues/2642)) -* **ci:** enforce pip --require-hashes to maybe satistify scorecard ([#2679](https://github.com/aws-powertools/powertools-lambda-python/issues/2679)) -* **ci:** add gitleaks in pre-commit hooks as an extra safety measure ([#2677](https://github.com/aws-powertools/powertools-lambda-python/issues/2677)) * **ci:** improves dependabot based on ossf scorecard recommendations ([#2647](https://github.com/aws-powertools/powertools-lambda-python/issues/2647)) -* **ci:** use deps sha for docs and gitpod images based on ossf findings ([#2662](https://github.com/aws-powertools/powertools-lambda-python/issues/2662)) +* **ci:** address ossf scorecard findings on npm, pip, and top-level permission leftover ([#2694](https://github.com/aws-powertools/powertools-lambda-python/issues/2694)) +* **ci:** use sast on every commit on any supported language ([#2646](https://github.com/aws-powertools/powertools-lambda-python/issues/2646)) +* **ci:** enforce pip --require-hashes to maybe satistify scorecard ([#2679](https://github.com/aws-powertools/powertools-lambda-python/issues/2679)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.24.6 to 1.37.0 in /layer/scripts/layer-balancer ([#2653](https://github.com/aws-powertools/powertools-lambda-python/issues/2653)) * **deps:** bump pydantic from 1.10.10 to 1.10.11 ([#2671](https://github.com/aws-powertools/powertools-lambda-python/issues/2671)) -* **deps:** bump pydantic from 1.10.9 to 1.10.10 ([#2624](https://github.com/aws-powertools/powertools-lambda-python/issues/2624)) -* **deps:** migrate from retry to retry2 to address CVE-2022-42969 ([#2665](https://github.com/aws-powertools/powertools-lambda-python/issues/2665)) +* **deps:** bump actions/dependency-review-action from 2.5.1 to 3.0.6 ([#2650](https://github.com/aws-powertools/powertools-lambda-python/issues/2650)) * **deps:** bump squidfunk/mkdocs-material from `3837c0f` to `a28ed81` in /docs ([#2669](https://github.com/aws-powertools/powertools-lambda-python/issues/2669)) -* **deps:** bump actions/setup-node from 3.6.0 to 3.7.0 ([#2689](https://github.com/aws-powertools/powertools-lambda-python/issues/2689)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.17.8 to 1.18.27 in /layer/scripts/layer-balancer ([#2651](https://github.com/aws-powertools/powertools-lambda-python/issues/2651)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.24.6 to 1.37.0 in /layer/scripts/layer-balancer ([#2653](https://github.com/aws-powertools/powertools-lambda-python/issues/2653)) * **deps:** bump golang.org/x/sync from 0.1.0 to 0.3.0 in /layer/scripts/layer-balancer ([#2649](https://github.com/aws-powertools/powertools-lambda-python/issues/2649)) -* **deps:** bump actions/dependency-review-action from 2.5.1 to 3.0.6 ([#2650](https://github.com/aws-powertools/powertools-lambda-python/issues/2650)) * **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.16.16 to 1.18.1 in /layer/scripts/layer-balancer ([#2654](https://github.com/aws-powertools/powertools-lambda-python/issues/2654)) +* **deps:** migrate from retry to retry2 to address CVE-2022-42969 ([#2665](https://github.com/aws-powertools/powertools-lambda-python/issues/2665)) +* **deps:** bump actions/setup-node from 3.6.0 to 3.7.0 ([#2689](https://github.com/aws-powertools/powertools-lambda-python/issues/2689)) +* **deps:** bump pydantic from 1.10.9 to 1.10.10 ([#2624](https://github.com/aws-powertools/powertools-lambda-python/issues/2624)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.17.8 to 1.18.27 in /layer/scripts/layer-balancer ([#2651](https://github.com/aws-powertools/powertools-lambda-python/issues/2651)) +* **deps-dev:** bump sentry-sdk from 1.26.0 to 1.27.0 ([#2652](https://github.com/aws-powertools/powertools-lambda-python/issues/2652)) * **deps-dev:** bump ruff from 0.0.275 to 0.0.276 ([#2655](https://github.com/aws-powertools/powertools-lambda-python/issues/2655)) -* **deps-dev:** bump ruff from 0.0.276 to 0.0.277 ([#2682](https://github.com/aws-powertools/powertools-lambda-python/issues/2682)) * **deps-dev:** bump typed-ast from 1.5.4 to 1.5.5 ([#2670](https://github.com/aws-powertools/powertools-lambda-python/issues/2670)) +* **deps-dev:** bump ruff from 0.0.276 to 0.0.277 ([#2682](https://github.com/aws-powertools/powertools-lambda-python/issues/2682)) * **deps-dev:** bump sentry-sdk from 1.27.0 to 1.27.1 ([#2701](https://github.com/aws-powertools/powertools-lambda-python/issues/2701)) -* **deps-dev:** bump mypy-boto3-appconfigdata from 1.26.70 to 1.27.0 ([#2636](https://github.com/aws-powertools/powertools-lambda-python/issues/2636)) -* **deps-dev:** bump sentry-sdk from 1.26.0 to 1.27.0 ([#2652](https://github.com/aws-powertools/powertools-lambda-python/issues/2652)) -* **deps-dev:** bump mypy-boto3-dynamodb from 1.26.158 to 1.26.164 ([#2622](https://github.com/aws-powertools/powertools-lambda-python/issues/2622)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.27.0 to 1.28.0 ([#2700](https://github.com/aws-powertools/powertools-lambda-python/issues/2700)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.27.0 to 1.28.0 ([#2699](https://github.com/aws-powertools/powertools-lambda-python/issues/2699)) +* **deps-dev:** bump mypy-boto3-lambda from 1.27.0 to 1.28.0 ([#2698](https://github.com/aws-powertools/powertools-lambda-python/issues/2698)) +* **deps-dev:** bump mypy-boto3-appconfigdata from 1.26.70 to 1.27.0 ([#2636](https://github.com/aws-powertools/powertools-lambda-python/issues/2636)) +* **deps-dev:** bump aws-cdk from 2.86.0 to 2.87.0 ([#2696](https://github.com/aws-powertools/powertools-lambda-python/issues/2696)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.26.158 to 1.26.164 ([#2622](https://github.com/aws-powertools/powertools-lambda-python/issues/2622)) +* **deps-dev:** bump mypy-boto3-cloudwatch from 1.27.0 to 1.28.0 ([#2697](https://github.com/aws-powertools/powertools-lambda-python/issues/2697)) +* **user-agent:** support patching botocore session ([#2614](https://github.com/aws-powertools/powertools-lambda-python/issues/2614)) From 66b1dc89bacf73923c2b0f787e48258471f8f951 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Fri, 7 Jul 2023 12:00:40 +0200 Subject: [PATCH 42/73] chore(ci): prevent sast codeql to run in forks (#2711) --- .github/workflows/codeql-analysis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b728a4c2400..3bbff1988d1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -20,6 +20,7 @@ permissions: jobs: analyze: name: Analyze + if: github.repository == 'aws-powertools/powertools-lambda-python' runs-on: ubuntu-latest permissions: security-events: write From a26eacfcd111b16ec19c2c9eb98e4ad8f2ea57bc Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Fri, 7 Jul 2023 14:32:17 +0200 Subject: [PATCH 43/73] docs(batch): fix custom batch processor example (#2714) --- docs/utilities/batch.md | 2 +- examples/batch_processing/src/custom_partial_processor.py | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index b20598106c5..1b9894a0256 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -346,7 +346,7 @@ You can create your own partial batch processor from scratch by inheriting the ` You can then use this class as a context manager, or pass it to `batch_processor` to use as a decorator on your Lambda handler function. -```python hl_lines="9-12 20 35 41 48 59 64 68 76" title="Creating a custom batch processor" +```python hl_lines="9-11 19 33 39 46 57 62 66 74" title="Creating a custom batch processor" --8<-- "examples/batch_processing/src/custom_partial_processor.py" ``` diff --git a/examples/batch_processing/src/custom_partial_processor.py b/examples/batch_processing/src/custom_partial_processor.py index 353f612e7cc..f4aaa5733b5 100644 --- a/examples/batch_processing/src/custom_partial_processor.py +++ b/examples/batch_processing/src/custom_partial_processor.py @@ -7,8 +7,7 @@ from aws_lambda_powertools import Logger from aws_lambda_powertools.utilities.batch import ( - BasePartialBatchProcessor, - EventType, + BasePartialProcessor, process_partial_response, ) @@ -17,7 +16,7 @@ logger = Logger() -class MyPartialProcessor(BasePartialBatchProcessor): +class MyPartialProcessor(BasePartialProcessor): """ Process a record and stores successful results at a Amazon DynamoDB Table @@ -29,8 +28,7 @@ class MyPartialProcessor(BasePartialBatchProcessor): def __init__(self, table_name: str): self.table_name = table_name - - super().__init__(event_type=EventType.SQS) + super().__init__() def _prepare(self): # It's called once, *before* processing From f13a4c352d064f4cb6fcbe245e666534412dccad Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Fri, 7 Jul 2023 14:32:44 +0200 Subject: [PATCH 44/73] chore(governance): update active maintainers list (#2715) --- MAINTAINERS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 3a008e9509a..bc75596003b 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -51,8 +51,6 @@ This is document explains who the maintainers are (see below), what they do in t | Maintainer | GitHub ID | Affiliation | | ----------------- | ------------------------------------------------------- | ----------- | | Heitor Lessa | [heitorlessa](https://github.com/heitorlessa) | Amazon | -| Alexander Melnyk | [am29d](https://github.com/am29d) | Amazon | -| Michal Ploski | [mploski](https://github.com/mploski) | Amazon | | Simon Thulbourn | [sthulb](https://github.com/sthulb) | Amazon | | Ruben Fonseca | [rubenfonseca](https://github.com/rubenfonseca) | Amazon | | Leandro Damascena | [leandrodamascena](https://github.com/leandrodamascena) | Amazon | @@ -65,6 +63,8 @@ Previous active maintainers who contributed to this project. | ----------------- | ----------------------------------------------- | ----------- | | Tom McCarthy | [cakepietoast](https://github.com/cakepietoast) | MongoDB | | Nicolas Moutschen | [nmoutschen](https://github.com/nmoutschen) | Apollo | +| Alexander Melnyk | [am29d](https://github.com/am29d) | Amazon | +| Michal Ploski | [mploski](https://github.com/mploski) | Amazon | ## Labels From cc9de078a2bb726fc3ca2e3fb486316d4faa6aaa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 22:28:14 +0200 Subject: [PATCH 45/73] chore(deps): bump docker/setup-buildx-action from 2.8.0 to 2.9.0 (#2718) --- .github/workflows/publish_v2_layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index ba3e99a81f5..0a139da79be 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -93,7 +93,7 @@ jobs: # NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM) - name: Set up Docker Buildx id: builder - uses: docker/setup-buildx-action@16c0bc4a6e6ada2cfd8afd41d22d95379cf7c32a # v2.8.0 + uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 with: install: true driver: docker From 1bfcc7e5cfd2cccff689a4a54fb369a9ed25a187 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 23:50:14 +0100 Subject: [PATCH 46/73] chore(deps-dev): bump mypy-boto3-appconfig from 1.27.0 to 1.28.0 (#2722) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index d4d09ef1c24..8e4e4ff29bb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1428,13 +1428,13 @@ reports = ["lxml"] [[package]] name = "mypy-boto3-appconfig" -version = "1.27.0" -description = "Type annotations for boto3.AppConfig 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.AppConfig 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-appconfig-1.27.0.tar.gz", hash = "sha256:223cda564d54cf18f57b43b7438535c71edc610a5b260ed66af207c768ca115b"}, - {file = "mypy_boto3_appconfig-1.27.0-py3-none-any.whl", hash = "sha256:8e7a84286489b28ea5ffa7553573a15b74d911f9f166d6b4098aeae61f67347a"}, + {file = "mypy-boto3-appconfig-1.28.0.tar.gz", hash = "sha256:753044339ce1da00e0b60f387ed957013712ab69ca51a9b56859a4ae502c806a"}, + {file = "mypy_boto3_appconfig-1.28.0-py3-none-any.whl", hash = "sha256:5708545675610ceb686339e90f4d6f8276f9e2ad2f15db2833ebc593185708f5"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "b4d202782b00785f2337b6950d37f1167e8e913e2c40fc95ec24dc8f9eb9d98e" +content-hash = "00e3603fbe08f17b568520155d100d9b66511e22d70ec83c89febabdf7cc41ed" diff --git a/pyproject.toml b/pyproject.toml index 71ac772d4d5..b642b7dbc70 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ aws-cdk-lib = "^2.75.0" "aws-cdk.aws-apigatewayv2-authorizers-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^4.0.0" python-snappy = "^0.6.1" -mypy-boto3-appconfig = "^1.26.71" +mypy-boto3-appconfig = "^1.28.0" mypy-boto3-cloudformation = "^1.28.0" mypy-boto3-cloudwatch = "^1.28.0" mypy-boto3-dynamodb = "^1.26.164" From bc87ff59d23ce3250ecf1fefe8f0a1d21d45d688 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 23:57:35 +0100 Subject: [PATCH 47/73] chore(deps-dev): bump mypy-boto3-s3 from 1.27.0 to 1.28.0 (#2721) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8e4e4ff29bb..88f65eaf254 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1526,13 +1526,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-s3" -version = "1.27.0" -description = "Type annotations for boto3.S3 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.S3 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-s3-1.27.0.tar.gz", hash = "sha256:12c3c9d0e818c2de88f879cdad5f68fb6a7bfbc8cf01c85ae354a9f6b6c38558"}, - {file = "mypy_boto3_s3-1.27.0-py3-none-any.whl", hash = "sha256:0edcbebb22c564721d9ddc3db19537672382d4e9f05d132223be92eabea4f9bc"}, + {file = "mypy-boto3-s3-1.28.0.tar.gz", hash = "sha256:27867ca325a845700a008f3fca995006b32f2e0d18afe676352b49453f477d69"}, + {file = "mypy_boto3_s3-1.28.0-py3-none-any.whl", hash = "sha256:789a32560ec1882e3a2c5bbb7aa97952b05e54507e2174eab6535ceaffb04cee"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "00e3603fbe08f17b568520155d100d9b66511e22d70ec83c89febabdf7cc41ed" +content-hash = "ed7c056b89a5908c9e265dfeb522ff2de8d0f1c6d874be0ff645c720fe0e311b" diff --git a/pyproject.toml b/pyproject.toml index b642b7dbc70..2dfe71d2a09 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,7 @@ mypy-boto3-lambda = "^1.28.0" mypy-boto3-logs = "^1.26.149" mypy-boto3-secretsmanager = "^1.26.135" mypy-boto3-ssm = "^1.26.162" -mypy-boto3-s3 = "^1.26.163" +mypy-boto3-s3 = "^1.28.0" mypy-boto3-xray = "^1.26.122" types-requests = "^2.31.0" typing-extensions = "^4.6.2" From 31cb71868847c015e0a52b48a1333d1715b4820a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Jul 2023 00:04:16 +0100 Subject: [PATCH 48/73] chore(deps-dev): bump mypy-boto3-logs from 1.27.0 to 1.28.1 (#2723) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 88f65eaf254..d87615ea2e5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1512,13 +1512,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-logs" -version = "1.27.0" -description = "Type annotations for boto3.CloudWatchLogs 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.1" +description = "Type annotations for boto3.CloudWatchLogs 1.28.1 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-logs-1.27.0.tar.gz", hash = "sha256:f7c527864a2d21c037f174b7a6d4099d593b23c072d14e8e515f29207e0f7226"}, - {file = "mypy_boto3_logs-1.27.0-py3-none-any.whl", hash = "sha256:acc9ee5407c985c023be151957ceadb34e3ad964b310c32b599d707cc22e0b23"}, + {file = "mypy-boto3-logs-1.28.1.tar.gz", hash = "sha256:e0278a977d68c15120c0f2f4a85b46d0ca3e17c676c7d218dbbb3cfa1b4c8ef1"}, + {file = "mypy_boto3_logs-1.28.1-py3-none-any.whl", hash = "sha256:0ab3b7b39f1c3b0d530096fe2bfb9df09b989b0ea718e5ecbf823c32b016e319"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "ed7c056b89a5908c9e265dfeb522ff2de8d0f1c6d874be0ff645c720fe0e311b" +content-hash = "f0710af5948c534f1d3c0e3ed36d8d579276c48599036483311241faacab6183" diff --git a/pyproject.toml b/pyproject.toml index 2dfe71d2a09..a9cefcfe4c1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,7 @@ mypy-boto3-cloudformation = "^1.28.0" mypy-boto3-cloudwatch = "^1.28.0" mypy-boto3-dynamodb = "^1.26.164" mypy-boto3-lambda = "^1.28.0" -mypy-boto3-logs = "^1.26.149" +mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.26.135" mypy-boto3-ssm = "^1.26.162" mypy-boto3-s3 = "^1.28.0" From 977e8497c062b29f55a8c526b9fe3514c675105b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Jul 2023 00:09:57 +0100 Subject: [PATCH 49/73] chore(deps-dev): bump mypy-boto3-ssm from 1.27.0 to 1.28.0 (#2724) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index d87615ea2e5..95c5a1859ef 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1554,13 +1554,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-ssm" -version = "1.27.0" -description = "Type annotations for boto3.SSM 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.SSM 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-ssm-1.27.0.tar.gz", hash = "sha256:1803f1aa582a2f7f2c6a8aa17c1f5f5eccd9f66ae8f5d1f8b2ae26dc237b4a94"}, - {file = "mypy_boto3_ssm-1.27.0-py3-none-any.whl", hash = "sha256:07e0a2ab5957439e527c8381a54d9479d07b9e95b96a7cfcfcefddf3c4a78e29"}, + {file = "mypy-boto3-ssm-1.28.0.tar.gz", hash = "sha256:15482d2bff7995230549d145547f0ea92d01b68716aa25297e2a2da015922309"}, + {file = "mypy_boto3_ssm-1.28.0-py3-none-any.whl", hash = "sha256:e6ac60818c807baeeb0ef6714832c23904f2ed463fc40133059e2f63abd432fa"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "f0710af5948c534f1d3c0e3ed36d8d579276c48599036483311241faacab6183" +content-hash = "5d21d1d4738cb9dbebece1be5c8520d9ce11544941ff72c6818bc35f4c9cf6a2" diff --git a/pyproject.toml b/pyproject.toml index a9cefcfe4c1..bbe36136068 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,7 +63,7 @@ mypy-boto3-dynamodb = "^1.26.164" mypy-boto3-lambda = "^1.28.0" mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.26.135" -mypy-boto3-ssm = "^1.26.162" +mypy-boto3-ssm = "^1.28.0" mypy-boto3-s3 = "^1.28.0" mypy-boto3-xray = "^1.26.122" types-requests = "^2.31.0" From 5ec1fa81454cf137855cf54d709cbe4b323fcf11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Jul 2023 00:17:46 +0100 Subject: [PATCH 50/73] chore(deps-dev): bump mypy-boto3-xray from 1.27.0 to 1.28.0 (#2720) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 95c5a1859ef..450d47e09ee 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1568,13 +1568,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-xray" -version = "1.27.0" -description = "Type annotations for boto3.XRay 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.XRay 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-xray-1.27.0.tar.gz", hash = "sha256:8f4b75eeb77f17e3807d1aab21284748f1651dd6a15cc700279d91897bacbc49"}, - {file = "mypy_boto3_xray-1.27.0-py3-none-any.whl", hash = "sha256:4e7092b6dc070561360087471c34497ea2cc9c9bd9ae4b46896c690388ae9902"}, + {file = "mypy-boto3-xray-1.28.0.tar.gz", hash = "sha256:8ce07598f7eeabe66e8dc8cb7e906efb96198b9102f58e9315e6daf166abf3e7"}, + {file = "mypy_boto3_xray-1.28.0-py3-none-any.whl", hash = "sha256:64cd601a829c274665b977853f85b27464986e9eec1ebc03f5bc4530a400b2f6"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "5d21d1d4738cb9dbebece1be5c8520d9ce11544941ff72c6818bc35f4c9cf6a2" +content-hash = "c35983a8d0ca6ec0abd2b8eac6e418607feb83ebea30c6bb933991b593edc4e0" diff --git a/pyproject.toml b/pyproject.toml index bbe36136068..cc8eec3cf87 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,7 +65,7 @@ mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.26.135" mypy-boto3-ssm = "^1.28.0" mypy-boto3-s3 = "^1.28.0" -mypy-boto3-xray = "^1.26.122" +mypy-boto3-xray = "^1.28.0" types-requests = "^2.31.0" typing-extensions = "^4.6.2" mkdocs-material = "^9.1.17" From 288ce7e76cf56536576ca37616291406e03feb7b Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Mon, 10 Jul 2023 21:59:22 +0200 Subject: [PATCH 51/73] fix(logger): ensure logs stream to stdout by default, not stderr (#2736) --- aws_lambda_powertools/logging/logger.py | 3 ++- tests/functional/test_logger.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/logging/logger.py b/aws_lambda_powertools/logging/logger.py index 31405ff4e26..6ea085d5808 100644 --- a/aws_lambda_powertools/logging/logger.py +++ b/aws_lambda_powertools/logging/logger.py @@ -232,7 +232,8 @@ def __init__( ) self.child = child self.logger_formatter = logger_formatter - self.logger_handler = logger_handler or logging.StreamHandler(stream) + self._stream = stream or sys.stdout + self.logger_handler = logger_handler or logging.StreamHandler(self._stream) self.log_uncaught_exceptions = log_uncaught_exceptions self._is_deduplication_disabled = resolve_truthy_env_var_choice( diff --git a/tests/functional/test_logger.py b/tests/functional/test_logger.py index feb034b5e46..de589b9accc 100644 --- a/tests/functional/test_logger.py +++ b/tests/functional/test_logger.py @@ -945,3 +945,17 @@ def test_logger_log_uncaught_exceptions(service_name, stdout): # THEN it should contain our custom exception hook with a copy of our logger assert isinstance(exception_hook, functools.partial) assert exception_hook.keywords.get("logger") == logger + + +def test_stream_defaults_to_stdout(service_name, capsys): + # GIVEN Logger is initialized without any explicit stream + logger = Logger(service=service_name) + msg = "testing stdout" + + # WHEN logging statements are issued + logger.info(msg) + + # THEN we should default to standard output, not standard error. + # NOTE: we can't assert on capsys.readouterr().err due to a known bug: https://github.com/pytest-dev/pytest/issues/5997 + log = json.loads(capsys.readouterr().out.strip()) + assert log["message"] == msg From 07803d125079b37c6ae43a6f6002ac314eae7ffb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 22:42:27 +0100 Subject: [PATCH 52/73] chore(deps): bump zgosalvez/github-actions-ensure-sha-pinned-actions from 2.1.3 to 2.1.4 (#2738) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/secure_workflows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml index bf0823b091b..1b29de4bc0c 100644 --- a/.github/workflows/secure_workflows.yml +++ b/.github/workflows/secure_workflows.yml @@ -32,4 +32,4 @@ jobs: - name: Checkout code uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Ensure 3rd party workflows have SHA pinned - uses: zgosalvez/github-actions-ensure-sha-pinned-actions@555a30da2656b4a7cf47b107800bef097723363e # v2.1.3 + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@f32435541e24cd6a4700a7f52bb2ec59e80603b1 # v2.1.4 From 31a7b0e3db128e3eb6e9f269a5900fd962ee4474 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 22:43:20 +0100 Subject: [PATCH 53/73] chore(deps-dev): bump mypy-boto3-dynamodb from 1.27.0 to 1.28.0 (#2740) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 450d47e09ee..d0f5a47e502 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1484,13 +1484,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-dynamodb" -version = "1.27.0" -description = "Type annotations for boto3.DynamoDB 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.DynamoDB 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-dynamodb-1.27.0.tar.gz", hash = "sha256:8c6642e56a324c5bdf161e19277dd08475d87af8fadfe0a6f86824bbbebfbd99"}, - {file = "mypy_boto3_dynamodb-1.27.0-py3-none-any.whl", hash = "sha256:56bb013af0086ae891ef39d332dab0c5f2a4ea39afb16b567eb0de1f16e8edcb"}, + {file = "mypy-boto3-dynamodb-1.28.0.tar.gz", hash = "sha256:d12ed66edd7ded7089297b533d77e8b8ed8844da4e097cd912b61a08bfe4948b"}, + {file = "mypy_boto3_dynamodb-1.28.0-py3-none-any.whl", hash = "sha256:622f3d14dc1835a17ca511672d2f8fd08c03c4930f2845d06d1632b9f0c92aaf"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "c35983a8d0ca6ec0abd2b8eac6e418607feb83ebea30c6bb933991b593edc4e0" +content-hash = "3ac06f518d08b4b53145891c321c9da53473e80da22130663d0bf288bf5b8659" diff --git a/pyproject.toml b/pyproject.toml index cc8eec3cf87..3a6f3e67e63 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,7 +59,7 @@ python-snappy = "^0.6.1" mypy-boto3-appconfig = "^1.28.0" mypy-boto3-cloudformation = "^1.28.0" mypy-boto3-cloudwatch = "^1.28.0" -mypy-boto3-dynamodb = "^1.26.164" +mypy-boto3-dynamodb = "^1.28.0" mypy-boto3-lambda = "^1.28.0" mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.26.135" From 850800aa065a8e9bf695405cbe7ca9d322e12fe6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 22:49:26 +0100 Subject: [PATCH 54/73] chore(deps-dev): bump mypy-boto3-secretsmanager from 1.27.0 to 1.28.0 (#2739) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index d0f5a47e502..d0d4c19a11f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1540,13 +1540,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-secretsmanager" -version = "1.27.0" -description = "Type annotations for boto3.SecretsManager 1.27.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.0" +description = "Type annotations for boto3.SecretsManager 1.28.0 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-secretsmanager-1.27.0.tar.gz", hash = "sha256:e03060559b4ab234ea08b45f5271a9e1f256061ffda7a4f912b463d7fcd3a219"}, - {file = "mypy_boto3_secretsmanager-1.27.0-py3-none-any.whl", hash = "sha256:a1fd92a98f7dd421808f708430a7b3fd2e14ca564f52fe53499f57e54868c4f5"}, + {file = "mypy-boto3-secretsmanager-1.28.0.tar.gz", hash = "sha256:ee2341a09370209b9ed5d96488baf831b1487c931f420fa5f9cf4a18b2e46311"}, + {file = "mypy_boto3_secretsmanager-1.28.0-py3-none-any.whl", hash = "sha256:160a5bf3cf9b45201f17920472403ed98cdc65256914b167f0539f76e509dbdf"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "3ac06f518d08b4b53145891c321c9da53473e80da22130663d0bf288bf5b8659" +content-hash = "85c26ffbf49fbfeaa6d43f9dd523f379c8b3ffd99f60070f7ddb5ead0b525749" diff --git a/pyproject.toml b/pyproject.toml index 3a6f3e67e63..da4dd62a833 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,7 @@ mypy-boto3-cloudwatch = "^1.28.0" mypy-boto3-dynamodb = "^1.28.0" mypy-boto3-lambda = "^1.28.0" mypy-boto3-logs = "^1.28.1" -mypy-boto3-secretsmanager = "^1.26.135" +mypy-boto3-secretsmanager = "^1.28.0" mypy-boto3-ssm = "^1.28.0" mypy-boto3-s3 = "^1.28.0" mypy-boto3-xray = "^1.28.0" From 2c4420731f2e36f4e0ef3eb11c4a5e13296070c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 22:49:48 +0100 Subject: [PATCH 55/73] chore(deps-dev): bump sentry-sdk from 1.27.1 to 1.28.0 (#2741) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index d0d4c19a11f..25a34953a45 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2330,13 +2330,13 @@ pbr = "*" [[package]] name = "sentry-sdk" -version = "1.27.1" +version = "1.28.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = "*" files = [ - {file = "sentry-sdk-1.27.1.tar.gz", hash = "sha256:53f36293a0da271a22f476259d2fda76c0b8a1cb96b16d6e6e6aca490d7f3451"}, - {file = "sentry_sdk-1.27.1-py2.py3-none-any.whl", hash = "sha256:24308bd05a1f7d65e40acc68a768b4e5c35462039bfd6ae2ca116b92a7b53c78"}, + {file = "sentry-sdk-1.28.0.tar.gz", hash = "sha256:2281ba98011cfa9bc9bb15c1074b6dd9f7fdfce94033cd25b50f18f078ffed4c"}, + {file = "sentry_sdk-1.28.0-py2.py3-none-any.whl", hash = "sha256:b8b363aaa3f3d6a3acc1aa571efa4db29fb440339fed03560bb1276b8d2c2509"}, ] [package.dependencies] From 62766e75016653d4973336cd177c6e3ede25a037 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 12 Jul 2023 09:47:48 +0100 Subject: [PATCH 56/73] feat(metrics): support to set default dimension in EphemeralMetrics (#2748) metrics: add default dimension into EphemeralMetrics --- aws_lambda_powertools/metrics/metrics.py | 41 ++++++++++++++++++++++ aws_lambda_powertools/shared/user_agent.py | 6 ++-- docs/core/metrics.md | 3 +- tests/functional/test_metrics.py | 40 +++++++++++++++++++++ 4 files changed, 85 insertions(+), 5 deletions(-) diff --git a/aws_lambda_powertools/metrics/metrics.py b/aws_lambda_powertools/metrics/metrics.py index 4d6a7d3140d..487f2ab9b2f 100644 --- a/aws_lambda_powertools/metrics/metrics.py +++ b/aws_lambda_powertools/metrics/metrics.py @@ -128,5 +128,46 @@ class EphemeralMetrics(MetricManager): - Create the same metrics with different dimensions more than once """ + _dimensions: Dict[str, str] = {} + _default_dimensions: Dict[str, Any] = {} + def __init__(self, service: Optional[str] = None, namespace: Optional[str] = None): + self.default_dimensions = self._default_dimensions + self.dimension_set = self._dimensions + + self.dimension_set.update(**self._default_dimensions) super().__init__(namespace=namespace, service=service) + + def set_default_dimensions(self, **dimensions) -> None: + """Persist dimensions across Lambda invocations + + Parameters + ---------- + dimensions : Dict[str, Any], optional + metric dimensions as key=value + + Example + ------- + **Sets some default dimensions that will always be present across metrics and invocations** + + from aws_lambda_powertools import Metrics + + metrics = Metrics(namespace="ServerlessAirline", service="payment") + metrics.set_default_dimensions(environment="demo", another="one") + + @metrics.log_metrics() + def lambda_handler(): + return True + """ + for name, value in dimensions.items(): + self.add_dimension(name, value) + + self.default_dimensions.update(**dimensions) + + def clear_default_dimensions(self) -> None: + self.default_dimensions.clear() + + def clear_metrics(self) -> None: + super().clear_metrics() + # re-add default dimensions + self.set_default_dimensions(**self.default_dimensions) diff --git a/aws_lambda_powertools/shared/user_agent.py b/aws_lambda_powertools/shared/user_agent.py index 098be7a503a..c682c24b34f 100644 --- a/aws_lambda_powertools/shared/user_agent.py +++ b/aws_lambda_powertools/shared/user_agent.py @@ -112,7 +112,7 @@ def register_feature_to_session(session, feature): def register_feature_to_botocore_session(botocore_session, feature): """ Register the given feature string to the event system of the provided botocore session - + Please notice this function is for patching botocore session and is different from previous one which is for patching boto3 session @@ -127,7 +127,7 @@ def register_feature_to_botocore_session(botocore_session, feature): ------ AttributeError If the provided session does not have an event system. - + Examples -------- **register data-masking user-agent to botocore session** @@ -139,7 +139,7 @@ def register_feature_to_botocore_session(botocore_session, feature): >>> session = botocore.session.Session() >>> register_feature_to_botocore_session(botocore_session=session, feature="data-masking") >>> key_provider = StrictAwsKmsMasterKeyProvider(key_ids=self.keys, botocore_session=session) - + """ try: botocore_session.register(TARGET_SDK_EVENT, _create_feature_function(feature)) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index bb93d99eb4f..052406300dc 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -274,12 +274,11 @@ You can use `EphemeralMetrics` class when looking to isolate multiple instances **Differences between `EphemeralMetrics` and `Metrics`** -`EphemeralMetrics` has only two differences while keeping nearly the exact same set of features: +`EphemeralMetrics` has only one difference while keeping nearly the exact same set of features: | Feature | Metrics | EphemeralMetrics | | ----------------------------------------------------------------------------------------------------------- | ------- | ---------------- | | **Share data across instances** (metrics, dimensions, metadata, etc.) | Yes | - | -| **[Default dimensions](#adding-default-dimensions) that persists across Lambda invocations** (metric flush) | Yes | - | !!! question "Why not changing the default `Metrics` behaviour to not share data across instances?" diff --git a/tests/functional/test_metrics.py b/tests/functional/test_metrics.py index d7063f88744..5a6222f248d 100644 --- a/tests/functional/test_metrics.py +++ b/tests/functional/test_metrics.py @@ -1115,6 +1115,46 @@ def test_metrics_reuse_metadata_set(metric, dimension, namespace): assert my_metrics_2.metadata_set == my_metrics.metadata_set +def test_log_ephemeral_metrics_with_default_dimensions(capsys, metrics, dimensions, namespace): + # GIVEN Metrics is initialized + my_metrics = EphemeralMetrics(namespace=namespace) + default_dimensions = {"environment": "test", "log_group": "/lambda/test"} + + # WHEN we utilize log_metrics with default dimensions to serialize + # and flush metrics and clear all metrics and dimensions from memory + # at the end of a function execution + @my_metrics.log_metrics(default_dimensions=default_dimensions) + def lambda_handler(evt, ctx): + for metric in metrics: + my_metrics.add_metric(**metric) + + lambda_handler({}, {}) + first_invocation = capture_metrics_output(capsys) + + lambda_handler({}, {}) + second_invocation = capture_metrics_output(capsys) + + # THEN we should have default dimensions in both outputs + assert "environment" in first_invocation + assert "environment" in second_invocation + + +def test_ephemeral_metrics_isolated_data_set_with_default_dimension(metric, dimension, namespace, capsys): + # GIVEN two EphemeralMetrics instances are initialized + # One with default dimension and another without + my_metrics = EphemeralMetrics(namespace=namespace) + my_metrics.set_default_dimensions(dev="powertools") + isolated_metrics = EphemeralMetrics(namespace=namespace) + + # WHEN metrics added to the both instances + my_metrics.add_metric(**metric) + isolated_metrics.add_metric(**metric) + + # THEN the second instance should not have dimensions + assert my_metrics.metric_set == isolated_metrics.metric_set + assert my_metrics.dimension_set != isolated_metrics.dimension_set + + def test_ephemeral_metrics_isolates_data_set(metric, dimension, namespace, metadata): # GIVEN two EphemeralMetrics instances are initialized my_metrics = EphemeralMetrics(namespace=namespace) From e2372f19b8daddf5ccb55bed890ea2f4bebd9b2b Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Wed, 12 Jul 2023 14:25:48 +0200 Subject: [PATCH 57/73] chore(ci): introduce provenance and attestation in release (#2746) Co-authored-by: Leandro Damascena --- .github/actions/seal-restore/action.yml | 82 ++++++++ .github/actions/seal/action.yml | 93 +++++++++ .../upload-release-provenance/action.yml | 67 ++++++ .../verify-provenance/verify_provenance.sh | 111 ++++++++++ .github/workflows/publish_v2_layer.yml | 52 ++++- .github/workflows/release.yml | 193 +++++++++--------- .../reusable_deploy_v2_layer_stack.yml | 22 +- .github/workflows/reusable_deploy_v2_sar.yml | 28 ++- .github/workflows/secure_workflows.yml | 2 + MAINTAINERS.md | 16 +- SECURITY.md | 5 +- .../media/continuous_deployment_practices.png | Bin 0 -> 400492 bytes .../continuous_integration_practices.png | Bin 0 -> 405660 bytes docs/security.md | 110 ++++++++++ mkdocs.yml | 1 + 15 files changed, 670 insertions(+), 112 deletions(-) create mode 100644 .github/actions/seal-restore/action.yml create mode 100644 .github/actions/seal/action.yml create mode 100644 .github/actions/upload-release-provenance/action.yml create mode 100755 .github/actions/verify-provenance/verify_provenance.sh create mode 100644 docs/media/continuous_deployment_practices.png create mode 100644 docs/media/continuous_integration_practices.png create mode 100644 docs/security.md diff --git a/.github/actions/seal-restore/action.yml b/.github/actions/seal-restore/action.yml new file mode 100644 index 00000000000..beadad90cbc --- /dev/null +++ b/.github/actions/seal-restore/action.yml @@ -0,0 +1,82 @@ +name: "Restore sealed source code" +description: "Restore sealed source code and confirm integrity hash" + +# PROCESS +# +# 1. Exports artifact name using Prefix + GitHub Run ID (unique for each release trigger) +# 2. Compress entire source code as tarball OR given files +# 3. Create and export integrity hash for tarball +# 4. Upload artifact +# 5. Remove archive + +# USAGE +# +# - name: Seal and upload +# id: seal_source_code +# uses: ./.github/actions/seal +# with: +# artifact_name_prefix: "source" +# +# - name: Restore sealed source code +# uses: ./.github/actions/seal-restore +# with: +# integrity_hash: ${{ needs.seal_source_code.outputs.integrity_hash }} +# artifact_name: ${{ needs.seal_source_code.outputs.artifact_name }} + +# NOTES +# +# To be used together with .github/actions/seal + +inputs: + integrity_hash: + description: "Integrity hash to verify" + required: true + artifact_name: + description: "Sealed artifact name to restore" + required: true + +runs: + using: "composite" + steps: + - id: adjust-path + run: echo "${{ github.action_path }}" >> $GITHUB_PATH + shell: bash + + - name: Download artifacts + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: ${{ inputs.artifact_name }} + path: . + + - id: integrity_hash + name: Create integrity hash for downloaded artifact + run: | + HASH=$(sha256sum "${ARTIFACT_NAME}.tar" | awk '{print $1}') + + echo "current_hash=${HASH}" >> "$GITHUB_OUTPUT" + env: + ARTIFACT_NAME: ${{ inputs.artifact_name }} + shell: bash + + - id: verify_hash + name: Verify sealed artifact integrity hash + run: test "${CURRENT_HASH}" = "${PROVIDED_HASH}" || exit 1 + env: + ARTIFACT_NAME: ${{ inputs.artifact_name }} + PROVIDED_HASH: ${{ inputs.integrity_hash }} + CURRENT_HASH: ${{ steps.integrity_hash.outputs.current_hash }} + shell: bash + + # Restore and overwrite tarball in current directory + - id: overwrite + name: Extract tarball + run: tar -xvf "${ARTIFACT_NAME}".tar + env: + ARTIFACT_NAME: ${{ inputs.artifact_name }} + shell: bash + + - name: Remove archive + run: rm -f "${ARTIFACT_NAME}.tar" + env: + ARTIFACT_NAME: ${{ inputs.artifact_name }} + shell: bash diff --git a/.github/actions/seal/action.yml b/.github/actions/seal/action.yml new file mode 100644 index 00000000000..3438056c872 --- /dev/null +++ b/.github/actions/seal/action.yml @@ -0,0 +1,93 @@ +name: "Seal and hash source code" +description: "Seal and export source code as a tarball artifact along with its integrity hash" + +# PROCESS +# +# 1. Exports artifact name using Prefix + GitHub Run ID (unique for each release trigger) +# 2. Compress entire source code as tarball OR given files +# 3. Create and export integrity hash for tarball +# 4. Upload artifact +# 5. Remove archive + +# USAGE +# +# - name: Seal and upload +# id: seal_source_code +# uses: ./.github/actions/seal +# with: +# artifact_name_prefix: "source" + +inputs: + files: + description: "Files to seal separated by space" + required: false + artifact_name_prefix: + description: "Prefix to use when exporting artifact" + required: true + +outputs: + integrity_hash: + description: "Source code integrity hash" + value: ${{ steps.integrity_hash.outputs.integrity_hash }} + artifact_name: + description: "Artifact name containTemporary branch created with staged changed" + value: ${{ steps.export_artifact_name.outputs.artifact_name }} + +runs: + using: "composite" + steps: + - id: adjust-path + run: echo "${{ github.action_path }}" >> $GITHUB_PATH + shell: bash + + - id: export_artifact_name + name: Export final artifact name + run: echo "artifact_name=${ARTIFACT_PREFIX}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" + env: + GITHUB_RUN_ID: ${{ github.run_id }} + ARTIFACT_PREFIX: ${{ inputs.artifact_name_prefix }} + shell: bash + + # By default, create a tarball of the current directory minus .git + # otherwise it breaks GH Actions when restoring it + - id: compress_all + if: ${{ !inputs.files }} + name: Create tarball for entire source + run: tar --exclude-vcs -cvf "${ARTIFACT_NAME}".tar * + env: + ARTIFACT_NAME: ${{ steps.export_artifact_name.outputs.artifact_name }} + shell: bash + + # If a list of files are given, then create a tarball for those only + - id: compress_selected_files + if: ${{ inputs.files }} + name: Create tarball for selected files + run: tar --exclude-vcs -cvf "${ARTIFACT_NAME}".tar "${FILES}" + env: + FILES: ${{ inputs.files }} + ARTIFACT_NAME: ${{ steps.export_artifact_name.outputs.artifact_name }} + shell: bash + + - id: integrity_hash + name: Create and export integrity hash for tarball + run: | + HASH=$(sha256sum "${ARTIFACT_NAME}.tar" | awk '{print $1}') + + echo "integrity_hash=${HASH}" >> "$GITHUB_OUTPUT" + env: + ARTIFACT_NAME: ${{ steps.export_artifact_name.outputs.artifact_name }} + shell: bash + + - name: Upload artifacts + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + if-no-files-found: error + name: ${{ steps.export_artifact_name.outputs.artifact_name }} + path: ${{ steps.export_artifact_name.outputs.artifact_name }}.tar + retention-days: 1 + + - name: Remove archive + run: rm -f "${ARTEFACT_NAME}.tar" + env: + ARTIFACT_NAME: ${{ steps.export_artifact_name.outputs.artifact_name }} + shell: bash diff --git a/.github/actions/upload-release-provenance/action.yml b/.github/actions/upload-release-provenance/action.yml new file mode 100644 index 00000000000..e4c1e52c0d2 --- /dev/null +++ b/.github/actions/upload-release-provenance/action.yml @@ -0,0 +1,67 @@ +name: "Upload provenance attestation to release" +description: "Download and upload newly generated provenance attestation to latest release." + +# PROCESS +# +# 1. Downloads provenance attestation artifact generated earlier in the release pipeline +# 2. Updates latest GitHub draft release pointing to newly git release tag +# 3. Uploads provenance attestation file to latest GitHub draft release + +# USAGE +# +# - name: Upload provenance +# id: upload-provenance +# uses: ./.github/actions/upload-release-provenance +# with: +# release_version: ${{ needs.seal.outputs.RELEASE_VERSION }} +# provenance_name: ${{needs.provenance.outputs.provenance-name}} +# github_token: ${{ secrets.GITHUB_TOKEN }} + +# NOTES +# +# There are no outputs. +# + +inputs: + provenance_name: + description: "Provenance artifact name to download" + required: true + release_version: + description: "Release version (e.g., 2.20.0)" + required: true + github_token: + description: "GitHub token for GitHub CLI" + required: true + +runs: + using: "composite" + steps: + - id: adjust-path + run: echo "${{ github.action_path }}" >> $GITHUB_PATH + shell: bash + + - id: download-provenance + name: Download newly generated provenance + uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # v3.0.1 + with: + name: ${{ inputs.provenance_name }} + + - id: sync-release-tag + name: Update draft release tag to release commit tag + run: | + CURRENT_DRAFT_RELEASE=$(gh release list | awk '{ if ($2 == "Draft") print $1}') + gh release edit "${CURRENT_DRAFT_RELEASE}" --tag v"${RELEASE_VERSION}" + env: + RELEASE_VERSION: ${{ inputs.release_version }} + GH_TOKEN: ${{ inputs.github_token }} + shell: bash + + - id: upload-provenance + name: Upload provenance to release tag + # clobber flag means overwrite release asset if available (eventual consistency, retried failed steps) + run: gh release upload --clobber v"${RELEASE_VERSION}" "${PROVENANCE_FILE}" + env: + RELEASE_VERSION: ${{ inputs.release_version }} + PROVENANCE_FILE: ${{ inputs.provenance_name }} + GH_TOKEN: ${{ inputs.github_token }} + shell: bash diff --git a/.github/actions/verify-provenance/verify_provenance.sh b/.github/actions/verify-provenance/verify_provenance.sh new file mode 100755 index 00000000000..ca8bf57c6be --- /dev/null +++ b/.github/actions/verify-provenance/verify_provenance.sh @@ -0,0 +1,111 @@ +#!/bin/bash +set -uo pipefail # prevent accessing unset env vars, prevent masking pipeline errors to the next command + +#docs +#title :verify_provenance.sh +#description :This script will download and verify a signed Powertools for AWS Lambda (Python) release build with SLSA Verifier +#author :@heitorlessa +#date :July 1st 2023 +#version :0.1 +#usage :bash verify_provenance.sh {release version} +#notes :Meant to use in GitHub Actions or locally (MacOS, Linux, WSL). +#os_version :Ubuntu 22.04.2 LTS +#============================================================================== + +# Check if RELEASE_VERSION is provided as a command line argument +if [[ $# -eq 1 ]]; then + export readonly RELEASE_VERSION="$1" +else + echo "ERROR: Please provider Powertools release version as a command line argument." + echo "Example: bash verify_provenance.sh 2.20.0" + exit 1 +fi + +export readonly ARCHITECTURE=$(uname -m | sed 's/x86_64/amd64/g') # arm64, x86_64 ->amd64 +export readonly OS_NAME=$(uname -s | tr '[:upper:]' '[:lower:]') # darwin, linux +export readonly SLSA_VERIFIER_VERSION="2.3.0" +export readonly SLSA_VERIFIER_CHECKSUM_FILE="SHA256SUM.md" +export readonly SLSA_VERIFIER_BINARY="./slsa-verifier-${OS_NAME}-${ARCHITECTURE}" + +export readonly RELEASE_BINARY="aws_lambda_powertools-${RELEASE_VERSION}-py3-none-any.whl" +export readonly ORG="aws-powertools" +export readonly REPO="powertools-lambda-python" +export readonly PROVENANCE_FILE="multiple.intoto.jsonl" + +export readonly FILES=("${SLSA_VERIFIER_BINARY}" "${SLSA_VERIFIER_CHECKSUM_FILE}" "${PROVENANCE_FILE}" "${RELEASE_BINARY}") + +function debug() { + TIMESTAMP=$(date -u "+%FT%TZ") # 2023-05-10T07:53:59Z + echo ""${TIMESTAMP}" DEBUG - $1" +} + +function download_slsa_verifier() { + debug "[*] Downloading SLSA Verifier for - Binary: slsa-verifier-${OS_NAME}-${ARCHITECTURE}" + curl --location --silent -O "https://github.com/slsa-framework/slsa-verifier/releases/download/v${SLSA_VERIFIER_VERSION}/slsa-verifier-${OS_NAME}-${ARCHITECTURE}" + + debug "[*] Downloading SLSA Verifier checksums" + curl --location --silent -O "https://raw.githubusercontent.com/slsa-framework/slsa-verifier/f59b55ef2190581d40fc1a5f3b7a51cab2f4a652/${SLSA_VERIFIER_CHECKSUM_FILE}" + + debug "[*] Verifying SLSA Verifier binary integrity" + CURRENT_HASH=$(sha256sum "${SLSA_VERIFIER_BINARY}" | awk '{print $1}') + if [[ $(grep "${CURRENT_HASH}" "${SLSA_VERIFIER_CHECKSUM_FILE}") ]]; then + debug "[*] SLSA Verifier binary integrity confirmed" + chmod +x "${SLSA_VERIFIER_BINARY}" + else + debug "[!] Failed integrity check for SLSA Verifier binary: ${SLSA_VERIFIER_BINARY}" + exit 1 + fi +} + +function download_provenance() { + debug "[*] Downloading attestation for - Release: https://github.com/${ORG}/${REPO}/releases/v${RELEASE_VERSION}" + + curl --location --silent -O "https://github.com/${ORG}/${REPO}/releases/download/v${RELEASE_VERSION}/${PROVENANCE_FILE}" +} + +function download_release_artifact() { + debug "[*] Downloading ${RELEASE_VERSION} release from PyPi" + python -m pip download \ + --only-binary=:all: \ + --no-deps \ + --quiet \ + aws-lambda-powertools=="${RELEASE_VERSION}" +} + +function verify_provenance() { + debug "[*] Verifying attestation with slsa-verifier" + "${SLSA_VERIFIER_BINARY}" verify-artifact \ + --provenance-path "${PROVENANCE_FILE}" \ + --source-uri github.com/${ORG}/${REPO} \ + ${RELEASE_BINARY} +} + +function cleanup() { + debug "[*] Cleaning up previously downloaded files" + rm "${SLSA_VERIFIER_BINARY}" + rm "${SLSA_VERIFIER_CHECKSUM_FILE}" + rm "${PROVENANCE_FILE}" + rm "${RELEASE_BINARY}" + echo "${FILES[@]}" | xargs -n1 echo "Removed file: " +} + +function main() { + download_slsa_verifier + download_provenance + download_release_artifact + verify_provenance + cleanup +} + +main + +# Lessons learned +# +# 1. If source doesn't match provenance +# +# FAILED: SLSA verification failed: source used to generate the binary does not match provenance: expected source 'awslabs/aws-lambda-powertools-python', got 'heitorlessa/aws-lambda-powertools-test' +# +# 2. Avoid building deps during download in Test registry endpoints +# +# FAILED: Could not find a version that satisfies the requirement poetry-core>=1.3.2 (from versions: 1.2.0) +# diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index 0a139da79be..82ff1488f55 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -24,6 +24,8 @@ name: Deploy v2 layer to all regions # with: # latest_published_version: ${{ needs.seal.outputs.RELEASE_VERSION }} # pre_release: ${{ inputs.pre_release }} +# source_code_artifact_name: ${{ needs.seal.outputs.artifact_name }} +# source_code_integrity_hash: ${{ needs.seal.outputs.integrity_hash }} on: @@ -32,6 +34,14 @@ on: latest_published_version: description: "Latest PyPi published version to rebuild latest docs for, e.g. 2.0.0, 2.0.0a1 (pre-release)" required: true + source_code_artifact_name: + description: "Artifact name to restore sealed source code" + type: string + required: true + source_code_integrity_hash: + description: "Sealed source code integrity hash" + type: string + required: true pre_release: description: "Publishes documentation using a pre-release tag (2.0.0a1)." default: false @@ -48,10 +58,22 @@ on: default: false type: boolean required: false + source_code_artifact_name: + description: "Artifact name to restore sealed source code" + type: string + required: true + source_code_integrity_hash: + description: "Sealed source code integrity hash" + type: string + required: true permissions: contents: read + +env: + RELEASE_COMMIT: ${{ github.sha }} + jobs: build-layer: permissions: @@ -68,9 +90,16 @@ jobs: - name: checkout uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 with: - fetch-depth: 0 + ref: ${{ env.RELEASE_COMMIT }} + + - name: Restore sealed source code + uses: ./.github/actions/seal-restore + with: + integrity_hash: ${{ inputs.source_code_integrity_hash }} + artifact_name: ${{ inputs.source_code_artifact_name }} + - name: Install poetry - run: pipx install poetry + run: pipx install git+https://github.com/python-poetry/poetry@68b88e5390720a3dd84f02940ec5200bfce39ac6 # v1.5.0 - name: Setup Node.js uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 with: @@ -128,6 +157,8 @@ jobs: artefact-name: "cdk-layer-artefact" environment: "layer-beta" latest_published_version: ${{ inputs.latest_published_version }} + source_code_artifact_name: ${{ inputs.source_code_artifact_name }} + source_code_integrity_hash: ${{ inputs.source_code_integrity_hash }} prod: needs: beta @@ -144,6 +175,8 @@ jobs: artefact-name: "cdk-layer-artefact" environment: "layer-prod" latest_published_version: ${{ inputs.latest_published_version }} + source_code_artifact_name: ${{ inputs.source_code_artifact_name }} + source_code_integrity_hash: ${{ inputs.source_code_integrity_hash }} sar-beta: needs: beta # canaries run on Layer Beta env @@ -160,6 +193,9 @@ jobs: artefact-name: "cdk-layer-artefact" environment: "layer-beta" package-version: ${{ inputs.latest_published_version }} + source_code_artifact_name: ${{ inputs.source_code_artifact_name }} + source_code_integrity_hash: ${{ inputs.source_code_integrity_hash }} + sar-prod: needs: sar-beta @@ -176,6 +212,9 @@ jobs: artefact-name: "cdk-layer-artefact" environment: "layer-prod" package-version: ${{ inputs.latest_published_version }} + source_code_artifact_name: ${{ inputs.source_code_artifact_name }} + source_code_integrity_hash: ${{ inputs.source_code_integrity_hash }} + # Updating the documentation with the latest Layer ARNs is a two-phase process # @@ -201,7 +240,14 @@ jobs: - name: Checkout repository # reusable workflows start clean, so we need to checkout again uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 with: - fetch-depth: 0 + ref: ${{ env.RELEASE_COMMIT }} + + - name: Restore sealed source code + uses: ./.github/actions/seal-restore + with: + integrity_hash: ${{ inputs.source_code_integrity_hash }} + artifact_name: ${{ inputs.source_code_artifact_name }} + - name: Download CDK layer artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 566fe9db3da..96b66d71823 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,14 +7,14 @@ name: Release # 1. [Seal] Bump to release version and export source code with integrity hash # 2. [Quality check] Restore sealed source code, run tests, linting, security and complexity base line # 3. [Build] Restore sealed source code, create and export hashed build artifact for PyPi release (wheel, tarball) -# 4. [Release] Restore built artifact, and publish package to PyPi prod repository -# 5. [Create Tag] Restore sealed source code, and create a new git tag using released version -# 6. [PR to bump version] Restore sealed source code, and create a PR to update trunk with latest released project metadata -# 7. [Publish Layer] Compile Layer and kick off pipeline for beta, prod, and canary releases -# 8. [Publish Layer] Update docs with latest Layer ARNs and Changelog -# 9. [Publish Layer] Create PR to update trunk so staged docs also point to the latest Layer ARN, when merged -# 10. [Publish Layer] Builds a new user guide and API docs with release version; update /latest pointing to newly released version -# 11. [Post release] Close all issues labeled "pending-release" and notify customers about the release +# 4. [Provenance] Generates provenance for build, signs attestation with GitHub OIDC claims to confirm it came from this release pipeline, commit, org, repo, branch, hash, etc. +# 5. [Release] Restore built artifact, and publish package to PyPi prod repository +# 6. [Create Tag] Restore sealed source code, create a new git tag using released version, uploads provenance to latest draft release +# 7. [PR to bump version] Restore sealed source code, and create a PR to update trunk with latest released project metadata +# 8. [Publish Layer] Compile Layer and kick off pipeline for beta, prod, and canary releases +# 9. [Publish Layer] Update docs with latest Layer ARNs and Changelog +# 10. [Publish Layer] Create PR to update trunk so staged docs also point to the latest Layer ARN, when merged +# 12. [Post release] Close all issues labeled "pending-release" and notify customers about the release # # === Manual activities === # @@ -22,7 +22,11 @@ name: Release # 2. Update draft release notes after this workflow completes # 3. If not already set, use `v` as a tag, e.g., v1.26.4, and select develop as target branch +# NOTE +# # See MAINTAINERS.md "Releasing a new version" for release mechanisms +# +# Every job is isolated and starts a new fresh container. env: RELEASE_COMMIT: ${{ github.sha }} @@ -65,7 +69,8 @@ jobs: permissions: contents: read outputs: - SOURCE_CODE_HASH: ${{ steps.integrity.outputs.SOURCE_CODE_HASH }} + integrity_hash: ${{ steps.seal_source_code.outputs.integrity_hash }} + artifact_name: ${{ steps.seal_source_code.outputs.artifact_name }} RELEASE_VERSION: ${{ steps.release_version.outputs.RELEASE_VERSION }} steps: - name: Export release version @@ -83,7 +88,7 @@ jobs: - name: Install poetry run: | pipx install git+https://github.com/python-poetry/poetry@68b88e5390720a3dd84f02940ec5200bfce39ac6 # v1.5.0 - pipx inject poetry git+https://github.com/monim67/poetry-bumpversion@ef49c63acef7fe8680789ddb31f376cc898f0012 # v0.3.0 + pipx inject poetry git+https://github.com/monim67/poetry-bumpversion@315fe3324a699fa12ec20e202eb7375d4327d1c4 # v0.3.1 - name: Bump package version id: versioning @@ -91,27 +96,11 @@ jobs: env: RELEASE_VERSION: ${{ steps.release_version.outputs.RELEASE_VERSION}} - - name: Create integrity hash - id: integrity - run: echo "SOURCE_CODE_HASH=${HASH}" >> "$GITHUB_OUTPUT" - env: - # paths to hash and why they're important to protect - # - # aws_lambda_powertools/ - source code - # pyproject.toml - project metadata - # poetry.lock - project dependencies - # layer/ - layer infrastructure and pipeline - # .github/ - github scripts and actions used in the release - # docs/ - user guide documentation - # examples/ - user guide code snippets - HASH: ${{ hashFiles('aws_lambda_powertools/**', 'pyproject.toml', 'poetry.lock', 'layer/**', '.github/**', 'docs/**', 'examples/**')}} - - - name: Upload sealed source code - uses: ./.github/actions/upload-artifact + - name: Seal and upload + id: seal_source_code + uses: ./.github/actions/seal with: - name: source-${{ steps.integrity.outputs.SOURCE_CODE_HASH }} - path: . - + artifact_name_prefix: "source" # This job runs our automated test suite, complexity and security baselines # it ensures previously merged have been tested as part of the pull request process @@ -124,8 +113,6 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - env: - SOURCE_INTEGRITY_HASH: ${{ needs.seal.outputs.SOURCE_CODE_HASH }} steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -133,10 +120,10 @@ jobs: ref: ${{ env.RELEASE_COMMIT }} - name: Restore sealed source code - uses: ./.github/actions/download-artifact + uses: ./.github/actions/seal-restore with: - name: source-${{ env.SOURCE_INTEGRITY_HASH }} - path: . + integrity_hash: ${{ needs.seal.outputs.integrity_hash }} + artifact_name: ${{ needs.seal.outputs.artifact_name }} - name: Debug cache restore run: cat pyproject.toml @@ -157,16 +144,16 @@ jobs: # it checks out code from release commit for custom actions to work # then restores the sealed source code (overwrites any potential tampering) # it's done separately from release job to enforce least privilege. - # We export just the final build artifact for release (release-) + # We export just the final build artifact for release build: runs-on: ubuntu-latest needs: [quality_check, seal] permissions: contents: read outputs: - BUILD_INTEGRITY_HASH: ${{ steps.integrity.outputs.BUILD_INTEGRITY_HASH }} - env: - SOURCE_INTEGRITY_HASH: ${{ needs.seal.outputs.SOURCE_CODE_HASH }} + integrity_hash: ${{ steps.seal_build.outputs.integrity_hash }} + artifact_name: ${{ steps.seal_build.outputs.artifact_name }} + attestation_hashes: ${{ steps.encoded_hash.outputs.attestation_hashes }} steps: # NOTE: we need actions/checkout to configure git first (pre-commit hooks in make dev) - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -174,10 +161,10 @@ jobs: ref: ${{ env.RELEASE_COMMIT }} - name: Restore sealed source code - uses: ./.github/actions/download-artifact + uses: ./.github/actions/seal-restore with: - name: source-${{ env.SOURCE_INTEGRITY_HASH }} - path: . + integrity_hash: ${{ needs.seal.outputs.integrity_hash }} + artifact_name: ${{ needs.seal.outputs.artifact_name }} - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@68b88e5390720a3dd84f02940ec5200bfce39ac6 # v1.5.0 @@ -190,64 +177,69 @@ jobs: - name: Build python package and wheel run: poetry build - # NOTE: Ran out of time to create a composite action out of this - # because GitHub Action inputs do not support arrays and it became fragile to join multiple strings then split - # keeping these hard coded for now until we have a cleaner way to reuse files/dirs we want to hash - - name: Source code tampering check - run: test "${SOURCE_INTEGRITY_HASH}" = "${CURRENT_HASH}" || exit 1 - env: - CURRENT_HASH: ${{ hashFiles('aws_lambda_powertools/**', 'pyproject.toml', 'poetry.lock', 'layer/**', '.github/**', 'docs/**', 'examples/**')}} - - - name: Create integrity hash for build artifact - id: integrity - run: echo "BUILD_INTEGRITY_HASH=${HASH}" >> "$GITHUB_OUTPUT" - env: - # paths to hash and why they're important to protect - # - # dist/ - package distribution build - HASH: ${{ hashFiles('dist/**')}} - - - name: Upload build artifact - uses: ./.github/actions/upload-artifact + - name: Seal and upload + id: seal_build + uses: ./.github/actions/seal with: - name: build-${{ steps.integrity.outputs.BUILD_INTEGRITY_HASH}} - path: dist/ + artifact_name_prefix: "build" + files: "dist/" + + # NOTE: SLSA retraces our build to its artifact to ensure it wasn't tampered + # coupled with GitHub OIDC, SLSA can then confidently sign it came from this release pipeline+commit+branch+org+repo+actor+integrity hash + - name: Create attestation encoded hash for provenance + id: encoded_hash + working-directory: dist + run: echo "attestation_hashes=$(sha256sum ./* | base64 -w0)" >> "$GITHUB_OUTPUT" + + # This job creates a provenance file that describes how our release was built (all steps) + # after it verifies our build is reproducible within the same pipeline + # it confirms that its own software and the CI build haven't been tampered with (Trust but verify) + # lastly, it creates and sign an attestation (multiple.intoto.jsonl) that confirms + # this build artifact came from this GitHub org, branch, actor, commit ID, inputs that triggered this pipeline, and matches its integrity hash + # NOTE: supply chain threats review (we protect against all of them now): https://slsa.dev/spec/v1.0/threats-overview + provenance: + needs: [seal, build] + permissions: + contents: write # nested job explicitly require despite upload assets being set to false + actions: read # To read the workflow path. + id-token: write # To sign the provenance. + # NOTE: provenance fails if we use action pinning... it's a Github limitation + # because SLSA needs to trace & attest it came from a given branch; pinning doesn't expose that information + # https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/generic/README.md#referencing-the-slsa-generator + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.7.0 + with: + base64-subjects: ${{ needs.build.outputs.attestation_hashes }} + upload-assets: false # we upload its attestation in create_tag job, otherwise it creates a new release # This job uses release artifact to publish to PyPi # it exchanges JWT tokens with GitHub to obtain PyPi credentials # since it's already registered as a Trusted Publisher. # It uses the sealed build artifact (.whl, .tar.gz) to release it release: - needs: [build, seal] + needs: [build, seal, provenance] environment: release runs-on: ubuntu-latest permissions: id-token: write # OIDC for PyPi Trusted Publisher feature env: RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }} - BUILD_INTEGRITY_HASH: ${{ needs.build.outputs.BUILD_INTEGRITY_HASH }} steps: # NOTE: we need actions/checkout in order to use our local actions (e.g., ./.github/actions) - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 with: ref: ${{ env.RELEASE_COMMIT }} - - name: Restore sealed build - uses: ./.github/actions/download-artifact + - name: Restore sealed source code + uses: ./.github/actions/seal-restore with: - name: build-${{ env.BUILD_INTEGRITY_HASH }} - path: . - - - name: Source code tampering check - run: test "${BUILD_INTEGRITY_HASH}" = "${CURRENT_HASH}" || exit 1 - env: - CURRENT_HASH: ${{ hashFiles('dist/**')}} + integrity_hash: ${{ needs.build.outputs.integrity_hash }} + artifact_name: ${{ needs.build.outputs.artifact_name }} - name: Upload to PyPi prod if: ${{ !inputs.skip_pypi }} uses: pypa/gh-action-pypi-publish@f5622bde02b04381239da3573277701ceca8f6a0 # v1.8.7 - # March 1st: PyPi test is under maintenance.... + # PyPi test maintenance affected us numerous times, leaving for history purposes # - name: Upload to PyPi test # if: ${{ !inputs.skip_pypi }} # uses: pypa/gh-action-pypi-publish@f5622bde02b04381239da3573277701ceca8f6a0 # v1.8.7 @@ -261,12 +253,10 @@ jobs: # otherwise the release commit will be used as the basis for the tag. # Later, we create a PR to update trunk with our newest release version (e.g., bump_version job) create_tag: - needs: [release, seal] + needs: [release, seal, provenance] runs-on: ubuntu-latest permissions: contents: write - env: - SOURCE_INTEGRITY_HASH: ${{ needs.seal.outputs.SOURCE_CODE_HASH }} steps: # NOTE: we need actions/checkout to authenticate and configure git first - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -274,18 +264,10 @@ jobs: ref: ${{ env.RELEASE_COMMIT }} - name: Restore sealed source code - uses: ./.github/actions/download-artifact + uses: ./.github/actions/seal-restore with: - name: source-${{ env.SOURCE_INTEGRITY_HASH }} - path: . - - # NOTE: Ran out of time to create a composite action out of this - # because GitHub Action inputs do not support arrays and it became fragile when making it reusable with strings - # keeping these hard coded for now until we have a cleaner way to reuse files/dirs we want to hash - - name: Source code tampering check - run: test "${SOURCE_INTEGRITY_HASH}" = "${CURRENT_HASH}" || exit 1 - env: - CURRENT_HASH: ${{ hashFiles('aws_lambda_powertools/**', 'pyproject.toml', 'poetry.lock', 'layer/**', '.github/**', 'docs/**', 'examples/**')}} + integrity_hash: ${{ needs.seal.outputs.integrity_hash }} + artifact_name: ${{ needs.seal.outputs.artifact_name }} - id: setup-git name: Git client setup and refresh tip @@ -303,6 +285,14 @@ jobs: env: RELEASE_VERSION: ${{ needs.seal.outputs.RELEASE_VERSION }} + - name: Upload provenance + id: upload-provenance + uses: ./.github/actions/upload-release-provenance + with: + release_version: ${{ needs.seal.outputs.RELEASE_VERSION }} + provenance_name: ${{needs.provenance.outputs.provenance-name}} + github_token: ${{ secrets.GITHUB_TOKEN }} + # Creates a PR with the latest version we've just released # since our trunk is protected against any direct pushes from automation bump_version: @@ -311,8 +301,6 @@ jobs: contents: write # create-pr action creates a temporary branch pull-requests: write # create-pr action creates a PR using the temporary branch runs-on: ubuntu-latest - env: - SOURCE_INTEGRITY_HASH: ${{ needs.seal.outputs.SOURCE_CODE_HASH }} steps: # NOTE: we need actions/checkout to authenticate and configure git first - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -320,18 +308,10 @@ jobs: ref: ${{ env.RELEASE_COMMIT }} - name: Restore sealed source code - uses: ./.github/actions/download-artifact + uses: ./.github/actions/seal-restore with: - name: source-${{ env.SOURCE_INTEGRITY_HASH }} - path: . - - # NOTE: Ran out of time to create a composite action out of this - # because GitHub Action inputs do not support arrays and it became fragile when making it reusable with strings - # keeping these hard coded for now until we have a cleaner way to reuse files/dirs we want to hash - - name: Source code tampering check - run: test "${SOURCE_INTEGRITY_HASH}" = "${CURRENT_HASH}" || exit 1 - env: - CURRENT_HASH: ${{ hashFiles('aws_lambda_powertools/**', 'pyproject.toml', 'poetry.lock', 'layer/**', '.github/**', 'docs/**', 'examples/**')}} + integrity_hash: ${{ needs.seal.outputs.integrity_hash }} + artifact_name: ${{ needs.seal.outputs.artifact_name }} - name: Create PR id: create-pr @@ -363,6 +343,8 @@ jobs: with: latest_published_version: ${{ needs.seal.outputs.RELEASE_VERSION }} pre_release: ${{ inputs.pre_release }} + source_code_artifact_name: ${{ needs.seal.outputs.artifact_name }} + source_code_integrity_hash: ${{ needs.seal.outputs.integrity_hash }} post_release: needs: [seal, release, publish_layer] @@ -378,6 +360,13 @@ jobs: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 with: ref: ${{ env.RELEASE_COMMIT }} + + - name: Restore sealed source code + uses: ./.github/actions/seal-restore + with: + integrity_hash: ${{ needs.seal.outputs.integrity_hash }} + artifact_name: ${{ needs.seal.outputs.artifact_name }} + - name: Close issues related to this release uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: diff --git a/.github/workflows/reusable_deploy_v2_layer_stack.yml b/.github/workflows/reusable_deploy_v2_layer_stack.yml index 3186009493e..360f4c8fbc9 100644 --- a/.github/workflows/reusable_deploy_v2_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v2_layer_stack.yml @@ -46,10 +46,21 @@ on: description: "Latest version that is published" required: true type: string + source_code_artifact_name: + description: "Artifact name to restore sealed source code" + type: string + required: true + source_code_integrity_hash: + description: "Sealed source code integrity hash" + type: string + required: true permissions: contents: read +env: + RELEASE_COMMIT: ${{ github.sha }} # it gets propagated from the caller for security reasons + jobs: deploy-cdk-stack: runs-on: ubuntu-latest @@ -126,8 +137,17 @@ jobs: steps: - name: checkout uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + ref: ${{ env.RELEASE_COMMIT }} + + - name: Restore sealed source code + uses: ./.github/actions/seal-restore + with: + integrity_hash: ${{ inputs.source_code_integrity_hash }} + artifact_name: ${{ inputs.source_code_artifact_name }} + - name: Install poetry - run: pipx install poetry + run: pipx install git+https://github.com/python-poetry/poetry@68b88e5390720a3dd84f02940ec5200bfce39ac6 # v1.5.0 - name: aws credentials uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 with: diff --git a/.github/workflows/reusable_deploy_v2_sar.yml b/.github/workflows/reusable_deploy_v2_sar.yml index 1ca76a2a706..beab36f24c2 100644 --- a/.github/workflows/reusable_deploy_v2_sar.yml +++ b/.github/workflows/reusable_deploy_v2_sar.yml @@ -28,6 +28,8 @@ name: Deploy V2 SAR # artefact-name: "cdk-layer-artefact" # environment: "layer-beta" # package-version: ${{ inputs.latest_published_version }} +# source_code_artifact_name: ${{ inputs.source_code_artifact_name }} +# source_code_integrity_hash: ${{ inputs.source_code_integrity_hash }} permissions: id-token: write @@ -38,6 +40,7 @@ env: AWS_REGION: eu-west-1 SAR_NAME: aws-lambda-powertools-python-layer TEST_STACK_NAME: serverlessrepo-v2-powertools-layer-test-stack + RELEASE_COMMIT: ${{ github.sha }} # it gets propagated from the caller for security reasons on: workflow_call: @@ -58,6 +61,14 @@ on: description: "GitHub Environment to use for encrypted secrets" required: true type: string + source_code_artifact_name: + description: "Artifact name to restore sealed source code" + type: string + required: true + source_code_integrity_hash: + description: "Sealed source code integrity hash" + type: string + required: true jobs: deploy-sar-app: @@ -67,13 +78,28 @@ jobs: matrix: architecture: ["x86_64", "arm64"] steps: - - name: Checkout + - name: checkout uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + ref: ${{ env.RELEASE_COMMIT }} + + - name: Restore sealed source code + uses: ./.github/actions/seal-restore + with: + integrity_hash: ${{ inputs.source_code_integrity_hash }} + artifact_name: ${{ inputs.source_code_artifact_name }} + + - name: AWS credentials uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 with: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} + + # NOTE + # We connect to Layers account to log our intent to publish a SAR Layer + # we then jump to our specific SAR Account with the correctly scoped IAM Role + # this allows us to have a single trail when a release occurs for a given layer (beta+prod+SAR beta+SAR prod) - name: AWS credentials SAR role uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 id: aws-credentials-sar-role diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml index 1b29de4bc0c..418c4c446a5 100644 --- a/.github/workflows/secure_workflows.yml +++ b/.github/workflows/secure_workflows.yml @@ -33,3 +33,5 @@ jobs: uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Ensure 3rd party workflows have SHA pinned uses: zgosalvez/github-actions-ensure-sha-pinned-actions@f32435541e24cd6a4700a7f52bb2ec59e80603b1 # v2.1.4 + with: + allowlist: slsa-framework/slsa-github-generator diff --git a/MAINTAINERS.md b/MAINTAINERS.md index bc75596003b..be831ef46d4 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -220,18 +220,23 @@ section Build Checksum : active, 8s Build release artifact : active, 39s Seal : active, 8s +section Provenance + Attest build : active, 8s + Sign attestation : active, attestation, 10:06, 8s + section Release Checksum : active, 8s PyPi temp credentials : active, 8s - Publish PyPi : active, pypi, 10:06, 29s + Publish PyPi : active, pypi, 10:07, 29s -PyPi release : milestone, m2, 10:06,1s +PyPi release : milestone, m2, 10:07,1s section Git release Checksum : active, after pypi, 8s Git Tag : active, 8s Bump package version : active, 8s Create PR : active, 8s + Upload attestation : active, 8s section Layer release Build (x86+ARM) : active, layer_build, 10:08, 6m @@ -323,6 +328,13 @@ timeline : Build release artifact : Seal and upload artifact + Provenance : Detect build environment + : Generate SLSA Builder + : Verify SLSA Builder provenance + : Create and sign provenance + : Seal and upload artifact + : Write to public ledger + Release : Restore sealed build : Integrity check : PyPi ephemeral credentials diff --git a/SECURITY.md b/SECURITY.md index 9ac1494b13d..885ffb18f2c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,8 +1,7 @@ -## Reporting a Vulnerability +## Reporting a vulnerability -If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security -via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com. +If you discover a potential security issue in this project, we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) or directly via email to . Please do **not** create a public GitHub issue. diff --git a/docs/media/continuous_deployment_practices.png b/docs/media/continuous_deployment_practices.png new file mode 100644 index 0000000000000000000000000000000000000000..645190fb9aee115ab7470f464fb1fa9b1ee66072 GIT binary patch literal 400492 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�&;da}>lUL)*t(%dMBeJNaLVO^wbuFguGfdG2hCH$2><~!gUC8r!xA+D zyB3-(8xZXfI7mNkb+W6u+qGV(Jwa;h;UUH3C-cIZF?7I3I55l*Pl!iDP`hG3XD$9E}4-`t0 zDds3w!}hV3=&QgW>UdVTB^;b7)May0c3QJ(VD7C*bdV5Lz@NaQ7ncU!d5VeNv_X81 zz~CR{li^obq46#SFsm>z@=zra*rzKvIW z*&qz%KkgT3d)Xr6kC}p0Sr5`nrJcq$53jHFrnF#LunQmYRzRX#m57qT zsmhCg2h2Mkg!!HW^6fv}LYgl>bOjHa#d_>aFUPwr+Sh~ZOwxq|YJvwJihUxy$9Hrh zg&8OZ3j1687*``?wn(;Wk?DasgN-7WmQfIoMzQF5g{{{rzOJM3HnZ7JZ5xl%zHC|@ zoHcjipG-nOc;{^FkkK0D_((UNVo+O#Ly(1V^)!FbE|t_){9O_Ggid0CFN10+#(~gtAdwXmuyzxmR2iPsCRw2vNW=c}k308ZY4S&lGTin+eK%7x)_vwz`+DG_zo|`ORGPJ-KU6+Esr0F&ozIvufzT zbpf`5zK}iHG$NT<$5#W6Bnup@xwcu#1D$LJZzA1vhB`=O`>|__>iWjT5OLT!_Cu=S zaMMUI65}y#>2uMW(wF=`wGcgMIE^<_V~*}uI!HXBJ1|+X^fV8Q{At6^Ak$=qYGs~Z&Ash~dQjSI1iL(}z+Mmx8;Ccg1JDs!3hMAi6&ff+HCV21rz-t$WX zF7p)9ge4(_j&=ZIFY&zd!;cB>!;|{6EDj;~VJqOeo5aOw&I~ec&%ednsP55twXl-D zm^203(PgMbGDZ)E)q@}o~xDN;=PoVxz= ze*u_j0M-OsTYZ>fq$O&j+d`{+$W?bkEyeV6N* zu3~m%GB^VV&8%lSk#zJpZYWzMQ|z-)Gm35Xs>HOtBZjGZ#E}J+DKjtYn32OlpS@7g z&U3oCYhOfl-g(OCpn#e0PnTNSys4a(-ijpU-c839-=o`O==H?WLxr98pfvLarS+PU zwfOq&a&jTe!99a8m<@@hdOWbeT*3^f-6hxA#0Tu~NQBtQX zQSJ%l!O)qr8EXRGHSmo7mbYptBr?_3htRE5^LVZkuNm)ntD}Rpvt;M}bkwG>d<|EA zmn>gG#zW73pueMY$S?(yB(IK4iuJPLLBYoFz#mIp9)j2ymN{7cfG~BZdBZGlwC>sx z6$h$vzH&mq;?5;rSx&9z(`NGQ^NKNR?Hr^r4(SWTh#=1TXKO##EGT)HA-*F9keTsy z*FZgejeyQ{)c2k4u&zWJa)5-kWQ~7q$<-dvP;5h3qGIY2tm8{rK%SK}XxY}V zTt;fr@xIwG<(uwm0go%G&O%V0>yG>Tt>F1xA!;+B5&A)}W`ZdXr(tIT+`@O|ybYtPG2%0K9Is3hJUEtP#s zFV8k(acQR7I=CctKhf@V%h)x_@1>A7YeDh?32;!lln_lDR*2rGxJ(=QB z68x#u(Y?wpRch>z@JJcs6{P#ty+Bx?4UeO*{;o(RV*5Iv5<3|&{|y&~v2#Zwi#Ht} zj#U?XFVvGfAB~SqVKIk4;MNR0`*8bg`;CO1kKSmmJV*dS#BNA45J+i$np^YDKM}}% zZEwPvrGBb4dxq9K4On0wVZ?&9@;I{GSJInQDqFx1aqdlKFpw0@+04^celZx)RAzo8 zlQx7j%gw*KYSD{UyykP#PthuBPDd_LLrjQfzn=pUu=ov`V16-=A+b@2r2w7ek?>U3 zk`3zHEp<)P>#xtllzsV%+19^qT>8#rjRsyw?f2$VF1^~9=bH03kY2w{nQ>M)t_GvG z9o-r>OWO>*>^^eer^piRsX~zOi18&oA^T-~t{A?hTk5ASQ9nX}`Bvz9)i+lK$pNRz zP83yFJ4FRAUTREs-Tm2R_FfZTLnQd;PZ#Z>9NK)@q^mayCF+p-z%17gGm2!<1Uy1N zemL;@6FB)K6$KlGJoz+qCk%6hjICpizdjr&i5&G zUYA5h@EG?-cLu>l$-$!?nhd|+Pez*Uv{5wcjml9BJUj+vi6c1!5+$Ic_3=dGL03B< z8fw&fAzPfe6ZljMJ><@0%afKw2HdQ)*GK1Ecs4IbJ=iOShOSCx+5ii{r!QI=1*eOu zTO_yc6mLnCZoOC=Sp*ea=~HT(2fVTGl)Y|@D#fl+n$z)HJW2v9-z|ekPu~w1nEW_e zzjH1$Rzow{Hg_4ZQpm;BJN_}OTANUV?pDiJb`~vOf>|;0l80$Zi0OkU&MlJFE=Hhb zl6Q|tJ3c8?E&?*zo|UFv5t)Hq{%%PT^JeSC=`5h;`Vgi$5N#>JBmS)kYIm*gf#<@d z!$QQVk^Z)k$L(@ez0ZNSTv6tY52%t&^GNxm^?b(@H_`11iGHnjy1#6-p?@4UQf*Bq zwF^ywZeIO_Y1-)XsEf43`PuvY9L|ga3>SV~BT&Tqa3!wrG^8axfKk&lQxvE;C0i4C zeOWJUziwSHRSoH9n`uf@F+~!zzloONHmwdNlgtckT`u*m{W9eWmlbGi&KR@pp*0u( zVT5tp$|&l0M;hk%Xz#UgWjcklxcw17c(pU4%qTcR?NPJuCbrSme`u+o(4K{Rv`K`t z<{(nf>9}Agzjy+TGEKEf$sBJLo;&SeCpV+F2su?sYrB4gs+Uqc5^hQI7qd;Q~tT1K;NVWEDj!n@ZUl71)-=!UuPP zA*z7jB#%+%lJWsTB^bY_5+Z+p&IL*0VT#CsWdPo;jcnSFL79@}2H&HPyP4KlTuY2< z+TCLg$BDI^T8GhdGm%dLUZp!kOg$1)Wd><)76-Bd`l@XZffp|_4_0Gs z)1k!sp%O~AIIsYLA<1*QQv}W+1*Po*YoygRw5DKS; z^d4{dW2b(oV0`uurt-S6r7B~QogcvS9MD0rMdIFD8&h*fHX*5x9 zzI~bNm{sva&u_)Rmn|YtO$95}g!o@a>pj%2)vg_y!plEU4mF9kv)_Uv0P0|BRm;yX9r0N_dCfDz&9zb_TK05|JeuBQ})tE-WFqU^69g=M*)sQB?NAM*Y z986H&HBoF_fn2Wl8y`|!HhL8{Tl++ep7#k(wIr;Ie9OOQJJB1>`P3E@qF5z%{=Qg) z320Shh`#etw8eAX-33AD-qJTFol4r++Emu|t2X;I@aQaZe>?m2kox)D)rIn}tEcLH ziTqDco(+LK+bvV>GbLmisiFw4LHE9ssj;Tl8Ae}$YETHg@xZEAK`jq!A zprMPDH*N9C=j5W+XvQ*c*c?Z_8_YSYb#VZ4v+9zK>h0AmKU8KlUF>=by5>VvcUF%&%`fOu?l|Iw*30iS zV>2;Z2_PM9R#CYzlF!l zQUD^YTlZ;x13Kx^viP6U+G*i|e0ub{iFD>ed((##8OASLIM;sql-l|Z9x#mHe4`cc zN00#MugkoHmwy|in+04M*BG76$g~?SMMKq=^C~rs76tQM#SUwPG0j!cn=jk?=`XDg zaZfR&p#9Bn%B8beZWc&`#-6ysKv2F!!5CwZk@-}IneMM6Y|)jr7LQDVo`9d9$>$X7}wvATyL%+s39b!L!S;SRKcJ+;&!RW(Y>Y z$YslNTbQSUIAwXrmqHUpPF-0qBz4iGYf8wYDF7bV1= z+1vEXww3I18z|S6Oz{hNuET77{5X(~X+z1>jRsry}7{&@oN?> zt>A$}b{gKpGWH!4o^!DQkNf71SHCyR#N<@RrBSJg!<(u!n?fTgI}+LQ+^EFc^_=#G zyM-iY-a37vjgtvo7a6>dJlYt3|M3ZExP+JIEtHyrz#iqI*rH5 zHTk~(3xbFUNDBxkNSBnOMkC!lN=jfz2$F*#D&5`PF>-WEcXv!$a^z_E?)^FE_xlH) z=bSsP`?_9b_jV>ma!z;(Fmm7V!mGq5fB!~+qo6F#(KGVj4gbvEc?cPQewVERWGiya zfxmUD;eo5}k+s_T`YXv@+^wV1Sw-4aiHuGWx1ld}Ual(J(!XaloMWJk@>Tyd11P0n zhELVnj$e#Z0J~tvs$NDsJEEkNuLMIj<&U`?sMV?Qi{(J3^ilk;RA1Ndl*f9Gt8P2G z*@jKqYo8ytS4d0#r@n-~+9+76t;*tE>3*YE^0TA+0!gLEh=x7`%a!xC0sz;gV<_Lo z^QX;v${&H=CP&_c0!3wt&CU5Sxax~n`%Vjjw<`=Bwm$=M*@B;~q4lp~pD|(N$#%ac zG^@7_X8G~u7X^2Kc31L`0(-)L(z=+F?c!KU=eQ1w2UQoFr7WvfeS*>d$Tn|0@@5bw9n*OV83EK98mUYwA@I+6{P z3Kcy`WIS|I_tP$H$EPZ7%Pq21?;O?yJ?$*jiq%VE4wl8J7`@r943o0 z0|)p3E%X%Wp2-5`k}4~=2!=-oeQ>xPP|U-ovL>8!zb;|d*V}rexok#2ldmd5psZ64 zaNcGVqe-B@af6@`hjN$#`8vPaVV6?m1(thDt={#z-qrIJFF-7A`>z@i^RdHqk%>IO zLeP#=zH(IDD))@{-iI%vPK`U0I3umWZ)3%WsNBiVUkj!|^;hYZ^kyAR8I*LJk<8w_ z2Aj1ah}hW+W51Nd`ZmyaUz%3^W%q5N~bDjbGA$YV9l8@@OZ?utGPtEa3Q4(&l{qBq~U&L z%2gfJgpW$&z(<_m^uxC_W6qGvy|pj`s=Iveiy0Pc@4GA3$tG94-HScESvY$|%QTj* z&-yUh1aOi7nQzHD|3xU4;JObOn9TPTDZM(VF)N@QOTB@^3yh)Hvb>N{QM(4IYiHHA z?5?(touG0^utl$GOu)9mRmqH9`gNkwY`yp8}E-FX91K z;M8jz+J+%4A)n7<+h?St&qcBKmE(zygMZN8p{G%L~ow2mQ0ijGUz>pA%MU9`YxR>KSPoL}F=+qu<$=JY#g?@xqn0s+eFd%VU54 zXvZE*dLkmim`a;`8XF^unW5O%w__b`u}yir3PFG122j$vr+of=8UD*R!XPP<*G7G& zsn!lQ3D?Vtps+?{}FyQ*hULfhJF^XeHwpMWUbiE+`C{dcVPEIoOIkzpmdU8ze9v zWRHAC`=8eV2Zt8gPklz(P;;3ol_PGj;rc2+frWP<`Z)6y4_R!zD|*H5yRB zv9igeu-X@%yVl+k#%JUe?k$g@ z_a9FaN&EN-dexL}Ok6tS7Vw|fUJKGVB~OV49)C4t&VX=#u(EAtNZ3)`(Ho7Jx|iop@7x`NC9F*>HL87&5_tD%^0tn z(Dikiy_f7*@<*?h;|j}}lG%d>u#U=G|BrXPKpGp1Xay3O*=@To@Q6W<@%?=4wM^DL zZkb7onBFU`hFyE>)z?!bQMd^cq(oZ|AL2=DnsA>e4viL`X(|(n?mxJt*X&+RzvH{; zQZUqYNX+w5m~F@~?CIU18UAjQ*?bcDW!4$dd}~pNljEdSSfavau(dp&TjP?^XuGA0 z-cj~n*N&G3t*FoCW8aX za^VU=Ubq@h)sTs!a`z9%+KZaRdpnt`uEP2vC2#6u#Uj%Hj#k;i#h6>V9@tS8xqMQ! zLqB`mmX2c?v5P&V>S{PsjngWIBX;9I*8r?`Y`%T?BQ#f6jahNv$xZ>QLgfQTnK7}+ z=IcC?{^LmLNOcuw$FBNW**JtR??0p$`>~-fO}gj(FyW!3koV_il5R`2<&zy!$oToq zKjCdbl4_hum1FtQJPfsFy-`=DM7zlWDuS26ZkWd3|5Q(?p;a$#+xMyDOTQY$2)|}z zvInuUOt&0c?>;ZJW;T|9_z4pgXWi0YbWka*Zr%8dzs*bo8pYc?WosRV*Weg-1;d&_ zohadIpIt)q*>>BGkIi)T+ItboWub<;nKr3Dc*`_KiBo^K5%$dgle~9pY5K`o{!WPx>jnWD&hlx8yL_GK{3%6P`Xg+b%}uhFZ~Ek4*d$$7K<*ORXVTiTghFt)PnWXzNTetd)8J zedA>Cy^=3>UP83FfcuJeS9KBYsV@9_u?Sdmy$3eWLh{AKT!Hcap+=@R6P?&57S94U zm|NX#vC2L0zvY}-%|6hs3cL02m4;l_UEZ8xqmRl+#f9%hDaC4EMMo#yd(r2 zn!iu42iQg)%r~zL=oTyMSU0?VO0pCApS;JaRvhpFg*<#<;^$Es6-OEsD*kG}8pJiP zX6EAO&VfS=ChfLeMumn_^2ZDhzdP119ZK%ItU0zr!f#zHuh3eVm*(L4%C_#_ri_!X zXi5_;j4B^%@x-&b_qycEVAENit8>dp%k<}TpWLKFmjU>l{F%}9)L4LEsiHi~{!28~ z2JLmZwxUqbw+Z4ya-X#z2!yAC0Y-?0BCbls-ZHIEVMd2trQgVXeP7eLEJguoM7G5JB{pV$Q#cuX5 zn~G;Dj!a&>FmX4p&nT-!8!y;+wMzlk*<1O!Le_znc&CXRS)rOusz?9^;ms^qrRe~N z$%eUtl;*H)z&Q8INK3VcibzJ2_NB*<;!Z6Q_oH(*Ejjp7_e!(72!?Fau=CWu!q>2U zIgs%)LfSODMh2B*BkR%xPOHxmw0Z|yUl|VL6(JRqpLvNfABgqa-C$bq9Yh8nPo!VN z!D`a?*=HoA>!sh_mg-K6JZ}q7A9g5Og!5mzn?e*E<-o`rXoUY%2U zt!xXOfW@=15Z}iUcLC9-IRPG6AzVBd3f6UCt9X~OUxbQkBtaI17~3A#<+keC#WA>l zrfGxW4!@oeeE;eEef7q5-!fJRZP02}iQ2s=SZ*tj{DHdLjD&w)ZLuIPZGGE1UyA01 z^gLvKUr=WO7Z+GZ&&#!=;4@e>3&qNAUB6!h2dh3cJ7jcfldFtP2kcn$o!#0oh-yYa zq;8BZ!}uO$2(^K^2{nVQOKt-J?Rp{`FaJx}0>&vhCo_ghmne6K9)|A2~H7WbBDB(ADNBHOepqT{QiWzQ; zOYt=GaqJA}$f%A&OcYS+HY1BX157p9?uM*2*)P^bzO)uC(6;r=L+*?=>_~hq_OOPR z7<}m~a2@q9dD_NOuN$lDT)d0VTK=7qB#AV|PGHd@CcPlyPO3@lqC^1HWQ6UB+HgeI z`gq&fhBcG9^^{H*L$2mSXmbz)v^VAAKMU(4CJylEoh?#~>Ul1ZC0(_6;LsiI@@-C{ z4KsiLA@Zy#X1lQ$?K#s=EdvT-CqF^8XzG4CO02PM+c03NIK|^V{JRZPMHOMqot##B z`lVS9Hq!A;sa4$XHNsvpsHx4wvi`wNK3kyVY z8d`;vRv;-p2V784j1P7B=_^XX7VEKY!sJ=CYp~mrI?D4YTGjC+!*$}&xYh$Epz!n; z{|9BD#fHWEDpjEc__C{V%U|8O`)4D9J`MX;j`@RqDTt4Hzsy(0#v<=CbyP^a?=x2i~Hj^Fsdlcf_jCSyZ&r`P%o$*zH7bDo#C8OTPV%dpE!G1lON=>E6wUCTdvt8I`kr|l8cKbX|X1P=?zdWXqy zBt&QA!Sf#yoqESJsPyVt^&%!me(RIt>S)JELBbd+p0%<%-(&T#$AGxF4Np*{^_R@2 zc4xdgWn)rH!^m(Nhe?EePY&& zm_6md6m>= zU1Yox82{c;&(VtdFHI5I^+g3X=&JpBkPVZFi2KA<*u*FIwo4W}Z`w<#NWER`YUp8J z-Qg~{g-d6udXZ^W{;ir`S7Sv^YQ?$%YiadD{%sS^IQ4z6W|aGLp;KgzQ5RzNo~uc4 z$KFB3&8OJ&`d+o@qGpMlH1Xg@g7!J-GmLK@f6c7k$$HAsuLjLlAj-a%X4S-V zK<#+5N7qa?Rbut%c_^yQ{QPYcBL>l!_wibwwjZ-vBsBnCQ(pq`FfcIQ=gJO&6GCo4K6pw5UL4}4QRSl(Opw2 z$p@Xh3l>n*+-rERb`kd8RpvZT>>tIP-yRl0t+$(@;|e&?nJBkCYM>;;#3x;cGVfQ% z$}7Rnb2jN@RUmw!sEiGTquC{-WmVCkic3it8-bq*VH+n~X&S3>HFI ztb5~F`RTPb+3a7^2*o_B3T!VXVV=zKJcFN(y?iave*7YjzK*!GC*uYRYDwyLnM~zw z|GIvySo)m;gGkNF+Og%5_TpfwFDHm?G4ACx!DbJ!EA6xCCi)MWhaqI&N>U0D0W)RA zva+IknY+bmN^oNNFVUngu_WGFV@}A?+wSqvji)NLYcnY|cs0kW%_x$RWZVle>?EA& z-0CMz z1`OzFilKg9D2SdUa@&pU4n1}{?9th-NHx|GeN$1$klE~AXQ+1$z@^yP;EoAX8J?Z} zbn-LrJw+BNEwo(fX z_tlV+Y+Mg9o@AvbPfRyLb*MAK;;FeA4$6}*HV+_|%77++eEvOuI=~f`;1|!CN`vlWp z>TP)DM$jd#&fksRu}iL9(Uj73+AB|59fze)!Oz@>4L+C8-g4J-wLz!P3KuLhyZBaO zyjO}Bt)S!wBea7(VElh-)V*&sYl^5KetMk19zj+Pao1_L(`J~+%xO=*zD&T3nlUiWsC|CIhC zC9MJ$fAPU(MfEN@G$m@FqGS!KjwM=ciF zrK?>u+~8Oor41$}GO(-9gPq)Hoz_<@E73fw(+zR+eIQDCSpUlSMtjbQ29oNZDgs@B z<>}Z{m3*CfWV>oE?c}I0X6@a<24|-xucl8oKp|ISP9PzB8du*{rwmsXD>Y-e?^zMj zv^iF$kDpSZH%g{&%wF}A_;sk##q6!fn`(56q->o~#_NuO{&K164^R+-IjOMpWURcy zk(65H+xItJ3}t}OhSha76EfN54WoBSt#Y2@ zhtr|jRReGB&nY4urvH?5$P<56iq{YWeIfS?GfWtJp;>c+a<&=e)3*L6N}L^?6zYgy z0<R`=X{s$f`0wFQn=3)yn#1i4>-AqRhB! zZmU4SdI9>KKyiuWRq5X(2PX}eS*2jt`Rd9k6whx8z3{O4P0Y2S6`rur2k(L;JzLQ-f)X)7YTTqSIEbDHgA6C(IeL&ONu zU5dukZRzLV7~|Xir+$ClXN}^KR{(hfuQms?_;>dy->7Ogks-xS+w_#T9jvXsQE=H9 zJS3Zhw%vpvbdH-rL?42KS+-Z)O>(0d0w)9MBI=KY^8}()Iu2fFva=!$YpRoy1WOHO zN+^*6R&+i-;q4f@>`vy+)hD7!I?2uUms^P$x#h-mRW>H#I2w<4(xT=gHz(Fqr{}SX zG|7769_qe(2qaI6kP88)aUDpZzJ^aQO`Upleg?pyM4C}WAyIuF^cJzB& zR^G5XVF0-=a=JjkSn4Ox%B}tVQZkY;kS7mON^xBxP~X_fQEeePsGyqK(9Ja(2eXmU zNt4;Kx~85P8A7JgEwFtURQTR{W$46-o%>;Af0Hy*$i1A&JO+8UE&h;&(1qoAkUOG2 zV<=a&`M7{{#!vZpd2P@$geEmP`GBXzaitl5xW6=^`(EC~H3LL;5C#N#H|TyB&&2uZ zYI2!l@ap|7_kEChu|g<0lZpQq-%A?%ovM~D%z5>U@9&uUHsS$@yg^CH^J^SB7F%2n zuEWJTPJHVLtw+D70!Ur6TJXfWfL)Q}Tsdh)vw|iY*`zOh-DGG|M9of#=~exawhR_F z*0V{ujXnzfF)m?3?8Xbr!b@`&lMGa4VAp}NgOuCWpQk!*_HPNXLP-4bl;&7=2L+tJ z0m@#Isf(P8lkhfrQJSt7u6F#sTt5ePw~1Y0nR9hdStGnne~5s+huPLcnH)67n4#sMLa%z*m3nEm^c1%Vgg<5hCBX!~@ zB}CtBOzW)PpE)eje00k}Zy*Gj3wbE;eO#59Hq%aj438kU*i?;LS<$3TuY;6V&msY`?gu(Y9}69d&DRAtF*=Q8NC4@fA>%D z<~A%Ps+hR_*Nel|bowjLZ0kc|?OTN|JfC9HR-a~FfVeAs5c^HTcaAi+k3|*m#Zwr7 zmGwx}*o^yp=JuR1a&HE{8o}`~#I6?ohG)Hg^}K{yLR##oqV=gtON`7ubbfdhN?#0T zhbYrMz7MW1xE(l0N;)!8XDlo%QZks zGA9HuQtsuqwXn1_DH3YR6sWvfKj|>BjqMv7^wR+`m<4r2y+tUmC3qIv6*^|2)ao=N zEcEfZnzOuU?5Y47PZNWDN7VzC$7_UkMLF|b=peISd{;PK>o|FWvfif|-rDy*qrK&! zx-v68#S?fwdf-8KTRq2)lu%0nI4C%zN(sFhe|}Z#-6PZe9eDIU9nt#3!6+c- zc7N2}51=+B5;n3=VJV8}`ezt{p@QL(n6~<}}x-WEKmFeuE9G&*e%Q<^uNAbzcAzvJz)> zqM}vFei5$Tt+cgb6#sHTHSL(k=eU#Ne8;qR$EA@{{!KfdxbyqvoPVo6p5lq|Y+FUO zE`Ce*JBVMPWsn59!&0+jdo4#SyxG?MI19=|&qS2KY0{ELKPD61-d;hE#kb4B$LqLi zzF6x**NVDfLC+Py_AcndwV8Ht44q0Ezwx&>ITg*QOZ=Onnd59}k3I`BWg^AjQN_<` zI9^_?63q{iOhYdCS@x-`t#OHXd(uSEBhYIHhZUe`^_wt{m{+k1v)EhVtV5%M8?W2n zXsTS?WcSuA($3=2T85dbWu)m$i01EDa}=sl>ZU|RRG)=u>jHQlx(8xO$8z{)(mc1? zTjpg^uhuhnUH8#Ja5?zYfbD$Y!JiV@ujJK~v_>g&1SzOb)iDF*NG;~^f#z<`1EV$4pYbt2N}>0H6Cy?YE>?ez7HBi@ z6MJ(s*AdE zfKc^B2Oq$+9Eavf;+`jWg8&ZlTSkK{Yt$_z_iG!>@s)S(zx0qzBRlf0WM$Z;b8O#W z67R5DM3-6Ly7X`)pYhwyz7eJ&%f0wcf2!>FB6+k%t~Bb0qT=o9vbzHZ)6q{|<^*K> z4op8b70mJ!^X)O+D}6B+OdZGhv^VVjFzDxzI&O7g12d9ART2>~k)WAjQN=>W(7yIYY^pkWv*K6l&Ra zHMT=(rlS4vp^fRC-Cg?&SJfIAm<6O#9s`i z@ttrv0ivm7>521&CsUV|#Q;sD$h+9oM6>FIHwi@+0Xy#WCYsn1CY>3ikW;Dh2vASd z3sUtdHCFaHZ&M&JogO6%cI~=MYqFLqh#0GzLP=tQEEav0S%oX)P9_qoNqJY~n-r`g zd(|b9D(FqXi>2>s|4qm*MIwAZs1}9HyMvSxH*TjyLg5~gI5{55bmAYQf9~rQ?6lD; zk6Pg)2U5@Gx7*vbN%Y9Rx7#2)8UIe@wb!|5_>Sbb`1-SfJak)3y;Sc14(Oxz+OJQRV#;|TATr_a z6S`ngv?lZy4InA1Ma-hu1$Z(lHeQas;0|;w@Id|3X6aooEJ91%aq@9Vrw{o~U+!mp z*P0yl^EP~$J!OYzEp-^Pztte&6@omowO>d?F*6fxTz0pD47sdHUH^Mw#5lYL75d-H zMsh;KTa`!F)N#rAJ)_m8qDgBuQipXbG5pGK?<#hv7i-sO9-0N+jw&^;z>`*NBPJ8w zcR==ug{$X`Wslq)?CPN=3N3lRxs5}a#mAm78uf^W(R1t1PO%x_lFp`)vKt$yC@L#t z8Q$HECS+QKs9ar0EACv~o8Qw?<>6b6-X!xwS{)olu8*b2c(*P^vhiP|&tCzS=G5dh zu)`k8{W;gW`p@4(`xaGEYO9uyF{g%gcQ9{s7_jnK`0El6kC?Nq@$9E(9G1jt8r%=a z@UnpD!gH;{QT4;c0C&;oXzSe}?!wJtsIEVKE+kt;3Z zSf93~61%f1A<~TpnzTxDB_oj{u6q)(Oe0x&dHbTshq`SuyU9G;H-J&s!4l&<3VTe( zP}DJx*Z*!xa4@KAi#0E&(blCUT&DV?NRRD+(4|&=*p}`*geSLi`@@?zal%W}RXce%6cHK5p zp9GK~hS~MpB&NGd6RnLNDYc>$A6nJbwo7CUQQw&V+2O13+26x=2wq1c9JM->oWf;z zGJih55oxC&M@TdI2jFR50L~y|E0TogX#jWz0RRQaH@Xwr7>QP0~U2v%gE7wWiUU ze$J4Ptlj(i)f{A@+T1Cq&Nlb=8Dtn9;QU;>#K_?68DqPn7m*f$&RM+ALFHO!sy5fo zp5mmhYF#Gt$0A*HW}Zr3VSyPQ=36IstgjyNNnlNxSNT1HeXzp!y zB3$VJU(4|%v0}1kNH6X^p^3l{m&-&ntQoZz%DT1>h^d9^hEv(B{dvJ(W-M)YbG0i^ zLKK^z@xzZ#)K*`Bh<~@DbLRWmVR20_&Q)jpor_Li3x2oc6RabAj7G$r>rEoaI$o+& zYvyJo{wmoiSDqyc94>m#x!;3Lke>!eF-9TW>;R6XwG6A-=k!dR3=|l}mkTaFtiTZ` zAUpk!%3fG}3gG*gD>ZPLlLD6g{P~ZLR{F~H*3!~1L!o#45a52|BDnF+Udd)At;Qfu zl|4>2OJ@7G?tt5-wbATwyOk2B=NMoLy^o+zcheJd+(k}<@ul$fWV05kwk=D(6UEy5(qOn(w+r?R%_4>$y<7*NTTlpmdW<}} zJxScWoTC@hJUsW~Q#@X@%KcC?v!OC`@TNYzX?AY#4T8*!-h7hxNF&S5ZsT^tDt0a< zD9M@cH=-R;Lgi(;1-8zf`Y1Nr zUcp#wwPN<%%Z>F{vR828B#KW3_|=5!9ZUd3JS!E=2L?MD_BO=|iE+ml^SPjuSjZEk z))B=Y*HivBYN4jjakHbX1j~n24c~TO1xqLlk2b!+c7-Y}`8W9Lfz5E28!XXSy+&@V zf{B^T(Q>0K5xbn$Il=|Lz48-(j1&Ib8_Oa8btXMs$fPZe~t|8Yp5>XUo5$nB>u zs&|cQ8AIdsA!?cfd`SmS;;jeJ+`@j$&)y~9sBFl?@|7VN)OtmZn} z^m3pPzFVsbUAnkDo7r{`{U^_DJ~&iP_a#!N)eApwTDwbxHra8ZDSYkbc(K+Fqy?lE zcpv}=KNoevQWSH7{HDS5Ga`N^sqqNC=ipM7B|V$B_%u_rXJxa5It+2vOS!ZpBr!89 zpg^q$+oA)mK}g8u;nW}cCJk6k@*E)%aqDS_S-f_wvPm7U!8@)qtHe8r2rF*#YQk;u zSFf^yi)6YpdT22{f z;ynAK{=$$%-4!~0rLKQLmH)Bq1%s9H%LP)V+g;FE8u`hd=0E;s4^XHk zt}w|B_$q&M0uTwL6?2jph<()NR=oy(0Z9vCX)c^)fM>A`fL@onHJ-9hyGj5cDKX4H z(xR5Z1437&#agfzoj;|eYmq~v_Dk|m!tOMs#DaS9D+%1xN4><>_n=#7N}}`|EQtcVk21)Zpevr~8s`8c*6Q zKgYV|5@fEE)#I}l%+D`qK7Jbm@$dijM$*O^eviOHg9*0*9d)gbV2ff?hA_osT=o^? zA&uHB3D|I5>uqf%m45RDw?NU?En%yb%q8W?_s%SLc?l?+z`!D9TWikpXEM)q7(Yma zug>VU7RG-XzEql|nk#0c?m2)hBT79RS7^m(J1?IHxK#Z51;qD&*UXgEmgr9Ox^U2I zHdi=p+WlpwJv6UXb^1Z4Ach9t{)+Y3jfv-Y1UF+~434qil$`tREhR~6N!djIK{z{z!=x*FE${qm->ZDE3M z&7`Ed?d5MNNR->fx>}s$zSKC4yswdFpF25ur`=RmO0M^G(&Tfv7nsx#y&e#mw-0|M zL&PnOo)m({GNyxp>7lPDmhTMfc-017MP-?tF73hh3%(9i&7(+qZFV}aU|-QUR|xZ& zXF|79m4}HV>h7pe>TnSh(;9msYPY{B^K`Bvchbblu`+yC6S}mtq`RxA$SVzSH_)snhD84KlQ4O1nMciBm$(U$cPUk$ z6MW2#zap`F`YZ9l5)zFH_($qNl5S~@M`FLJu0aih)E3aE3=rg9Cy+oe=CdKAz6N$toy7K#|!ZjAZS8{x$A_ z2z332;H&s);%rZi@h8n|-UQzbf;xhh#}T+QHc>|}jv$*nQG=CpYp zra%X4P*E6a6cDPd&>5wVLLgBJG>5y?qRoBaDx|Tn`*h1=f6HL|<7#mn zETx4+Y40%b^S$<|_W`gfofusimZa6i?gGc}n@;I>_BYbk!J!e9lA1+H* zWL)}8p>36zI1K6Wr{qk8b|pvU+Fq~y5v7Y|V%#iRhA)YR>bpO;((RXTDf}gPoQkXh zlXacV9WJ@sZlS}nl*>h#JC^fWy)MF#QzK_Y+#oCtUyab&D<06Ret@5ubRe6F_s#jP zbYBEb?sL@nyNqbiDcX#n_tx`W+xG$D{76e^@_Wpr(R6&kex}b2E2kyl+h%uULCESV zzh(cck(wA~#gsvkdL0s;xV?)apIg*>%xrw>kLph|qBzZy?>u-kmJ$weMAsl_7GN+u z01#>Qz}-F`63@Q-Zz6Yda5d~dcEEK$Hz?>wfaqD6=0$6j#qKRyWFyR*fqk|!MZ7xa zL|ckep*f$_160vJj*5$ud79xNg)pvLy9=|T4+V%_Us>d@lpm0NYT<@iWe4E5W9^UR zRD){6#Dz^&lCmzi*SPy4_14!%6i^UGJn>DBrsigLS6DDT3W-po=eO%H5$|60+@V>l zu_m-%X^JmDDS_#fYG-p9H?eFa4RdSGJ)Q(=5fo~LznfOC`6?UCf%FgfnF zm*UR9^~_Xq zEaphN(Pmg{uVj+kk{`Yz@-ntSCQPeDn>EG){^i=aCv-YixN19JnW%7jV2mf$tFfx# zY-j!kZ1DfG0OEb(sIe9<)zGxm_9=AeJ<)Y}?UZL!%*I=D&elp!fKO5)=&9h%;(k?r+z9zEJ&HzV^8N za%yBhAd!RKvMKgkpkmyn9Qhq(%^mw<%^vq?yQHh|$9KrL8&4@~p$>H#a;kPcG7=ZP zF(>eg9fVC^Me09Ywu<2vkEgZ&tUZ2cz^shD4(G;fE<<3X5c-fiJ1mXThe(?Xq9^Dn zz72~YAT!GYRrDWs{*CT&jXl?9;RgTvN2UlV_FJt>6rt^0?KcYUiM5SSJTZ#)V}1a0$99LVl;vTW^0b^(#uWrF48f56?)~U+ zb3Jqk&rS~&EbzDYpr5yk-I_U@nqn>n-7{&Au6VSGx?Y*)AMGt@ z6@SW2*wpTo^{l&E+|0Bc+phio^Kz_rGy}7AF6WuOFsmnt36(N#;zq65|2EVclN#Zf zc*AM<=Q1lG*r-i~YU(q2r_q*mCPgGoehkMts!Stx`6uQXFi8;lfJEdpYKkXiLgJlW zbDu-S_D08qw62mj+V6}w0OU39^}1#JriH-XG0eyceFaoYQfz1@p*`iLSkIZr>&VJI z#m1ET+o_S#xqmO)t&7mvEdt&SSPN%Afh9U<2_n8`df~IPJbh+HsM#Y%Q_q|Uy;sRH z>K*ulxnO;)#LnYFp~uIjbg+IN3%VO3z!MzTCg0iEfx2H^@AWVQ4n*`+Ka3cvvxxgT z+zbwV|0P6c+89DG_L%n9rGP6gRUJKthS~B}11qV!$T8b6wZ#GH3 zlFr_pubRX5{pq+1nGTEx60rH{|6YHdp@!RyhzU2vB4Lgz1+yFuFN$oh?~eOXPJ1^- zIQcZbkM$81&7mOP;^uHfz4!Qpzj0I@Zx;J@QFT0<|%c$5OIEZ)qR%kci_8Z zf=a<+-R2Ko=l*h6DHAO3@k)#pmfU?lKNfUNH-zqD)gszfvbb}87e*v0(3L^8gxZeC zR{oXJAg68?3|UYAQaWEa=Y#A^v<^R-#d#k-3wID2&4H@o9%eYe!Wz$N4sG}U(0oVP z@XtV5!UiGKnbg0}s{H(ZD0b9*VP>QFoJ5#iuv-tP=$SZS9)}a(BYW=$TEWz?kZ>Q?o+*u9m?bCd1Df_K(Hik-aEnJZgg7gB;*Thn%-;C&N ze4Ughh|U^yJO(x}Fs3cYQ4rpb=G-}Nq9I{j_QM-S&NSnW=836Iok9`MnWJ9J8z+>F zml3Op7#!Qwj@nmx6lqwJ2l;)W+cu>5dk4~Ulr(_&)^!2*6vvHjF7}R}Rjj5!Iv$i$ zZp(74PwIB3s1+%W5yp#NXCzcCrgH^Wz*$0nugm=%TGL`pZoLwWXOk|^H@;SzxT^Qq zQGKRjbV`|z`1qpjQMe^~)HsaElu*37rZ!g=S)RRH$~1NIFIO9YHsT+ir#U~6#Ar~^ z+b%_qyqHd36Ak<~j8Q_VZW!!)JWT;dz8~`xsf;ErH_c{)&Jfu<>-B z7v5r}BPZ^Xp?6rGDUONd?tSNmZD&Dd(R;rAsci-Dh=ndJPMVdtN@tHVx9A<&p{7SA17TJ?28=cyji{R&Bc_(g*1Z zs{BDAvTps%$Llg{7KT4&nZKc#|Ax#_x7c>~Tpua7oBZzSf`+^}sLC9lM*Ley3c#-W z>|Z$219d2p6?Tc%LFVhiQnVJTxdwk8;86_c%-oH70g#zA?Hk2fg-m0IQ2hbw51(HT zBz=}m{qgOS;lwIo7%kSRj0BU5-iE@2IX$Rkgga={!hx^-F(W4@w{{b$f2EbEmqJn% zb*Fy;x%;-2OZNB2okwsGs|uhPif*W<3ta8CHd!xZl5#0_Z9beOq0GhVs2|^c$`VrO|2ys?6d&i~_!=Xe(?0`=(`0Y1yiD94Ns0Ez z8w}sF=D_h}?Bz79JMNL8&JQK$Fo}w6v|nzBj;OSe5Fj$PUu;QU6tmRVkcGav{U;h) zv{hy=zJ_~7zv=AaqE$^@-5@QtjoOS=lj^r5z&?>;{BS+QO*Y2=%it?3lkXV5fj$eJ z%TkYT;v==#vS_lH*QIevuP?%!UXchR$XmO{ZB)qX->Y;{s1Xs@fY6$)gPvH40u9fA z%T{}8^a1N3HTk;`&h5mjn-e!{jCE^{^@$4MBGTdY_GE;&G#Q){yvj=dJnz=efsiQtiJR`GTY5n6tkLsln)7s zqn8@+_UjjgjcrUwKM96*?Dhy5QS7Fr>s^8GeXTB!c%O1El+@T_>w58kfW#WHK9rLTnqG$g6)oroSkH4pud8XjQhPL&j7#bTH z_HppZa<237EG`ff`m~rME=1TX<*pQmO(jUL&`p|F=eKf9rQ3~p$!ZB#qt3bdsd4La z@rF~^wT?oE?|*21l)~RzY$coX%0kk2F&@NwbFdohRDS5yb(d6EC^%GE^%c64{}iA= zt>gJ_2uIy|t&rAx>_ray0X~lXQ2^uukb`+06_PKHD=J z@!E#ER<~<<*-Cju<;A449+C5ddE5|v1@aS{<+jq(2{y}Tw6q`M$W^YpMJd1iPxRw- z@6B;P_%pMd?@MJz{|C?h1XFP6Yk4xPWcN&`kAtGDOIPnqSV~5xyzvL-G@K>3ri!vp zqZJ44%th*@3M^6lq?btOX^ElSu3EQ_imB(oI3UwbrXL=d>8rCl8?P7SuKinKOL#k1SVf1n|4v!jT#x96x#`2`pe6 zNAJMsSDLT3tGDfw{}uxFVK3rEZMuJVGU;?HMZwa;V?O>pG&x5uO2?(7e9<=q1C?OIO zB1m_LAkxTI>5!HN>5@h|+={excc*}KZ;%e@?(Xh}Z*9-H-uImQ-Tyr==R6M&&xXBn zX4cGaX3bj5kqmnO+9-0yJjmN!TNJ{JvRZ=@_1ePbP$5{`mYI550_yF>EwAONqJhgT zTD_FWW%KT>`SYBfGCie_lqA*<0yt;Inph| z(LY*x)mE;3%vj7_Juj}A?%18H%_8kUHT}FCrLAS+LIu68C@@QHroqQcbPSs%?)gjg zfuX1+b>**4!|O&O%loj62-oQWR1|}w@5rmFRBQbQqR*oQrDzIqSVWUX)b~rat8}=` z3z_Aj`hv+z&Xkb^ibHXDAcW!;!)2@O-iM<{VG61uZr_p1!!0RJBV)Y6rcPXOnl#wE z_~kqN;`Z-II$7dz6&j|8etuBXcP{x{e0)lxN_5_pRnl#{MRC=$*SD3asP>EuUG&8g zd-Xc4U~8x?L)_bfyO~>^_qKKPVx@|&x3>lt94&qxU#GM&|CD!^VBeUPXioQ+swHWt zx(b*|IIny`H$Cg^%dcgI7HT4o6~Nc`J!dcIj@~_T-Lu2)(}C?Is2EAEaVgd5iX>pp z*nkXw-*@jniZ>>T^Kt(iM?;6oYw)`6Etsz^MhGIRe4w|7Q5i_X+?WdegW!IvE5-UDs6G}3Dh=SI1MS^0cWosCVqm1Q#Ek48LEPhK7sZ@hyyu_6gB z>1+wP%2%sMmU=seiPasmVc8hnhT58)mXVS3GH3jBqhyY1>veTxCdS7@q^6=iwfIDIe$8;iBZX%BT=7OP1G*_`&GOSVb_OTJEbS9#} z%pRE&Dmc6_xHerhcACyu{bf@}%2H?AzM($H-@XPbK+0G7#IQ4dK4Mw;Bv#i<@uZqH z@=J`4eVXLqMPH_oTyCVF;#jD4&h!3j7Zsj}%X*FQRM=Q43>~W|a{TtuT1vE+GW!k} z7YB86UgFHV+|2K-U5yXIW8LJ}yQd=Yb{ypGBV+try1U}oylO7Iz46I*8+9drQZ4In z!Pec*B~7SnTO^p5+PZxEioG8g(K%tU889wa2248z&=kD*7U!1B5&>1=Q8ebMyM3ud zd3iTJkbFAE_kvJoDt|#!TqKb|ENYS_>NT9Q;yRuuaPZpjT*)?R%TyL zWE>6z0_9k@rtx5VMIS!P@N|r8cYWAN8d5Z_=A{Hr`1`^Wo*LKZL3plDL*}~U%Q91_ zGcQ%n39omk z&!bf9$bKl;)Z81%Ox>GR)GOxT@-i!-ei$f&Q%}JcIS0xrC+zt`2_b2dtW)!Dm-F52 zu2I9HmGKgq&OE+N%HqYA^61&`HT?F*64;*V9Wk?+fB7*UEciJV(`}Wt^J-8&^>CBf z*QhIa@h#0@+hHwo;fpBtkbK~v|dK&BgJif(O zoj)nf2frK8eM!iTjv+T=mHJ5yJ6eoz7`$wFD_(wbmlh!+{Uw=(dO0|A*NrA}Ic4a}dlv&T<1%Fg zqiRJc`x_hV%%q89@kagjuhw72e={n-6JE)2s-oKLCVuQM+-MXwu8bNtVEY{jnhYV0 ztMOeP1X*Bxu?4;-W96s@Z&AJ#*-;`a-vhlEyLd-+FZs~El*3C}BERfhtwc7q6M1L{*>6y~KnjvE%Qyp^| zZPw9TF^Y}?FNmlcqg@`GL>{Zr(`SWRM+paQ^AAQDA{Na9d2=MoBSn0h^MA@VhEDDW zOYUElIuhw>*4xFU1~{q0gv;24Qu#&@w{`>$t5pV;x|OP#_O&JQb6ET2MhUx@!5Km+ zm_EzTCRznpu;9KO>$g~^t%uzPc(|Oiwv~q_kdpUz_+R_-SHIDCm?_%+_N>zONONre z1CJQ&dpBhOv&2fmY8-8R&9#!h_cBc2{cyW4r)Wu|wVPbyniTGj;Am=9qt|0&yMiu9 zYXoV!-ox}x%RXn?${yFgI%Jhu)e0 z%Q??(BKbWEW`RhEqzFtbpk^96^j$Gc_3ag2+SZla`ASN{*Xd4gasDK|amHmoHOb0X zB;8JmyJxz6-pY;6np8ZW8M{f&j5%_DF3Rl(2$Cen>yV_s4mvMcfAw67Q$wmE&ny2$ z%ynM$`@#}-;t&KP(awuY+5Ru{!qxdhkzsb0iast?`oVqqelN|f)LNL&yw2Pv)VZ32 zmoF*2)M`E%zA^%ChzTw8} zIc{}T{L?`d=8TT+YMja*A+^=(s#(^%R;}Z(O}EH@s{2Xw*q}Q;CE&$X-x?7&7V2VC zVYGo!?pM31%gB~JT;CAJ>D^XX95=3L_dS=F4_LBHt9P3@&yJ@*8xLs5B-k3bUO(ur z&@i#w3O`NKbmfYQv*b--IXpgAI8!UsrBc_!I9Q@y9&@|mf^^?^YolC0@kU-d9D#7# zw4U+AuV1`SZ{BHIF2`WMttdc2mF@AI^>UCYnP)E%gNJHV)^IOzd%tFc-+^>>dt2%U zZ$S;C6R{7kwTJ&crIAd^QgeG4gYe6jFDd6f>TEo2y&xY_A)ITX_->^K%ao+prImk3 zeXfvetgyGYm%L)VymD_l;`#1Jn7PbD#e5C*UFi=;8_I&1Y2DrCocuai-C|^9WIpFV z8ZLsRnLo9f5!JutHSxZ+PFcI~(lm@o_^mlNQap?$13`Je!j286iR4u0mWV6 z;cCT!K~B5(2}c$p5f^nxi{^6G=k9ycHmtQjUBkZ+@2M-AE>F9KAV)W%N%K0XJmVnI z)XZ+2-YjC=@SWX%Y4(jM-$Ug&qXbvkW9^p-S54kt(8dPoxe^n~S0vUs>iNW{XQ#c7 z@Whq|8_(rS9zD-wOi-2DpWdlhF${qX9#!(5(bk;z3X2_VGpUL+G9QnLMLfxUnq9X% z+S;Fi3;kLVDBMihB6Z>^pY@7E8HY+E@!MmX%aeWUp9hCUXdSybT`fc2im8`&(=Qeu zu6GR2&M(WBGG4Y#ZK3wLzeaz--vNu$(!jFvAM*Z?dr0M%v$Gw1K~1E)JNDt~iobPf zMn0OCL9sSR{T{F8r}y8gnJaUIWGY55X|?1&(R-Z88I={{eBk^fi*0Sk7yE!z^)Aoe z{UeHu!nD;B+jR_)31`06fEtdbIBwxx1MSlOoujhG(<1wU)2)5rtHxZmw7L3nQN5#A&oz_&Q+9n}U)P(3 z?aiicW*;mzOlX`$Nwh^gUD z^+j=m-`MJ!`4Y)vFg8MPkE5f%~3`;ISX4-g{ozpZb?1;3c}_X zvsPw;ktVZEoS9ydvbnjho|x~jQyG0Z!++2N zl~jh;%waeur`RSIKjeJ>bwkkvg5e`c-Pfc|LqS)27+vWCUCN7ZBB)|;Vq(#f1@e$X z7miDyhX}2`qtLF$0cq}N=?@ARJmg79j&^L`O_FJREZE8GH!04p@4gW0?^^T_y?&!d zlx18bt#NCWI&Q?lhsJ7YE2;3YQ)+gfd#%n!6y4tRvruQI)S$QL@_xoWppyZp9mGGd5-#Ut$F6&aPp{x zEc-X_orl+-Uo9B;9gD~DuoKv%WiRShRQqjv_lWE(GAg=KEVhWZ%sK7zUHQCo zTSmn%?I#1N3-&PEs>V6u$dC3YIz>?Q(m!rIXjk8OY5V2ehf|p%6X6U(%&pL;Fy*5 z%dMQ9rc~_N>*ktz7XFYQ%X!3Axm$8MXnpZ`)ZEhV+u-YHI%ue>Kij+rdVeEtbDl$d zvd#I$q~c;hj<#}ju))()#}k>2G($n05LM*G4twdz84sKJC3K&6-S2l%ES2AeIXEZ1 z(AwzC;(g3z{SjMkYpaa4!+$RlYenHpb%&z7z&r9KI*A8&N)Xn9igXAnL+yjQ)Ml2E z^gof`RlS?NrWq1T6uSypApVl;DpB$WVIZ0l|Hb-_kV_#pxB(U~tWczN+m76KDe%2e zqOJ#eMbi+Qc&93xH~vf?^F?IY7_GVzqL?%aDq7B~v{l}Gkn@@ zuxOXai0Z@L;rl)sKUEY@KZ>K$2%#ZCMW9i$CUVtovxyS@<6E%ws9@)>EIkY`z3!PiJM1+U!3U)D7mFsq3u zD9@0y>(<@kcJv~7(Ev&GdhjtY%ZmhZj|7~%t3!db%Fl@Ok|KYEVA0$nlf&Zw`0xez z0}3xy7nJ@3wDB(7=}n1a_Zig#p1&bt>hbSU3Zeu>f_UFQWCP

VwBP_zp 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�K;`40nx=qTuW_6o9F1A;Tn7DkN*gUgI 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 NEunBb>!!iu{{j8}3?={o literal 0 HcmV?d00001 diff --git a/docs/media/continuous_integration_practices.png b/docs/media/continuous_integration_practices.png new file mode 100644 index 0000000000000000000000000000000000000000..03a69a477a3d448b55ed83b5a3ad88e754684c76 GIT binary patch literal 405660 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

?B17w;+S)7TiHB(Hxm!1%285h&NC5k7 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≫7bzO z%yYAlibzl)v;^urM8}^BKWIa{LxWG2{C9C!B?uo19C(a9$)qmkl2Ac|lc+pfyZ++WKfXN2Cd>$L*jj zDbc)?WogA>V8m`J1h@7olS=ljl9ldi*KLb;V|L!bZ~rpg=5GUO!QYltBKJ#;SmX)y zJalz44oss&4$b$aAkt%{j6l;s*}VBt`>A8)0}cY64y?fBF@*+S3T3-_shSeLDnaK* z`O^F>^InP|0bnkPwggHh^@oCj>LQB_+VUtfg{|nx_aGppPdJi#AH>`BfxX6V^rCG$ zk^{H-aB2NRacL`O&<~OJ{xTN#>e@KZ$3G#ztK%kNT5p<~GH7U1uOD%p_2ODR*e%Zg zRF>mo#1M!nDT5jfJgDfT+})5Gdua@`Cq*sd=u@OsZtX-i@AR`h;}!+uJZ(7P-Y7(S z)M18Zsc+1wQ7GT6KT7}L;)w5?=)5wjGZ&Y2Z%MuhshvIKm`vl*BA6E;Ni-`-cQb&tIBkrdr#(q=2-m#B>{;2a2%s{<756>dGNIr(>V&^`?|As+B>7EtmbZ zfck2D!3e(d4E1x#6S0>+y?kH_Dh3^w0yX=V6UPsyLDD*Zqw~rLP+zRVs0CTHt&yY) z7p~vroPDPCRIZ&Wyrre(;Rp7=ss}-o7hR8Ap6quLkoZsS)lR$K=0h+wSjgg=rWw@PzeL+^xtZH?MJTlr^aL4t-&~@dlsb+7=P3_lW1g5(qhZNG!m{e)&Le#_FSI8tlY2HNOU|6iF*^A9l%_J)(FnPD2ycc@nG7c9w4*@|Dq z^95zQuNgSTeZ_Ezcs@1t-`k!aqIMXw(z*bLJgnkh*>RdFHkB{0D5$t|S}}TN6}}To z{zL~QYsFk1pDM^tzjBwuxbG^POW*8e}makXcZl% z0IG#Q0(fQ@ck7sc;k=4!0$;x8YFrQ>@YnS|f#`=t**l7_wud+YIJ6+{IyoTu8=dt- zzg~Kh1Z3p!{BsV=U-Ri-!W4WE6(<1i?2aqj`6;sZJ3o0C?N)LlCZwW&-t+&-OXw?I z-5?nODWbEg{`L1izXQt62zb*^n75bq=gZ#>nZLgb!if%St-R4>{q^@hgcS%Q_@Pap zB>aw|U-84wcmVGpmj=20|DhQ0%>PjQeUtr(g(uf&bvCreO zvcI7L&O-kXJ0#3Nx^zRVepLaQkbza>iC~lNFZMu-hy=oOWc!_Tn%x#sFTRSMC%Bl$ z>i0FB9?d@d&J_QLjJkxWU3Km!QTz`P^J7iJf1*X{MugN4Q~U2??q@Lu`q-oMM?dcV z%^O6cFU=3r8k_#|^caL5+HXDpN#D`<`zbk2sgoR~djI=WjbD3;|9JHiJ`8c9;+X2d ze<4$U3QzwG(62GcOb6&Rv+Va9|N3v>%e@5nV}H*H%JTlPy#GWwSTK}@*~HrLzhe-c z`vV=epeYRh2HmaafOg??rT%_|?l)vPSzrkIgyMx;(*Fi&8Ztl=wGNSwv+hRWYy&J&wE2}{NzhmJ#6i!Aq W88d^+y_8enKM66J`?+`Zy#611=sN%a literal 0 HcmV?d00001 diff --git a/docs/security.md b/docs/security.md new file mode 100644 index 00000000000..edaedaf1ecd --- /dev/null +++ b/docs/security.md @@ -0,0 +1,110 @@ +--- +title: Security +description: Security practices and processes for Powertools for AWS Lambda (Python) +--- + + + +## Overview + +[![Open Source Security Foundation Best Practices](https://bestpractices.coreinfrastructure.org/projects/7535/badge)](https://bestpractices.coreinfrastructure.org/projects/7535) + +This page describes our security processes and supply chain practices. + +!!! info "We continuously check and evolve our practices, therefore it is possible some diagrams may be eventually consistent." + +--8<-- "SECURITY.md" + +## Supply chain + +### Verifying signed builds + +!!! note "Starting from v2.20.0 releases, builds are [reproducible](https://slsa.dev/spec/v0.1/faq#q-what-about-reproducible-builds){target="_blank"} and signed publicly." + +
+![SLSA Supply Chain Threats](https://slsa.dev/images/v1.0/supply-chain-threats.svg) + +Supply Chain Threats visualized by SLSA +
+ +#### Terminology + +We use [SLSA](https://slsa.dev/spec/v1.0/about){target="_blank"} to ensure our builds are reproducible and to adhere to [supply chain security practices](https://slsa.dev/spec/v1.0/threats-overview). + +Within our [releases page](https://github.com/aws-powertools/powertools-lambda-python/releases), you will notice a new metadata file: `multiple.intoto.jsonl`. It's metadata to describe **where**, **when**, and **how** our build artifacts were produced - or simply, **attestation** in SLSA terminology. + +For this to be useful, we need a **verification tool** - [SLSA Verifier](https://github.com/slsa-framework/slsa-verifier). SLSA Verifier decodes attestation to confirm the authenticity, identity, and the steps we took in our release pipeline (_e.g., inputs, git commit/branch, GitHub org/repo, build SHA256, etc._). + +#### HOWTO + +You can do this manually or automated via a shell script. We maintain the latter to ease adoption in CI systems (feel free to modify to your needs). + +=== "Manually" + + * Download [SLSA Verifier binary](https://github.com/slsa-framework/slsa-verifier#download-the-binary) + * Download the [latest release artifact from PyPi](https://pypi.org/project/aws-lambda-powertools/#files) (either wheel or tar.gz ) + * Download `multiple.intoto.jsonl` attestation from the [latest release](https://github.com/aws-powertools/powertools-lambda-python/releases/latest) under _Assets_ + + !!! note "Next steps assume macOS as the operating system, and release v2.20.0" + + You should have the following files in the current directory: + + * **SLSA Verifier tool**: `slsa-verifier-darwin-arm64` + * **Powertools Release artifact**: `aws_lambda_powertools-2.20.0-py3-none-any.whl` + * **Powertools attestation**: `multiple.intoto.jsonl` + + You can now run SLSA Verifier with the following options: + + ```bash + ./slsa-verifier-darwin-arm64 verify-artifact \ + --provenance-path "multiple.intoto.jsonl" \ + --source-uri github.com/aws-powertools/powertools-lambda-python \ + aws_lambda_powertools-2.20.0-py3-none-any.whl + ``` + +=== "Automated" + + ```shell title="Verifying a release with verify_provenance.sh script" + bash verify_provenance.sh 2.20.0 + ``` + + !!! question "Wait, what does this script do?" + + I'm glad you asked! It takes the following actions: + + 1. **Downloads SLSA Verifier** using the pinned version (_e.g., 2.3.0) + 2. **Verifies the integrity** of our newly downloaded SLSA Verifier tool + 3. **Downloads attestation** file for the given release version + 4. **Downloads `aws-lambda-powertools`** release artifact from PyPi for the given release version + 5. **Runs SLSA Verifier against attestation**, GitHub Source, and release binary + 6. **Cleanup** by removing downloaded files to keep your current directory tidy + + ??? info "Expand or [click here](https://github.com/heitorlessa/aws-lambda-powertools-python/blob/refactor/ci-seal/.github/actions/verify-provenance/verify_provenance.sh#L95){target="_blank"} to see the script source code" + + ```bash title=".github/actions/verify-provenance/verify_provenance.sh" + ---8<-- ".github/actions/verify-provenance/verify_provenance.sh" + ``` + +### Continuous integration practices + +!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}." + +Since all code changes require a pull request (PR) along with one or more reviewers, we automate quality and security checks **before**, **during**, and **after** a PR is merged to trunk (`develop`). + +This is a snapshot of our automated checks at a glance. + + + +![Continuous Integration practices](./media/continuous_integration_practices.png) + +### Continuous deployment practices + +!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}." + +Releases are triggered by maintainers along with a reviewer - [detailed info here](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md#releasing-a-new-version){target="_blank"}. In addition to [checks that run for every code change](#continuous-integration-practices), our pipeline requires a manual approval before releasing. + +We use a combination of provenance and signed attestation for our builds, source code sealing, SAST scanners, Python specific static code analysis, ephemeral credentials that last a given job step, and more. + +This is a snapshot of our automated checks at a glance. + +![Continuous Deployment practices](./media/continuous_deployment_practices.png) diff --git a/mkdocs.yml b/mkdocs.yml index b2de3b79a96..2315152a3c9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -12,6 +12,7 @@ nav: - API reference: api/" target="_blank - Upgrade guide: upgrade.md - We Made This (Community): we_made_this.md + - Security: security.md - Core utilities: - core/tracer.md - core/logger.md From d9dba96f63c62fa4ecd4a2f818f78b2eb53a0f26 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 12 Jul 2023 14:55:54 +0100 Subject: [PATCH 58/73] chore(streaming): replace deprecated Version classes from distutils (#2752) --- aws_lambda_powertools/utilities/streaming/compat.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/utilities/streaming/compat.py b/aws_lambda_powertools/utilities/streaming/compat.py index 383edb8b70a..531c7c6e7fa 100644 --- a/aws_lambda_powertools/utilities/streaming/compat.py +++ b/aws_lambda_powertools/utilities/streaming/compat.py @@ -7,7 +7,6 @@ this file completely. See https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html. """ import logging -from distutils.version import StrictVersion from io import IOBase from typing import Optional @@ -24,7 +23,11 @@ logger = logging.getLogger(__name__) -if StrictVersion(botocore.__version__) < StrictVersion("1.29.13"): # noqa: C901 +# Splitting the botocore version string into major, minor, and patch versions, +# and performing a conditional check based on the extracted versions. +major, minor, patch = map(int, botocore.__version__.split(".")) + +if major == 1 and (minor < 29 or patch < 13): class PowertoolsStreamingBody(IOBase): """Wrapper class for a HTTP response body. From 4585cfc0329a7eecebb5850b214302afa26fca30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jul 2023 22:44:54 +0100 Subject: [PATCH 59/73] chore(deps-dev): bump ruff from 0.0.277 to 0.0.278 (#2758) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 38 +++++++++++++++++++------------------- pyproject.toml | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/poetry.lock b/poetry.lock index 25a34953a45..1ef12ae7c7d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2272,28 +2272,28 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.0.277" +version = "0.0.278" description = "An extremely fast Python linter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.0.277-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:3250b24333ef419b7a232080d9724ccc4d2da1dbbe4ce85c4caa2290d83200f8"}, - {file = "ruff-0.0.277-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:3e60605e07482183ba1c1b7237eca827bd6cbd3535fe8a4ede28cbe2a323cb97"}, - {file = "ruff-0.0.277-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7baa97c3d7186e5ed4d5d4f6834d759a27e56cf7d5874b98c507335f0ad5aadb"}, - {file = "ruff-0.0.277-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74e4b206cb24f2e98a615f87dbe0bde18105217cbcc8eb785bb05a644855ba50"}, - {file = "ruff-0.0.277-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:479864a3ccd8a6a20a37a6e7577bdc2406868ee80b1e65605478ad3b8eb2ba0b"}, - {file = "ruff-0.0.277-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:468bfb0a7567443cec3d03cf408d6f562b52f30c3c29df19927f1e0e13a40cd7"}, - {file = "ruff-0.0.277-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f32ec416c24542ca2f9cc8c8b65b84560530d338aaf247a4a78e74b99cd476b4"}, - {file = "ruff-0.0.277-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:14a7b2f00f149c5a295f188a643ac25226ff8a4d08f7a62b1d4b0a1dc9f9b85c"}, - {file = "ruff-0.0.277-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9879f59f763cc5628aa01c31ad256a0f4dc61a29355c7315b83c2a5aac932b5"}, - {file = "ruff-0.0.277-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f612e0a14b3d145d90eb6ead990064e22f6f27281d847237560b4e10bf2251f3"}, - {file = "ruff-0.0.277-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:323b674c98078be9aaded5b8b51c0d9c424486566fb6ec18439b496ce79e5998"}, - {file = "ruff-0.0.277-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3a43fbe026ca1a2a8c45aa0d600a0116bec4dfa6f8bf0c3b871ecda51ef2b5dd"}, - {file = "ruff-0.0.277-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:734165ea8feb81b0d53e3bf523adc2413fdb76f1264cde99555161dd5a725522"}, - {file = "ruff-0.0.277-py3-none-win32.whl", hash = "sha256:88d0f2afb2e0c26ac1120e7061ddda2a566196ec4007bd66d558f13b374b9efc"}, - {file = "ruff-0.0.277-py3-none-win_amd64.whl", hash = "sha256:6fe81732f788894a00f6ade1fe69e996cc9e485b7c35b0f53fb00284397284b2"}, - {file = "ruff-0.0.277-py3-none-win_arm64.whl", hash = "sha256:2d4444c60f2e705c14cd802b55cd2b561d25bf4311702c463a002392d3116b22"}, - {file = "ruff-0.0.277.tar.gz", hash = "sha256:2dab13cdedbf3af6d4427c07f47143746b6b95d9e4a254ac369a0edb9280a0d2"}, + {file = "ruff-0.0.278-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:1a90ebd8f2a554db1ee8d12b2f3aa575acbd310a02cd1a9295b3511a4874cf98"}, + {file = "ruff-0.0.278-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:38ca1c0c8c1221fe64c0a66784c91501d09a8ed02a4dbfdc117c0ce32a81eefc"}, + {file = "ruff-0.0.278-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c62a0bde4d20d087cabce2fa8b012d74c2e985da86d00fb3359880469b90e31"}, + {file = "ruff-0.0.278-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7545bb037823cd63dca19280f75a523a68bd3e78e003de74609320d6822b5a52"}, + {file = "ruff-0.0.278-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb380d2d6fdb60656a0b5fa78305535db513fc72ce11f4532cc1641204ef380"}, + {file = "ruff-0.0.278-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d11149c7b186f224f2055e437a030cd83b164a43cc0211314c33ad1553ed9c4c"}, + {file = "ruff-0.0.278-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:666e739fb2685277b879d493848afe6933e3be30d40f41fe0e571ad479d57d77"}, + {file = "ruff-0.0.278-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ec8b0469b54315803aaf1fbf9a37162a3849424cab6182496f972ad56e0ea702"}, + {file = "ruff-0.0.278-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c25b96602695a147d62a572865b753ef56aff1524abab13b9436724df30f9bd7"}, + {file = "ruff-0.0.278-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a48621f5f372d5019662db5b3dbfc5f1450f927683d75f1153fe0ebf20eb9698"}, + {file = "ruff-0.0.278-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1078125123a3c68e92463afacedb7e41b15ccafc09e510c6c755a23087afc8de"}, + {file = "ruff-0.0.278-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3ce0d620e257b4cad16e2f0c103b2f43a07981668a3763380542e8a131d11537"}, + {file = "ruff-0.0.278-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1cae4c07d334eb588f171f1363fa89a8911047eb93184276be11a24dbbc996c7"}, + {file = "ruff-0.0.278-py3-none-win32.whl", hash = "sha256:70d39f5599d8449082ab8ce542fa98e16413145eb411dd1dc16575b44565d52d"}, + {file = "ruff-0.0.278-py3-none-win_amd64.whl", hash = "sha256:e131595ab7f4ce61a1650463bd2fe304b49e7d0deb0dfa664b92817c97cdba5f"}, + {file = "ruff-0.0.278-py3-none-win_arm64.whl", hash = "sha256:737a0cfb6c36aaa92d97a46957dfd5e55329299074ad06ed12663b98e0c6fc82"}, + {file = "ruff-0.0.278.tar.gz", hash = "sha256:1a9f1d925204cfba81b18368b7ac943befcfccc3a41e170c91353b674c6b7a66"}, ] [[package]] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "85c26ffbf49fbfeaa6d43f9dd523f379c8b3ffd99f60070f7ddb5ead0b525749" +content-hash = "ff7263132eb51129dddb083b164cb96f98cd9bf68f4937ee9180fa494de4d531" diff --git a/pyproject.toml b/pyproject.toml index da4dd62a833..317fadd8de2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" sentry-sdk = "^1.22.2" -ruff = ">=0.0.272,<0.0.278" +ruff = ">=0.0.272,<0.0.279" retry2 = "^0.9.5" [tool.coverage.run] From 1664713ca04cc0b8e49fc564018d215ade66776b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jul 2023 22:45:21 +0100 Subject: [PATCH 60/73] chore(deps): bump docker/setup-buildx-action from 2.9.0 to 2.9.1 (#2755) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish_v2_layer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index 82ff1488f55..8d37b8f9828 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -122,7 +122,7 @@ jobs: # NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM) - name: Set up Docker Buildx id: builder - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 + uses: docker/setup-buildx-action@4c0219f9ac95b02789c1075625400b2acbff50b1 # v2.9.1 with: install: true driver: docker From 65c9f8ae9f8c60ccc1c73f5fad410d9172fb294d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 05:59:46 +0100 Subject: [PATCH 61/73] chore(deps-dev): bump pytest-asyncio from 0.21.0 to 0.21.1 (#2756) --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1ef12ae7c7d..a6ee1a8d067 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1878,13 +1878,13 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "pytest-asyncio" -version = "0.21.0" +version = "0.21.1" description = "Pytest support for asyncio" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-asyncio-0.21.0.tar.gz", hash = "sha256:2b38a496aef56f56b0e87557ec313e11e1ab9276fc3863f6a7be0f1d0e415e1b"}, - {file = "pytest_asyncio-0.21.0-py3-none-any.whl", hash = "sha256:f2b3366b7cd501a4056858bd39349d5af19742aed2d81660b7998b6341c7eb9c"}, + {file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"}, + {file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "ff7263132eb51129dddb083b164cb96f98cd9bf68f4937ee9180fa494de4d531" +content-hash = "c04b158500c12b4a5cb2acc0263b900a463bd6a61aab9c751054a06d61becf49" diff --git a/pyproject.toml b/pyproject.toml index 317fadd8de2..381449bab99 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ isort = "^5.11.5" pytest-cov = "^4.1.0" pytest-mock = "^3.11.1" pdoc3 = "^0.10.0" -pytest-asyncio = "^0.21.0" +pytest-asyncio = "^0.21.1" bandit = "^1.7.5" radon = "^5.1.0" xenon = "^0.9.0" From 88b1c28959f41178ceb7665e328b4e53d55233aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 06:01:02 +0100 Subject: [PATCH 62/73] chore(deps): bump pypa/gh-action-pypi-publish from 1.8.7 to 1.8.8 (#2754) --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 96b66d71823..c87b4c72154 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -237,12 +237,12 @@ jobs: - name: Upload to PyPi prod if: ${{ !inputs.skip_pypi }} - uses: pypa/gh-action-pypi-publish@f5622bde02b04381239da3573277701ceca8f6a0 # v1.8.7 + uses: pypa/gh-action-pypi-publish@f8c70e705ffc13c3b4d1221169b84f12a75d6ca8 # v1.8.8 # PyPi test maintenance affected us numerous times, leaving for history purposes # - name: Upload to PyPi test # if: ${{ !inputs.skip_pypi }} - # uses: pypa/gh-action-pypi-publish@f5622bde02b04381239da3573277701ceca8f6a0 # v1.8.7 + # uses: pypa/gh-action-pypi-publish@f8c70e705ffc13c3b4d1221169b84f12a75d6ca8 # v1.8.8 # with: # repository-url: https://test.pypi.org/legacy/ From 0523ff64606514ea3e59c07c8c69c83d751f61fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 06:36:53 +0100 Subject: [PATCH 63/73] chore(deps-dev): bump cfn-lint from 0.77.10 to 0.78.1 (#2757) --- poetry.lock | 12 ++++++------ pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index a6ee1a8d067..83b77115ee9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -365,20 +365,20 @@ files = [ [[package]] name = "cfn-lint" -version = "0.77.10" +version = "0.78.1" description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ - {file = "cfn-lint-0.77.10.tar.gz", hash = "sha256:c3bd6f5ae12641b6f99e100a4654e12448a9e16a0e0579afec8369709e12c904"}, - {file = "cfn_lint-0.77.10-py3-none-any.whl", hash = "sha256:88ecb273a1a1770f206b957374cf33cb0b0779d14da482e9800e879897af9fa0"}, + {file = "cfn-lint-0.78.1.tar.gz", hash = "sha256:46118362b2e13b79ba3ae6b3c28b7df5fcd437c06f5bcc3384d13a2defdb7d06"}, + {file = "cfn_lint-0.78.1-py3-none-any.whl", hash = "sha256:2dacb19d5f70c0d49f466302507707cfa4914f65b8fc9310ae3771a273cec044"}, ] [package.dependencies] -aws-sam-translator = ">=1.68.0" +aws-sam-translator = ">=1.70.0" jschema-to-python = ">=1.2.3,<1.3.0" jsonpatch = "*" -jsonschema = ">=3.0,<5" +jsonschema = ">=3.0,<4.18" junit-xml = ">=1.9,<2.0" networkx = ">=2.4,<4" pyyaml = ">5.4" @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "c04b158500c12b4a5cb2acc0263b900a463bd6a61aab9c751054a06d61becf49" +content-hash = "063b702b25c1f2a7dab895b012d91b2f4d7765f806425e8c67726f4255dd1589" diff --git a/pyproject.toml b/pyproject.toml index 381449bab99..1c23a72a55e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,7 +86,7 @@ all = ["pydantic", "aws-xray-sdk", "fastjsonschema"] aws-sdk = ["boto3"] [tool.poetry.group.dev.dependencies] -cfn-lint = "0.77.10" +cfn-lint = "0.78.1" mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" From 8625ccb415ec6fe4f4213d75d96ae6418e7ffa0c Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Thu, 13 Jul 2023 15:22:24 +0200 Subject: [PATCH 64/73] docs(process): explain our integration automated checks; revamp navigation (#2764) --- MAINTAINERS.md | 805 +-------------------------------- docs/automation.md | 90 ++++ docs/diagram_src/cicd_steps.md | 106 +++++ docs/index.md | 8 +- docs/maintainers.md | 662 +++++++++++++++++++++++++++ docs/security.md | 24 +- docs/stylesheets/extra.css | 8 + mkdocs.yml | 64 +-- 8 files changed, 908 insertions(+), 859 deletions(-) create mode 100644 docs/automation.md create mode 100644 docs/diagram_src/cicd_steps.md create mode 100644 docs/maintainers.md diff --git a/MAINTAINERS.md b/MAINTAINERS.md index be831ef46d4..2fa7b2eed23 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -1,804 +1,3 @@ - -## Table of contents + -- [Overview](#overview) -- [Current Maintainers](#current-maintainers) -- [Emeritus](#emeritus) -- [Labels](#labels) -- [Maintainer Responsibilities](#maintainer-responsibilities) - - [Uphold Code of Conduct](#uphold-code-of-conduct) - - [Prioritize Security](#prioritize-security) - - [Review Pull Requests](#review-pull-requests) - - [Triage New Issues](#triage-new-issues) - - [Triage Bug Reports](#triage-bug-reports) - - [Triage RFCs](#triage-rfcs) - - [Releasing a new version](#releasing-a-new-version) - - [Release process visualized](#release-process-visualized) - - [Drafting release notes](#drafting-release-notes) - - [Run end to end tests](#run-end-to-end-tests) - - [Releasing a documentation hotfix](#releasing-a-documentation-hotfix) - - [Maintain Overall Health of the Repo](#maintain-overall-health-of-the-repo) - - [Manage Roadmap](#manage-roadmap) - - [Add Continuous Integration Checks](#add-continuous-integration-checks) - - [Negative Impact on the Project](#negative-impact-on-the-project) - - [Becoming a maintainer](#becoming-a-maintainer) -- [Common scenarios](#common-scenarios) - - [Contribution is stuck](#contribution-is-stuck) - - [Insufficient feedback or information](#insufficient-feedback-or-information) - - [Crediting contributions](#crediting-contributions) - - [Is that a bug?](#is-that-a-bug) - - [Mentoring contributions](#mentoring-contributions) - - [Long running issues or PRs](#long-running-issues-or-prs) -- [E2E framework](#e2e-framework) - - [Structure](#structure) - - [Mechanics](#mechanics) - - [Authoring a new feature E2E test](#authoring-a-new-feature-e2e-test) - - [1. Define infrastructure](#1-define-infrastructure) - - [2. Deploy/Delete infrastructure when tests run](#2-deploydelete-infrastructure-when-tests-run) - - [3. Access stack outputs for E2E tests](#3-access-stack-outputs-for-e2e-tests) - - [Internals](#internals) - - [Test runner parallelization](#test-runner-parallelization) - - [CDK CLI parallelization](#cdk-cli-parallelization) - -## Overview - -> **Please treat this content as a living document.** - -This is document explains who the maintainers are (see below), what they do in this repo, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). - -## Current Maintainers - -| Maintainer | GitHub ID | Affiliation | -| ----------------- | ------------------------------------------------------- | ----------- | -| Heitor Lessa | [heitorlessa](https://github.com/heitorlessa) | Amazon | -| Simon Thulbourn | [sthulb](https://github.com/sthulb) | Amazon | -| Ruben Fonseca | [rubenfonseca](https://github.com/rubenfonseca) | Amazon | -| Leandro Damascena | [leandrodamascena](https://github.com/leandrodamascena) | Amazon | - -## Emeritus - -Previous active maintainers who contributed to this project. - -| Maintainer | GitHub ID | Affiliation | -| ----------------- | ----------------------------------------------- | ----------- | -| Tom McCarthy | [cakepietoast](https://github.com/cakepietoast) | MongoDB | -| Nicolas Moutschen | [nmoutschen](https://github.com/nmoutschen) | Apollo | -| Alexander Melnyk | [am29d](https://github.com/am29d) | Amazon | -| Michal Ploski | [mploski](https://github.com/mploski) | Amazon | - -## Labels - -These are the most common labels used by maintainers to triage issues, pull requests (PR), and for project management: - -| Label | Usage | Notes | -| ---------------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -| triage | New issues that require maintainers review | Issue template | -| bug | Unexpected, reproducible and unintended software behavior | PR/Release automation; Doc snippets are excluded; | -| not-a-bug | New and existing bug reports incorrectly submitted as bug | Analytics | -| documentation | Documentation improvements | PR/Release automation; Doc additions, fixes, etc.; | -| feature-request | New or enhancements to existing features | Issue template | -| typing | New or enhancements to static typing | Issue template | -| RFC | Technical design documents related to a feature request | Issue template | -| bug-upstream | Bug caused by upstream dependency | | -| help wanted | Tasks you want help from anyone to move forward | Bandwidth, complex topics, etc. | -| need-customer-feedback | Tasks that need more feedback before proceeding | 80/20% rule, uncertain, etc. | -| need-more-information | Missing information before making any calls | | -| need-documentation | PR is missing or has incomplete documentation | | -| need-issue | PR is missing a related issue for tracking change | PR automation | -| need-rfc | Feature request requires a RFC to improve discussion | | -| pending-release | Merged changes that will be available soon | Release automation auto-closes/notifies it | -| revisit-in-3-months | Blocked issues/PRs that need to be revisited | Often related to `need-customer-feedback`, prioritization, etc. | -| breaking-change | Changes that will cause customer impact and need careful triage | | -| do-not-merge | PRs that are blocked for varying reasons | Timeline is uncertain | -| size/XS | PRs between 0-9 LOC | PR automation | -| size/S | PRs between 10-29 LOC | PR automation | -| size/M | PRs between 30-99 LOC | PR automation | -| size/L | PRs between 100-499 LOC | PR automation | -| size/XL | PRs between 500-999 LOC, often PRs that grown with feedback | PR automation | -| size/XXL | PRs with 1K+ LOC, largely documentation related | PR automation | -| tests | PRs that add or change tests | PR automation | -| `` | PRs related to a Powertools for AWS Lambda (Python) utility, e.g. `parameters`, `tracer` | PR automation | -| feature | New features or minor changes | PR/Release automation | -| dependencies | Changes that touch dependencies, e.g. Dependabot, etc. | PR/ automation | -| github-actions | Changes in GitHub workflows | PR automation | -| github-templates | Changes in GitHub issue/PR templates | PR automation | -| internal | Changes in governance and chores (linting setup, baseline, etc.) | PR automation | -| tech-debt | Changes in tech debt | | -| customer-reference | Authorization to use company name in our documentation | Public Relations | -| community-content | Suggested content to feature in our documentation | Public Relations | - -## Maintainer Responsibilities - -Maintainers are active and visible members of the community, and have [maintain-level permissions on a repository](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization). Use those privileges to serve the community and evolve code as follows. - -Be aware of recurring ambiguous situations and [document them](#common-scenarios) to help your fellow maintainers. - -### Uphold Code of Conduct - -Model the behavior set forward by the [Code of Conduct](CODE_OF_CONDUCT.md) and raise any violations to other maintainers and admins. There could be unusual circumstances where inappropriate behavior does not immediately fall within the [Code of Conduct](CODE_OF_CONDUCT.md). - -These might be nuanced and should be handled with extra care - when in doubt, do not engage and reach out to other maintainers and admins. - -### Prioritize Security - -Security is your number one priority. Maintainer's Github keys must be password protected securely and any reported security vulnerabilities are addressed before features or bugs. - -Note that this repository is monitored and supported 24/7 by Amazon Security, see [Reporting a Vulnerability](SECURITY.md) for details. - -### Review Pull Requests - -Review pull requests regularly, comment, suggest, reject, merge and close. Accept only high quality pull-requests. Provide code reviews and guidance on incoming pull requests. - -PRs are [labeled](#labels) based on file changes and semantic title. Pay attention to whether labels reflect the current state of the PR and correct accordingly. - -Use and enforce [semantic versioning](https://semver.org/) pull request titles, as these will be used for [CHANGELOG](CHANGELOG.md) and [Release notes](https://github.com/aws-powertools/powertools-lambda-python/releases) - make sure they communicate their intent at the human level. - -> TODO: This is an area we want to automate using the new GitHub GraphQL API. - -For issues linked to a PR, make sure `pending release` label is applied to them when merging. [Upon release](#releasing-a-new-version), these issues will be notified which release version contains their change. - -See [Common scenarios](#common-scenarios) section for additional guidance. - -### Triage New Issues - -Manage [labels](#labels), review issues regularly, and create new labels as needed by the project. Remove `triage` label when you're able to confirm the validity of a request, a bug can be reproduced, etc. Give priority to the original author for implementation, unless it is a sensitive task that is best handled by maintainers. - -> TODO: This is an area we want to automate using the new GitHub GraphQL API. - -Make sure issues are assigned to our [board of activities](https://github.com/orgs/awslabs/projects/51/) and have the right [status](https://docs.powertools.aws.dev/lambda/python/latest/roadmap/#roadmap-status-definition). - -Use our [labels](#labels) to signal good first issues to new community members, and to set expectation that this might need additional feedback from the author, other customers, experienced community members and/or maintainers. - -Be aware of [casual contributors](https://opensource.com/article/17/10/managing-casual-contributors) and recurring contributors. Provide the experience and attention you wish you had if you were starting in open source. - -See [Common scenarios](#common-scenarios) section for additional guidance. - -### Triage Bug Reports - -Be familiar with [our definition of bug](#is-that-a-bug). If it's not a bug, you can close it or adjust its title and labels - always communicate the reason accordingly. - -For bugs caused by upstream dependencies, replace `bug` with `bug-upstream` label. Ask the author whether they'd like to raise the issue upstream or if they prefer us to do so. - -Assess the impact and make the call on whether we need an emergency release. Contact other [maintainers](#current-maintainers) when in doubt. - -See [Common scenarios](#common-scenarios) section for additional guidance. - -### Triage RFCs - -RFC is a collaborative process to help us get to the most optimal solution given the context. Their purpose is to ensure everyone understands what this context is, their trade-offs, and alternative solutions that were part of the research before implementation begins. - -Make sure you ask these questions in mind when reviewing: - -- Does it use our [RFC template](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=RFC%2Ctriage&template=rfc.yml&title=RFC%3A+TITLE)? -- Does the match our [Tenets](https://docs.powertools.aws.dev/lambda/python/latest/#tenets)? -- Does the proposal address the use case? If so, is the recommended usage explicit? -- Does it focus on the mechanics to solve the use case over fine-grained implementation details? -- Can anyone familiar with the code base implement it? -- If approved, are they interested in contributing? Do they need any guidance? -- Does this significantly increase the overall project maintenance? Do we have the skills to maintain it? -- If we can't take this use case, are there alternative projects we could recommend? Or does it call for a new project altogether? - -When necessary, be upfront that the time to review, approve, and implement a RFC can vary - see [Contribution is stuck](#contribution-is-stuck). Some RFCs may be further updated after implementation, as certain areas become clearer. - -Some examples using our initial and new RFC templates: #92, #94, #95, #991, #1226 - -### Releasing a new version - -Firstly, make sure the commit history in the `develop` branch **(1)** it's up to date, **(2)** commit messages are semantic, and **(3)** commit messages have their respective area, for example `feat(logger): `, `chore(ci): ...`). - -**Looks good, what's next?** - -Kickoff the `Release` workflow with the intended version - this might take around 25m-30m to complete. - -Once complete, you can start drafting the release notes to let customers know **what changed and what's in it for them (a.k.a why they should care)**. We have guidelines in the release notes section so you know what good looks like. - -> **NOTE**: Documentation might take a few minutes to reflect the latest version due to caching and CDN invalidations. - -#### Release process visualized - -Every release makes hundreds of checks, security scans, canaries and deployments - all of these are automated. - -This is a close visual representation of the main steps (GitHub Actions UI should be the source of truth), along with the approximate time it takes for each key step to complete. - - - -```mermaid -gantt - -title Release process -dateFormat HH:mm -axisFormat %H:%M - -Release commit : milestone, m1, 10:00,2m - -section Seal - Bump release version : active, 8s - Prevent source tampering : active, 43s -section QA - Quality checks : active, 2.2m -section Build - Checksum : active, 8s - Build release artifact : active, 39s - Seal : active, 8s -section Provenance - Attest build : active, 8s - Sign attestation : active, attestation, 10:06, 8s - -section Release - Checksum : active, 8s - PyPi temp credentials : active, 8s - Publish PyPi : active, pypi, 10:07, 29s - -PyPi release : milestone, m2, 10:07,1s - -section Git release - Checksum : active, after pypi, 8s - Git Tag : active, 8s - Bump package version : active, 8s - Create PR : active, 8s - Upload attestation : active, 8s - -section Layer release - Build (x86+ARM) : active, layer_build, 10:08, 6m - Deploy Beta : active, layer_beta, after layer_build, 6.3m - Deploy Prod : active, layer_prod, after layer_beta, 6.3m - -Layer release : milestone, m3, 10:26,1s - -section SAR release - Deploy Beta : active, sar_beta, after layer_beta, 2.2m - Deploy Prod : active, sar_prod, after sar_beta, 2.2m - -SAR release : milestone, m4, 10:25,1s - -section Docs - Create PR (Layer ARN) : active, after layer_prod, 8s - Release versioned docs : active, 2.2m - -Documentation release : milestone, m4, 10:28,1m - -section Post-release - Close pending issues : active, 8s - -Release complete : milestone, m6, 10:31,2m -``` - -If we combine our CI and CD pipelines into a single diagram, it looks like this: - -```mermaid -timeline - title Powertools for AWS Lambda (Python) CI/CD pipeline - - section Continuous Integration - Project setup
(make dev) : Code checkout - : Virtual environment - : Dependencies - : Git pre-commit hooks - : Local branch - : Local changes - : Local tests - - Pre-commit checks
(git commit) : Merge conflict check - : Trailing whitespaces - : TOML checks - : Code linting (standards) - : Markdown linting - : CloudFormation linting - : GitHub Actions linting - : Terraform linting - : Secrets linting - - Pre-Pull Request
(make pr) : Code linting - : Docs linting - : Static typing analysis - : Tests (unit|functional|perf) - : Security baseline - : Complexity baseline - : +pre-commit checks - - Pull Request
(CI checks) : Semantic PR title check - : Related issue check - : Acknowledgment check - : Code coverage diff - : Contribution size check - : Contribution category check - : Dependency vulnerability check - : GitHub Actions security check - : +pre-pull request checks - - After merge
(CI checks) : End-to-end tests - : Longer SAST check - : Security posture check (scorecard) - : GitHub Actions security check - : Rebuild Changelog - : Deploy staging docs - : Update draft release - - section Continuous Delivery - - Source code anti-tampering : Checkout release commit code - : Bump release version - : Seal and upload artifact - - Quality Assurance : Restore sealed code - : +Continuous Integration checks - - Build : Restore sealed code - : Integrity check - : Build release artifact - : Seal and upload artifact - - Provenance : Detect build environment - : Generate SLSA Builder - : Verify SLSA Builder provenance - : Create and sign provenance - : Seal and upload artifact - : Write to public ledger - - Release : Restore sealed build - : Integrity check - : PyPi ephemeral credentials - : Publish PyPi - : Baking time - - Git tagging : Restore sealed code - : Integrity check - : Bump git tag - : Create temporary branch - : Create PR - - Lambda Layers : Fetch PyPi release - : Build x86 architecture - : Build ARM architecture - : Deploy Beta - : Canary testing - : Deploy Prod - - Lambda Layers SAR : Deploy Beta - : Deploy Prod - - Documentation : Update Lambda Layer ARNs - : Build User Guide - : Build API Guide - : Rebuild Changelog - : Release new version - : Update latest alias - : Create temporary branch - : Create PR - - Post-release : Close pending-release issues - : Notify customers -``` - -#### Drafting release notes - -Visit the [Releases page](https://github.com/aws-powertools/powertools-lambda-python/releases) and choose the edit pencil button. - -Make sure the `tag` field reflects the new version you're releasing, the target branch field is set to `develop`, and `release title` matches your tag e.g., `v1.26.0`. - -You'll notice we group all changes based on their [labels](#labels) like `feature`, `bug`, `documentation`, etc. - -**I spotted a typo or incorrect grouping - how do I fix it?** - -Edit the respective PR title and update their [labels](#labels). Then run the [Release Drafter workflow](https://github.com/aws-powertools/powertools-lambda-python/actions/workflows/release-drafter.yml) to update the Draft release. - -> **NOTE**: This won't change the CHANGELOG as the merge commit is immutable. Don't worry about it. We'd only rewrite git history only if this can lead to confusion and we'd pair with another maintainer. - -**All looking good, what's next?** - -The best part comes now. Replace the placeholder `[Human readable summary of changes]` with what you'd like to communicate to customers what this release is all about. Rule of thumb: always put yourself in the customers shoes. - -These are some questions to keep in mind when drafting your first or future release notes: - -- Can customers understand at a high level what changed in this release? -- Is there a link to the documentation where they can read more about each main change? -- Are there any graphics or [code snippets](carbon.now.sh/) that can enhance readability? -- Are we calling out any key contributor(s) to this release? - - All contributors are automatically credited, use this as an exceptional case to feature them - -Once you're happy, hit `Publish release` πŸŽ‰πŸŽ‰πŸŽ‰. - -This will kick off the [Publishing workflow](https://github.com/aws-powertools/powertools-lambda-python/actions/workflows/release.yml) and within a few minutes you should see the latest version in PyPi, and all issues labeled as `pending-release` will be closed and notified. - -### Run end to end tests - -E2E tests are run on every push to `develop` or manually via [run-e2e-tests workflow](https://github.com/aws-powertools/powertools-lambda-python/actions/workflows/run-e2e-tests.yml). - -To run locally, you need [AWS CDK CLI](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites) and an [account bootstrapped](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html) (`cdk bootstrap`). With a default AWS CLI profile configured, or `AWS_PROFILE` environment variable set, run `make e2e tests`. - -### Releasing a documentation hotfix - -You can rebuild the latest documentation without a full release via this [GitHub Actions Workflow](https://github.com/aws-powertools/powertools-lambda-python/actions/workflows/rebuild_latest_docs.yml). Choose `Run workflow`, keep `develop` as the branch, and input the latest Powertools for AWS Lambda (Python) version available. - -This workflow will update both user guide and API documentation. - -### Maintain Overall Health of the Repo - -> TODO: Coordinate renaming `develop` to `main` - -Keep the `develop` branch at production quality at all times. Backport features as needed. Cut release branches and tags to enable future patches. - -### Manage Roadmap - -See [Roadmap section](https://docs.powertools.aws.dev/lambda/python/latest/roadmap/) - -Ensure the repo highlights features that should be elevated to the project roadmap. Be clear about the feature’s status, priority, target version, and whether or not it should be elevated to the roadmap. - -### Add Continuous Integration Checks - -Add integration checks that validate pull requests and pushes to ease the burden on Pull Request reviewers. Continuously revisit areas of improvement to reduce operational burden in all parties involved. - -### Negative Impact on the Project - -Actions that negatively impact the project will be handled by the admins, in coordination with other maintainers, in balance with the urgency of the issue. Examples would be [Code of Conduct](CODE_OF_CONDUCT.md) violations, deliberate harmful or malicious actions, spam, monopolization, and security risks. - -### Becoming a maintainer - -In 2023, we will revisit this. We need to improve our understanding of how other projects are doing, their mechanisms to promote key contributors, and how they interact daily. - -We suspect this process might look similar to the [OpenSearch project](https://github.com/opensearch-project/.github/blob/main/MAINTAINERS.md#becoming-a-maintainer). - -## Common scenarios - -These are recurring ambiguous situations that new and existing maintainers may encounter. They serve as guidance. It is up to each maintainer to follow, adjust, or handle in a different manner as long as [our conduct is consistent](#uphold-code-of-conduct) - -### Contribution is stuck - -A contribution can get stuck often due to lack of bandwidth and language barrier. For bandwidth issues, check whether the author needs help. Make sure you get their permission before pushing code into their existing PR - do not create a new PR unless strictly necessary. - -For language barrier and others, offer a 1:1 chat to get them unblocked. Often times, English might not be their primary language, and writing in public might put them off, or come across not the way they intended to be. - -In other cases, you may have constrained capacity. Use `help wanted` label when you want to signal other maintainers and external contributors that you could use a hand to move it forward. - -### Insufficient feedback or information - -When in doubt, use `need-more-information` or `need-customer-feedback` labels to signal more context and feedback are necessary before proceeding. You can also use `revisit-in-3-months` label when you expect it might take a while to gather enough information before you can decide. - -### Crediting contributions - -We credit all contributions as part of each [release note](https://github.com/aws-powertools/powertools-lambda-python/releases) as an automated process. If you find contributors are missing from the release note you're producing, please add them manually. - -### Is that a bug? - -A bug produces incorrect or unexpected results at runtime that differ from its intended behavior. Bugs must be reproducible. They directly affect customers experience at runtime despite following its recommended usage. - -Documentation snippets, use of internal components, or unadvertised functionalities are not considered bugs. - -### Mentoring contributions - -Always favor mentoring issue authors to contribute, unless they're not interested or the implementation is sensitive (_e.g., complexity, time to release, etc._). - -Make use of `help wanted` and `good first issue` to signal additional contributions the community can help. - -### Long running issues or PRs - -Try offering a 1:1 call in the attempt to get to a mutual understanding and clarify areas that maintainers could help. - -In the rare cases where both parties don't have the bandwidth or expertise to continue, it's best to use the `revisit-in-3-months` label. By then, see if it's possible to break the PR or issue in smaller chunks, and eventually close if there is no progress. - -## E2E framework - -### Structure - -Our E2E framework relies on [Pytest fixtures](https://docs.pytest.org/en/6.2.x/fixture.html) to coordinate infrastructure and test parallelization - see [Test Parallelization](#test-runner-parallelization) and [CDK CLI Parallelization](#cdk-cli-parallelization). - -**tests/e2e structure** - -```shell -. -β”œβ”€β”€ __init__.py -β”œβ”€β”€ conftest.py # builds Lambda Layer once -β”œβ”€β”€ logger -β”‚ β”œβ”€β”€ __init__.py -β”‚ β”œβ”€β”€ conftest.py # deploys LoggerStack -β”‚ β”œβ”€β”€ handlers -β”‚ β”‚ └── basic_handler.py -β”‚ β”œβ”€β”€ infrastructure.py # LoggerStack definition -β”‚ └── test_logger.py -β”œβ”€β”€ metrics -β”‚ β”œβ”€β”€ __init__.py -β”‚ β”œβ”€β”€ conftest.py # deploys MetricsStack -β”‚ β”œβ”€β”€ handlers -β”‚ β”‚ β”œβ”€β”€ basic_handler.py -β”‚ β”‚ └── cold_start.py -β”‚ β”œβ”€β”€ infrastructure.py # MetricsStack definition -β”‚ └── test_metrics.py -β”œβ”€β”€ tracer -β”‚ β”œβ”€β”€ __init__.py -β”‚ β”œβ”€β”€ conftest.py # deploys TracerStack -β”‚ β”œβ”€β”€ handlers -β”‚ β”‚ β”œβ”€β”€ async_capture.py -β”‚ β”‚ └── basic_handler.py -β”‚ β”œβ”€β”€ infrastructure.py # TracerStack definition -β”‚ └── test_tracer.py -└── utils - β”œβ”€β”€ __init__.py - β”œβ”€β”€ data_builder # build_service_name(), build_add_dimensions_input, etc. - β”œβ”€β”€ data_fetcher # get_traces(), get_logs(), get_lambda_response(), etc. - β”œβ”€β”€ infrastructure.py # base infrastructure like deploy logic, etc. -``` - -Where: - -- **`/infrastructure.py`**. Uses CDK to define the infrastructure a given feature needs. -- **`/handlers/`**. Lambda function handlers to build, deploy, and exposed as stack output in PascalCase (e.g., `BasicHandler`). -- **`utils/`**. Test utilities to build data and fetch AWS data to ease assertion -- **`conftest.py`**. Deploys and deletes a given feature infrastructure. Hierarchy matters: - - **Top-level (`e2e/conftest`)**. Builds Lambda Layer only once and blocks I/O across all CPU workers. - - **Feature-level (`e2e//conftest`)**. Deploys stacks in parallel and make them independent of each other. - -### Mechanics - -Under [`BaseInfrastructure`](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/e2e/utils/infrastructure.py), we hide the complexity of deployment and delete coordination under `deploy`, `delete`, and `create_lambda_functions` methods. - -This allows us to benefit from test and deployment parallelization, use IDE step-through debugging for a single test, run one, subset, or all tests and only deploy their related infrastructure, without any custom configuration. - -> Class diagram to understand abstraction built when defining a new stack (`LoggerStack`) - -```mermaid -classDiagram - class InfrastructureProvider { - <> - +deploy() Dict - +delete() - +create_resources() - +create_lambda_functions() Dict~Functions~ - } - - class BaseInfrastructure { - +deploy() Dict - +delete() - +create_lambda_functions() Dict~Functions~ - +add_cfn_output() - } - - class TracerStack { - +create_resources() - } - - class LoggerStack { - +create_resources() - } - - class MetricsStack { - +create_resources() - } - - class EventHandlerStack { - +create_resources() - } - - InfrastructureProvider <|-- BaseInfrastructure : implement - BaseInfrastructure <|-- TracerStack : inherit - BaseInfrastructure <|-- LoggerStack : inherit - BaseInfrastructure <|-- MetricsStack : inherit - BaseInfrastructure <|-- EventHandlerStack : inherit -``` - -### Authoring a new feature E2E test - -Imagine you're going to create E2E for Event Handler feature for the first time. Keep the following mental model when reading: - -```mermaid -graph LR - A["1. Define infrastructure"]-->B["2. Deploy/Delete infrastructure"]-->C["3.Access Stack outputs" ] -``` - -#### 1. Define infrastructure - -We use CDK as our Infrastructure as Code tool of choice. Before you start using CDK, you'd take the following steps: - -1. Create `tests/e2e/event_handler/infrastructure.py` file -2. Create a new class `EventHandlerStack` and inherit from `BaseInfrastructure` -3. Override `create_resources` method and define your infrastructure using CDK -4. (Optional) Create a Lambda function under `handlers/alb_handler.py` - -> Excerpt `tests/e2e/event_handler/infrastructure.py` - -```python -class EventHandlerStack(BaseInfrastructure): - def create_resources(self): - functions = self.create_lambda_functions() - - self._create_alb(function=functions["AlbHandler"]) - ... - - def _create_alb(self, function: Function): - vpc = ec2.Vpc.from_lookup( - self.stack, - "VPC", - is_default=True, - region=self.region, - ) - - alb = elbv2.ApplicationLoadBalancer(self.stack, "ALB", vpc=vpc, internet_facing=True) - CfnOutput(self.stack, "ALBDnsName", value=alb.load_balancer_dns_name) - ... -``` - -> Excerpt `tests/e2e/event_handler/handlers/alb_handler.py` - -```python -from aws_lambda_powertools.event_handler import ALBResolver, Response, content_types - -app = ALBResolver() - - -@app.get("/todos") -def hello(): - return Response( - status_code=200, - content_type=content_types.TEXT_PLAIN, - body="Hello world", - cookies=["CookieMonster", "MonsterCookie"], - headers={"Foo": ["bar", "zbr"]}, - ) - - -def lambda_handler(event, context): - return app.resolve(event, context) -``` - -#### 2. Deploy/Delete infrastructure when tests run - -We need to create a Pytest fixture for our new feature under `tests/e2e/event_handler/conftest.py`. - -This will instruct Pytest to deploy our infrastructure when our tests start, and delete it when they complete whether tests are successful or not. Note that this file will not need any modification in the future. - -> Excerpt `conftest.py` for Event Handler - -```python -import pytest - -from tests.e2e.event_handler.infrastructure import EventHandlerStack - - -@pytest.fixture(autouse=True, scope="module") -def infrastructure(): - """Setup and teardown logic for E2E test infrastructure - - Yields - ------ - Dict[str, str] - CloudFormation Outputs from deployed infrastructure - """ - stack = EventHandlerStack() - try: - yield stack.deploy() - finally: - stack.delete() - -``` - -#### 3. Access stack outputs for E2E tests - -Within our tests, we should now have access to the `infrastructure` fixture we defined earlier in `tests/e2e/event_handler/conftest.py`. - -We can access any Stack Output using pytest dependency injection. - -> Excerpt `tests/e2e/event_handler/test_header_serializer.py` - -```python -@pytest.fixture -def alb_basic_listener_endpoint(infrastructure: dict) -> str: - dns_name = infrastructure.get("ALBDnsName") - port = infrastructure.get("ALBBasicListenerPort", "") - return f"http://{dns_name}:{port}" - - -def test_alb_headers_serializer(alb_basic_listener_endpoint): - # GIVEN - url = f"{alb_basic_listener_endpoint}/todos" - ... -``` - -### Internals - -#### Test runner parallelization - -Besides speed, we parallelize our end-to-end tests to ease asserting async side-effects may take a while per test too, _e.g., traces to become available_. - -The following diagram demonstrates the process we take every time you use `make e2e` locally or at CI: - -```mermaid -graph TD - A[make e2e test] -->Spawn{"Split and group tests
by feature and CPU"} - - Spawn -->|Worker0| Worker0_Start["Load tests"] - Spawn -->|Worker1| Worker1_Start["Load tests"] - Spawn -->|WorkerN| WorkerN_Start["Load tests"] - - Worker0_Start -->|Wait| LambdaLayer["Lambda Layer build"] - Worker1_Start -->|Wait| LambdaLayer["Lambda Layer build"] - WorkerN_Start -->|Wait| LambdaLayer["Lambda Layer build"] - - LambdaLayer -->|Worker0| Worker0_Deploy["Launch feature stack"] - LambdaLayer -->|Worker1| Worker1_Deploy["Launch feature stack"] - LambdaLayer -->|WorkerN| WorkerN_Deploy["Launch feature stack"] - - Worker0_Deploy -->|Worker0| Worker0_Tests["Run tests"] - Worker1_Deploy -->|Worker1| Worker1_Tests["Run tests"] - WorkerN_Deploy -->|WorkerN| WorkerN_Tests["Run tests"] - - Worker0_Tests --> ResultCollection - Worker1_Tests --> ResultCollection - WorkerN_Tests --> ResultCollection - - ResultCollection{"Wait for workers
Collect test results"} - ResultCollection --> TestEnd["Report results"] - ResultCollection --> DeployEnd["Delete Stacks"] -``` - -#### CDK CLI parallelization - -For CDK CLI to work with [independent CDK Apps](https://docs.aws.amazon.com/cdk/v2/guide/apps.html), we specify an output directory when synthesizing our stack and deploy from said output directory. - -```mermaid -flowchart TD - subgraph "Deploying distinct CDK Apps" - EventHandlerInfra["Event Handler CDK App"] --> EventHandlerSynth - TracerInfra["Tracer CDK App"] --> TracerSynth - EventHandlerSynth["cdk synth --out cdk.out/event_handler"] --> EventHandlerDeploy["cdk deploy --app cdk.out/event_handler"] - - TracerSynth["cdk synth --out cdk.out/tracer"] --> TracerDeploy["cdk deploy --app cdk.out/tracer"] - end -``` - -We create the typical CDK `app.py` at runtime when tests run, since we know which feature and Python version we're dealing with (locally or at CI). - -> Excerpt `cdk_app_V39.py` for Event Handler created at deploy phase - -```python -from tests.e2e.event_handler.infrastructure import EventHandlerStack -stack = EventHandlerStack() -stack.create_resources() -stack.app.synth() -``` - -When we run E2E tests for a single feature or all of them, our `cdk.out` looks like this: - -```shell -total 8 -drwxr-xr-x 18 lessa staff 576B Sep 6 15:38 event-handler -drwxr-xr-x 3 lessa staff 96B Sep 6 15:08 layer_build --rw-r--r-- 1 lessa staff 32B Sep 6 15:08 layer_build.diff -drwxr-xr-x 18 lessa staff 576B Sep 6 15:38 logger -drwxr-xr-x 18 lessa staff 576B Sep 6 15:38 metrics -drwxr-xr-x 22 lessa staff 704B Sep 9 10:52 tracer -``` - -```mermaid -classDiagram - class CdkOutDirectory { - feature_name/ - layer_build/ - layer_build.diff - } - - class EventHandler { - manifest.json - stack_outputs.json - cdk_app_V39.py - asset.uuid/ - ... - } - - class StackOutputsJson { - BasicHandlerArn: str - ALBDnsName: str - ... - } - - CdkOutDirectory <|-- EventHandler : feature_name/ - StackOutputsJson <|-- EventHandler -``` - -Where: - -- **``**. Contains CDK Assets, CDK `manifest.json`, our `cdk_app_.py` and `stack_outputs.json` -- **`layer_build`**. Contains our Lambda Layer source code built once, used by all stacks independently -- **`layer_build.diff`**. Contains a hash on whether our source code has changed to speed up further deployments and E2E tests - -Together, all of this allows us to use Pytest like we would for any project, use CDK CLI and its [context methods](https://docs.aws.amazon.com/cdk/v2/guide/context.html#context_methods) (`from_lookup`), and use step-through debugging for a single E2E test without any extra configuration. - -> NOTE: VSCode doesn't support debugging processes spawning sub-processes (like CDK CLI does w/ shell and CDK App). Maybe [this works](https://stackoverflow.com/a/65339352). PyCharm works just fine. +Maintainers' playbook moved: https://docs.powertools.aws.dev/lambda/python/latest/maintainers/ diff --git a/docs/automation.md b/docs/automation.md new file mode 100644 index 00000000000..d0aacb89977 --- /dev/null +++ b/docs/automation.md @@ -0,0 +1,90 @@ +--- +title: Automation +description: Automation practices and processes for Powertools for AWS Lambda (Python) +--- + + + +## Continuous integration practices + +!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}." + +Since all code changes require a pull request (PR) along with one or more reviewers, we automate quality and security checks **before**, **during**, and **after** a PR is merged to trunk (`develop`). + +We use a combination of tools coupled with peer review to increase its compound effect in detecting issues early. + +This is a snapshot of our automated checks at a glance. + + + +![Continuous Integration practices](./media/continuous_integration_practices.png) + +### Pre-commit checks + +> [**Pre-commit configuration**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml){target="_blank"}. + +Pre-commit checks are crucial for a fast feedback loop while ensuring security practices at the individual change level. + +To prevent scenarios where these checks are intentionally omitted at the client side, we run at [CI level too](#pull-request-checks). + +!!! note "These run locally only for changed files" + +* [**Merge conflict check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L10){target="_blank"}. Checks for merge strings in each individual change accidentally left unresolved to prevent breakage. +* [**Code linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L22){target="_blank"}. Linter checks for industry quality standards and known bad practices that could lead to abuse. +* [**CloudFormation linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L34){target="_blank"}. `cfn-lint` ensures [best practices](https://github.com/aws-cloudformation/cfn-lint/blob/86f0370bd43b400ed4c485180dbc2697f73367b2/docs/rules.md){target=""_blank"} at our documentation examples. +* [**Markdown linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L25){target="_blank}. Primarily [industry markdown practices](https://github.com/DavidAnson/markdownlint/blob/d01180ec5a014083ee9d574b693a8d7fbc1e566d/README.md#rules--aliases){target="_blank"} at this stage. +* [**GitHub Actions linting**](https://github.com/rhysd/actionlint/blob/main/docs/checks.md){target="_blank"}. `actionlint` ensures workflows follow [GitHub Actions security practices](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}. It guards against numerous [leading practices](https://github.com/rhysd/actionlint/blob/main/docs/checks.md){target="_blank"} to prevent common configuration mistakes, insecure inline scripts, among many others. +* [**Terraform linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L43){target="_blank"}. As of now, largely formatting until we increase our Terraform coverage in documentation examples. +* [**Secrets linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/.pre-commit-config.yaml#L49){target="_blank"}. Detects industry credentials that might be accidentally leaked in source code. + +### Pre-Pull Request checks + +For an improved contributing experience, most of our checks can run locally. For maintainers, this also means increased focus on reviewing actual value instead of standards and security malpractices that can be caught earlier. + +!!! note "These are in addition to [pre-commit checks](#pre-commit-checks)." + +* [**Static typing analysis**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L108). `mypy` checks for static typing annotations to prevent common bugs in Python that may or may not lead to abuse. +* [**Tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L31){target="_blank"}. We run `unit`, `functional`, and `performance` tests ([_see our definition_](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank"}). Besides breaking changes, we are investing in mutation testing to find additional sources of bugs and potential abuse. +* [**Security baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank"}. `bandit` detects common security issues defined by Python Code Quality Authority (PyCQA). +* [**Complexity baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L79){target="_blank"}. We run a series of maintenability and cyclomatic checks to reduce code and logic complexity. This aids reviewers' cognitive overhead and long-term maintainers revisiting legacy code at a later date. + +### Pull Request checks + +While we trust contributors and maintainers do go through pre-commit and pre-pull request due diligence, we verify them at CI level. + +!!! note "Checks described earlier are omitted to improve reading experience." + +* [**Semantic PR title**](https://github.com/Ezard/semantic-prs){target="_blank"}. We enforce PR titles follow semantic naming, for example `chore(category): change`. This benefits contributors with a lower entry bar, no need for semantic commits. It also benefits everyone looking for an [useful changelog message](https://docs.powertools.aws.dev/lambda/python/latest/changelog/){target="_blank"} on **what** changed and **where**. +* [**Related issue check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L44){target="_blank"}. [Every change require an issue](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#contributing-via-pull-requests){target="_blank"} describing its needs. This enforces a PR has a related issue by blocking merge operations if missing. +* [**Acknowledgment check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L63){target="_blank"}. [Ensures PR template](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/PULL_REQUEST_TEMPLATE.md#L36){target="_blank"} is used and every contributor is aware of code redistribution. +* [**Code coverage diff**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/quality_check.yml#L73){target="_blank"}. Educates contributors and maintainers about code coverage differences for a given change. +* [**Contribution size check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_label_added.yml#L44){target="_blank"}. Suggests contributors and maintainers to break up large changes (100-499 LOC) in smaller PRs. It helps reduce overlooking security and other practices due to increased cognitive overhead. +* [**Dependency vulnerability check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/dependency-review.yml#L22){target="_blank"}. Verifies any dependency changes for common vulnerability exposures (CVEs), in addition to our daily check on any dependencies used (e.g., Python, Docker, Go, etc.) +* [**GitHub Actions security check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/secure_workflows.yml#L35){target="_blank"}. Enforces use of immutable 3rd-party GitHub Actions (_e.g., `actions/checkout@_`) to prevent abuse. Upgrades are handled by a [separate automated process](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/dependabot.yml#L4){target="_blank"} that includes a maintainer review to also prevent unexpected behavior changes. + +### After merge checks + +!!! note "Checks described earlier are omitted to improve reading experience." + +We strike a balance in security and contribution experience. These automated checks take several minutes to complete. Failures are reviewed by a maintainer on-call and before a release. + +* [**End-to-end tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/run-e2e-tests.yml#L41){target="_blank"}. We run E2E with a [high degree of parallelization](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#test-runner-parallelization). While it is designed to also run locally, it may incur AWS charges to contributors. For additional security, all infrastructure is ephemeral per change and per Python version. +* [**SAST check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/codeql-analysis.yml#L20){target="_blank"}. GitHub CodeQL runs ~30m static analysis in the entire codebase. +* [**Security posture check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/ossf_scorecard.yml#L14){target="_blank"}. OSSF Scorecard runs numerous automated checks upon changes, and raises security alerts if [OSSF security practices](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"} are no longer followed. +* [**Rebuild Changelog**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/build_changelog.yml#L23){target="_blank"}. We rebuild our entire changelog upon changes and create a PR for maintainers. This has the added benefit in keeping a [protected branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches){target="_blank"} while keeping removing error-prone tasks from maintainers. +* [**Stage documentation**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_push_docs.yml#L27C16-L27C16){target="_blank"}. We rebuild and deploy changes to the documentation to a [staged version](https://docs.powertools.aws.dev/lambda/python/stage/){target="_blank"}. This gives us safety that our docs can always be rebuilt, and ready to release to production when needed. +* [**Update draft release**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/release-drafter.yml#L25){target="_blank"}. We use [Release Drafter](https://github.com/release-drafter/release-drafter){target="_blank"} to generate a portion of our release notes and to always keep a fresh draft upon changes. You can read our [thoughts on a good quality release notes here](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#drafting-release-notes){target="_blank"} (human readable changes + automation). + +## Continuous deployment practices + +!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}." + +Releases are triggered by maintainers along with a reviewer - [detailed info here](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md#releasing-a-new-version){target="_blank"}. In addition to [checks that run for every code change](#continuous-integration-practices), our pipeline requires a manual approval before releasing. + +We use a combination of provenance and signed attestation for our builds, source code sealing, SAST scanners, Python specific static code analysis, ephemeral credentials that last a given job step, and more. + +This is a snapshot of our automated checks at a glance. + +![Continuous Deployment practices](./media/continuous_deployment_practices.png) + +!!! info "More details to come" diff --git a/docs/diagram_src/cicd_steps.md b/docs/diagram_src/cicd_steps.md new file mode 100644 index 00000000000..381ec9ea5b3 --- /dev/null +++ b/docs/diagram_src/cicd_steps.md @@ -0,0 +1,106 @@ + + +```mermaid +timeline + title Powertools for AWS Lambda (Python) CI/CD pipeline + + section Continuous Integration + Project setup
(make dev) : Code checkout + : Virtual environment + : Dependencies + : Git pre-commit hooks + : Local branch + : Local changes + : Local tests + + Pre-commit checks
(git commit) : Merge conflict check + : Trailing whitespaces + : TOML checks + : Code linting (standards) + : Markdown linting + : CloudFormation linting + : GitHub Actions linting + : Terraform linting + : Secrets linting + + Pre-Pull Request
(make pr) : Code linting + : Docs linting + : Static typing analysis + : Tests (unit|functional|perf) + : Security baseline + : Complexity baseline + : +pre-commit checks + + Pull Request
(CI checks) : Semantic PR title check + : Related issue check + : Acknowledgment check + : Code coverage diff + : Contribution size check + : Contribution category check + : Dependency vulnerability check + : GitHub Actions security check + : +pre-pull request checks + + After merge
(CI checks) : End-to-end tests + : Longer SAST check + : Security posture check (scorecard) + : GitHub Actions security check + : Rebuild Changelog + : Deploy staging docs + : Update draft release + + section Continuous Delivery + + Source code anti-tampering : Checkout release commit code + : Bump release version + : Seal and upload artifact + + Quality Assurance : Restore sealed code + : +Continuous Integration checks + + Build : Restore sealed code + : Integrity check + : Build release artifact + : Seal and upload artifact + + Provenance : Detect build environment + : Generate SLSA Builder + : Verify SLSA Builder provenance + : Create and sign provenance + : Seal and upload artifact + : Write to public ledger + + Release : Restore sealed build + : Integrity check + : PyPi ephemeral credentials + : Publish PyPi + : Baking time + + Git tagging : Restore sealed code + : Integrity check + : Bump git tag + : Create temporary branch + : Create PR + + Lambda Layers : Fetch PyPi release + : Build x86 architecture + : Build ARM architecture + : Deploy Beta + : Canary testing + : Deploy Prod + + Lambda Layers SAR : Deploy Beta + : Deploy Prod + + Documentation : Update Lambda Layer ARNs + : Build User Guide + : Build API Guide + : Rebuild Changelog + : Release new version + : Update latest alias + : Create temporary branch + : Create PR + + Post-release : Close pending-release issues + : Notify customers +``` diff --git a/docs/index.md b/docs/index.md index 939a2da9c29..aab8f441b1e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,10 +26,12 @@ Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverles You can install Powertools for AWS Lambda (Python) using one of the following options: -* **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37**](#){: .copyMe}:clipboard: -* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37**](#){: .copyMe}:clipboard: +* **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:37**](# "Replace {region} with your AWS region, e.g., eu-west-1"){: .copyMe}:clipboard: +* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:37**](# "Replace {region} with your AWS region, e.g., eu-west-1"){: .copyMe}:clipboard: * **Pip**: **[`pip install "aws-lambda-powertools"`](#){: .copyMe}:clipboard:** +!!! question "Looking for Pip signed releases? [Learn more about verifying signed builds](./security.md#verifying-signed-builds)" + ??? question "Using Pip? You might need to install additional dependencies." [**Tracer**](./core/tracer.md){target="_blank"}, [**Validation**](./utilities/validation.md){target="_blank"} and [**Parser**](./utilities/parser.md){target="_blank"} require additional dependencies. If you prefer to install all of them, use [**`pip install "aws-lambda-powertools[all]"`**](#){: .copyMe}:clipboard:. @@ -42,7 +44,7 @@ You can install Powertools for AWS Lambda (Python) using one of the following op ### Local development -!!! info "Using Powertools for AWS Lambda (Python) via Lambda Layer? Simply add [**`"aws-lambda-powertools[all]"`**](#){: .copyMe}:clipboard: as a development dependency." +!!! info "Using Lambda Layer? Simply add [**`"aws-lambda-powertools[all]"`**](#){: .copyMe}:clipboard: as a development dependency." Powertools for AWS Lambda (Python) relies on the [AWS SDK bundled in the Lambda runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html){target="_blank"}. This helps us achieve an optimal package size and initialization. However, when developing locally, you need to install AWS SDK as a development dependency (not as a production dependency): diff --git a/docs/maintainers.md b/docs/maintainers.md new file mode 100644 index 00000000000..6fc00c83cd9 --- /dev/null +++ b/docs/maintainers.md @@ -0,0 +1,662 @@ +--- +title: Maintainers playbook +description: Playbook for active maintainers in Powertools for AWS Lambda (Python) +--- + + + +## Overview + +!!! note "Please treat this content as a living document." + +This is document explains who the maintainers are, their responsibilities, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). + +## Current Maintainers + +| Maintainer | GitHub ID | Affiliation | +| ----------------- | ------------------------------------------------------- | ----------- | +| Heitor Lessa | [heitorlessa](https://github.com/heitorlessa) | Amazon | +| Simon Thulbourn | [sthulb](https://github.com/sthulb) | Amazon | +| Ruben Fonseca | [rubenfonseca](https://github.com/rubenfonseca) | Amazon | +| Leandro Damascena | [leandrodamascena](https://github.com/leandrodamascena) | Amazon | + +## Emeritus + +Previous active maintainers who contributed to this project. + +| Maintainer | GitHub ID | Affiliation | +| ----------------- | ----------------------------------------------- | ----------- | +| Tom McCarthy | [cakepietoast](https://github.com/cakepietoast) | MongoDB | +| Nicolas Moutschen | [nmoutschen](https://github.com/nmoutschen) | Apollo | +| Alexander Melnyk | [am29d](https://github.com/am29d) | Amazon | +| Michal Ploski | [mploski](https://github.com/mploski) | Amazon | + +## Labels + +These are the most common labels used by maintainers to triage issues, pull requests (PR), and for project management: + +| Label | Usage | Notes | +| ---------------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------- | +| triage | New issues that require maintainers review | Issue template | +| bug | Unexpected, reproducible and unintended software behavior | PR/Release automation; Doc snippets are excluded; | +| not-a-bug | New and existing bug reports incorrectly submitted as bug | Analytics | +| documentation | Documentation improvements | PR/Release automation; Doc additions, fixes, etc.; | +| feature-request | New or enhancements to existing features | Issue template | +| typing | New or enhancements to static typing | Issue template | +| RFC | Technical design documents related to a feature request | Issue template | +| bug-upstream | Bug caused by upstream dependency | | +| help wanted | Tasks you want help from anyone to move forward | Bandwidth, complex topics, etc. | +| need-customer-feedback | Tasks that need more feedback before proceeding | 80/20% rule, uncertain, etc. | +| need-more-information | Missing information before making any calls | | +| need-documentation | PR is missing or has incomplete documentation | | +| need-issue | PR is missing a related issue for tracking change | PR automation | +| need-rfc | Feature request requires a RFC to improve discussion | | +| pending-release | Merged changes that will be available soon | Release automation auto-closes/notifies it | +| revisit-in-3-months | Blocked issues/PRs that need to be revisited | Often related to `need-customer-feedback`, prioritization, etc. | +| breaking-change | Changes that will cause customer impact and need careful triage | | +| do-not-merge | PRs that are blocked for varying reasons | Timeline is uncertain | +| size/XS | PRs between 0-9 LOC | PR automation | +| size/S | PRs between 10-29 LOC | PR automation | +| size/M | PRs between 30-99 LOC | PR automation | +| size/L | PRs between 100-499 LOC | PR automation | +| size/XL | PRs between 500-999 LOC, often PRs that grown with feedback | PR automation | +| size/XXL | PRs with 1K+ LOC, largely documentation related | PR automation | +| tests | PRs that add or change tests | PR automation | +| `` | PRs related to a Powertools for AWS Lambda (Python) utility, e.g. `parameters`, `tracer` | PR automation | +| feature | New features or minor changes | PR/Release automation | +| dependencies | Changes that touch dependencies, e.g. Dependabot, etc. | PR/ automation | +| github-actions | Changes in GitHub workflows | PR automation | +| github-templates | Changes in GitHub issue/PR templates | PR automation | +| internal | Changes in governance and chores (linting setup, baseline, etc.) | PR automation | +| tech-debt | Changes in tech debt | | +| customer-reference | Authorization to use company name in our documentation | Public Relations | +| community-content | Suggested content to feature in our documentation | Public Relations | + +## Maintainer Responsibilities + +Maintainers are active and visible members of the community, and have [maintain-level permissions on a repository](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization). Use those privileges to serve the community and evolve code as follows. + +Be aware of recurring ambiguous situations and [document them](#common-scenarios) to help your fellow maintainers. + +### Uphold Code of Conduct + +Model the behavior set forward by the [Code of Conduct](CODE_OF_CONDUCT.md) and raise any violations to other maintainers and admins. There could be unusual circumstances where inappropriate behavior does not immediately fall within the [Code of Conduct](CODE_OF_CONDUCT.md). + +These might be nuanced and should be handled with extra care - when in doubt, do not engage and reach out to other maintainers and admins. + +### Prioritize Security + +Security is your number one priority. Maintainer's Github keys must be password protected securely and any reported security vulnerabilities are addressed before features or bugs. + +Note that this repository is monitored and supported 24/7 by Amazon Security, see [Reporting a Vulnerability](SECURITY.md) for details. + +### Review Pull Requests + +Review pull requests regularly, comment, suggest, reject, merge and close. Accept only high quality pull-requests. Provide code reviews and guidance on incoming pull requests. + +PRs are [labeled](#labels) based on file changes and semantic title. Pay attention to whether labels reflect the current state of the PR and correct accordingly. + +Use and enforce [semantic versioning](https://semver.org/) pull request titles, as these will be used for [CHANGELOG](CHANGELOG.md) and [Release notes](https://github.com/aws-powertools/powertools-lambda-python/releases) - make sure they communicate their intent at the human level. + +> TODO: This is an area we want to automate using the new GitHub GraphQL API. + +For issues linked to a PR, make sure `pending release` label is applied to them when merging. [Upon release](#releasing-a-new-version), these issues will be notified which release version contains their change. + +See [Common scenarios](#common-scenarios) section for additional guidance. + +### Triage New Issues + +Manage [labels](#labels), review issues regularly, and create new labels as needed by the project. Remove `triage` label when you're able to confirm the validity of a request, a bug can be reproduced, etc. Give priority to the original author for implementation, unless it is a sensitive task that is best handled by maintainers. + +> TODO: This is an area we want to automate using the new GitHub GraphQL API. + +Make sure issues are assigned to our [board of activities](https://github.com/orgs/awslabs/projects/51/) and have the right [status](https://docs.powertools.aws.dev/lambda/python/latest/roadmap/#roadmap-status-definition). + +Use our [labels](#labels) to signal good first issues to new community members, and to set expectation that this might need additional feedback from the author, other customers, experienced community members and/or maintainers. + +Be aware of [casual contributors](https://opensource.com/article/17/10/managing-casual-contributors) and recurring contributors. Provide the experience and attention you wish you had if you were starting in open source. + +See [Common scenarios](#common-scenarios) section for additional guidance. + +### Triage Bug Reports + +Be familiar with [our definition of bug](#is-that-a-bug). If it's not a bug, you can close it or adjust its title and labels - always communicate the reason accordingly. + +For bugs caused by upstream dependencies, replace `bug` with `bug-upstream` label. Ask the author whether they'd like to raise the issue upstream or if they prefer us to do so. + +Assess the impact and make the call on whether we need an emergency release. Contact other [maintainers](#current-maintainers) when in doubt. + +See [Common scenarios](#common-scenarios) section for additional guidance. + +### Triage RFCs + +RFC is a collaborative process to help us get to the most optimal solution given the context. Their purpose is to ensure everyone understands what this context is, their trade-offs, and alternative solutions that were part of the research before implementation begins. + +Make sure you ask these questions in mind when reviewing: + +- Does it use our [RFC template](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=RFC%2Ctriage&template=rfc.yml&title=RFC%3A+TITLE)? +- Does the match our [Tenets](https://docs.powertools.aws.dev/lambda/python/latest/#tenets)? +- Does the proposal address the use case? If so, is the recommended usage explicit? +- Does it focus on the mechanics to solve the use case over fine-grained implementation details? +- Can anyone familiar with the code base implement it? +- If approved, are they interested in contributing? Do they need any guidance? +- Does this significantly increase the overall project maintenance? Do we have the skills to maintain it? +- If we can't take this use case, are there alternative projects we could recommend? Or does it call for a new project altogether? + +When necessary, be upfront that the time to review, approve, and implement a RFC can vary - see [Contribution is stuck](#contribution-is-stuck). Some RFCs may be further updated after implementation, as certain areas become clearer. + +Some examples using our initial and new RFC templates: #92, #94, #95, #991, #1226 + +### Releasing a new version + +Firstly, make sure the commit history in the `develop` branch **(1)** it's up to date, **(2)** commit messages are semantic, and **(3)** commit messages have their respective area, for example `feat(logger): `, `chore(ci): ...`). + +**Looks good, what's next?** + +Kickoff the `Release` workflow with the intended version - this might take around 25m-30m to complete. + +Once complete, you can start drafting the release notes to let customers know **what changed and what's in it for them (a.k.a why they should care)**. We have guidelines in the release notes section so you know what good looks like. + +> **NOTE**: Documentation might take a few minutes to reflect the latest version due to caching and CDN invalidations. + +#### Release process visualized + +Every release makes hundreds of checks, security scans, canaries and deployments - all of these are automated. + +This is a close visual representation of the main steps (GitHub Actions UI should be the source of truth), along with the approximate time it takes for each key step to complete. + + + +```mermaid +gantt + +title Release process +dateFormat HH:mm +axisFormat %H:%M + +Release commit : milestone, m1, 10:00,2m + +section Seal + Bump release version : active, 8s + Prevent source tampering : active, 43s +section QA + Quality checks : active, 2.2m +section Build + Checksum : active, 8s + Build release artifact : active, 39s + Seal : active, 8s +section Provenance + Attest build : active, 8s + Sign attestation : active, attestation, 10:06, 8s + +section Release + Checksum : active, 8s + PyPi temp credentials : active, 8s + Publish PyPi : active, pypi, 10:07, 29s + +PyPi release : milestone, m2, 10:07,1s + +section Git release + Checksum : active, after pypi, 8s + Git Tag : active, 8s + Bump package version : active, 8s + Create PR : active, 8s + Upload attestation : active, 8s + +section Layer release + Build (x86+ARM) : active, layer_build, 10:08, 6m + Deploy Beta : active, layer_beta, after layer_build, 6.3m + Deploy Prod : active, layer_prod, after layer_beta, 6.3m + +Layer release : milestone, m3, 10:26,1s + +section SAR release + Deploy Beta : active, sar_beta, after layer_beta, 2.2m + Deploy Prod : active, sar_prod, after sar_beta, 2.2m + +SAR release : milestone, m4, 10:25,1s + +section Docs + Create PR (Layer ARN) : active, after layer_prod, 8s + Release versioned docs : active, 2.2m + +Documentation release : milestone, m4, 10:28,1m + +section Post-release + Close pending issues : active, 8s + +Release complete : milestone, m6, 10:31,2m +``` + +#### Drafting release notes + +Visit the [Releases page](https://github.com/aws-powertools/powertools-lambda-python/releases) and choose the edit pencil button. + +Make sure the `tag` field reflects the new version you're releasing, the target branch field is set to `develop`, and `release title` matches your tag e.g., `v1.26.0`. + +You'll notice we group all changes based on their [labels](#labels) like `feature`, `bug`, `documentation`, etc. + +**I spotted a typo or incorrect grouping - how do I fix it?** + +Edit the respective PR title and update their [labels](#labels). Then run the [Release Drafter workflow](https://github.com/aws-powertools/powertools-lambda-python/actions/workflows/release-drafter.yml) to update the Draft release. + +> **NOTE**: This won't change the CHANGELOG as the merge commit is immutable. Don't worry about it. We'd only rewrite git history only if this can lead to confusion and we'd pair with another maintainer. + +**All looking good, what's next?** + +The best part comes now. Replace the placeholder `[Human readable summary of changes]` with what you'd like to communicate to customers what this release is all about. Rule of thumb: always put yourself in the customers shoes. + +These are some questions to keep in mind when drafting your first or future release notes: + +- Can customers understand at a high level what changed in this release? +- Is there a link to the documentation where they can read more about each main change? +- Are there any graphics or [code snippets](carbon.now.sh/) that can enhance readability? +- Are we calling out any key contributor(s) to this release? + - All contributors are automatically credited, use this as an exceptional case to feature them + +Once you're happy, hit `Publish release` πŸŽ‰πŸŽ‰πŸŽ‰. + +This will kick off the [Publishing workflow](https://github.com/aws-powertools/powertools-lambda-python/actions/workflows/release.yml) and within a few minutes you should see the latest version in PyPi, and all issues labeled as `pending-release` will be closed and notified. + +### Run end to end tests + +E2E tests are run on every push to `develop` or manually via [run-e2e-tests workflow](https://github.com/aws-powertools/powertools-lambda-python/actions/workflows/run-e2e-tests.yml). + +To run locally, you need [AWS CDK CLI](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites) and an [account bootstrapped](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html) (`cdk bootstrap`). With a default AWS CLI profile configured, or `AWS_PROFILE` environment variable set, run `make e2e tests`. + +### Releasing a documentation hotfix + +You can rebuild the latest documentation without a full release via this [GitHub Actions Workflow](https://github.com/aws-powertools/powertools-lambda-python/actions/workflows/rebuild_latest_docs.yml). Choose `Run workflow`, keep `develop` as the branch, and input the latest Powertools for AWS Lambda (Python) version available. + +This workflow will update both user guide and API documentation. + +### Maintain Overall Health of the Repo + +> TODO: Coordinate renaming `develop` to `main` + +Keep the `develop` branch at production quality at all times. Backport features as needed. Cut release branches and tags to enable future patches. + +### Manage Roadmap + +See [Roadmap section](https://docs.powertools.aws.dev/lambda/python/latest/roadmap/) + +Ensure the repo highlights features that should be elevated to the project roadmap. Be clear about the feature’s status, priority, target version, and whether or not it should be elevated to the roadmap. + +### Add Continuous Integration Checks + +Add integration checks that validate pull requests and pushes to ease the burden on Pull Request reviewers. Continuously revisit areas of improvement to reduce operational burden in all parties involved. + +### Negative Impact on the Project + +Actions that negatively impact the project will be handled by the admins, in coordination with other maintainers, in balance with the urgency of the issue. Examples would be [Code of Conduct](CODE_OF_CONDUCT.md) violations, deliberate harmful or malicious actions, spam, monopolization, and security risks. + +### Becoming a maintainer + +In 2023, we will revisit this. We need to improve our understanding of how other projects are doing, their mechanisms to promote key contributors, and how they interact daily. + +We suspect this process might look similar to the [OpenSearch project](https://github.com/opensearch-project/.github/blob/main/MAINTAINERS.md#becoming-a-maintainer). + +## Common scenarios + +These are recurring ambiguous situations that new and existing maintainers may encounter. They serve as guidance. It is up to each maintainer to follow, adjust, or handle in a different manner as long as [our conduct is consistent](#uphold-code-of-conduct) + +### Contribution is stuck + +A contribution can get stuck often due to lack of bandwidth and language barrier. For bandwidth issues, check whether the author needs help. Make sure you get their permission before pushing code into their existing PR - do not create a new PR unless strictly necessary. + +For language barrier and others, offer a 1:1 chat to get them unblocked. Often times, English might not be their primary language, and writing in public might put them off, or come across not the way they intended to be. + +In other cases, you may have constrained capacity. Use `help wanted` label when you want to signal other maintainers and external contributors that you could use a hand to move it forward. + +### Insufficient feedback or information + +When in doubt, use `need-more-information` or `need-customer-feedback` labels to signal more context and feedback are necessary before proceeding. You can also use `revisit-in-3-months` label when you expect it might take a while to gather enough information before you can decide. + +### Crediting contributions + +We credit all contributions as part of each [release note](https://github.com/aws-powertools/powertools-lambda-python/releases) as an automated process. If you find contributors are missing from the release note you're producing, please add them manually. + +### Is that a bug? + +A bug produces incorrect or unexpected results at runtime that differ from its intended behavior. Bugs must be reproducible. They directly affect customers experience at runtime despite following its recommended usage. + +Documentation snippets, use of internal components, or unadvertised functionalities are not considered bugs. + +### Mentoring contributions + +Always favor mentoring issue authors to contribute, unless they're not interested or the implementation is sensitive (_e.g., complexity, time to release, etc._). + +Make use of `help wanted` and `good first issue` to signal additional contributions the community can help. + +### Long running issues or PRs + +Try offering a 1:1 call in the attempt to get to a mutual understanding and clarify areas that maintainers could help. + +In the rare cases where both parties don't have the bandwidth or expertise to continue, it's best to use the `revisit-in-3-months` label. By then, see if it's possible to break the PR or issue in smaller chunks, and eventually close if there is no progress. + +## E2E framework + +### Structure + +Our E2E framework relies on [Pytest fixtures](https://docs.pytest.org/en/6.2.x/fixture.html) to coordinate infrastructure and test parallelization - see [Test Parallelization](#test-runner-parallelization) and [CDK CLI Parallelization](#cdk-cli-parallelization). + +**tests/e2e structure** + +```shell +. +β”œβ”€β”€ __init__.py +β”œβ”€β”€ conftest.py # builds Lambda Layer once +β”œβ”€β”€ logger +β”‚ β”œβ”€β”€ __init__.py +β”‚ β”œβ”€β”€ conftest.py # deploys LoggerStack +β”‚ β”œβ”€β”€ handlers +β”‚ β”‚ └── basic_handler.py +β”‚ β”œβ”€β”€ infrastructure.py # LoggerStack definition +β”‚ └── test_logger.py +β”œβ”€β”€ metrics +β”‚ β”œβ”€β”€ __init__.py +β”‚ β”œβ”€β”€ conftest.py # deploys MetricsStack +β”‚ β”œβ”€β”€ handlers +β”‚ β”‚ β”œβ”€β”€ basic_handler.py +β”‚ β”‚ └── cold_start.py +β”‚ β”œβ”€β”€ infrastructure.py # MetricsStack definition +β”‚ └── test_metrics.py +β”œβ”€β”€ tracer +β”‚ β”œβ”€β”€ __init__.py +β”‚ β”œβ”€β”€ conftest.py # deploys TracerStack +β”‚ β”œβ”€β”€ handlers +β”‚ β”‚ β”œβ”€β”€ async_capture.py +β”‚ β”‚ └── basic_handler.py +β”‚ β”œβ”€β”€ infrastructure.py # TracerStack definition +β”‚ └── test_tracer.py +└── utils + β”œβ”€β”€ __init__.py + β”œβ”€β”€ data_builder # build_service_name(), build_add_dimensions_input, etc. + β”œβ”€β”€ data_fetcher # get_traces(), get_logs(), get_lambda_response(), etc. + β”œβ”€β”€ infrastructure.py # base infrastructure like deploy logic, etc. +``` + +Where: + +- **`/infrastructure.py`**. Uses CDK to define the infrastructure a given feature needs. +- **`/handlers/`**. Lambda function handlers to build, deploy, and exposed as stack output in PascalCase (e.g., `BasicHandler`). +- **`utils/`**. Test utilities to build data and fetch AWS data to ease assertion +- **`conftest.py`**. Deploys and deletes a given feature infrastructure. Hierarchy matters: + - **Top-level (`e2e/conftest`)**. Builds Lambda Layer only once and blocks I/O across all CPU workers. + - **Feature-level (`e2e//conftest`)**. Deploys stacks in parallel and make them independent of each other. + +### Mechanics + +Under [`BaseInfrastructure`](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/e2e/utils/infrastructure.py), we hide the complexity of deployment and delete coordination under `deploy`, `delete`, and `create_lambda_functions` methods. + +This allows us to benefit from test and deployment parallelization, use IDE step-through debugging for a single test, run one, subset, or all tests and only deploy their related infrastructure, without any custom configuration. + +> Class diagram to understand abstraction built when defining a new stack (`LoggerStack`) + +```mermaid +classDiagram + class InfrastructureProvider { + <> + +deploy() Dict + +delete() + +create_resources() + +create_lambda_functions() Dict~Functions~ + } + + class BaseInfrastructure { + +deploy() Dict + +delete() + +create_lambda_functions() Dict~Functions~ + +add_cfn_output() + } + + class TracerStack { + +create_resources() + } + + class LoggerStack { + +create_resources() + } + + class MetricsStack { + +create_resources() + } + + class EventHandlerStack { + +create_resources() + } + + InfrastructureProvider <|-- BaseInfrastructure : implement + BaseInfrastructure <|-- TracerStack : inherit + BaseInfrastructure <|-- LoggerStack : inherit + BaseInfrastructure <|-- MetricsStack : inherit + BaseInfrastructure <|-- EventHandlerStack : inherit +``` + +### Authoring a new feature E2E test + +Imagine you're going to create E2E for Event Handler feature for the first time. Keep the following mental model when reading: + +```mermaid +graph LR + A["1. Define infrastructure"]-->B["2. Deploy/Delete infrastructure"]-->C["3.Access Stack outputs" ] +``` + +#### 1. Define infrastructure + +We use CDK as our Infrastructure as Code tool of choice. Before you start using CDK, you'd take the following steps: + +1. Create `tests/e2e/event_handler/infrastructure.py` file +2. Create a new class `EventHandlerStack` and inherit from `BaseInfrastructure` +3. Override `create_resources` method and define your infrastructure using CDK +4. (Optional) Create a Lambda function under `handlers/alb_handler.py` + +> Excerpt `tests/e2e/event_handler/infrastructure.py` + +```python +class EventHandlerStack(BaseInfrastructure): + def create_resources(self): + functions = self.create_lambda_functions() + + self._create_alb(function=functions["AlbHandler"]) + ... + + def _create_alb(self, function: Function): + vpc = ec2.Vpc.from_lookup( + self.stack, + "VPC", + is_default=True, + region=self.region, + ) + + alb = elbv2.ApplicationLoadBalancer(self.stack, "ALB", vpc=vpc, internet_facing=True) + CfnOutput(self.stack, "ALBDnsName", value=alb.load_balancer_dns_name) + ... +``` + +> Excerpt `tests/e2e/event_handler/handlers/alb_handler.py` + +```python +from aws_lambda_powertools.event_handler import ALBResolver, Response, content_types + +app = ALBResolver() + + +@app.get("/todos") +def hello(): + return Response( + status_code=200, + content_type=content_types.TEXT_PLAIN, + body="Hello world", + cookies=["CookieMonster", "MonsterCookie"], + headers={"Foo": ["bar", "zbr"]}, + ) + + +def lambda_handler(event, context): + return app.resolve(event, context) +``` + +#### 2. Deploy/Delete infrastructure when tests run + +We need to create a Pytest fixture for our new feature under `tests/e2e/event_handler/conftest.py`. + +This will instruct Pytest to deploy our infrastructure when our tests start, and delete it when they complete whether tests are successful or not. Note that this file will not need any modification in the future. + +> Excerpt `conftest.py` for Event Handler + +```python +import pytest + +from tests.e2e.event_handler.infrastructure import EventHandlerStack + + +@pytest.fixture(autouse=True, scope="module") +def infrastructure(): + """Setup and teardown logic for E2E test infrastructure + + Yields + ------ + Dict[str, str] + CloudFormation Outputs from deployed infrastructure + """ + stack = EventHandlerStack() + try: + yield stack.deploy() + finally: + stack.delete() + +``` + +#### 3. Access stack outputs for E2E tests + +Within our tests, we should now have access to the `infrastructure` fixture we defined earlier in `tests/e2e/event_handler/conftest.py`. + +We can access any Stack Output using pytest dependency injection. + +> Excerpt `tests/e2e/event_handler/test_header_serializer.py` + +```python +@pytest.fixture +def alb_basic_listener_endpoint(infrastructure: dict) -> str: + dns_name = infrastructure.get("ALBDnsName") + port = infrastructure.get("ALBBasicListenerPort", "") + return f"http://{dns_name}:{port}" + + +def test_alb_headers_serializer(alb_basic_listener_endpoint): + # GIVEN + url = f"{alb_basic_listener_endpoint}/todos" + ... +``` + +### Internals + +#### Test runner parallelization + +Besides speed, we parallelize our end-to-end tests to ease asserting async side-effects may take a while per test too, _e.g., traces to become available_. + +The following diagram demonstrates the process we take every time you use `make e2e` locally or at CI: + +```mermaid +graph TD + A[make e2e test] -->Spawn{"Split and group tests
by feature and CPU"} + + Spawn -->|Worker0| Worker0_Start["Load tests"] + Spawn -->|Worker1| Worker1_Start["Load tests"] + Spawn -->|WorkerN| WorkerN_Start["Load tests"] + + Worker0_Start -->|Wait| LambdaLayer["Lambda Layer build"] + Worker1_Start -->|Wait| LambdaLayer["Lambda Layer build"] + WorkerN_Start -->|Wait| LambdaLayer["Lambda Layer build"] + + LambdaLayer -->|Worker0| Worker0_Deploy["Launch feature stack"] + LambdaLayer -->|Worker1| Worker1_Deploy["Launch feature stack"] + LambdaLayer -->|WorkerN| WorkerN_Deploy["Launch feature stack"] + + Worker0_Deploy -->|Worker0| Worker0_Tests["Run tests"] + Worker1_Deploy -->|Worker1| Worker1_Tests["Run tests"] + WorkerN_Deploy -->|WorkerN| WorkerN_Tests["Run tests"] + + Worker0_Tests --> ResultCollection + Worker1_Tests --> ResultCollection + WorkerN_Tests --> ResultCollection + + ResultCollection{"Wait for workers
Collect test results"} + ResultCollection --> TestEnd["Report results"] + ResultCollection --> DeployEnd["Delete Stacks"] +``` + +#### CDK CLI parallelization + +For CDK CLI to work with [independent CDK Apps](https://docs.aws.amazon.com/cdk/v2/guide/apps.html), we specify an output directory when synthesizing our stack and deploy from said output directory. + +```mermaid +flowchart TD + subgraph "Deploying distinct CDK Apps" + EventHandlerInfra["Event Handler CDK App"] --> EventHandlerSynth + TracerInfra["Tracer CDK App"] --> TracerSynth + EventHandlerSynth["cdk synth --out cdk.out/event_handler"] --> EventHandlerDeploy["cdk deploy --app cdk.out/event_handler"] + + TracerSynth["cdk synth --out cdk.out/tracer"] --> TracerDeploy["cdk deploy --app cdk.out/tracer"] + end +``` + +We create the typical CDK `app.py` at runtime when tests run, since we know which feature and Python version we're dealing with (locally or at CI). + +> Excerpt `cdk_app_V39.py` for Event Handler created at deploy phase + +```python +from tests.e2e.event_handler.infrastructure import EventHandlerStack +stack = EventHandlerStack() +stack.create_resources() +stack.app.synth() +``` + +When we run E2E tests for a single feature or all of them, our `cdk.out` looks like this: + +```shell +total 8 +drwxr-xr-x 18 lessa staff 576B Sep 6 15:38 event-handler +drwxr-xr-x 3 lessa staff 96B Sep 6 15:08 layer_build +-rw-r--r-- 1 lessa staff 32B Sep 6 15:08 layer_build.diff +drwxr-xr-x 18 lessa staff 576B Sep 6 15:38 logger +drwxr-xr-x 18 lessa staff 576B Sep 6 15:38 metrics +drwxr-xr-x 22 lessa staff 704B Sep 9 10:52 tracer +``` + +```mermaid +classDiagram + class CdkOutDirectory { + feature_name/ + layer_build/ + layer_build.diff + } + + class EventHandler { + manifest.json + stack_outputs.json + cdk_app_V39.py + asset.uuid/ + ... + } + + class StackOutputsJson { + BasicHandlerArn: str + ALBDnsName: str + ... + } + + CdkOutDirectory <|-- EventHandler : feature_name/ + StackOutputsJson <|-- EventHandler +``` + +Where: + +- **``**. Contains CDK Assets, CDK `manifest.json`, our `cdk_app_.py` and `stack_outputs.json` +- **`layer_build`**. Contains our Lambda Layer source code built once, used by all stacks independently +- **`layer_build.diff`**. Contains a hash on whether our source code has changed to speed up further deployments and E2E tests + +Together, all of this allows us to use Pytest like we would for any project, use CDK CLI and its [context methods](https://docs.aws.amazon.com/cdk/v2/guide/context.html#context_methods) (`from_lookup`), and use step-through debugging for a single E2E test without any extra configuration. + +> NOTE: VSCode doesn't support debugging processes spawning sub-processes (like CDK CLI does w/ shell and CDK App). Maybe [this works](https://stackoverflow.com/a/65339352). PyCharm works just fine. diff --git a/docs/security.md b/docs/security.md index edaedaf1ecd..b3475e2c0c0 100644 --- a/docs/security.md +++ b/docs/security.md @@ -85,26 +85,4 @@ You can do this manually or automated via a shell script. We maintain the latter ---8<-- ".github/actions/verify-provenance/verify_provenance.sh" ``` -### Continuous integration practices - -!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}." - -Since all code changes require a pull request (PR) along with one or more reviewers, we automate quality and security checks **before**, **during**, and **after** a PR is merged to trunk (`develop`). - -This is a snapshot of our automated checks at a glance. - - - -![Continuous Integration practices](./media/continuous_integration_practices.png) - -### Continuous deployment practices - -!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}." - -Releases are triggered by maintainers along with a reviewer - [detailed info here](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md#releasing-a-new-version){target="_blank"}. In addition to [checks that run for every code change](#continuous-integration-practices), our pipeline requires a manual approval before releasing. - -We use a combination of provenance and signed attestation for our builds, source code sealing, SAST scanners, Python specific static code analysis, ephemeral credentials that last a given job step, and more. - -This is a snapshot of our automated checks at a glance. - -![Continuous Deployment practices](./media/continuous_deployment_practices.png) + diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index ca6ab06903d..8d6903b5f75 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -22,6 +22,14 @@ font-size: 0.75rem } +.md-tabs__link { + font-size: 0.8rem +} + +.md-tabs__link--active { + border-bottom: 6px solid white +} + .md-nav__link--active { font-weight: bold } diff --git a/mkdocs.yml b/mkdocs.yml index 2315152a3c9..77322a535be 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,34 +5,37 @@ repo_url: https://github.com/aws-powertools/powertools-lambda-python edit_uri: edit/develop/docs nav: - - Homepage: index.md - - Changelog: changelog.md + - Homepage: + - index.md + - Changelog: changelog.md + - API reference: api/" target="_blank + - Upgrade guide: upgrade.md + - We Made This (Community): we_made_this.md + - Features: + - core/tracer.md + - core/logger.md + - core/metrics.md + - Event Handler: + - core/event_handler/api_gateway.md + - core/event_handler/appsync.md + - utilities/parameters.md + - utilities/batch.md + - utilities/typing.md + - utilities/validation.md + - utilities/data_classes.md + - utilities/parser.md + - utilities/idempotency.md + - utilities/feature_flags.md + - utilities/streaming.md + - utilities/middleware_factory.md + - utilities/jmespath_functions.md + - CloudFormation Custom Resources: https://github.com/aws-cloudformation/custom-resource-helper" target="_blank - Tutorial: tutorial/index.md - - Roadmap: roadmap.md - - API reference: api/" target="_blank - - Upgrade guide: upgrade.md - - We Made This (Community): we_made_this.md - - Security: security.md - - Core utilities: - - core/tracer.md - - core/logger.md - - core/metrics.md - - Event Handler: - - core/event_handler/api_gateway.md - - core/event_handler/appsync.md - - Utilities: - - utilities/parameters.md - - utilities/batch.md - - utilities/typing.md - - utilities/validation.md - - utilities/data_classes.md - - utilities/parser.md - - utilities/idempotency.md - - utilities/feature_flags.md - - utilities/streaming.md - - utilities/middleware_factory.md - - utilities/jmespath_functions.md - - CloudFormation Custom Resources: https://github.com/aws-cloudformation/custom-resource-helper" target="_blank + - Processes: + - Security: security.md + - Automation: automation.md + - Roadmap: roadmap.md + - Maintainers: maintainers.md theme: name: material @@ -42,13 +45,13 @@ theme: - scheme: default primary: deep purple toggle: - icon: material/toggle-switch-off-outline + icon: material/lightbulb name: Switch to dark mode - scheme: slate primary: indigo accent: teal toggle: - icon: material/toggle-switch + icon: material/lightbulb-outline name: Switch to light mode features: - header.autohide @@ -58,6 +61,7 @@ theme: - navigation.instant - navigation.indexes - navigation.tracking + - navigation.tabs - content.code.annotate - content.code.copy icon: @@ -92,7 +96,7 @@ markdown_extensions: class: mermaid format: !!python/name:pymdownx.superfences.fence_code_format -copyright: Copyright © 2022 Amazon Web Services +copyright: Copyright © 2023 Amazon Web Services plugins: - git-revision-date From 9ac305fca640a40d5e964874b0eacd15942bbcd5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:39:36 +0200 Subject: [PATCH 65/73] chore(ci): changelog rebuild (#2766) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 54 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b59a4d6368e..0a5ee05b4f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * **docs:** ensure alias is applied to versioned releases ([#2644](https://github.com/aws-powertools/powertools-lambda-python/issues/2644)) * **docs:** ensure version alias is in an array to prevent "you're not viewing the latest version" incorrect message ([#2629](https://github.com/aws-powertools/powertools-lambda-python/issues/2629)) +* **logger:** ensure logs stream to stdout by default, not stderr ([#2736](https://github.com/aws-powertools/powertools-lambda-python/issues/2736)) ## Code Refactoring @@ -15,42 +16,67 @@ ## Documentation +* **batch:** fix custom batch processor example ([#2714](https://github.com/aws-powertools/powertools-lambda-python/issues/2714)) * **contributing:** add code integration journey graph ([#2685](https://github.com/aws-powertools/powertools-lambda-python/issues/2685)) * **maintainers:** add cicd pipeline diagram ([#2692](https://github.com/aws-powertools/powertools-lambda-python/issues/2692)) +* **process:** explain our integration automated checks; revamp navigation ([#2764](https://github.com/aws-powertools/powertools-lambda-python/issues/2764)) + +## Features + +* **metrics:** support to set default dimension in EphemeralMetrics ([#2748](https://github.com/aws-powertools/powertools-lambda-python/issues/2748)) ## Maintenance -* **ci:** add gitleaks in pre-commit hooks as an extra safety measure ([#2677](https://github.com/aws-powertools/powertools-lambda-python/issues/2677)) * **ci:** use deps sha for docs and gitpod images based on ossf findings ([#2662](https://github.com/aws-powertools/powertools-lambda-python/issues/2662)) * **ci:** prevent merging PRs that do not meet minimum requirements ([#2639](https://github.com/aws-powertools/powertools-lambda-python/issues/2639)) +* **ci:** enforce pip --require-hashes to maybe satistify scorecard ([#2679](https://github.com/aws-powertools/powertools-lambda-python/issues/2679)) * **ci:** enforce top-level permission to minimum fail-safe permission as per openssf ([#2638](https://github.com/aws-powertools/powertools-lambda-python/issues/2638)) +* **ci:** introduce provenance and attestation in release ([#2746](https://github.com/aws-powertools/powertools-lambda-python/issues/2746)) * **ci:** propagate checkout permission to nested workflows ([#2642](https://github.com/aws-powertools/powertools-lambda-python/issues/2642)) * **ci:** improves dependabot based on ossf scorecard recommendations ([#2647](https://github.com/aws-powertools/powertools-lambda-python/issues/2647)) -* **ci:** address ossf scorecard findings on npm, pip, and top-level permission leftover ([#2694](https://github.com/aws-powertools/powertools-lambda-python/issues/2694)) +* **ci:** add gitleaks in pre-commit hooks as an extra safety measure ([#2677](https://github.com/aws-powertools/powertools-lambda-python/issues/2677)) +* **ci:** prevent sast codeql to run in forks ([#2711](https://github.com/aws-powertools/powertools-lambda-python/issues/2711)) * **ci:** use sast on every commit on any supported language ([#2646](https://github.com/aws-powertools/powertools-lambda-python/issues/2646)) -* **ci:** enforce pip --require-hashes to maybe satistify scorecard ([#2679](https://github.com/aws-powertools/powertools-lambda-python/issues/2679)) +* **ci:** address ossf scorecard findings on npm, pip, and top-level permission leftover ([#2694](https://github.com/aws-powertools/powertools-lambda-python/issues/2694)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.17.8 to 1.18.27 in /layer/scripts/layer-balancer ([#2651](https://github.com/aws-powertools/powertools-lambda-python/issues/2651)) +* **deps:** bump docker/setup-buildx-action from 2.8.0 to 2.9.0 ([#2718](https://github.com/aws-powertools/powertools-lambda-python/issues/2718)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.24.6 to 1.37.0 in /layer/scripts/layer-balancer ([#2653](https://github.com/aws-powertools/powertools-lambda-python/issues/2653)) -* **deps:** bump pydantic from 1.10.10 to 1.10.11 ([#2671](https://github.com/aws-powertools/powertools-lambda-python/issues/2671)) +* **deps:** bump golang.org/x/sync from 0.1.0 to 0.3.0 in /layer/scripts/layer-balancer ([#2649](https://github.com/aws-powertools/powertools-lambda-python/issues/2649)) * **deps:** bump actions/dependency-review-action from 2.5.1 to 3.0.6 ([#2650](https://github.com/aws-powertools/powertools-lambda-python/issues/2650)) +* **deps:** bump pydantic from 1.10.9 to 1.10.10 ([#2624](https://github.com/aws-powertools/powertools-lambda-python/issues/2624)) +* **deps:** bump pydantic from 1.10.10 to 1.10.11 ([#2671](https://github.com/aws-powertools/powertools-lambda-python/issues/2671)) +* **deps:** migrate from retry to retry2 to address CVE-2022-42969 ([#2665](https://github.com/aws-powertools/powertools-lambda-python/issues/2665)) * **deps:** bump squidfunk/mkdocs-material from `3837c0f` to `a28ed81` in /docs ([#2669](https://github.com/aws-powertools/powertools-lambda-python/issues/2669)) -* **deps:** bump golang.org/x/sync from 0.1.0 to 0.3.0 in /layer/scripts/layer-balancer ([#2649](https://github.com/aws-powertools/powertools-lambda-python/issues/2649)) +* **deps:** bump zgosalvez/github-actions-ensure-sha-pinned-actions from 2.1.3 to 2.1.4 ([#2738](https://github.com/aws-powertools/powertools-lambda-python/issues/2738)) * **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.16.16 to 1.18.1 in /layer/scripts/layer-balancer ([#2654](https://github.com/aws-powertools/powertools-lambda-python/issues/2654)) -* **deps:** migrate from retry to retry2 to address CVE-2022-42969 ([#2665](https://github.com/aws-powertools/powertools-lambda-python/issues/2665)) +* **deps:** bump docker/setup-buildx-action from 2.9.0 to 2.9.1 ([#2755](https://github.com/aws-powertools/powertools-lambda-python/issues/2755)) +* **deps:** bump pypa/gh-action-pypi-publish from 1.8.7 to 1.8.8 ([#2754](https://github.com/aws-powertools/powertools-lambda-python/issues/2754)) * **deps:** bump actions/setup-node from 3.6.0 to 3.7.0 ([#2689](https://github.com/aws-powertools/powertools-lambda-python/issues/2689)) -* **deps:** bump pydantic from 1.10.9 to 1.10.10 ([#2624](https://github.com/aws-powertools/powertools-lambda-python/issues/2624)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.17.8 to 1.18.27 in /layer/scripts/layer-balancer ([#2651](https://github.com/aws-powertools/powertools-lambda-python/issues/2651)) -* **deps-dev:** bump sentry-sdk from 1.26.0 to 1.27.0 ([#2652](https://github.com/aws-powertools/powertools-lambda-python/issues/2652)) -* **deps-dev:** bump ruff from 0.0.275 to 0.0.276 ([#2655](https://github.com/aws-powertools/powertools-lambda-python/issues/2655)) -* **deps-dev:** bump typed-ast from 1.5.4 to 1.5.5 ([#2670](https://github.com/aws-powertools/powertools-lambda-python/issues/2670)) +* **deps-dev:** bump mypy-boto3-cloudwatch from 1.27.0 to 1.28.0 ([#2697](https://github.com/aws-powertools/powertools-lambda-python/issues/2697)) * **deps-dev:** bump ruff from 0.0.276 to 0.0.277 ([#2682](https://github.com/aws-powertools/powertools-lambda-python/issues/2682)) -* **deps-dev:** bump sentry-sdk from 1.27.0 to 1.27.1 ([#2701](https://github.com/aws-powertools/powertools-lambda-python/issues/2701)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.27.0 to 1.28.0 ([#2700](https://github.com/aws-powertools/powertools-lambda-python/issues/2700)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.27.0 to 1.28.0 ([#2699](https://github.com/aws-powertools/powertools-lambda-python/issues/2699)) +* **deps-dev:** bump sentry-sdk from 1.27.0 to 1.27.1 ([#2701](https://github.com/aws-powertools/powertools-lambda-python/issues/2701)) +* **deps-dev:** bump typed-ast from 1.5.4 to 1.5.5 ([#2670](https://github.com/aws-powertools/powertools-lambda-python/issues/2670)) * **deps-dev:** bump mypy-boto3-lambda from 1.27.0 to 1.28.0 ([#2698](https://github.com/aws-powertools/powertools-lambda-python/issues/2698)) -* **deps-dev:** bump mypy-boto3-appconfigdata from 1.26.70 to 1.27.0 ([#2636](https://github.com/aws-powertools/powertools-lambda-python/issues/2636)) +* **deps-dev:** bump ruff from 0.0.275 to 0.0.276 ([#2655](https://github.com/aws-powertools/powertools-lambda-python/issues/2655)) +* **deps-dev:** bump sentry-sdk from 1.26.0 to 1.27.0 ([#2652](https://github.com/aws-powertools/powertools-lambda-python/issues/2652)) * **deps-dev:** bump aws-cdk from 2.86.0 to 2.87.0 ([#2696](https://github.com/aws-powertools/powertools-lambda-python/issues/2696)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.26.158 to 1.26.164 ([#2622](https://github.com/aws-powertools/powertools-lambda-python/issues/2622)) -* **deps-dev:** bump mypy-boto3-cloudwatch from 1.27.0 to 1.28.0 ([#2697](https://github.com/aws-powertools/powertools-lambda-python/issues/2697)) +* **deps-dev:** bump mypy-boto3-appconfig from 1.27.0 to 1.28.0 ([#2722](https://github.com/aws-powertools/powertools-lambda-python/issues/2722)) +* **deps-dev:** bump mypy-boto3-s3 from 1.27.0 to 1.28.0 ([#2721](https://github.com/aws-powertools/powertools-lambda-python/issues/2721)) +* **deps-dev:** bump mypy-boto3-logs from 1.27.0 to 1.28.1 ([#2723](https://github.com/aws-powertools/powertools-lambda-python/issues/2723)) +* **deps-dev:** bump mypy-boto3-ssm from 1.27.0 to 1.28.0 ([#2724](https://github.com/aws-powertools/powertools-lambda-python/issues/2724)) +* **deps-dev:** bump mypy-boto3-xray from 1.27.0 to 1.28.0 ([#2720](https://github.com/aws-powertools/powertools-lambda-python/issues/2720)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.27.0 to 1.28.0 ([#2740](https://github.com/aws-powertools/powertools-lambda-python/issues/2740)) +* **deps-dev:** bump mypy-boto3-secretsmanager from 1.27.0 to 1.28.0 ([#2739](https://github.com/aws-powertools/powertools-lambda-python/issues/2739)) +* **deps-dev:** bump sentry-sdk from 1.27.1 to 1.28.0 ([#2741](https://github.com/aws-powertools/powertools-lambda-python/issues/2741)) +* **deps-dev:** bump ruff from 0.0.277 to 0.0.278 ([#2758](https://github.com/aws-powertools/powertools-lambda-python/issues/2758)) +* **deps-dev:** bump pytest-asyncio from 0.21.0 to 0.21.1 ([#2756](https://github.com/aws-powertools/powertools-lambda-python/issues/2756)) +* **deps-dev:** bump mypy-boto3-appconfigdata from 1.26.70 to 1.27.0 ([#2636](https://github.com/aws-powertools/powertools-lambda-python/issues/2636)) +* **deps-dev:** bump cfn-lint from 0.77.10 to 0.78.1 ([#2757](https://github.com/aws-powertools/powertools-lambda-python/issues/2757)) +* **governance:** update active maintainers list ([#2715](https://github.com/aws-powertools/powertools-lambda-python/issues/2715)) +* **streaming:** replace deprecated Version classes from distutils ([#2752](https://github.com/aws-powertools/powertools-lambda-python/issues/2752)) * **user-agent:** support patching botocore session ([#2614](https://github.com/aws-powertools/powertools-lambda-python/issues/2614)) From 0db5ffdfd73f84bda0fb0096e6e2f8cfd41a18b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 22:07:07 +0100 Subject: [PATCH 66/73] chore(deps-dev): bump mypy-boto3-s3 from 1.28.0 to 1.28.3 (#2774) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 83b77115ee9..377d555c491 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1526,13 +1526,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-s3" -version = "1.28.0" -description = "Type annotations for boto3.S3 1.28.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.3" +description = "Type annotations for boto3.S3 1.28.3 service generated with mypy-boto3-builder 7.14.6" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-s3-1.28.0.tar.gz", hash = "sha256:27867ca325a845700a008f3fca995006b32f2e0d18afe676352b49453f477d69"}, - {file = "mypy_boto3_s3-1.28.0-py3-none-any.whl", hash = "sha256:789a32560ec1882e3a2c5bbb7aa97952b05e54507e2174eab6535ceaffb04cee"}, + {file = "mypy-boto3-s3-1.28.3.tar.gz", hash = "sha256:c2b454413126079a6434a3e05a75cb4cad947c7624e53ba3846cb829a2230c4b"}, + {file = "mypy_boto3_s3-1.28.3-py3-none-any.whl", hash = "sha256:58d4e65c9dabbdc9a8896f7cd3d6475f4331183220a2b41ba1862bf5b3c592bc"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "063b702b25c1f2a7dab895b012d91b2f4d7765f806425e8c67726f4255dd1589" +content-hash = "a817e4ec12351164d59c42ab663278d3a63b6c6f682ccfb879adad0c27f7875c" diff --git a/pyproject.toml b/pyproject.toml index 1c23a72a55e..115e66426cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,7 @@ mypy-boto3-lambda = "^1.28.0" mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.28.0" mypy-boto3-ssm = "^1.28.0" -mypy-boto3-s3 = "^1.28.0" +mypy-boto3-s3 = "^1.28.3" mypy-boto3-xray = "^1.28.0" types-requests = "^2.31.0" typing-extensions = "^4.6.2" From d1c2295c4a010e548013b53e196a730a1396ed4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 22:07:28 +0100 Subject: [PATCH 67/73] chore(deps): bump github.com/aws/aws-sdk-go-v2 from 1.18.1 to 1.19.0 in /layer/scripts/layer-balancer (#2771) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 2 +- layer/scripts/layer-balancer/go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index 2bf2bb59af0..48eb6474011 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -3,7 +3,7 @@ module layerbalancer go 1.18 require ( - github.com/aws/aws-sdk-go-v2 v1.18.1 + github.com/aws/aws-sdk-go-v2 v1.19.0 github.com/aws/aws-sdk-go-v2/config v1.18.27 github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index a006ad16887..cd94e8860d2 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,5 +1,6 @@ -github.com/aws/aws-sdk-go-v2 v1.18.1 h1:+tefE750oAb7ZQGzla6bLkOwfcQCEtC5y2RqoqCeqKo= github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k= +github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= github.com/aws/aws-sdk-go-v2/config v1.18.27 h1:Az9uLwmssTE6OGTpsFqOnaGpLnKDqNYOJzWuC6UAYzA= From fc242cfe286b09e5ed47c3c1986ad2802ad0d04e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 22:09:04 +0100 Subject: [PATCH 68/73] chore(deps): bump actions/setup-python from 4.6.1 to 4.7.0 (#2768) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish_v2_layer.yml | 2 +- .github/workflows/quality_check.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/reusable_deploy_v2_layer_stack.yml | 2 +- .github/workflows/reusable_publish_docs.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index 8d37b8f9828..d7712d0b912 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -105,7 +105,7 @@ jobs: with: node-version: "16.12" - name: Setup python - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: "3.10" cache: "pip" diff --git a/.github/workflows/quality_check.yml b/.github/workflows/quality_check.yml index 74da419bab3..c51ea493f10 100644 --- a/.github/workflows/quality_check.yml +++ b/.github/workflows/quality_check.yml @@ -54,7 +54,7 @@ jobs: - name: Install poetry run: pipx install poetry - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: ${{ matrix.python-version }} cache: "poetry" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c87b4c72154..c1b2bdb0026 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -131,7 +131,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@68b88e5390720a3dd84f02940ec5200bfce39ac6 # v1.5.0 - name: Set up Python - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: "3.10" cache: "poetry" @@ -169,7 +169,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@68b88e5390720a3dd84f02940ec5200bfce39ac6 # v1.5.0 - name: Set up Python - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: "3.10" cache: "poetry" diff --git a/.github/workflows/reusable_deploy_v2_layer_stack.yml b/.github/workflows/reusable_deploy_v2_layer_stack.yml index 360f4c8fbc9..f7d7dc0d409 100644 --- a/.github/workflows/reusable_deploy_v2_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v2_layer_stack.yml @@ -158,7 +158,7 @@ jobs: with: node-version: "16.12" - name: Setup python - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: "3.10" cache: "pip" diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index 8dfc45973ad..fa89ecff8a5 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -50,7 +50,7 @@ jobs: - name: Install poetry run: pipx install poetry - name: Set up Python - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: "3.10" cache: "poetry" diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 658be430d28..5e694731db7 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -55,7 +55,7 @@ jobs: - name: Install poetry run: pipx install poetry - name: "Use Python" - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: ${{ matrix.version }} architecture: "x64" From 8d52b036a68583a4ca0ff2805f7d579f01abd637 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 22:09:26 +0100 Subject: [PATCH 69/73] chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.18.27 to 1.18.28 in /layer/scripts/layer-balancer (#2770) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 20 +++++++-------- layer/scripts/layer-balancer/go.sum | 38 +++++++++++++++-------------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index 48eb6474011..604de62aed9 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.19.0 - github.com/aws/aws-sdk-go-v2/config v1.18.27 + github.com/aws/aws-sdk-go-v2/config v1.18.28 github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 @@ -12,15 +12,15 @@ require ( require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.26 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.27 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index cd94e8860d2..15ab97a4160 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -3,28 +3,30 @@ github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyD github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= -github.com/aws/aws-sdk-go-v2/config v1.18.27 h1:Az9uLwmssTE6OGTpsFqOnaGpLnKDqNYOJzWuC6UAYzA= -github.com/aws/aws-sdk-go-v2/config v1.18.27/go.mod h1:0My+YgmkGxeqjXZb5BYme5pc4drjTnM+x1GJ3zv42Nw= -github.com/aws/aws-sdk-go-v2/credentials v1.13.26 h1:qmU+yhKmOCyujmuPY7tf5MxR/RKyZrOPO3V4DobiTUk= -github.com/aws/aws-sdk-go-v2/credentials v1.13.26/go.mod h1:GoXt2YC8jHUBbA4jr+W3JiemnIbkXOfxSXcisUsZ3os= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 h1:LxK/bitrAr4lnh9LnIS6i7zWbCOdMsfzKFBI6LUCS0I= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4/go.mod h1:E1hLXN/BL2e6YizK1zFlYd8vsfi2GTjbjBazinMmeaM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 h1:A5UqQEmPaCFpedKouS4v+dHCTUo2sKqhoKO9U5kxyWo= +github.com/aws/aws-sdk-go-v2/config v1.18.28 h1:TINEaKyh1Td64tqFvn09iYpKiWjmHYrG1fa91q2gnqw= +github.com/aws/aws-sdk-go-v2/config v1.18.28/go.mod h1:nIL+4/8JdAuNHEjn/gPEXqtnS02Q3NXB/9Z7o5xE4+A= +github.com/aws/aws-sdk-go-v2/credentials v1.13.27 h1:dz0yr/yR1jweAnsCx+BmjerUILVPQ6FS5AwF/OyG1kA= +github.com/aws/aws-sdk-go-v2/credentials v1.13.27/go.mod h1:syOqAek45ZXZp29HlnRS/BNgMIW6uiRmeuQsz4Qh2UE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 h1:kP3Me6Fy3vdi+9uHd7YLr6ewPxRL+PU6y15urfTaamU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5/go.mod h1:Gj7tm95r+QsDoN2Fhuz/3npQvcZbkEf5mL70n3Xfluc= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34/go.mod h1:wZpTEecJe0Btj3IYnDx/VlUzor9wm3fJHyvLpQF0VwY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 h1:srIVS45eQuewqz6fKKu6ZGXaq6FuFg5NzgQBAM6g8Y4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28/go.mod h1:7VRpKQQedkfIEXb4k52I7swUnZP0wohVajJMRn3vsUw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 h1:LWA+3kDM8ly001vJ1X1waCuLJdtTl48gwkPKWy9sosI= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35/go.mod h1:0Eg1YjxE0Bhn56lx+SHJwCzhW+2JGtizsrx+lCqrfm0= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 h1:bkRyG4a929RCnpVSTvLM2j/T4ls015ZhhYApbmYs15s= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28/go.mod h1:jj7znCIg05jXlaGBlFMGP8+7UN3VtCkRBG2spnmRQkU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 h1:yOpYx+FTBdpk/g+sBU6Cb1H0U/TLEcYYp66mYqsPpcc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 h1:8r5m1BoAWkn0TDC34lUculryf7nUF25EgIMdjvGCkgo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36/go.mod h1:Rmw2M1hMVTwiUhjwMoIBFWFJMhvJbct06sSidxInkhY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 h1:IiDolu/eLmuB18DRZibj77n1hHQT7z12jnGO7Ze3pLc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29/go.mod h1:fDbkK4o7fpPXWn8YAPmTieAMuB9mk/VgvW64uaUqxd4= github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 h1:xzyM5ZR9kZW0/Bkw5EiihOy6B+BYclp5K+yb6OHjc7s= github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0/go.mod h1:Q8zQi5nZpjUF/H55dKEpKfEvFWJkgZzjjqvDb2AR5b4= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 h1:nneMBM2p79PGWBQovYO/6Xnc2ryRMw3InnDJq1FHkSY= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.12/go.mod h1:HuCOxYsF21eKrerARYO6HapNeh9GBNq7fius2AcwodY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 h1:2qTR7IFk7/0IN/adSFhYu9Xthr0zVFTgBrmPldILn80= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12/go.mod h1:E4VrHCPzmVB/KFXtqBGKb3c8zpbNBgKe3fisDNLAW5w= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 h1:XFJ2Z6sNUUcAz9poj+245DMkrHE4h2j5I9/xD50RHfE= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.2/go.mod h1:dp0yLPsLBOi++WTxzCjA/oZqi6NPIhoR+uF7GeMU9eg= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE05JjEsT6fCDtDA9k= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13/go.mod h1:BzqsVVFduubEmzrVtUFQQIQdFqvUItF8XUq2EnS8Wog= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 h1:e5mnydVdCVWxP+5rPAGi2PYxC7u2OZgH1ypC114H04U= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.3/go.mod h1:yVGZA1CPkmUhBdA039jXNJJG7/6t+G+EBWmFq23xqnY= github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= From ca0ec3aef9a286a56077d0df959161abf3791c93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 22:10:19 +0100 Subject: [PATCH 70/73] chore(deps-dev): bump sentry-sdk from 1.28.0 to 1.28.1 (#2772) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 377d555c491..a979f4629a8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2330,13 +2330,13 @@ pbr = "*" [[package]] name = "sentry-sdk" -version = "1.28.0" +version = "1.28.1" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = "*" files = [ - {file = "sentry-sdk-1.28.0.tar.gz", hash = "sha256:2281ba98011cfa9bc9bb15c1074b6dd9f7fdfce94033cd25b50f18f078ffed4c"}, - {file = "sentry_sdk-1.28.0-py2.py3-none-any.whl", hash = "sha256:b8b363aaa3f3d6a3acc1aa571efa4db29fb440339fed03560bb1276b8d2c2509"}, + {file = "sentry-sdk-1.28.1.tar.gz", hash = "sha256:dcd88c68aa64dae715311b5ede6502fd684f70d00a7cd4858118f0ba3153a3ae"}, + {file = "sentry_sdk-1.28.1-py2.py3-none-any.whl", hash = "sha256:6bdb25bd9092478d3a817cb0d01fa99e296aea34d404eac3ca0037faa5c2aa0a"}, ] [package.dependencies] From 961e78cdb73da78ca1e976a82faba761b471289b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 22:11:58 +0100 Subject: [PATCH 71/73] chore(deps): bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.0 to 1.37.1 in /layer/scripts/layer-balancer (#2769) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 2 +- layer/scripts/layer-balancer/go.sum | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index 604de62aed9..ce67f824a6c 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.19.0 github.com/aws/aws-sdk-go-v2/config v1.18.28 - github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 + github.com/aws/aws-sdk-go-v2/service/lambda v1.37.1 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index 15ab97a4160..38d0b70db29 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,4 +1,3 @@ -github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k= github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= @@ -9,18 +8,16 @@ github.com/aws/aws-sdk-go-v2/credentials v1.13.27 h1:dz0yr/yR1jweAnsCx+BmjerUILV github.com/aws/aws-sdk-go-v2/credentials v1.13.27/go.mod h1:syOqAek45ZXZp29HlnRS/BNgMIW6uiRmeuQsz4Qh2UE= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 h1:kP3Me6Fy3vdi+9uHd7YLr6ewPxRL+PU6y15urfTaamU= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5/go.mod h1:Gj7tm95r+QsDoN2Fhuz/3npQvcZbkEf5mL70n3Xfluc= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34/go.mod h1:wZpTEecJe0Btj3IYnDx/VlUzor9wm3fJHyvLpQF0VwY= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28/go.mod h1:7VRpKQQedkfIEXb4k52I7swUnZP0wohVajJMRn3vsUw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 h1:yOpYx+FTBdpk/g+sBU6Cb1H0U/TLEcYYp66mYqsPpcc= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 h1:8r5m1BoAWkn0TDC34lUculryf7nUF25EgIMdjvGCkgo= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36/go.mod h1:Rmw2M1hMVTwiUhjwMoIBFWFJMhvJbct06sSidxInkhY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 h1:IiDolu/eLmuB18DRZibj77n1hHQT7z12jnGO7Ze3pLc= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29/go.mod h1:fDbkK4o7fpPXWn8YAPmTieAMuB9mk/VgvW64uaUqxd4= -github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 h1:xzyM5ZR9kZW0/Bkw5EiihOy6B+BYclp5K+yb6OHjc7s= -github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0/go.mod h1:Q8zQi5nZpjUF/H55dKEpKfEvFWJkgZzjjqvDb2AR5b4= +github.com/aws/aws-sdk-go-v2/service/lambda v1.37.1 h1:BRdW2JcxZSsen77Y0WoWIWY4+H9EXT55uEPWZKIcDHY= +github.com/aws/aws-sdk-go-v2/service/lambda v1.37.1/go.mod h1:zmdE2b9ZX8milexhZc3SeC3LwJRJpJ0k0fsuMBOSCEI= github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE05JjEsT6fCDtDA9k= github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4= From 4b0b2b808c79798f7f9bb0849e57a435c3ac1261 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Jul 2023 11:25:02 +0100 Subject: [PATCH 72/73] chore(deps-dev): bump mypy-boto3-secretsmanager from 1.28.0 to 1.28.3 (#2773) --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index a979f4629a8..d38f6010bb4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1540,13 +1540,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-secretsmanager" -version = "1.28.0" -description = "Type annotations for boto3.SecretsManager 1.28.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.3" +description = "Type annotations for boto3.SecretsManager 1.28.3 service generated with mypy-boto3-builder 7.14.6" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-secretsmanager-1.28.0.tar.gz", hash = "sha256:ee2341a09370209b9ed5d96488baf831b1487c931f420fa5f9cf4a18b2e46311"}, - {file = "mypy_boto3_secretsmanager-1.28.0-py3-none-any.whl", hash = "sha256:160a5bf3cf9b45201f17920472403ed98cdc65256914b167f0539f76e509dbdf"}, + {file = "mypy-boto3-secretsmanager-1.28.3.tar.gz", hash = "sha256:d8e07c8d33392a626b174b6681df3b4c9dfe6ea76de00bda891720d26e63889a"}, + {file = "mypy_boto3_secretsmanager-1.28.3-py3-none-any.whl", hash = "sha256:c662b6ea74a218c801f692012d1d86e0f7f9f9fc6d3a53e7d6e99fae7d87e2c1"}, ] [package.dependencies] @@ -2749,4 +2749,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "a817e4ec12351164d59c42ab663278d3a63b6c6f682ccfb879adad0c27f7875c" +content-hash = "a5c056fc77c478f4afcacebd74b687f8c8417fe53956fefc0526c407ebfd5424" diff --git a/pyproject.toml b/pyproject.toml index 115e66426cb..b82bf9ddba0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,7 @@ mypy-boto3-cloudwatch = "^1.28.0" mypy-boto3-dynamodb = "^1.28.0" mypy-boto3-lambda = "^1.28.0" mypy-boto3-logs = "^1.28.1" -mypy-boto3-secretsmanager = "^1.28.0" +mypy-boto3-secretsmanager = "^1.28.3" mypy-boto3-ssm = "^1.28.0" mypy-boto3-s3 = "^1.28.3" mypy-boto3-xray = "^1.28.0" From 2e746d77845f36f32f9f6d0c26734e4fcae2d89d Mon Sep 17 00:00:00 2001 From: "Powertools for AWS Lambda (Python) bot" Date: Fri, 14 Jul 2023 13:02:54 +0000 Subject: [PATCH 73/73] chore: version bump --- aws_lambda_powertools/shared/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/version.py b/aws_lambda_powertools/shared/version.py index 24ce0f2fd70..2180577256d 100644 --- a/aws_lambda_powertools/shared/version.py +++ b/aws_lambda_powertools/shared/version.py @@ -1,3 +1,3 @@ """Exposes version constant to avoid circular dependencies.""" -VERSION = "2.19.0" +VERSION = "2.20.0" diff --git a/pyproject.toml b/pyproject.toml index b82bf9ddba0..82af9d1915a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "2.19.0" +version = "2.20.0" description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"]