From dc3e6f6a41b4b1133be663afad21e7a27de9e69f Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:22:16 +0000 Subject: [PATCH 01/28] bump uv --- .devcontainer/devcontainer.json | 4 +-- .devcontainer/install-ci-tooling.py | 2 +- extensions/context.py | 25 ++++++++++--------- pyproject.toml | 2 +- .../devcontainer.json.jinja-base | 2 +- template/extensions/context.py.jinja-base | 1 + uv.lock | 8 +++--- 7 files changed, 23 insertions(+), 21 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3d70bd491..0fe831b63 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -22,7 +22,7 @@ "-AmazonWebServices.aws-toolkit-vscode", // the AWS CLI feature installs this automatically, but it's causing problems in VS Code // basic tooling // "eamodio.gitlens@15.5.1", - "coderabbit.coderabbit-vscode@0.16.0", + "coderabbit.coderabbit-vscode@0.16.1", "ms-vscode.live-server@0.5.2025051301", "MS-vsliveshare.vsliveshare@1.0.5905", "github.copilot@1.388.0", @@ -62,5 +62,5 @@ "initializeCommand": "sh .devcontainer/initialize-command.sh", "onCreateCommand": "sh .devcontainer/on-create-command.sh", "postStartCommand": "sh .devcontainer/post-start-command.sh" - // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 99d2d16a # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 71b2d03b # spellchecker:disable-line } diff --git a/.devcontainer/install-ci-tooling.py b/.devcontainer/install-ci-tooling.py index 880938cbb..e28b2b168 100644 --- a/.devcontainer/install-ci-tooling.py +++ b/.devcontainer/install-ci-tooling.py @@ -5,7 +5,7 @@ import subprocess import sys -UV_VERSION = "0.9.11" +UV_VERSION = "0.9.17" COPIER_VERSION = "9.11.0" COPIER_TEMPLATE_EXTENSIONS_VERSION = "0.3.3" PRE_COMMIT_VERSION = "4.5.0" diff --git a/extensions/context.py b/extensions/context.py index 7b6b895c5..cda14760d 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -11,16 +11,16 @@ class ContextUpdater(ContextHook): @override def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: # These are duplicated in the install-ci-tooling.py script in this repository - context["uv_version"] = "0.9.11" + context["uv_version"] = "0.9.17" context["pre_commit_version"] = "4.5.0" # These also in pyproject.toml context["copier_version"] = "9.11.0" context["copier_template_extensions_version"] = "0.3.3" ####### - context["pnpm_version"] = "10.24.0" + context["pnpm_version"] = "10.25.0" # These are duplicated in the pyproject.toml of this repository context["pyright_version"] = "1.1.407" - context["pytest_version"] = "9.0.1" + context["pytest_version"] = "9.0.2" context["pytest_randomly_version"] = "4.0.1" context["pytest_cov_version"] = "7.0.0" ####### @@ -33,29 +33,30 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["pulumi_okta_version"] = "6.1.0" context["boto3_version"] = "1.41.2" context["ephemeral_pulumi_deploy_version"] = "0.0.5" - context["pydantic_version"] = "2.12.4" - context["pyinstaller_version"] = "6.16.0" + context["pydantic_version"] = "2.12.5" + context["pyinstaller_version"] = "6.17.0" context["setuptools_version"] = "80.7.1" context["strawberry_graphql_version"] = "0.287.0" - context["fastapi_version"] = "0.121.0" + context["fastapi_version"] = "0.124.2" context["fastapi_offline_version"] = "1.7.4" context["uvicorn_version"] = "0.38.0" context["lab_auto_pulumi_version"] = "0.1.17" context["ariadne_codegen_version"] = "0.15.2" context["pytest_mock_version"] = "3.15.1" - context["uuid_utils_version"] = "0.11.0" + context["uuid_utils_version"] = "0.12.0" context["syrupy_version"] = "5.0.0" context["structlog_version"] = "25.5.0" context["httpx_version"] = "0.28.1" context["python_kiota_bundle_version"] = "1.9.7" + context["vcrpy_version"] = "8.1.0" ####### context["node_version"] = "24.7.0" context["nuxt_ui_version"] = "^4.2.1" - context["nuxt_version"] = "^4.2.0" + context["nuxt_version"] = "^4.2.2" context["nuxt_icon_version"] = "^2.1.0" context["typescript_version"] = "^5.9.3" - context["playwright_version"] = "^1.56.0" - context["vue_version"] = "^3.5.22" + context["playwright_version"] = "^1.57.0" + context["vue_version"] = "^3.5.25" context["vue_tsc_version"] = "^3.1.2" context["vue_devtools_api_version"] = "^8.0.0" context["vue_router_version"] = "^4.6.0" @@ -66,7 +67,7 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["nuxt_eslint_version"] = "^1.10.0" context["zod_version"] = "^4.1.12" context["zod_from_json_schema_version"] = "^0.5.1" - context["types_node_version"] = "^24.10.1" + context["types_node_version"] = "^25.0.0" context["nuxt_apollo_version"] = "5.0.0-alpha.15" context["graphql_codegen_cli_version"] = "^6.0.0" context["graphql_codegen_typescript_version"] = "^5.0.0" @@ -83,7 +84,7 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["node_kiota_bundle_version"] = "1.0.0-preview.99" ####### # These are duplicated in the CI files for this repository - context["gha_checkout"] = "v5.0.0" + context["gha_checkout"] = "v6.0.1" context["gha_setup_python"] = "v6.0.0" context["gha_cache"] = "v4.2.4" context["gha_linux_runner"] = "ubuntu-24.04" diff --git a/pyproject.toml b/pyproject.toml index e4f2cb669..55d0c0fcb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ description = "Add your description here" readme = "README.md" requires-python = ">=3.12.7" dependencies = [ - "pytest>=9.0.1", + "pytest>=9.0.2", "pytest-cov>=7.0.0", "pytest-randomly>=4.0.1", "pyright[nodejs]>=1.1.407", diff --git a/template/.devcontainer/devcontainer.json.jinja-base b/template/.devcontainer/devcontainer.json.jinja-base index 4a118dd60..33cf5f35c 100644 --- a/template/.devcontainer/devcontainer.json.jinja-base +++ b/template/.devcontainer/devcontainer.json.jinja-base @@ -28,7 +28,7 @@ "-AmazonWebServices.aws-toolkit-vscode", // the AWS CLI feature installs this automatically, but it's causing problems in VS Code{% endraw %}{% endif %}{% raw %} // basic tooling // "eamodio.gitlens@15.5.1", - "coderabbit.coderabbit-vscode@0.16.0", + "coderabbit.coderabbit-vscode@0.16.1", "ms-vscode.live-server@0.5.2025051301", "MS-vsliveshare.vsliveshare@1.0.5905", "github.copilot@1.388.0", diff --git a/template/extensions/context.py.jinja-base b/template/extensions/context.py.jinja-base index f4085b16f..1b5a701cc 100644 --- a/template/extensions/context.py.jinja-base +++ b/template/extensions/context.py.jinja-base @@ -43,6 +43,7 @@ class ContextUpdater(ContextHook): context["structlog_version"] = "{{ structlog_version }}" context["httpx_version"] = "{{ httpx_version }}" context["python_kiota_bundle_version"] = "{{ python_kiota_bundle_version }}" + context["vcrpy_version"] = "{{ vcrpy_version }}" context["node_version"] = "{{ node_version }}" context["nuxt_ui_version"] = "{{ nuxt_ui_version }}" diff --git a/uv.lock b/uv.lock index ba3f48a19..52c915b84 100644 --- a/uv.lock +++ b/uv.lock @@ -62,7 +62,7 @@ requires-dist = [ { name = "copier", specifier = ">=9.11.0" }, { name = "copier-template-extensions", specifier = ">=0.3.3" }, { name = "pyright", extras = ["nodejs"], specifier = ">=1.1.407" }, - { name = "pytest", specifier = ">=9.0.1" }, + { name = "pytest", specifier = ">=9.0.2" }, { name = "pytest-cov", specifier = ">=7.0.0" }, { name = "pytest-randomly", specifier = ">=4.0.1" }, ] @@ -402,7 +402,7 @@ nodejs = [ [[package]] name = "pytest" -version = "9.0.1" +version = "9.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -411,9 +411,9 @@ dependencies = [ { name = "pluggy" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/07/56/f013048ac4bc4c1d9be45afd4ab209ea62822fb1598f40687e6bf45dcea4/pytest-9.0.1.tar.gz", hash = "sha256:3e9c069ea73583e255c3b21cf46b8d3c56f6e3a1a8f6da94ccb0fcf57b9d73c8", size = 1564125, upload-time = "2025-11-12T13:05:09.333Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/8b/6300fb80f858cda1c51ffa17075df5d846757081d11ab4aa35cef9e6258b/pytest-9.0.1-py3-none-any.whl", hash = "sha256:67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad", size = 373668, upload-time = "2025-11-12T13:05:07.379Z" }, + { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, ] [[package]] From ae1c48a6902c0489679ffe8a0ea124c48948f9e5 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:24:11 +0000 Subject: [PATCH 02/28] gha --- .github/workflows/ci.yaml | 12 ++++++------ .github/workflows/tag-on-merge.yaml | 2 +- extensions/context.py | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c44da0e29..75063b001 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,12 +25,12 @@ jobs: timeout-minutes: 8 runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5.0.0 + - uses: actions/checkout@v6.0.1 with: persist-credentials: false - name: Setup Python - uses: actions/setup-python@v6.0.0 + uses: actions/setup-python@v6.1.0 with: python-version: ${{ matrix.python-version }} @@ -50,7 +50,7 @@ jobs: timeout-minutes: 30 # this is the amount of time this action will wait to attempt to acquire the mutex lock before failing, e.g. if other jobs are queued up in front of it - name: Cache Pre-commit hooks - uses: actions/cache@v4.2.4 + uses: actions/cache@v4.3.0 env: cache-name: cache-pre-commit-hooks with: @@ -83,12 +83,12 @@ jobs: contents: write # needed for mutex steps: - - uses: actions/checkout@v5.0.0 + - uses: actions/checkout@v6.0.1 with: persist-credentials: false - name: Setup Python - uses: actions/setup-python@v6.0.0 + uses: actions/setup-python@v6.1.0 with: python-version: ${{ matrix.python-version }} @@ -134,7 +134,7 @@ jobs: timeout-minutes: 30 # this is the amount of time this action will wait to attempt to acquire the mutex lock before failing, e.g. if other jobs are queued up in front of it - name: Cache Pre-commit hooks - uses: actions/cache@v4.2.4 + uses: actions/cache@v4.3.0 env: cache-name: cache-pre-commit-hooks with: diff --git a/.github/workflows/tag-on-merge.yaml b/.github/workflows/tag-on-merge.yaml index 3c208ca70..2e9b2277c 100644 --- a/.github/workflows/tag-on-merge.yaml +++ b/.github/workflows/tag-on-merge.yaml @@ -14,7 +14,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v5.0.0 + - uses: actions/checkout@v6.0.1 with: ref: ${{ github.event.pull_request.merge_commit_sha }} fetch-depth: '0' diff --git a/extensions/context.py b/extensions/context.py index cda14760d..58c34128e 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -85,8 +85,8 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: ####### # These are duplicated in the CI files for this repository context["gha_checkout"] = "v6.0.1" - context["gha_setup_python"] = "v6.0.0" - context["gha_cache"] = "v4.2.4" + context["gha_setup_python"] = "v6.1.0" + context["gha_cache"] = "v4.3.0" context["gha_linux_runner"] = "ubuntu-24.04" ####### context["gha_upload_artifact"] = "v5.0.0" From 5184f186a29916c9676b81736df986ba9b10fd58 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:26:22 +0000 Subject: [PATCH 03/28] More actions --- extensions/context.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/context.py b/extensions/context.py index 58c34128e..8b977cf05 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -95,9 +95,9 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["gha_setup_buildx"] = "v3.11.1" context["buildx_version"] = "v0.27.0" context["gha_docker_build_push"] = "v6.18.0" - context["gha_configure_aws_credentials"] = "v5.1.0" + context["gha_configure_aws_credentials"] = "v5.1.1" context["gha_amazon_ecr_login"] = "v2.0.1" - context["gha_setup_node"] = "v6.0.0" + context["gha_setup_node"] = "v6.1.0" context["gha_action_gh_release"] = "v2.2.1" context["gha_mutex"] = "1ebad517141198e08d47cf72f3c0975316620a65 # v1.0.0-alpha.10" context["gha_pypi_publish"] = "v1.13.0" @@ -109,8 +109,8 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["gha_xlong_timeout_minutes"] = "45" ####### context["debian_release_name"] = "bookworm" - context["alpine_image_version"] = "3.22" - context["nginx_image_version"] = "1.29.1" + context["alpine_image_version"] = "3.23" + context["nginx_image_version"] = "1.29.4" ####### context["kiota_cli_version"] = "1.29.0" # These also in the tests/data.yml files in this repository and in copier.yaml From 082ee1155917577c9f6987e62a029fcacc4332a8 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:29:45 +0000 Subject: [PATCH 04/28] more context --- extensions/context.py | 2 ++ template/extensions/context.py.jinja-base | 2 ++ 2 files changed, 4 insertions(+) diff --git a/extensions/context.py b/extensions/context.py index 8b977cf05..8eb287229 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -49,6 +49,8 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["httpx_version"] = "0.28.1" context["python_kiota_bundle_version"] = "1.9.7" context["vcrpy_version"] = "8.1.0" + context["pytest_recording_version"] = "0.13.4" + context["pytest_asyncio_version"] = "1.3.0" ####### context["node_version"] = "24.7.0" context["nuxt_ui_version"] = "^4.2.1" diff --git a/template/extensions/context.py.jinja-base b/template/extensions/context.py.jinja-base index 1b5a701cc..e91e40d8b 100644 --- a/template/extensions/context.py.jinja-base +++ b/template/extensions/context.py.jinja-base @@ -44,6 +44,8 @@ class ContextUpdater(ContextHook): context["httpx_version"] = "{{ httpx_version }}" context["python_kiota_bundle_version"] = "{{ python_kiota_bundle_version }}" context["vcrpy_version"] = "{{ vcrpy_version }}" + context["pytest_recording_version"] = "{{ pytest_recording_version }}" + context["pytest_asyncio_version"] = "{{ pytest_asyncio_version }}" context["node_version"] = "{{ node_version }}" context["nuxt_ui_version"] = "{{ nuxt_ui_version }}" From b08479b46312ed8b085f6089848fa7844ab61ea1 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:31:03 +0000 Subject: [PATCH 05/28] aridane --- extensions/context.py | 1 + template/extensions/context.py.jinja-base | 1 + 2 files changed, 2 insertions(+) diff --git a/extensions/context.py b/extensions/context.py index 8eb287229..c743787cf 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -51,6 +51,7 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["vcrpy_version"] = "8.1.0" context["pytest_recording_version"] = "0.13.4" context["pytest_asyncio_version"] = "1.3.0" + context["ariadne_codegen_version"] = "0.17.0" ####### context["node_version"] = "24.7.0" context["nuxt_ui_version"] = "^4.2.1" diff --git a/template/extensions/context.py.jinja-base b/template/extensions/context.py.jinja-base index e91e40d8b..c3a2693a0 100644 --- a/template/extensions/context.py.jinja-base +++ b/template/extensions/context.py.jinja-base @@ -46,6 +46,7 @@ class ContextUpdater(ContextHook): context["vcrpy_version"] = "{{ vcrpy_version }}" context["pytest_recording_version"] = "{{ pytest_recording_version }}" context["pytest_asyncio_version"] = "{{ pytest_asyncio_version }}" + context["ariadne_codegen_version"] = "{{ ariadne_codegen_version }}" context["node_version"] = "{{ node_version }}" context["nuxt_ui_version"] = "{{ nuxt_ui_version }}" From 752d837eb2fa718dd256bffc37afb877e71bba28 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:33:13 +0000 Subject: [PATCH 06/28] fix --- extensions/context.py | 3 +-- template/extensions/context.py.jinja-base | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/extensions/context.py b/extensions/context.py index c743787cf..b95fdb0d4 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -41,7 +41,7 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["fastapi_offline_version"] = "1.7.4" context["uvicorn_version"] = "0.38.0" context["lab_auto_pulumi_version"] = "0.1.17" - context["ariadne_codegen_version"] = "0.15.2" + context["ariadne_codegen_version"] = "0.17.0" context["pytest_mock_version"] = "3.15.1" context["uuid_utils_version"] = "0.12.0" context["syrupy_version"] = "5.0.0" @@ -51,7 +51,6 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["vcrpy_version"] = "8.1.0" context["pytest_recording_version"] = "0.13.4" context["pytest_asyncio_version"] = "1.3.0" - context["ariadne_codegen_version"] = "0.17.0" ####### context["node_version"] = "24.7.0" context["nuxt_ui_version"] = "^4.2.1" diff --git a/template/extensions/context.py.jinja-base b/template/extensions/context.py.jinja-base index c3a2693a0..e91e40d8b 100644 --- a/template/extensions/context.py.jinja-base +++ b/template/extensions/context.py.jinja-base @@ -46,7 +46,6 @@ class ContextUpdater(ContextHook): context["vcrpy_version"] = "{{ vcrpy_version }}" context["pytest_recording_version"] = "{{ pytest_recording_version }}" context["pytest_asyncio_version"] = "{{ pytest_asyncio_version }}" - context["ariadne_codegen_version"] = "{{ ariadne_codegen_version }}" context["node_version"] = "{{ node_version }}" context["nuxt_ui_version"] = "{{ nuxt_ui_version }}" From 497af1213cd92fe68d6d39dc26367ba2ffed5e2f Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:41:17 +0000 Subject: [PATCH 07/28] pulumi --- ...ulumi %}pulumi-aws.yml{% endif %}.jinja-base | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/template/template/.github/workflows/{% if template_uses_pulumi %}pulumi-aws.yml{% endif %}.jinja-base b/template/template/.github/workflows/{% if template_uses_pulumi %}pulumi-aws.yml{% endif %}.jinja-base index 480ebf59c..9356f7bec 100644 --- a/template/template/.github/workflows/{% if template_uses_pulumi %}pulumi-aws.yml{% endif %}.jinja-base +++ b/template/template/.github/workflows/{% if template_uses_pulumi %}pulumi-aws.yml{% endif %}.jinja-base @@ -76,6 +76,16 @@ on: required: false default: '' type: string + DOWNLOAD_ARTIFACT_NAME: + description: 'Name of the artifact to download from the build job' + required: false + default: '' + type: string + DOWNLOAD_ARTIFACT_PATH: + description: 'Path to extract the downloaded artifact to' + required: false + default: '' + type: string secrets: iac-github-api-tokens: description: 'API tokens to use for Github IaC deployment when not using AWS Secrets Manager' @@ -107,6 +117,13 @@ jobs: with: python-version: ${{ inputs.PYTHON_VERSION }} + - name: Download Artifact + uses: actions/download-artifact@{% endraw %}{{ gha_download_artifact }}{% raw %} + if: ${{ inputs.DOWNLOAD_ARTIFACT_NAME != '' }} + with: + name: ${{ inputs.DOWNLOAD_ARTIFACT_NAME }} + path: ${{ inputs.DOWNLOAD_ARTIFACT_PATH }} + - name: Set up mutex # Github concurrency management is horrible, things get arbitrarily cancelled if queued up. So using mutex until github fixes itself. When multiple jobs are modifying cache at once, weird things can happen. possible issue is https://github.com/actions/toolkit/issues/658 uses: ben-z/gh-action-mutex@{% endraw %}{{ gha_mutex }}{% raw %} with: From e1e27183576321f1ef1da887c2f2f3159133d69a Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:46:55 +0000 Subject: [PATCH 08/28] more context --- extensions/context.py | 1 + template/extensions/context.py.jinja-base | 1 + 2 files changed, 2 insertions(+) diff --git a/extensions/context.py b/extensions/context.py index b95fdb0d4..945df641d 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -74,6 +74,7 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["graphql_codegen_cli_version"] = "^6.0.0" context["graphql_codegen_typescript_version"] = "^5.0.0" context["graphql_codegen_typescript_operations_version"] = "^5.0.0" + context["graphql_tools_mock_version"] = "^9.1.0" context["tailwindcss_version"] = "^4.1.11" context["iconify_vue_version"] = "^5.0.0" context["iconify_json_lucide_version"] = "^1.2.71" diff --git a/template/extensions/context.py.jinja-base b/template/extensions/context.py.jinja-base index e91e40d8b..65a5af4cd 100644 --- a/template/extensions/context.py.jinja-base +++ b/template/extensions/context.py.jinja-base @@ -69,6 +69,7 @@ class ContextUpdater(ContextHook): context["graphql_codegen_cli_version"] = "{{ graphql_codegen_cli_version }}" context["graphql_codegen_typescript_version"] = "{{ graphql_codegen_typescript_version }}" context["graphql_codegen_typescript_operations_version"] = "{{ graphql_codegen_typescript_operations_version }}" + context["graphql_tools_mock_version"] = "{{ graphql_tools_mock_version }}" context["tailwindcss_version"] = "{{ tailwindcss_version }}" context["iconify_vue_version"] = "{{ iconify_vue_version }}" context["iconify_json_lucide_version"] = "{{ iconify_json_lucide_version }}" From c7a1bea7e9af8050386de6c0e15f0f7acf2d5a33 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:47:26 +0000 Subject: [PATCH 09/28] more context --- extensions/context.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/context.py b/extensions/context.py index 945df641d..a9046814d 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -41,16 +41,16 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["fastapi_offline_version"] = "1.7.4" context["uvicorn_version"] = "0.38.0" context["lab_auto_pulumi_version"] = "0.1.17" - context["ariadne_codegen_version"] = "0.17.0" + context["ariadne_codegen_version"] = ">=0.17.0" context["pytest_mock_version"] = "3.15.1" - context["uuid_utils_version"] = "0.12.0" + context["uuid_utils_version"] = ">=0.12.0" context["syrupy_version"] = "5.0.0" context["structlog_version"] = "25.5.0" context["httpx_version"] = "0.28.1" - context["python_kiota_bundle_version"] = "1.9.7" - context["vcrpy_version"] = "8.1.0" - context["pytest_recording_version"] = "0.13.4" - context["pytest_asyncio_version"] = "1.3.0" + context["python_kiota_bundle_version"] = ">=1.9.7" + context["vcrpy_version"] = ">=8.1.0" + context["pytest_recording_version"] = ">=0.13.4" + context["pytest_asyncio_version"] = ">=1.3.0" ####### context["node_version"] = "24.7.0" context["nuxt_ui_version"] = "^4.2.1" From 756a2e43db2a112a042c754ff36a3c89915955e3 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 13:52:33 +0000 Subject: [PATCH 10/28] More fixues --- extensions/context.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/context.py b/extensions/context.py index a9046814d..8f3977d5d 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -36,16 +36,16 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["pydantic_version"] = "2.12.5" context["pyinstaller_version"] = "6.17.0" context["setuptools_version"] = "80.7.1" - context["strawberry_graphql_version"] = "0.287.0" - context["fastapi_version"] = "0.124.2" - context["fastapi_offline_version"] = "1.7.4" - context["uvicorn_version"] = "0.38.0" + context["strawberry_graphql_version"] = ">=0.287.0" + context["fastapi_version"] = ">=0.124.2" + context["fastapi_offline_version"] = ">=1.7.4" + context["uvicorn_version"] = ">=0.38.0" context["lab_auto_pulumi_version"] = "0.1.17" context["ariadne_codegen_version"] = ">=0.17.0" context["pytest_mock_version"] = "3.15.1" context["uuid_utils_version"] = ">=0.12.0" - context["syrupy_version"] = "5.0.0" - context["structlog_version"] = "25.5.0" + context["syrupy_version"] = ">=5.0.0" + context["structlog_version"] = ">=25.5.0" context["httpx_version"] = "0.28.1" context["python_kiota_bundle_version"] = ">=1.9.7" context["vcrpy_version"] = ">=8.1.0" From 2c010244f2a53e81315e50244013889ad1606454 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 14:03:55 +0000 Subject: [PATCH 11/28] codegen path --- .devcontainer/devcontainer.json | 2 +- .pre-commit-config.yaml | 10 +++++----- pyrightconfig.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 0fe831b63..6869992e6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -62,5 +62,5 @@ "initializeCommand": "sh .devcontainer/initialize-command.sh", "onCreateCommand": "sh .devcontainer/on-create-command.sh", "postStartCommand": "sh .devcontainer/post-start-command.sh" - // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 71b2d03b # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): db11d38d # spellchecker:disable-line } diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 86348a0bc..67bf40d83 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -257,7 +257,7 @@ repos: files: src/.+\.py$ exclude: | (?x)^( - .*/graphql_codegen/.*| + .*/generated/graphql/.*| .*/generated/open[-_]api/.*| template/.*| )$ @@ -267,14 +267,14 @@ repos: files: tests?/.+\.py$ exclude: | (?x)^( - .*/graphql_codegen/.*| + .*/generated/graphql/.*| .*/generated/open[-_]api/.*| template/.*| )$ - id: ruff-format exclude: | (?x)^( - .*/graphql_codegen/.*| + .*/generated/graphql/.*| .*/generated/open[-_]api/.*| )$ @@ -286,7 +286,7 @@ repos: # exclude the template files---duplication within them will be discovered during CI of that template instantiation exclude: | (?x)^( - .*/graphql_codegen/.*| + .*/generated/graphql/.*| .*/generated/open[-_]api/.*| template/.*| )$ @@ -302,7 +302,7 @@ repos: files: '.+\.py$' exclude: | (?x)^( - .*/graphql_codegen/.*| + .*/generated/graphql/.*| .*/generated/open[-_]api/.*| )$ # don't pass filenames else the command line sees them twice diff --git a/pyrightconfig.json b/pyrightconfig.json index 1e26d9d57..8ce005eaa 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -10,7 +10,7 @@ "**/.pipx_cache", "**/__pycache__", "**/vendor_files", - "**/graphql_codegen", + "**/generated/graphql", "**/generated/open_api", "**/.venv", "**/venv" From 76e6fb1d6ffe6d78f6dc269198521692dfd7f47f Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 14:12:16 +0000 Subject: [PATCH 12/28] node --- extensions/context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/context.py b/extensions/context.py index 8f3977d5d..b48037c67 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -52,7 +52,7 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["pytest_recording_version"] = ">=0.13.4" context["pytest_asyncio_version"] = ">=1.3.0" ####### - context["node_version"] = "24.7.0" + context["node_version"] = "24.11.1" context["nuxt_ui_version"] = "^4.2.1" context["nuxt_version"] = "^4.2.2" context["nuxt_icon_version"] = "^2.1.0" From 30927204ae4586d16a6e43e460b1834acb87aa3a Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:15:38 +0000 Subject: [PATCH 13/28] question --- tests/copier_data/data1.yaml | 1 + tests/copier_data/data2.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/copier_data/data1.yaml b/tests/copier_data/data1.yaml index bc5cd650f..7e695e718 100644 --- a/tests/copier_data/data1.yaml +++ b/tests/copier_data/data1.yaml @@ -11,3 +11,4 @@ repo_org_name_for_copyright: The Greatest Org template_uses_javascript: false template_uses_vuejs: false template_might_want_to_install_aws_ssm_port_forwarding_plugin: true +template_might_want_to_use_vcrpy: false diff --git a/tests/copier_data/data2.yaml b/tests/copier_data/data2.yaml index 90f125a98..4e92e5f78 100644 --- a/tests/copier_data/data2.yaml +++ b/tests/copier_data/data2.yaml @@ -13,3 +13,4 @@ repo_org_name_for_copyright: Initech Corporation template_uses_javascript: true template_uses_vuejs: true template_might_want_to_install_aws_ssm_port_forwarding_plugin: false +template_might_want_to_use_vcrpy: true From 2388dd3af3278acaba5e0b567bb7460a425bb052 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:17:44 +0000 Subject: [PATCH 14/28] downstream --- template/copier.yml.jinja-base | 7 ++++++- template/tests/copier_data/data1.yaml.jinja-base | 1 + template/tests/copier_data/data2.yaml.jinja-base | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/template/copier.yml.jinja-base b/template/copier.yml.jinja-base index 963d99495..40d3abb38 100644 --- a/template/copier.yml.jinja-base +++ b/template/copier.yml.jinja-base @@ -42,7 +42,12 @@ install_aws_ssm_port_forwarding_plugin: type: bool help: Should the AWS SSM Port Forwarding Plugin be installed? default: no{% endraw %}{% endif %}{% raw %} -{% endraw %}{% if template_uses_python %} +{% endraw %}{% if template_uses_python %}{% endraw %}{% endif %}{% raw %}{% endraw %}{% if template_might_want_to_use_vcrpy %}{% raw %} +configure_vcrpy: + type: bool + help: Should VCRpy be configured for use during unit testing in Python? + default: no{% endraw %}{% endif %}{% raw %} +{% endraw %} python_version: type: str help: What version of Python is used for development? diff --git a/template/tests/copier_data/data1.yaml.jinja-base b/template/tests/copier_data/data1.yaml.jinja-base index e363d3308..0f58e4f0e 100644 --- a/template/tests/copier_data/data1.yaml.jinja-base +++ b/template/tests/copier_data/data1.yaml.jinja-base @@ -7,6 +7,7 @@ install_claude_cli: false ssh_port_number: 12345 use_windows_in_ci: false {% endraw %}{% if template_might_want_to_install_aws_ssm_port_forwarding_plugin %}{% raw %}install_aws_ssm_port_forwarding_plugin: true{% endraw %}{% endif %}{% raw %} +{% endraw %}{% if template_might_want_to_use_vcrpy %}{% raw %}configure_vcrpy: true{% endraw %}{% endif %}{% raw %} {% endraw %}{% if template_uses_javascript %}{% raw %} node_version: 22.13.0{% endraw %}{% endif %}{% raw %} {% endraw %}{% if template_uses_python %}{% raw %} diff --git a/template/tests/copier_data/data2.yaml.jinja-base b/template/tests/copier_data/data2.yaml.jinja-base index aa7f10e08..51712214d 100644 --- a/template/tests/copier_data/data2.yaml.jinja-base +++ b/template/tests/copier_data/data2.yaml.jinja-base @@ -7,6 +7,7 @@ install_claude_cli: true ssh_port_number: 54321 use_windows_in_ci: true {% endraw %}{% if template_might_want_to_install_aws_ssm_port_forwarding_plugin %}{% raw %}install_aws_ssm_port_forwarding_plugin: false{% endraw %}{% endif %}{% raw %} +{% endraw %}{% if template_might_want_to_use_vcrpy %}{% raw %}configure_vcrpy: false{% endraw %}{% endif %}{% raw %} {% endraw %}{% if template_uses_javascript %}{% raw %} node_version: 22.14.0{% endraw %}{% endif %}{% raw %} {% endraw %}{% if template_uses_python %}{% raw %} From 460728251c0a14b70fae7a753aa9c5f1abe7e154 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:20:35 +0000 Subject: [PATCH 15/28] endif --- template/copier.yml.jinja-base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/copier.yml.jinja-base b/template/copier.yml.jinja-base index 40d3abb38..525cf469b 100644 --- a/template/copier.yml.jinja-base +++ b/template/copier.yml.jinja-base @@ -42,7 +42,7 @@ install_aws_ssm_port_forwarding_plugin: type: bool help: Should the AWS SSM Port Forwarding Plugin be installed? default: no{% endraw %}{% endif %}{% raw %} -{% endraw %}{% if template_uses_python %}{% endraw %}{% endif %}{% raw %}{% endraw %}{% if template_might_want_to_use_vcrpy %}{% raw %} +{% endraw %}{% if template_uses_python %}{% if template_might_want_to_use_vcrpy %}{% raw %} configure_vcrpy: type: bool help: Should VCRpy be configured for use during unit testing in Python? From 63f113e278097566d48f99b8234b83c6d67a4d28 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:22:21 +0000 Subject: [PATCH 16/28] fix --- copier.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/copier.yaml b/copier.yaml index 9798ee3d2..19af399ec 100644 --- a/copier.yaml +++ b/copier.yaml @@ -66,6 +66,12 @@ template_might_want_to_install_aws_ssm_port_forwarding_plugin: help: Is this template for something that might want the AWS SSM Port Forwarding plugin be installed? default: no +template_might_want_to_use_vcrpy: + type: bool + help: Is this template for something that might want to use VCRpy during unit testing? + default: no + when: "{{ template_uses_python }}" + _min_copier_version: "9.4" From a329aaffec30ee9295ed882bb6bbd32dcb801640 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:30:58 +0000 Subject: [PATCH 17/28] fixture --- ...emplate_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 template/resources/{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} diff --git a/template/resources/{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/resources/{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} new file mode 100644 index 000000000..e69de29bb From 471ef29a41a2d6bce9290552f3c68d41ba946f37 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:32:08 +0000 Subject: [PATCH 18/28] contents --- ...o_use_vcrpy %}vcrpy_fixtures.py{% endif %} | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/template/resources/{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/resources/{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} index e69de29bb..a6b9d621a 100644 --- a/template/resources/{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} +++ b/template/resources/{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} @@ -0,0 +1,44 @@ +from typing import cast + +import pytest +from pydantic import JsonValue +from vcr import VCR +from vcr.request import Request + + +def pytest_recording_configure( + vcr: VCR, + config: pytest.Config, # noqa: ARG001 # the config argument MUST be present (even when unused) or pytest-recording throws an error +): + vcr.match_on = cast("tuple[str]", vcr.match_on) # type: ignore[reportUnknownMemberType] # I know vcr.match_on is unknown, that's why I'm casting and isinstance-ing it...not sure if there's a different approach pyright prefers + assert isinstance(vcr.match_on, tuple), ( + f"vcr.match_on is not a tuple, it is a {type(vcr.match_on)} with value {vcr.match_on}" + ) + vcr.match_on += ("body",) # body is not included by default, but it seems relevant + + def before_record_request(request: Request) -> Request | None: + request_headers_to_filter = ("User-Agent",) + for header in request_headers_to_filter: + if header in request.headers: + del request.headers[header] + + return request + + vcr.before_record_request = before_record_request + + def before_record_response(response: dict[str, JsonValue]) -> dict[str, JsonValue]: + headers_to_filter = [ + "Transfer-Encoding", + "Date", + "Server", + ] # none of these headers in the response matter for unit testing, so might as well make the cassette files smaller + headers = response["headers"] + assert isinstance(headers, dict), ( + f"Expected response['headers'] to be a dict, got {type(headers)} with value {headers}" + ) + for header in headers_to_filter: + if header in headers: + del headers[header] + return response + + vcr.before_record_response = before_record_response From b0f51b5c4b787dc1cae20eb613c7cd2d4f2ed989 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:33:48 +0000 Subject: [PATCH 19/28] if --- ...mplate_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %}} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename template/resources/{{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} => {% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %}} (100%) diff --git a/template/resources/{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} similarity index 100% rename from template/resources/{% template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} rename to template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} From bc82a2b7ad1cece500135fa08b3dc42b1d1796f9 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:46:52 +0000 Subject: [PATCH 20/28] tidy --- ...ht_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} index a6b9d621a..ecb84a410 100644 --- a/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} +++ b/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} @@ -10,13 +10,17 @@ def pytest_recording_configure( vcr: VCR, config: pytest.Config, # noqa: ARG001 # the config argument MUST be present (even when unused) or pytest-recording throws an error ): - vcr.match_on = cast("tuple[str]", vcr.match_on) # type: ignore[reportUnknownMemberType] # I know vcr.match_on is unknown, that's why I'm casting and isinstance-ing it...not sure if there's a different approach pyright prefers + vcr.match_on = cast(tuple[str, ...], vcr.match_on) # pyright: ignore[reportUnknownMemberType] # I know vcr.match_on is unknown, that's why I'm casting and isinstance-ing it...not sure if there's a different approach pyright prefers assert isinstance(vcr.match_on, tuple), ( f"vcr.match_on is not a tuple, it is a {type(vcr.match_on)} with value {vcr.match_on}" ) vcr.match_on += ("body",) # body is not included by default, but it seems relevant def before_record_request(request: Request) -> Request | None: + # Skip recording any requests to our own server - let them run live + if request.host == "testserver": # pyright: ignore[reportUnknownMemberType] # new version of VCRpy has worse typing + return None + request_headers_to_filter = ("User-Agent",) for header in request_headers_to_filter: if header in request.headers: @@ -27,11 +31,11 @@ def pytest_recording_configure( vcr.before_record_request = before_record_request def before_record_response(response: dict[str, JsonValue]) -> dict[str, JsonValue]: - headers_to_filter = [ + headers_to_filter = ( "Transfer-Encoding", "Date", "Server", - ] # none of these headers in the response matter for unit testing, so might as well make the cassette files smaller + ) # none of these headers in the response matter for unit testing, so might as well make the cassette files smaller headers = response["headers"] assert isinstance(headers, dict), ( f"Expected response['headers'] to be a dict, got {type(headers)} with value {headers}" From 6a28776f41e8f40113b1b87ed774b4bde07acef0 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:49:23 +0000 Subject: [PATCH 21/28] More fixture --- ...t_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} index ecb84a410..c6c49075e 100644 --- a/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} +++ b/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} @@ -1,3 +1,4 @@ +import os from typing import cast import pytest @@ -6,6 +7,16 @@ from vcr import VCR from vcr.request import Request +@pytest.fixture(autouse=True) +def vcr_config() -> dict[str, list[str]]: + allowed_hosts: list[str] = [] + if ( + os.name == "nt" + ): # on Windows (in CI), the network calls happen at a lower level socket connection even to our FastAPI test client, and can get automatically blocked. This disables that automatic network guard, which isn't great...but since it's still in place on Linux, any actual problems would hopefully get caught before pushing to CI. + allowed_hosts = ["127.0.0.1", "localhost", "::1"] + return {"allowed_hosts": allowed_hosts} + + def pytest_recording_configure( vcr: VCR, config: pytest.Config, # noqa: ARG001 # the config argument MUST be present (even when unused) or pytest-recording throws an error From a67f70fa33a41e68d8fbce9999ca303ed51ff6d1 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 15:59:57 +0000 Subject: [PATCH 22/28] template --- pyrightconfig.json | 3 ++- ...late_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename template/{resources => copier_template_resources}/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} (100%) diff --git a/pyrightconfig.json b/pyrightconfig.json index 8ce005eaa..10ed15162 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -13,7 +13,8 @@ "**/generated/graphql", "**/generated/open_api", "**/.venv", - "**/venv" + "**/venv", + "**/copier_template_resources" ], "strictListInference": true, "strictDictionaryInference": true, diff --git a/template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} similarity index 100% rename from template/resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} rename to template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} From ebb35e14eaca079ec3681fb5a5837a62409acc2e Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 16:06:13 +0000 Subject: [PATCH 23/28] precommit --- .devcontainer/devcontainer.json | 2 +- .pre-commit-config.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6869992e6..36a0f5295 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -62,5 +62,5 @@ "initializeCommand": "sh .devcontainer/initialize-command.sh", "onCreateCommand": "sh .devcontainer/on-create-command.sh", "postStartCommand": "sh .devcontainer/post-start-command.sh" - // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): db11d38d # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): ce8ed462 # spellchecker:disable-line } diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 67bf40d83..a9e1bbd5e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,7 +42,7 @@ repos: # Reformatting (should generally come before any file format or other checks, because reformatting can change things) - repo: https://github.com/crate-ci/typos - rev: 6573587991823ef75e4d6ca97fe895f45e9f14e4 # frozen: v1 + rev: 802d5794ff9cf7b15610c47eca99cd1ab757d8d4 # frozen: v1 hooks: - id: typos exclude: | @@ -108,7 +108,7 @@ repos: )$ - repo: https://github.com/rbubley/mirrors-prettier - rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2 + rev: 14abee445aea04b39069c19b4bd54efff6775819 # frozen: v3.7.4 hooks: - id: prettier # TODO: get template YAML and MD files more in line with prettier expectations so we can start using prettier on those too @@ -195,7 +195,7 @@ repos: - id: check-case-conflict - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 83b816d020105076daac266dbf6bfed199a2da93 # frozen: 0.34.1 + rev: 16a6ad2fead09286ee6eb6b0a3fab55655a6c22a # frozen: 0.35.0 hooks: - id: check-github-workflows @@ -249,7 +249,7 @@ repos: description: Runs hadolint to lint Dockerfiles - repo: https://github.com/astral-sh/ruff-pre-commit - rev: 3db93a2be6f214ed722bf7bce095ec1b1715422a # frozen: v0.14.2 + rev: 1a1f58ba4c35362efe8fed2279715a905baee93d # frozen: v0.14.8 hooks: - id: ruff name: ruff-src @@ -279,7 +279,7 @@ repos: )$ - repo: https://github.com/pylint-dev/pylint - rev: 0eb92d25fd38ba5bad2f8d2ea7df63ad23e18ae3 # frozen: v4.0.2 + rev: e16f942166511d6fb4427e503a734152fae0c4fe # frozen: v4.0.4 hooks: - id: pylint name: pylint From e986f1f5647fe66d3ff9a9be9df1303ce89bbcd4 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 16:14:28 +0000 Subject: [PATCH 24/28] extend --- ...plate_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} index c6c49075e..f839aa317 100644 --- a/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} +++ b/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} @@ -13,7 +13,7 @@ def vcr_config() -> dict[str, list[str]]: if ( os.name == "nt" ): # on Windows (in CI), the network calls happen at a lower level socket connection even to our FastAPI test client, and can get automatically blocked. This disables that automatic network guard, which isn't great...but since it's still in place on Linux, any actual problems would hopefully get caught before pushing to CI. - allowed_hosts = ["127.0.0.1", "localhost", "::1"] + allowed_hosts.extend(["127.0.0.1", "localhost", "::1"]) return {"allowed_hosts": allowed_hosts} From 37b2e8b813ff4612d4c6ebb3c488422bd356a6bc Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 16:17:28 +0000 Subject: [PATCH 25/28] more vcrpy --- ...ate_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} index f839aa317..183e2fd36 100644 --- a/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} +++ b/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} @@ -54,6 +54,10 @@ def pytest_recording_configure( for header in headers_to_filter: if header in headers: del headers[header] + if ( + header.lower() in headers + ): # some headers are lowercased by the server in the response (e.g. Date, Server) + del headers[header.lower()] return response vcr.before_record_response = before_record_response From 5a5d0bd1968174d035e3c1cfe11eb009f071dacc Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 16:25:57 +0000 Subject: [PATCH 26/28] better hosts --- ...o_use_vcrpy %}vcrpy_fixtures.py{% endif %} | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} index 183e2fd36..8b97df907 100644 --- a/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} +++ b/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} @@ -6,15 +6,20 @@ from pydantic import JsonValue from vcr import VCR from vcr.request import Request +ALLOWED_HOSTS = ["testserver"] # Skip recording any requests to our own server - let them run live + +CUSTOM_ALLOWED_HOSTS: tuple[str, ...] = () + +ALLOWED_HOSTS.extend(CUSTOM_ALLOWED_HOSTS) +if ( + os.name == "nt" +): # on Windows (in CI), the network calls happen at a lower level socket connection even to our FastAPI test client, and can get automatically blocked. This disables that automatic network guard, which isn't great...but since it's still in place on Linux, any actual problems would hopefully get caught before pushing to CI. + ALLOWED_HOSTS.extend(["127.0.0.1", "localhost", "::1"]) + @pytest.fixture(autouse=True) def vcr_config() -> dict[str, list[str]]: - allowed_hosts: list[str] = [] - if ( - os.name == "nt" - ): # on Windows (in CI), the network calls happen at a lower level socket connection even to our FastAPI test client, and can get automatically blocked. This disables that automatic network guard, which isn't great...but since it's still in place on Linux, any actual problems would hopefully get caught before pushing to CI. - allowed_hosts.extend(["127.0.0.1", "localhost", "::1"]) - return {"allowed_hosts": allowed_hosts} + return {"allowed_hosts": ALLOWED_HOSTS} def pytest_recording_configure( @@ -28,10 +33,6 @@ def pytest_recording_configure( vcr.match_on += ("body",) # body is not included by default, but it seems relevant def before_record_request(request: Request) -> Request | None: - # Skip recording any requests to our own server - let them run live - if request.host == "testserver": # pyright: ignore[reportUnknownMemberType] # new version of VCRpy has worse typing - return None - request_headers_to_filter = ("User-Agent",) for header in request_headers_to_filter: if header in request.headers: From 90f9ebde4df216049c65260285eaeee054f2d81c Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 16:36:27 +0000 Subject: [PATCH 27/28] more error --- .devcontainer/devcontainer.json | 2 +- .devcontainer/windows-host-helper.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 36a0f5295..3f8268790 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -62,5 +62,5 @@ "initializeCommand": "sh .devcontainer/initialize-command.sh", "onCreateCommand": "sh .devcontainer/on-create-command.sh", "postStartCommand": "sh .devcontainer/post-start-command.sh" - // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): ce8ed462 # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 5b56d8b0 # spellchecker:disable-line } diff --git a/.devcontainer/windows-host-helper.sh b/.devcontainer/windows-host-helper.sh index 8624e443e..a071d4f7e 100644 --- a/.devcontainer/windows-host-helper.sh +++ b/.devcontainer/windows-host-helper.sh @@ -7,7 +7,7 @@ # If you're still having issues, make sure in Windows Developer Settings that you enabled Developer Mode, and also that you set your git config to have `core.autocrlf=false` and `core.symlinks=true` globally -set -e # Exit immediately on error +set -euo pipefail # Exit immediately on error if [ -z "$BASH_VERSION" ]; then echo "Error: This script must be run with bash (e.g., 'bash windows-host-helper.sh')." >&2 From 085bdbaf19b5800fba6d3adb226021434d9b114f Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Thu, 11 Dec 2025 16:40:48 +0000 Subject: [PATCH 28/28] filter --- ...want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} b/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} index 8b97df907..065f9bdcc 100644 --- a/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} +++ b/template/copier_template_resources/{% if template_might_want_to_use_vcrpy %}vcrpy_fixtures.py{% endif %} @@ -4,7 +4,6 @@ from typing import cast import pytest from pydantic import JsonValue from vcr import VCR -from vcr.request import Request ALLOWED_HOSTS = ["testserver"] # Skip recording any requests to our own server - let them run live @@ -19,7 +18,7 @@ if ( @pytest.fixture(autouse=True) def vcr_config() -> dict[str, list[str]]: - return {"allowed_hosts": ALLOWED_HOSTS} + return {"allowed_hosts": ALLOWED_HOSTS, "filter_headers": ["User-Agent"]} def pytest_recording_configure( @@ -32,16 +31,6 @@ def pytest_recording_configure( ) vcr.match_on += ("body",) # body is not included by default, but it seems relevant - def before_record_request(request: Request) -> Request | None: - request_headers_to_filter = ("User-Agent",) - for header in request_headers_to_filter: - if header in request.headers: - del request.headers[header] - - return request - - vcr.before_record_request = before_record_request - def before_record_response(response: dict[str, JsonValue]) -> dict[str, JsonValue]: headers_to_filter = ( "Transfer-Encoding",