diff --git a/.gitattributes b/.gitattributes index 1c9a7f9..9cfdbf9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,6 +6,7 @@ /.github/workflows/auto-approve.yml linguist-generated /.github/workflows/cdk-deploy-dev.yml linguist-generated /.github/workflows/cdk-deploy-test.yml linguist-generated +/.github/workflows/cdk-validate.yml linguist-generated /.github/workflows/pull-request-lint.yml linguist-generated /.gitignore linguist-generated /.projen/** linguist-generated diff --git a/.github/workflows/auto-approve.yml b/.github/workflows/auto-approve.yml index 82f1639..d5002b9 100644 --- a/.github/workflows/auto-approve.yml +++ b/.github/workflows/auto-approve.yml @@ -17,13 +17,16 @@ jobs: contents: write if: contains(github.event.pull_request.labels.*.name, 'auto-approve') && (github.event.pull_request.user.login == 'dependabot' || github.event.pull_request.user.login == 'dependabot[bot]') steps: - - env: + - id: auto_08f238e2 + env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }} run: gh pr review --approve "$PR_NUMBER" --repo "$GH_REPO" - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v7 + with: + persist-credentials: false - name: Enable Pull Request Automerge run: gh pr merge --merge --auto "${{ github.event.pull_request.number }}" env: diff --git a/.github/workflows/cdk-deploy-dev.yml b/.github/workflows/cdk-deploy-dev.yml index 4fd7f6c..3c4317b 100644 --- a/.github/workflows/cdk-deploy-dev.yml +++ b/.github/workflows/cdk-deploy-dev.yml @@ -16,23 +16,33 @@ jobs: id-token: write steps: - name: Checkout repository - uses: actions/checkout@v4 + id: checkout_repository + uses: actions/checkout@v7 + with: + persist-credentials: false - name: Setup python environment - uses: actions/setup-python@v5 + id: setup_python_environment + uses: actions/setup-python@v7 with: python-version: "3.13" - name: Setup uv - uses: astral-sh/setup-uv@v5 + id: setup_uv + uses: astral-sh/setup-uv@v10.0.1 + - name: Install dependencies + id: install_dependencies + run: uv sync + - name: Install cdk cli + id: install_cdk_cli + run: npm install -g aws-cdk@2.1139.0 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + id: configure_aws_credentials + uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::987654321012:role/GitHubDeployRole aws-region: us-east-1 - - name: Install dependencies - run: uv sync - - name: Install cdk cli - run: npm install -g aws-cdk@2.1130.0 - name: Validate CDK for the DEV environment + id: validate_cdk_for_the_dev_environment run: uv run projen dev:validate - name: Deploy CDK to the DEV environment on AWS account 987654321012 + id: deploy_cdk_to_the_dev_environment_on_aws_account_987654321012 run: uv run projen dev:deploy diff --git a/.github/workflows/cdk-deploy-test.yml b/.github/workflows/cdk-deploy-test.yml index 943a594..70ec245 100644 --- a/.github/workflows/cdk-deploy-test.yml +++ b/.github/workflows/cdk-deploy-test.yml @@ -16,23 +16,33 @@ jobs: id-token: write steps: - name: Checkout repository - uses: actions/checkout@v4 + id: checkout_repository + uses: actions/checkout@v7 + with: + persist-credentials: false - name: Setup python environment - uses: actions/setup-python@v5 + id: setup_python_environment + uses: actions/setup-python@v7 with: python-version: "3.13" - name: Setup uv - uses: astral-sh/setup-uv@v5 + id: setup_uv + uses: astral-sh/setup-uv@v10.0.1 + - name: Install dependencies + id: install_dependencies + run: uv sync + - name: Install cdk cli + id: install_cdk_cli + run: npm install -g aws-cdk@2.1139.0 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + id: configure_aws_credentials + uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::123456789012:role/GitHubDeployRole aws-region: us-east-1 - - name: Install dependencies - run: uv sync - - name: Install cdk cli - run: npm install -g aws-cdk@2.1130.0 - name: Validate CDK for the TEST environment + id: validate_cdk_for_the_test_environment run: uv run projen test:validate - name: Deploy CDK to the TEST environment on AWS account 123456789012 + id: deploy_cdk_to_the_test_environment_on_aws_account_123456789012 run: uv run projen test:deploy diff --git a/.github/workflows/cdk-validate.yml b/.github/workflows/cdk-validate.yml new file mode 100644 index 0000000..7c0fb50 --- /dev/null +++ b/.github/workflows/cdk-validate.yml @@ -0,0 +1,35 @@ +# ~~ Generated by projen. To modify, edit .projenrc.py and run "uv run projen". + +name: cdk-validate +on: + pull_request: {} + workflow_dispatch: {} +jobs: + validate: + name: Validate CDK app offline + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout repository + id: checkout_repository + uses: actions/checkout@v7 + with: + persist-credentials: false + - name: Setup python environment + id: setup_python_environment + uses: actions/setup-python@v7 + with: + python-version: "3.13" + - name: Setup uv + id: setup_uv + uses: astral-sh/setup-uv@v10.0.1 + - name: Install dependencies + id: install_dependencies + run: uv sync + - name: Install cdk cli + id: install_cdk_cli + run: npm install -g aws-cdk@2.1139.0 + - name: Validate CDK app against the default rule set + id: validate_cdk_app_against_the_default_rule_set + run: uv run projen validate diff --git a/.github/workflows/pull-request-lint.yml b/.github/workflows/pull-request-lint.yml index f9b8ad7..94ed431 100644 --- a/.github/workflows/pull-request-lint.yml +++ b/.github/workflows/pull-request-lint.yml @@ -19,7 +19,8 @@ jobs: pull-requests: write if: (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') steps: - - uses: amannn/action-semantic-pull-request@v6 + - id: validate-pr-title + uses: amannn/action-semantic-pull-request@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.gitignore b/.gitignore index 9a3a41f..9e07a12 100644 --- a/.gitignore +++ b/.gitignore @@ -92,6 +92,7 @@ cython_debug/ !/cdk.json /cdk.out/ .cdk.staging/ +!/.github/workflows/cdk-validate.yml !/.github/dependabot.yml !/.github/workflows/cdk-deploy-dev.yml !/.github/workflows/cdk-deploy-test.yml diff --git a/.projen/deps.json b/.projen/deps.json index 60c7cdf..7ce1639 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -2,7 +2,7 @@ "dependencies": [ { "name": "projen", - "version": "0.101.11", + "version": "0.103.7", "type": "devenv" }, { @@ -19,7 +19,7 @@ }, { "name": "aws-cdk-lib", - "version": "2.263.0", + "version": "2.267.0", "type": "runtime" }, { @@ -29,7 +29,7 @@ }, { "name": "pytest", - "version": "9.0.3", + "version": "9.1.1", "type": "test" } ], diff --git a/.projen/files.json b/.projen/files.json index 526fca0..aa55eb8 100644 --- a/.projen/files.json +++ b/.projen/files.json @@ -5,6 +5,7 @@ ".github/workflows/auto-approve.yml", ".github/workflows/cdk-deploy-dev.yml", ".github/workflows/cdk-deploy-test.yml", + ".github/workflows/cdk-validate.yml", ".github/workflows/pull-request-lint.yml", ".gitignore", ".projen/deps.json", diff --git a/.projen/tasks.json b/.projen/tasks.json index 655de10..88ed497 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -38,22 +38,35 @@ }, "steps": [ { - "exec": "git checkout -b scratch", + "execArgs": [ + "git", + "checkout", + "-b", + "scratch" + ], "name": "save current HEAD in \"scratch\" branch" }, { - "exec": "git checkout $BRANCH" + "exec": "git checkout \"$BRANCH\"" }, { - "exec": "git fetch origin", + "execArgs": [ + "git", + "fetch", + "origin" + ], "name": "fetch latest changes from origin" }, { - "exec": "git reset --hard origin/$BRANCH", + "exec": "git reset --hard \"origin/$BRANCH\"", "name": "hard reset to origin commit" }, { - "exec": "git clean -fdx", + "execArgs": [ + "git", + "clean", + "-fdx" + ], "name": "clean all untracked files" }, { @@ -199,7 +212,16 @@ "description": "Install dependencies and update lockfile", "steps": [ { - "exec": "uv sync && uv lock" + "execArgs": [ + "uv", + "sync" + ] + }, + { + "execArgs": [ + "uv", + "lock" + ] } ] }, @@ -294,9 +316,14 @@ "test": { "name": "test", "description": "Run tests", + "env": { + "PYTHONPATH": "src" + }, "steps": [ { - "exec": "pytest" + "execArgs": [ + "pytest" + ] } ] }, diff --git a/.projenrc.py b/.projenrc.py index 9fa4a9a..f9e40dc 100644 --- a/.projenrc.py +++ b/.projenrc.py @@ -8,7 +8,12 @@ from projen import YamlFile from projen.awscdk import AwsCdkPythonApp -from src.bin.cicd_helper import github_cicd +from src.bin.cicd_helper import ( + GITHUB_ACTIONS, + cdk_validate_workflow, + github_cicd, + pin_github_actions, +) from src.bin.env_helper import CDK_VALIDATE_COMMAND, cdk_action_task # Define the python module name and set the python version @@ -17,8 +22,8 @@ python_version = "3.13" python_major, python_minor = map(int, python_version.split(".")) python_requires = f">={python_version},<{python_major}.{python_minor + 1}" -cdk_version = "2.263.0" -cdk_cli_version = "2.1130.0" +cdk_version = "2.267.0" +cdk_cli_version = "2.1139.0" # Define the AWS region for the CDK app and github workflows # Default to us-east-1 if AWS_REGION is not set in your environment variables @@ -43,11 +48,11 @@ app_entrypoint=f"{python_module_name}/app.py", deps=["aws-cdk-github-oidc"], dev_deps=[ - "projen@0.101.11", + "projen@0.103.7", "ruff", "ty", ], # Find the latest projen version here: https://pypi.org/project/projen/ - pytest_options={"version": "9.0.3"}, + pytest_options={"version": "9.1.1"}, uv=True, uv_options={ "python_exec": f"python{python_version}", @@ -97,6 +102,9 @@ # so the CDK CLI knows which region to use project.tasks.add_environment("CDK_DEFAULT_REGION", aws_region) +# Tests import the stacks the same way src/app.py does, so put src on the module path +project.test_task.env("PYTHONPATH", python_module_name) + project.add_task( "validate", description="Validate the CDK app offline against the default CloudFormation rules", @@ -114,6 +122,12 @@ gh = project.github +# Keep projen-managed workflows (auto-approve, pull-request-lint) on the same action versions +pin_github_actions(gh) + +# Validate the CDK app offline on every pull request (no AWS credentials required) +cdk_validate_workflow(gh, python_version, cdk_cli_version) + # Add Dependabot configuration for uv YamlFile( project, @@ -151,7 +165,11 @@ # Add checkout step before the merge step auto_approve_workflow.add_override( "jobs.approve.steps.1", - {"name": "Checkout", "uses": "actions/checkout@v5"}, + { + "name": "Checkout", + "uses": GITHUB_ACTIONS["checkout"], + "with": {"persist-credentials": False}, + }, ) auto_approve_workflow.add_override( "jobs.approve.steps.2", diff --git a/pyproject.toml b/pyproject.toml index 6348ff4..367ab14 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ readme = "README.md" requires-python = ">=3.13,<3.14" dependencies = [ "aws-cdk-github-oidc", - "aws-cdk-lib==2.263.0", + "aws-cdk-lib==2.267.0", "constructs>=10.5.1,<11.0.0" ] @@ -19,4 +19,4 @@ dependencies = [ email = "danny@towardsthecloud.com" [dependency-groups] -dev = [ "projen==0.101.11", "ruff", "ty", "pytest==9.0.3" ] +dev = [ "projen==0.103.7", "ruff", "ty", "pytest==9.1.1" ] diff --git a/src/bin/cicd_helper.py b/src/bin/cicd_helper.py index 57454fd..6a98a8d 100644 --- a/src/bin/cicd_helper.py +++ b/src/bin/cicd_helper.py @@ -1,5 +1,78 @@ from projen import github +# Pinned GitHub Actions used by every workflow in this repo. `.projenrc.py` registers these +# with projen's actions provider so projen-managed workflows (auto-approve, pull-request-lint) +# render the same versions as the workflows built here. +GITHUB_ACTIONS = { + "checkout": "actions/checkout@v7", + "configure_aws_credentials": "aws-actions/configure-aws-credentials@v6", + "semantic_pull_request": "amannn/action-semantic-pull-request@v6", + "setup_python": "actions/setup-python@v7", + "setup_uv": "astral-sh/setup-uv@v10.0.1", # setup-uv publishes no floating v10 tag +} + + +def pin_github_actions(gh): + """Register GITHUB_ACTIONS with projen's actions provider so every workflow uses the same versions.""" + for action in GITHUB_ACTIONS.values(): + gh.actions.set(action.split("@")[0], action) + + +def cdk_environment_steps(python_version, cdk_cli_version): + """Checkout, Python, uv, project dependencies and the CDK CLI.""" + return [ + { + "name": "Checkout repository", + "uses": GITHUB_ACTIONS["checkout"], + # No job built here pushes to git, so keep the token out of .git/config + "with": {"persist-credentials": False}, + }, + { + "name": "Setup python environment", + "uses": GITHUB_ACTIONS["setup_python"], + "with": { + "python-version": python_version, + }, + }, + { + "name": "Setup uv", + "uses": GITHUB_ACTIONS["setup_uv"], + }, + { + "name": "Install dependencies", + "run": "uv sync", + }, + { + "name": "Install cdk cli", + "run": f"npm install -g aws-cdk@{cdk_cli_version}", + }, + ] + + +def cdk_validate_workflow(gh, python_version, cdk_cli_version): + """Validate the CDK app offline on pull requests, without AWS credentials.""" + workflow = github.GithubWorkflow(gh, "cdk-validate") + workflow.on(pull_request={}, workflow_dispatch={}) + workflow.add_jobs( + { + "validate": { + "name": "Validate CDK app offline", + "runsOn": ["ubuntu-latest"], + "permissions": { + "contents": github.workflows.JobPermission.READ, + }, + "steps": [ + *cdk_environment_steps(python_version, cdk_cli_version), + { + "name": "Validate CDK app against the default rule set", + "run": "uv run projen validate", + }, + ], + }, + } + ) + return workflow + def github_cicd(gh, account, env, python_version, aws_region, cdk_cli_version): # Add a GitHub workflow for deploying the CDK stacks to the AWS account @@ -20,37 +93,15 @@ def github_cicd(gh, account, env, python_version, aws_region, cdk_cli_version): "idToken": github.workflows.JobPermission.WRITE, }, "steps": [ - { - "name": "Checkout repository", - "uses": "actions/checkout@v4", - }, - { - "name": "Setup python environment", - "uses": "actions/setup-python@v5", - "with": { - "python-version": python_version, - }, - }, - { - "name": "Setup uv", - "uses": "astral-sh/setup-uv@v5", - }, + *cdk_environment_steps(python_version, cdk_cli_version), { "name": "Configure AWS credentials", - "uses": "aws-actions/configure-aws-credentials@v4", + "uses": GITHUB_ACTIONS["configure_aws_credentials"], "with": { "role-to-assume": f"arn:aws:iam::{account}:role/GitHubDeployRole", "aws-region": aws_region, }, }, - { - "name": "Install dependencies", - "run": "uv sync", - }, - { - "name": "Install cdk cli", - "run": f"npm install -g aws-cdk@{cdk_cli_version}", - }, { "name": f"Validate CDK for the {env.upper()} environment", "run": f"uv run projen {env}:validate", diff --git a/uv.lock b/uv.lock index 38aa616..bac3ef5 100644 --- a/uv.lock +++ b/uv.lock @@ -13,16 +13,15 @@ wheels = [ [[package]] name = "aws-cdk-asset-awscli-v1" -version = "2.2.282" +version = "2.2.292" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsii" }, { name = "publication" }, - { name = "typeguard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/30/90558d9e05c2b1a5a8d7d87332b4bed4a2e5d2eb04cc7064f6e9e0c8a2f2/aws_cdk_asset_awscli_v1-2.2.282.tar.gz", hash = "sha256:f86e61653927f77fb235b5ec148c955c610117430c869d182c8b20f7e07e2df2", size = 20740538, upload-time = "2026-05-25T21:33:20.444Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/2c/cb258b03e0fa3dcfd6e73e081e81783bbe138ab96641b49fe134308b9c5b/aws_cdk_asset_awscli_v1-2.2.292.tar.gz", hash = "sha256:06da203eeaecbbbf5f1ecd3b12140104e6a59b6a7f6182cfbda5c5deda4b6344", size = 21189256, upload-time = "2026-08-03T15:28:55.2Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/86/dcb45969f1b34351cfd9afdb6b35bff38a3e929c8bc42b07036879f3a62e/aws_cdk_asset_awscli_v1-2.2.282-py3-none-any.whl", hash = "sha256:24139da0eb1be59f8cfda22c6343d51e8d50bb89b5052b049cfab92683de7790", size = 20738955, upload-time = "2026-05-25T21:33:17.673Z" }, + { url = "https://files.pythonhosted.org/packages/a5/23/c307fefce170e5703b102398d6c541a9b52534a43718760c58677e62e98a/aws_cdk_asset_awscli_v1-2.2.292-py3-none-any.whl", hash = "sha256:01cfb33e2913df2d63448b0954ea4ed1bcb1d064514b4b7aa266eda915e8ebfc", size = 21187714, upload-time = "2026-08-03T15:28:51.844Z" }, ] [[package]] @@ -70,7 +69,7 @@ wheels = [ [[package]] name = "aws-cdk-lib" -version = "2.263.0" +version = "2.267.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aws-cdk-asset-awscli-v1" }, @@ -80,9 +79,9 @@ dependencies = [ { name = "jsii" }, { name = "publication" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d4/62/41de6ea7bf3c10a18a3d70c42c0fe770c8e7c4b20cb9a7b4d95e295b50d6/aws_cdk_lib-2.263.0.tar.gz", hash = "sha256:fc87a36758c93c95845bb4889c21a899eb639b78e43d09d965d9d924233e60f6", size = 55074638, upload-time = "2026-07-31T16:47:16.594Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/fc/9f6994dcef352b4ef5c3ae2ba3b92d224824ce96b41c1af900a702e253e7/aws_cdk_lib-2.267.0.tar.gz", hash = "sha256:2778f1befdda7401ad064d60f5442858c2dad2a1a87591264ca6f17da6ebd4a2", size = 55941121, upload-time = "2026-08-27T18:25:51.661Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/10/c3/e8d1cc686828e8213be2929db1d21b95beb50fcde36b6ecff309eae75916/aws_cdk_lib-2.263.0-py3-none-any.whl", hash = "sha256:a8d7928c7a01c25f6cb85c98e465df6ffd2b9e696bdb256257eeca2157c80609", size = 55742744, upload-time = "2026-07-31T16:46:31.48Z" }, + { url = "https://files.pythonhosted.org/packages/57/d3/13b384feaf2f33295d6b39532374951a9ae3598495d8bd336a0ccd8f807e/aws_cdk_lib-2.267.0-py3-none-any.whl", hash = "sha256:83e269742e10069b5df80b2b99ec55ffb097f31cbf62317b6cf44eb63d4a9430", size = 56644259, upload-time = "2026-08-27T18:25:10.109Z" }, ] [[package]] @@ -106,14 +105,14 @@ dev = [ [package.metadata] requires-dist = [ { name = "aws-cdk-github-oidc" }, - { name = "aws-cdk-lib", specifier = "==2.263.0" }, + { name = "aws-cdk-lib", specifier = "==2.267.0" }, { name = "constructs", specifier = ">=10.5.1,<11.0.0" }, ] [package.metadata.requires-dev] dev = [ - { name = "projen", specifier = "==0.101.11" }, - { name = "pytest", specifier = "==9.0.3" }, + { name = "projen", specifier = "==0.103.7" }, + { name = "pytest", specifier = "==9.1.1" }, { name = "ruff" }, { name = "ty" }, ] @@ -165,7 +164,7 @@ wheels = [ [[package]] name = "jsii" -version = "1.139.0" +version = "1.140.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -175,9 +174,9 @@ dependencies = [ { name = "typeguard" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c1/71/7c612c16291a6dc654bac00f56bef24c45f86e9a7c9668dc7d36f187e808/jsii-1.139.0.tar.gz", hash = "sha256:163c5d3ec00fd4ec89a33b9097f20a6f27626dd69d6875a8f7cc7577b8021ad0", size = 531387, upload-time = "2026-07-17T02:34:33.293Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c0/3e/b3edc1319658b3cc45dcf2d7b61742a4fcda5d453ef9583cdfccfe90ab77/jsii-1.140.0.tar.gz", hash = "sha256:454c874d963a862f6b90bc013c45a720e51292659f57249d9cae7cb2a189ec0e", size = 532926, upload-time = "2026-08-24T18:41:31.05Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/3e/fce01768f79b2d5d0cf6258b55045f4b083ee86fd5de24c1af38168312ab/jsii-1.139.0-py3-none-any.whl", hash = "sha256:11468f767c6da698ed9888a04352850af33ccccfec7656475626caf36fca8bbb", size = 501693, upload-time = "2026-07-17T02:34:31.747Z" }, + { url = "https://files.pythonhosted.org/packages/38/c6/78745af0249f2f1c1d2f2112dbcde0a4025daac1d0125a685163197c9fac/jsii-1.140.0-py3-none-any.whl", hash = "sha256:aa24f27d15d8d7db1ff32a9c56074bc87e728b30330ead97fb149419a3721a50", size = 503205, upload-time = "2026-08-24T18:41:29.071Z" }, ] [[package]] @@ -200,16 +199,16 @@ wheels = [ [[package]] name = "projen" -version = "0.101.11" +version = "0.103.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "constructs" }, { name = "jsii" }, { name = "publication" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/51/71/4be3673189287e80dd9c69858c71b2f6cb6a47877001be05e6222d8499ce/projen-0.101.11.tar.gz", hash = "sha256:4f4fdf92cba4f984065d787e56f831a042003db6dce483082150fa5d5f792e73", size = 5259131, upload-time = "2026-07-10T14:38:34.116Z" } +sdist = { url = "https://files.pythonhosted.org/packages/49/b9/8c4641ef185daedd388777e20108a7c4adfd22c1ba303b785e9719d25071/projen-0.103.7.tar.gz", hash = "sha256:259f9beb55638aa5bd16f0fd212f378d7fc621e593325280a41a5229f07e2801", size = 5567825, upload-time = "2026-08-28T10:18:10.102Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a8/0f/9feb085c4e0bfcfe59211a90897eee138124b35544b42ad663fceb0010e8/projen-0.101.11-py3-none-any.whl", hash = "sha256:5b5657bf192e469b08f7fe4597e19623d9fb7103ae1a63ee5e6aef7507acea92", size = 5265790, upload-time = "2026-07-10T14:38:31.108Z" }, + { url = "https://files.pythonhosted.org/packages/78/52/84971422f5e4274c2d4faad2195ff7ef067851184a561791ee38cb4abc6b/projen-0.103.7-py3-none-any.whl", hash = "sha256:237efcf349eded9b9b5f097501f74e4e3d02b97fea4dc459972e8833009ddcbb", size = 5574752, upload-time = "2026-08-28T10:18:07.719Z" }, ] [[package]] @@ -232,7 +231,7 @@ wheels = [ [[package]] name = "pytest" -version = "9.0.3" +version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -241,9 +240,9 @@ dependencies = [ { name = "pluggy" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]]