From ea0d50ea74330e7b996de33fd141e828fe6dfc92 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 10:52:44 +0000 Subject: [PATCH 01/10] fastapi --- .devcontainer/devcontainer.json | 2 +- .devcontainer/install-ci-tooling.py | 2 +- extensions/context.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 2169f3a8..879eea36 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -61,5 +61,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): a709f6c0 # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 90d2f6c1 # spellchecker:disable-line } diff --git a/.devcontainer/install-ci-tooling.py b/.devcontainer/install-ci-tooling.py index 76769fd6..230ea1ed 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.6" +UV_VERSION = "0.9.7" COPIER_VERSION = "9.10.3" COPIER_TEMPLATE_EXTENSIONS_VERSION = "0.3.3" PRE_COMMIT_VERSION = "4.3.0" diff --git a/extensions/context.py b/extensions/context.py index cf25ebe9..2c165fdc 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -11,7 +11,7 @@ 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.6" + context["uv_version"] = "0.9.7" context["pre_commit_version"] = "4.3.0" # These also in pyproject.toml context["copier_version"] = "9.10.3" @@ -37,7 +37,7 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["pyinstaller_version"] = "6.16.0" context["setuptools_version"] = "80.7.1" context["strawberry_graphql_version"] = "0.284.1" - context["fastapi_version"] = "0.120.2" + context["fastapi_version"] = "0.121.0" context["fastapi_offline_version"] = "1.7.4" context["uvicorn_version"] = "0.38.0" context["lab_auto_pulumi_version"] = "0.1.17" @@ -60,7 +60,7 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]: context["dotenv_cli_version"] = "^11.0.0" context["faker_version"] = "^10.1.0" context["vitest_version"] = "^3.2.4" - context["eslint_version"] = "^9.38.0" + context["eslint_version"] = "~9.38.0" context["nuxt_eslint_version"] = "^1.10.0" context["zod_version"] = "^4.1.12" context["zod_from_json_schema_version"] = "^0.5.1" From 3597f410fe5e668a4e59d8a4adaf041f8ad1c257 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 10:57:06 +0000 Subject: [PATCH 02/10] update hash --- .devcontainer/devcontainer.json | 2 +- .devcontainer/manual-setup-deps.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 879eea36..4c212450 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -61,5 +61,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): 90d2f6c1 # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): bf635da7 # spellchecker:disable-line } diff --git a/.devcontainer/manual-setup-deps.py b/.devcontainer/manual-setup-deps.py index ffc9f48a..0b9b5c3f 100644 --- a/.devcontainer/manual-setup-deps.py +++ b/.devcontainer/manual-setup-deps.py @@ -127,6 +127,15 @@ def main(): else: raise NotImplementedError(f"Package manager {env.package_manager} is not supported for installation") + result = subprocess.run( # update the devcontainer hash after changing lock files + ["python3", ".github/workflows/hash_git_files.py", ".", "--for-devcontainer-config-update", "--exit-zero"], + capture_output=True, + text=True, + check=True, + cwd=REPO_ROOT_DIR, + ) + print(result.stdout) + if __name__ == "__main__": main() From 071e456e715f9a5cfb7de37ddabb9c33e8211658 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 11:01:53 +0000 Subject: [PATCH 03/10] rabbit --- .coderabbit.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 8215e88f..6142f259 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -2,14 +2,14 @@ reviews: profile: assertive path_instructions: + - path: "**/vendor_files/**" + instructions: "These files came from a vendor and we're not allowed to change them. Refer to it if you need to understand how the main code interacts with it, but do not make comments about it." - path: "**/generated/open-api/**" instructions: "This is generated client code for the API. Refer to it if you need to understand how the main code interacts with it, but do not make comments about it." - path: "**/generated/open_api/**" instructions: "This is generated client code for the API. Refer to it if you need to understand how the main code interacts with it, but do not make comments about it." - path: "**/generated/graphql.ts" instructions: "This is generated client code for the API. Refer to it if you need to understand how the main code interacts with it, but do not make comments about it." - - path: "**/vendor_files/**" - instructions: "These files came from a vendor and we're not allowed to change them. Refer to it if you need to understand how the main code interacts with it, but do not make comments about it." tools: eslint: # when the code contains typescript, eslint will be run by pre-commit, and coderabbit often generates false positives enabled: false From c2f19fe89cd5380db2b215a7fa8cedb1bdef88e4 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 11:04:33 +0000 Subject: [PATCH 04/10] remove --- .coderabbit.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 6142f259..213afdd5 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -4,12 +4,6 @@ reviews: path_instructions: - path: "**/vendor_files/**" instructions: "These files came from a vendor and we're not allowed to change them. Refer to it if you need to understand how the main code interacts with it, but do not make comments about it." - - path: "**/generated/open-api/**" - instructions: "This is generated client code for the API. Refer to it if you need to understand how the main code interacts with it, but do not make comments about it." - - path: "**/generated/open_api/**" - instructions: "This is generated client code for the API. Refer to it if you need to understand how the main code interacts with it, but do not make comments about it." - - path: "**/generated/graphql.ts" - instructions: "This is generated client code for the API. Refer to it if you need to understand how the main code interacts with it, but do not make comments about it." tools: eslint: # when the code contains typescript, eslint will be run by pre-commit, and coderabbit often generates false positives enabled: false From 291cebd97aeb3fe97cb23a10d66c09ac311a0953 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 11:16:49 +0000 Subject: [PATCH 05/10] skip in CI --- .devcontainer/devcontainer.json | 2 +- .devcontainer/manual-setup-deps.py | 6 +++++- .../.github/actions/install_deps/action.yml.jinja-base | 7 ++++++- template/.github/workflows/ci.yaml.jinja-base | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4c212450..d4caf703 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -61,5 +61,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): bf635da7 # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 45c8a46e # spellchecker:disable-line } diff --git a/.devcontainer/manual-setup-deps.py b/.devcontainer/manual-setup-deps.py index 0b9b5c3f..de2f4c6a 100644 --- a/.devcontainer/manual-setup-deps.py +++ b/.devcontainer/manual-setup-deps.py @@ -34,6 +34,9 @@ _ = parser.add_argument( "--no-node", action="store_true", default=False, help="Do not process any environments using node package managers" ) +_ = parser.add_argument( + "--skip-updating-devcontainer-hash", action="store_true", default=False, help="Do not update the devcontainer hash" +) class PackageManager(str, enum.Enum): @@ -126,7 +129,8 @@ def main(): ) else: raise NotImplementedError(f"Package manager {env.package_manager} is not supported for installation") - + if args.skip_updating_devcontainer_hash: + return result = subprocess.run( # update the devcontainer hash after changing lock files ["python3", ".github/workflows/hash_git_files.py", ".", "--for-devcontainer-config-update", "--exit-zero"], capture_output=True, diff --git a/template/.github/actions/install_deps/action.yml.jinja-base b/template/.github/actions/install_deps/action.yml.jinja-base index e97a1e9f..5068c331 100644 --- a/template/.github/actions/install_deps/action.yml.jinja-base +++ b/template/.github/actions/install_deps/action.yml.jinja-base @@ -39,6 +39,11 @@ inputs: type: string description: What region should the role use? required: false + skip-updating-devcontainer-hash: + type: boolean + description: Whether to skip updating the hash when running manual-setup-deps.py + default: true + required: false runs: @@ -78,5 +83,5 @@ runs: - name: Install dependencies # the funky syntax is github action ternary if: ${{ inputs.install-deps }} - run: python .devcontainer/manual-setup-deps.py ${{ inputs.python-version == 'notUsing' && '--no-python' || '' }} ${{ inputs.node-version == 'notUsing' && '--no-node' || '' }} + run: python .devcontainer/manual-setup-deps.py ${{ inputs.python-version == 'notUsing' && '--no-python' || '' }} ${{ inputs.node-version == 'notUsing' && '--no-node' || '' }} ${{ inputs.skip-updating-devcontainer-hash && '--skip-updating-devcontainer-hash' || '' }} shell: pwsh{% endraw %} diff --git a/template/.github/workflows/ci.yaml.jinja-base b/template/.github/workflows/ci.yaml.jinja-base index 1909b854..0677ca02 100644 --- a/template/.github/workflows/ci.yaml.jinja-base +++ b/template/.github/workflows/ci.yaml.jinja-base @@ -95,7 +95,7 @@ jobs: run: | # Remove any specification of a Python repository having a default other than PyPI...because in this CI pipeline we can only install from PyPI python $RUNNER_TEMP/replace_private_package_registries.py - python .devcontainer/manual-setup-deps.py --skip-check-lock + python .devcontainer/manual-setup-deps.py --skip-check-lock --skip-updating-devcontainer-hash # Add everything to git so that pre-commit recognizes the files and runs on them git add . git status From 4bf12fec7da057d83fd8cb36cc8323ae93a6c9e1 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 11:51:37 +0000 Subject: [PATCH 06/10] fix setup --- .devcontainer/devcontainer.json | 2 +- .devcontainer/manual-setup-deps.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index d4caf703..a565f025 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -61,5 +61,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): 45c8a46e # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): def90ec9 # spellchecker:disable-line } diff --git a/.devcontainer/manual-setup-deps.py b/.devcontainer/manual-setup-deps.py index de2f4c6a..474018f4 100644 --- a/.devcontainer/manual-setup-deps.py +++ b/.devcontainer/manual-setup-deps.py @@ -37,6 +37,12 @@ _ = parser.add_argument( "--skip-updating-devcontainer-hash", action="store_true", default=False, help="Do not update the devcontainer hash" ) +_ = parser.add_argument( + "--allow-uv-to-install-python", + action="store_true", + default=False, + help="Allow uv to install new versions of Python on the fly. This is typically only needed when instantiating the copier template.", +) class PackageManager(str, enum.Enum): @@ -63,7 +69,9 @@ def main(): args = parser.parse_args(sys.argv[1:]) is_windows = platform.system() == "Windows" uv_env = dict(os.environ) - uv_env.update({"UV_PYTHON_PREFERENCE": "only-system", "UV_PYTHON": args.python_version}) + uv_env.update({"UV_PYTHON": args.python_version}) + if not args.allow_uv_to_install_python: + uv_env.update({"UV_PYTHON_PREFERENCE": "only-system"}) generate_lock_file_only = args.only_create_lock check_lock_file = not (args.skip_check_lock or args.optionally_check_lock or generate_lock_file_only) if args.skip_check_lock and args.optionally_check_lock: From 9ea2112aabff9b272f74247fd1d61af0f45f468d Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 13:29:29 +0000 Subject: [PATCH 07/10] get out of tooling --- .../.devcontainer/install-ci-tooling.py.jinja-base | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/template/.devcontainer/install-ci-tooling.py.jinja-base b/template/.devcontainer/install-ci-tooling.py.jinja-base index 0623c0c9..d0e4d0db 100644 --- a/template/.devcontainer/install-ci-tooling.py.jinja-base +++ b/template/.devcontainer/install-ci-tooling.py.jinja-base @@ -36,21 +36,13 @@ _ = parser.add_argument( default=False, help="Skip installing the SSM plugin for AWS CLI", ) -_ = parser.add_argument( - "--allow-uv-to-install-python", - action="store_true", - default=False, - help="Allow uv to install new versions of Python on the fly. This is typically only needed when instantiating the copier template.", -) def main(): args = parser.parse_args(sys.argv[1:]) is_windows = platform.system() == "Windows" uv_env = dict(os.environ) - uv_env.update({"UV_PYTHON": args.python_version}) - if not args.allow_uv_to_install_python: - uv_env.update({"UV_PYTHON_PREFERENCE": "only-system"}) + uv_env.update({"UV_PYTHON": args.python_version, "UV_PYTHON_PREFERENCE": "only-system"}) uv_path = ((GITHUB_WINDOWS_RUNNER_BIN_PATH + "\\") if is_windows else "") + "uv" if is_windows: pwsh = shutil.which("pwsh") or shutil.which("powershell") From 27328d4e3bf22fbd2817d6fd99c7a9de344d7a65 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 14:07:26 +0000 Subject: [PATCH 08/10] more udate --- .devcontainer/devcontainer.json | 2 +- .devcontainer/manual-setup-deps.py | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a565f025..47a7d045 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -61,5 +61,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): def90ec9 # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 19a9bdca # spellchecker:disable-line } diff --git a/.devcontainer/manual-setup-deps.py b/.devcontainer/manual-setup-deps.py index 474018f4..e145d68b 100644 --- a/.devcontainer/manual-setup-deps.py +++ b/.devcontainer/manual-setup-deps.py @@ -15,8 +15,8 @@ _ = parser.add_argument( "--python-version", type=str, - default=f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}", - help="What version to install.", + default=None, + help="What version to install. This will override anything in .python-version files.", ) _ = parser.add_argument("--skip-check-lock", action="store_true", default=False, help="Skip the lock file check step") _ = parser.add_argument( @@ -69,7 +69,6 @@ def main(): args = parser.parse_args(sys.argv[1:]) is_windows = platform.system() == "Windows" uv_env = dict(os.environ) - uv_env.update({"UV_PYTHON": args.python_version}) if not args.allow_uv_to_install_python: uv_env.update({"UV_PYTHON_PREFERENCE": "only-system"}) generate_lock_file_only = args.only_create_lock @@ -89,6 +88,17 @@ def main(): if args.no_node and env.package_manager == PackageManager.PNPM: print(f"Skipping environment {env.path} as it uses a Node package manager and --no-node is set") continue + if env.package_manager == PackageManager.UV: + if args.python_version is not None: + uv_env.update({"UV_PYTHON": args.python_version}) + else: + python_version_path = env.lock_file.parent / ".python-version" + python_version_path_in_repo_root = REPO_ROOT_DIR / ".python-version" + if python_version_path.exists(): + uv_env.update({"UV_PYTHON": python_version_path.read_text().strip()}) + elif python_version_path_in_repo_root.exists(): + uv_env.update({"UV_PYTHON": python_version_path_in_repo_root.read_text().strip()}) + env_check_lock = check_lock_file if args.optionally_check_lock and env.lock_file.exists(): env_check_lock = True From 7d13d91c75a89a8e2eaf0916ef774535a40b1b0b Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 14:17:45 +0000 Subject: [PATCH 09/10] respect envvar --- .devcontainer/devcontainer.json | 2 +- .devcontainer/manual-setup-deps.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 47a7d045..6c8e762c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -61,5 +61,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): 19a9bdca # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): fb1801a9 # spellchecker:disable-line } diff --git a/.devcontainer/manual-setup-deps.py b/.devcontainer/manual-setup-deps.py index e145d68b..f4d04195 100644 --- a/.devcontainer/manual-setup-deps.py +++ b/.devcontainer/manual-setup-deps.py @@ -11,12 +11,13 @@ REPO_ROOT_DIR = Path(__file__).parent.parent.resolve() ENVS_CONFIG = REPO_ROOT_DIR / ".devcontainer" / "envs.json" +UV_PYTHON_ALREADY_CONFIGURED = "UV_PYTHON" in os.environ parser = argparse.ArgumentParser(description="Manual setup for dependencies in the repo") _ = parser.add_argument( "--python-version", type=str, default=None, - help="What version to install. This will override anything in .python-version files.", + help="What version to install. This will override anything in .python-version files. But if the UV_PYTHON envvar is set prior to starting the script, that will take precedence over everything.", ) _ = parser.add_argument("--skip-check-lock", action="store_true", default=False, help="Skip the lock file check step") _ = parser.add_argument( @@ -88,7 +89,7 @@ def main(): if args.no_node and env.package_manager == PackageManager.PNPM: print(f"Skipping environment {env.path} as it uses a Node package manager and --no-node is set") continue - if env.package_manager == PackageManager.UV: + if env.package_manager == PackageManager.UV and not UV_PYTHON_ALREADY_CONFIGURED: if args.python_version is not None: uv_env.update({"UV_PYTHON": args.python_version}) else: From bbb2ef40e5329308171fca5378f3776c3f53684f Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Mon, 3 Nov 2025 14:44:13 +0000 Subject: [PATCH 10/10] use executable --- .devcontainer/devcontainer.json | 2 +- .devcontainer/manual-setup-deps.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6c8e762c..b2b4212e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -61,5 +61,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): fb1801a9 # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): fbd1043f # spellchecker:disable-line } diff --git a/.devcontainer/manual-setup-deps.py b/.devcontainer/manual-setup-deps.py index f4d04195..6f6fe0d8 100644 --- a/.devcontainer/manual-setup-deps.py +++ b/.devcontainer/manual-setup-deps.py @@ -151,7 +151,7 @@ def main(): if args.skip_updating_devcontainer_hash: return result = subprocess.run( # update the devcontainer hash after changing lock files - ["python3", ".github/workflows/hash_git_files.py", ".", "--for-devcontainer-config-update", "--exit-zero"], + [sys.executable, ".github/workflows/hash_git_files.py", ".", "--for-devcontainer-config-update", "--exit-zero"], capture_output=True, text=True, check=True,