From 4fbc0272d83b26ae73a6b738ea1d0c4df09dc0ab Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Fri, 2 Oct 2026 16:14:20 +0000 Subject: [PATCH 1/5] chore: copier update from copier-base-template v0.1.12 Catch-up from base v0.1.10 before the prek pilot changes, kept as its own commit so the prek diff stays reviewable. Restored the template's custom consumer README and pyright_version context var that the update's rejects dropped; relocked faker. --- .claude/CLAUDE.md | 11 ----------- .config/.copier-answers.yml | 2 +- .config/.copier-managed-files.json | 2 -- .devcontainer/devcontainer.json | 2 +- .devcontainer/install-ci-tooling.py | 4 ++-- .devcontainer/manual-setup-deps.py | 2 ++ .github/actions/install_deps/action.yml | 2 +- .github/reusable_workflows/build-docker-image.yaml | 4 ++-- .github/workflows/ci.yaml | 1 - .github/workflows/pre-commit.yaml | 2 -- README.md | 2 +- extensions/context.py | 10 +++++----- pyproject.toml | 2 +- template/.claude/CLAUDE.md | 11 ----------- template/.devcontainer/manual-setup-deps.py | 2 ++ template/.github/actions/install_deps/action.yml | 2 +- template/.github/workflows/pre-commit.yaml | 2 -- uv.lock | 8 ++++---- 18 files changed, 23 insertions(+), 48 deletions(-) delete mode 100644 .claude/CLAUDE.md delete mode 100644 template/.claude/CLAUDE.md diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md deleted file mode 100644 index 6701cb40..00000000 --- a/.claude/CLAUDE.md +++ /dev/null @@ -1,11 +0,0 @@ -@../AGENTS.md - - diff --git a/.config/.copier-answers.yml b/.config/.copier-answers.yml index 78a63281..c9363c95 100644 --- a/.config/.copier-answers.yml +++ b/.config/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: v0.1.10 +_commit: v0.1.12 _src_path: gh:LabAutomationAndScreening/copier-base-template.git copier_answers_directory: .config description: Copier template for creating Python libraries and executables diff --git a/.config/.copier-managed-files.json b/.config/.copier-managed-files.json index e308c913..be092979 100644 --- a/.config/.copier-managed-files.json +++ b/.config/.copier-managed-files.json @@ -6,7 +6,6 @@ ".claude/.beads/.gitignore", ".claude/.beads/config.yaml", ".claude/.beads/metadata.json", - ".claude/CLAUDE.md", ".claude/commands/add-command.md", ".claude/commands/commit.md", ".claude/commands/create-adr.md", @@ -113,7 +112,6 @@ "template/.claude/.beads/.gitignore", "template/.claude/.beads/config.yaml", "template/.claude/.beads/metadata.json", - "template/.claude/CLAUDE.md", "template/.claude/commands/add-command.md", "template/.claude/commands/commit.md", "template/.claude/commands/create-adr.md", diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index fdecaf77..fc53236c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -67,5 +67,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): 0b1abb95 # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): bdd6d4e5 # spellchecker:disable-line } diff --git a/.devcontainer/install-ci-tooling.py b/.devcontainer/install-ci-tooling.py index 9fac24cb..5443c0b9 100644 --- a/.devcontainer/install-ci-tooling.py +++ b/.devcontainer/install-ci-tooling.py @@ -14,8 +14,8 @@ import tempfile from pathlib import Path -UV_VERSION = "0.12.15" -PNPM_VERSION = "12.4.2" +UV_VERSION = "0.12.21" +PNPM_VERSION = "12.8.1" COPIER_VERSION = "==9.18.2" COPIER_TEMPLATE_EXTENSIONS_VERSION = "==0.3.3" PRE_COMMIT_VERSION = "==4.6.2" diff --git a/.devcontainer/manual-setup-deps.py b/.devcontainer/manual-setup-deps.py index f859bf27..3d1142cd 100644 --- a/.devcontainer/manual-setup-deps.py +++ b/.devcontainer/manual-setup-deps.py @@ -169,6 +169,8 @@ def main(): # noqa: C901,PLR0912,PLR0915 # TODO: cleanup into some subfunctions pnpm_command = ["pnpm", "install", "--dir", str(env.path)] if env_check_lock: pnpm_command[1] = "ci" + if generate_lock_file_only: + pnpm_command.append("--lockfile-only") if is_windows: pwsh = shutil.which("pwsh") or shutil.which("powershell") if not pwsh: diff --git a/.github/actions/install_deps/action.yml b/.github/actions/install_deps/action.yml index a995b8fa..9b2286fd 100644 --- a/.github/actions/install_deps/action.yml +++ b/.github/actions/install_deps/action.yml @@ -92,7 +92,7 @@ runs: uses: pnpm/setup@v2.1.0 with: # an empty version makes pnpm/setup read it from the manifest in working-directory instead. Passing both a version and a package.json with a conflicting `packageManager` field is a hard error in pnpm/setup. - version: ${{ inputs.working-directory == 'notUsing' && '12.4.2' || '' }} + version: ${{ inputs.working-directory == 'notUsing' && '12.8.1' || '' }} working-directory: ${{ steps.pnpm-project.outputs.dir }} # cache-dependency-path is left at its default, which is the lock file inside working-directory -- the same one the probe above checks runtime: node@${{ inputs.node-version }} diff --git a/.github/reusable_workflows/build-docker-image.yaml b/.github/reusable_workflows/build-docker-image.yaml index 8fcb6517..ff0d76b2 100644 --- a/.github/reusable_workflows/build-docker-image.yaml +++ b/.github/reusable_workflows/build-docker-image.yaml @@ -194,14 +194,14 @@ jobs: tags: ${{ steps.calculate-build-context-hash.outputs.full_image_tag }} - name: Add git sha tag - if: ${{ inputs.push-role-name != 'no-push' }} + if: ${{ inputs.push-role-name != 'no-push' && github.ref_name == github.event.repository.default_branch }} # feature branch CI runs would otherwise pile hundreds of sha tags onto an unchanged image run: | GIT_SHA_TAG="git-sha-${{ github.sha }}" if aws ecr describe-images --region ${{ steps.parse_ecr_url.outputs.aws_region }} --registry-id=${{ steps.parse_ecr_url.outputs.aws_account_id }} --repository-name=${{ inputs.image_name }} --image-ids imageTag="$GIT_SHA_TAG" > /dev/null 2>&1; then echo "Tag $GIT_SHA_TAG already exists in ECR, skipping" else aws ecr batch-get-image --registry-id=${{ steps.parse_ecr_url.outputs.aws_account_id }} --repository-name=${{ inputs.image_name }} --image-ids imageTag=${{ steps.calculate-build-context-hash.outputs.build_context_tag }} --query 'images[].imageManifest' --output text > manifest.json - # Every job on the push path tags the git sha, and jobs that find their image already in ECR no longer serialize on the mutex, + # Every default-branch job on the push path tags the git sha, and jobs that find their image already in ECR no longer serialize on the mutex, # so another job can apply this same tag between the check above and the put below. ECR reports that as # ImageAlreadyExistsException, which by definition means the tag already points at this exact manifest, so it is safe to ignore. # ImageTagAlreadyExistsException (a different manifest on an immutable repository) is a real conflict and still fails the step. diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index de8f2b47..161f0516 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -172,7 +172,6 @@ jobs: - name: install new dependencies env: - SKIP_PLAYWRIGHT_INSTALL: "1" # Provide a fake token so it doesn't attempt to access AWS to generate a new one when the script is run if CodeArtifact is set as the registry CODEARTIFACT_AUTH_TOKEN: 'faketoken' run: | diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 5c641fa4..34b139d9 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -53,8 +53,6 @@ jobs: - name: Install latest versions of packages uses: ./.github/actions/install_deps - env: - SKIP_PLAYWRIGHT_INSTALL: "1" with: python-version: ${{ inputs.python-version }} node-version: ${{ inputs.node-version }} diff --git a/README.md b/README.md index 2b408e3e..769a5378 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ To create a new repository using this template: 1. Inside that devcontainer, run `python .devcontainer/install-ci-tooling.py` to install necessary tooling to instantiate the template (you can copy/paste the script from this repo...and you can paste it in the root of the repo if you want) 1. Delete all files currently in the repository. Optional...but makes it easiest to avoid git conflicts. 1. Run copier to instantiate the template: `copier copy --trust gh:LabAutomationAndScreening/copier-python-package-template.git .` -1. Run `SKIP_PLAYWRIGHT_INSTALL=1 python .devcontainer/manual-setup-deps.py --only-create-lock --allow-uv-to-install-python --skip-updating-devcontainer-hash` to generate the lock file(s) +1. Run `python .devcontainer/manual-setup-deps.py --only-create-lock --allow-uv-to-install-python --skip-updating-devcontainer-hash` to generate the lock file(s) 1. Stage all files to prepare for commit (`git add .`) 1. Run `python3 .github/workflows/hash_git_files.py . --for-devcontainer-config-update` to update the hash for your devcontainer file 1. Commit the changes (optional) diff --git a/extensions/context.py b/extensions/context.py index df779d74..6478e646 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -19,8 +19,8 @@ class ContextUpdater(ContextHook): def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just creating the dict self, context: dict[Any, Any] ) -> dict[Any, Any]: - context["uv_version"] = "0.12.15" - context["pnpm_version"] = "12.4.2" + context["uv_version"] = "0.12.21" + context["pnpm_version"] = "12.8.1" context["npm_version"] = "11.13.0" context["nvm_version"] = "0.40.5" context["pre_commit_version"] = "==4.6.2" @@ -45,10 +45,10 @@ def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just context["pyinstaller_version"] = ">=6.22.3" context["setuptools_version"] = "80.7.1" context["strawberry_graphql_version"] = "==0.298.0" - context["fastapi_version"] = ">=0.141.1" + context["fastapi_version"] = ">=0.142.2" context["fastapi_offline_version"] = ">=1.7.7" context["starlette_version"] = ">=1.7.0" - context["uvicorn_version"] = ">=0.53.0" + context["uvicorn_version"] = ">=0.54.0" context["lab_auto_pulumi_version"] = ">=0.3.0" context["ariadne_codegen_version"] = ">=0.18.0" context["pytest_mock_version"] = ">=3.16.0" @@ -63,7 +63,7 @@ def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just context["pytest_asyncio_version"] = ">=1.4.0" context["pytest_timeout_version"] = ">=2.4.0" context["pytest_reserial_version"] = ">=0.6.1" - context["python_faker_version"] = ">=40.39.0" + context["python_faker_version"] = ">=40.40.0" context["mutmut_version"] = ">=3.8.0" context["pyright_version"] = ">=1.1.414" context["pyrefly_version"] = ">=1.3.2" diff --git a/pyproject.toml b/pyproject.toml index 64b1e947..86f7ee40 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ dependencies = [ "pytest>=9.1.1", "pytest-cov>=7.1.0", "pytest-randomly>=5.0.0", - "faker>=40.39.0", + "faker>=40.40.0", "pyrefly>=1.3.2", "copier==9.18.2", "copier-template-extensions==0.3.3" diff --git a/template/.claude/CLAUDE.md b/template/.claude/CLAUDE.md deleted file mode 100644 index 6701cb40..00000000 --- a/template/.claude/CLAUDE.md +++ /dev/null @@ -1,11 +0,0 @@ -@../AGENTS.md - - diff --git a/template/.devcontainer/manual-setup-deps.py b/template/.devcontainer/manual-setup-deps.py index f859bf27..3d1142cd 100644 --- a/template/.devcontainer/manual-setup-deps.py +++ b/template/.devcontainer/manual-setup-deps.py @@ -169,6 +169,8 @@ def main(): # noqa: C901,PLR0912,PLR0915 # TODO: cleanup into some subfunctions pnpm_command = ["pnpm", "install", "--dir", str(env.path)] if env_check_lock: pnpm_command[1] = "ci" + if generate_lock_file_only: + pnpm_command.append("--lockfile-only") if is_windows: pwsh = shutil.which("pwsh") or shutil.which("powershell") if not pwsh: diff --git a/template/.github/actions/install_deps/action.yml b/template/.github/actions/install_deps/action.yml index a995b8fa..9b2286fd 100644 --- a/template/.github/actions/install_deps/action.yml +++ b/template/.github/actions/install_deps/action.yml @@ -92,7 +92,7 @@ runs: uses: pnpm/setup@v2.1.0 with: # an empty version makes pnpm/setup read it from the manifest in working-directory instead. Passing both a version and a package.json with a conflicting `packageManager` field is a hard error in pnpm/setup. - version: ${{ inputs.working-directory == 'notUsing' && '12.4.2' || '' }} + version: ${{ inputs.working-directory == 'notUsing' && '12.8.1' || '' }} working-directory: ${{ steps.pnpm-project.outputs.dir }} # cache-dependency-path is left at its default, which is the lock file inside working-directory -- the same one the probe above checks runtime: node@${{ inputs.node-version }} diff --git a/template/.github/workflows/pre-commit.yaml b/template/.github/workflows/pre-commit.yaml index 5c641fa4..34b139d9 100644 --- a/template/.github/workflows/pre-commit.yaml +++ b/template/.github/workflows/pre-commit.yaml @@ -53,8 +53,6 @@ jobs: - name: Install latest versions of packages uses: ./.github/actions/install_deps - env: - SKIP_PLAYWRIGHT_INSTALL: "1" with: python-version: ${{ inputs.python-version }} node-version: ${{ inputs.node-version }} diff --git a/uv.lock b/uv.lock index bff5b8a7..9e85d457 100644 --- a/uv.lock +++ b/uv.lock @@ -62,7 +62,7 @@ dependencies = [ requires-dist = [ { name = "copier", specifier = "==9.18.2" }, { name = "copier-template-extensions", specifier = "==0.3.3" }, - { name = "faker", specifier = ">=40.39.0" }, + { name = "faker", specifier = ">=40.40.0" }, { name = "pyrefly", specifier = ">=1.3.2" }, { name = "pytest", specifier = ">=9.1.1" }, { name = "pytest-cov", specifier = ">=7.1.0" }, @@ -159,14 +159,14 @@ wheels = [ [[package]] name = "faker" -version = "40.39.0" +version = "40.40.0" source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6d/62/fea935af7a312f073c99d470b05a7c96650ee8d9562ce82e8cb7ee4c1247/faker-40.39.0.tar.gz", hash = "sha256:52799ad96fcf92aab2fc96a9e03869bbf1a634300f7cd91c38dbfd51f639f6fa", size = 2029463, upload-time = "2026-09-14T16:50:17.939Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/43/7f5870d05331cb1649704040f51332d37f2468ed857de1e226482e2948b0/faker-40.40.0.tar.gz", hash = "sha256:803ee7f920679e7367c3f7b7f97752f5a9780aa5566c71723fbe57d591beafe1", size = 2029985, upload-time = "2026-09-29T00:56:19.983Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/45/c8/901282279841ebb59216433be01aac825fb905e1a597de3b7b5ab8b0c43e/faker-40.39.0-py3-none-any.whl", hash = "sha256:c4c7ec2cddfaf602c5a8a2c960614946aa8c161250bd9d49a8846cd24d1ef028", size = 2066232, upload-time = "2026-09-14T16:50:16.061Z" }, + { url = "https://files.pythonhosted.org/packages/e1/d2/58beb2b8355f89b483fa21b99fe9934ee7312e3ccf228bb7cefe9e8d979c/faker-40.40.0-py3-none-any.whl", hash = "sha256:cd45ebdd1363f92a45740ac49945e49fa18f7e10771884a83c796a235550d7b7", size = 2066663, upload-time = "2026-09-29T00:56:17.952Z" }, ] [[package]] From 325eabe8bdc4faa3e0f7b4cbd741f7f504f7c5f8 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Sat, 3 Oct 2026 11:29:05 +0000 Subject: [PATCH 2/5] build: copier update from copier-base-template prek-prep Pulls the forward-compatible prek migration groundwork from the copier-base-template prek-prep branch while still running pre-commit: seeded .prekignore, prek installed alongside pre-commit, lint-matrix dotfile cleanup with --show-diff-on-failure and a working log artifact name, the sync-dependencies stderr check, pyrefly --frozen, tool-neutral CodeRabbit wording, dual-prefix devcontainer hash detection, and prek run permissions with config-redirection denials. Template-specific follow-up: run the consumer config's pyright-on-tests hook with --frozen for the same reason as pyrefly. --- .claude/settings/permissions/bash.jsonc | 11 ++++++++++ .coderabbit.yaml | 8 ++++---- .config/.copier-answers.yml | 2 +- .config/.copier-managed-files.json | 1 + .devcontainer/devcontainer.json | 2 +- .devcontainer/install-ci-tooling.py | 12 +++++++++++ .github/workflows/ci.yaml | 20 +++++-------------- .github/workflows/hash_git_files.py | 6 +++++- .github/workflows/pre-commit.yaml | 9 +-------- .pre-commit-config.yaml | 6 +++--- .prekignore | 8 ++++++++ extensions/context.py | 1 + .../.claude/settings/permissions/bash.jsonc | 11 ++++++++++ template/.coderabbit.yaml | 8 ++++---- .../.devcontainer/install-ci-tooling.py.jinja | 12 +++++++++++ template/.github/workflows/hash_git_files.py | 6 +++++- template/.github/workflows/pre-commit.yaml | 9 +-------- template/.pre-commit-config.yaml | 8 ++++---- 18 files changed, 90 insertions(+), 50 deletions(-) create mode 100644 .prekignore diff --git a/.claude/settings/permissions/bash.jsonc b/.claude/settings/permissions/bash.jsonc index b6b9d83f..6e59e03d 100644 --- a/.claude/settings/permissions/bash.jsonc +++ b/.claude/settings/permissions/bash.jsonc @@ -19,6 +19,7 @@ "Bash(aws sts get*)", // Code Quality & Formatting "Bash(pre-commit run *)", + "Bash(prek run *)", // Core Shell Commands "Bash(COMMAND *)", // used in slash commands "Bash(kill *)", @@ -165,6 +166,16 @@ "Bash(task --dir=*)", "Bash(task -g *)", "Bash(task --global *)", + // Same reasoning for the hook runners: they must run the repo's own reviewed .pre-commit-config.yaml, and these flags are how to point them at another config or another repo + "Bash(pre-commit run -c *)", + "Bash(pre-commit run --config *)", + "Bash(pre-commit run --config=*)", + "Bash(prek run -c *)", + "Bash(prek run --config *)", + "Bash(prek run --config=*)", + "Bash(prek run -C *)", + "Bash(prek run --cd *)", + "Bash(prek run --cd=*)", // Destructive File Operations "Bash(chmod -R *)", diff --git a/.coderabbit.yaml b/.coderabbit.yaml index addc595c..a2932857 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -13,7 +13,7 @@ reviews: - 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: "**/*.py" - instructions: "Never express concerns about potential ruff rule violations, even those rules mentioned in other agent instructions; a pre-commit hook already runs a ruff check. Do not warn about unnecessary super().__init__() calls; pyrefly prefers those to be present. Do not warn about missing type hints; a pre-commit hook already checks for that." + instructions: "Never express concerns about potential ruff rule violations, even those rules mentioned in other agent instructions; the CI pipeline already runs a ruff check. Do not warn about unnecessary super().__init__() calls; pyrefly prefers those to be present. Do not warn about missing type hints; the CI pipeline already checks for that." - path: "**/.copier-answers.yml" instructions: "Do not comment about the `_commit` value needing to be a clean release tag. A CI job will fail if that is not the case." - path: ".config/.copier-managed-files.json" @@ -26,11 +26,11 @@ reviews: appears in multiple entries, the last entry is the authoritative owner; use parent_src to trace the full chain and identify the correct template repo for backporting. tools: - eslint: # when the code contains typescript, eslint will be run by pre-commit, and coderabbit often generates false positives + eslint: # when the code contains typescript, eslint will be run in the CI pipeline, and coderabbit often generates false positives enabled: false - ruff: # when the code contains python, ruff will be run by pre-commit, and coderabbit often generates false positives + ruff: # when the code contains python, ruff will be run in the CI pipeline, and coderabbit often generates false positives enabled: false - pylint: # when the code contains python, pylint will be run by pre-commit, and coderabbit often generates false positives + pylint: # when the code contains python, pylint will be run in the CI pipeline, and coderabbit often generates false positives enabled: false flake8: # we use ruff instead (when we use Python) enabled: false diff --git a/.config/.copier-answers.yml b/.config/.copier-answers.yml index c9363c95..b1036226 100644 --- a/.config/.copier-answers.yml +++ b/.config/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: v0.1.12 +_commit: v0.1.12-8-gf1f0f96d _src_path: gh:LabAutomationAndScreening/copier-base-template.git copier_answers_directory: .config description: Copier template for creating Python libraries and executables diff --git a/.config/.copier-managed-files.json b/.config/.copier-managed-files.json index be092979..9866582b 100644 --- a/.config/.copier-managed-files.json +++ b/.config/.copier-managed-files.json @@ -89,6 +89,7 @@ ".github/zizmor.yml", ".gitignore", ".pre-commit-config.yaml", + ".prekignore", ".python-version", "AGENTS.md", "CHANGELOG.md", diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index fc53236c..41f5e4a9 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -67,5 +67,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): bdd6d4e5 # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): daa2326f # spellchecker:disable-line } diff --git a/.devcontainer/install-ci-tooling.py b/.devcontainer/install-ci-tooling.py index 5443c0b9..e2ce9c7a 100644 --- a/.devcontainer/install-ci-tooling.py +++ b/.devcontainer/install-ci-tooling.py @@ -21,6 +21,7 @@ PRE_COMMIT_VERSION = "==4.6.2" # identify decides which files each pre-commit hook runs on, so a floating version silently changes what CI checks IDENTIFY_VERSION = "==2.6.20" +PREK_VERSION = "==0.5.4" TASK_VERSION = "==3.53.1" DOWNLOAD_TIMEOUT_SECONDS = 90 # Where uv places both itself and the executables of the tools it installs. Resolves from USERPROFILE @@ -282,6 +283,17 @@ def main(): env=uv_env, timeout=DOWNLOAD_TIMEOUT_SECONDS, ) + _ = subprocess.run( # noqa: S603 # this is all our own input + [ + uv_path, + "tool", + "install", + f"prek{PREK_VERSION}", + ], + check=True, + env=uv_env, + timeout=DOWNLOAD_TIMEOUT_SECONDS, + ) if not args.no_node: run_node_cmds(["npm -v", f"npm install -g pnpm@{PNPM_VERSION}", "pnpm -v"], is_windows=is_windows) # Task is installed outside the --no-node branch because CI always passes --no-node (pnpm/setup handles pnpm there), and every job still needs the task runner diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 161f0516..f003c823 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -149,14 +149,10 @@ jobs: - name: Delete files from initial repo run: | - # Delete everything except the folder containing the instantiated template + # Delete everything except the folder containing the instantiated template, including dotfiles so that none of them can mask one missing from the instantiated template # https://stackoverflow.com/questions/34057047/delete-all-directories-except-one - shopt -s extglob - rm -rf !(new-template) - rm -rf .github # apparently this folder doesn't get removed with the previous command for some reason - rm -rf .devcontainer # apparently this folder doesn't get removed with the previous command for some reason - rm -rf .claude # apparently this folder doesn't get removed with the previous command for some reason - rm -rf .config # apparently this folder doesn't get removed with the previous command for some reason + shopt -s extglob dotglob + rm -rf !(new-template|.git) ls -la - name: Move the instantiated template into the repo root @@ -214,13 +210,7 @@ jobs: - name: Run pre-commit run: | # skip devcontainer context hash because the template instantiation may make it different every time - SKIP=git-dirty,compute-devcontainer-context-hash pre-commit run -a || PRE_COMMIT_EXIT_CODE=$? - if [ -n "$PRE_COMMIT_EXIT_CODE" ]; then - echo "Pre-commit failed with exit code $PRE_COMMIT_EXIT_CODE" - echo "Showing git diff:" - git --no-pager diff - exit $PRE_COMMIT_EXIT_CODE - fi + SKIP=git-dirty,compute-devcontainer-context-hash pre-commit run -a --show-diff-on-failure - name: Save Pre-commit hooks cache if: ${{ steps.cache-probe.outputs.cache-hit != 'true' && steps.cache-recheck.outputs.cache-hit != 'true' }} @@ -233,7 +223,7 @@ jobs: if: ${{ failure() }} uses: actions/upload-artifact@v4.4.3 with: - name: pre-commit-log--${{ github.jobs.lint-matrix.name }} + name: pre-commit-log--${{ matrix.python-version }}--${{ strategy.job-index }} path: "${{ github.workspace }}/.precommit_cache/pre-commit.log" confirm-on-tagged-copier-template: diff --git a/.github/workflows/hash_git_files.py b/.github/workflows/hash_git_files.py index be7b172c..4652c32d 100644 --- a/.github/workflows/hash_git_files.py +++ b/.github/workflows/hash_git_files.py @@ -16,6 +16,10 @@ DEVCONTAINER_COMMENT_LINE_PREFIX = ( " // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): " ) +# Recognized before it is ever written, so that switching DEVCONTAINER_COMMENT_LINE_PREFIX to it later cannot leave a copy of this script that fails to find the line and inserts a duplicate +GIT_HOOK_DEVCONTAINER_COMMENT_LINE_PREFIX = ( + " // Devcontainer context hash (do not manually edit this, it's managed by a git hook): " +) DEVCONTAINER_COMMENT_LINE_SUFFIX = ( " # spellchecker:disable-line" # the typos hook can sometimes mess with the hash without this @@ -116,7 +120,7 @@ def find_devcontainer_hash_line(lines: list[str]) -> tuple[int, str | None]: # Check the line above it if i > 0: above_line = lines[i - 1] - if above_line.startswith(DEVCONTAINER_COMMENT_LINE_PREFIX): + if above_line.startswith((DEVCONTAINER_COMMENT_LINE_PREFIX, GIT_HOOK_DEVCONTAINER_COMMENT_LINE_PREFIX)): part_after_prefix = above_line.split(": ", 1)[1] part_before_suffix = part_after_prefix.split("#")[0] current_hash = part_before_suffix.strip() diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 34b139d9..e8fa0729 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -89,14 +89,7 @@ jobs: restore-keys: ${{ env.CACHE_RESTORE_KEY }} - name: Run pre-commit - run: | - pre-commit run -a || PRE_COMMIT_EXIT_CODE=$? - if [ -n "$PRE_COMMIT_EXIT_CODE" ]; then - echo "Pre-commit failed with exit code $PRE_COMMIT_EXIT_CODE" - echo "Showing git diff:" - git --no-pager diff - exit $PRE_COMMIT_EXIT_CODE - fi + run: pre-commit run -a --show-diff-on-failure - name: Save Pre-commit hooks cache if: ${{ steps.cache-probe.outputs.cache-hit != 'true' && steps.cache-recheck.outputs.cache-hit != 'true' }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 96be46df..9ce4af65 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,8 +30,8 @@ repos: name: ensure python dependencies are up to date during commits stages: [pre-commit] - # When the install does change things, it exits 0, so needed to check for the phrase 'operations' in stdout in order to cause things pre-commit command to fail - entry: python -c "import subprocess,sys; results=subprocess.run(['uv', 'sync', '--frozen'],timeout=360,capture_output=True); print ('stdout- ' + results.stdout.decode('utf-8', 'strict')); print ('stderr- ' + results.stderr.decode('utf-8', 'strict')); sys.exit(int(results.returncode or int('Installed' in results.stdout.decode('utf-8', 'strict'))));" + # When the install does change things, it exits 0, so needed to check for the phrase 'Installed' in stderr (where uv writes its progress) in order to cause things pre-commit command to fail + entry: python -c "import subprocess,sys; results=subprocess.run(['uv', 'sync', '--frozen'],timeout=360,capture_output=True); print ('stdout- ' + results.stdout.decode('utf-8', 'strict')); print ('stderr- ' + results.stderr.decode('utf-8', 'strict')); sys.exit(int(results.returncode or int('Installed' in results.stderr.decode('utf-8', 'strict'))));" # don't pass filenames else the command line sees them twice pass_filenames: false language: system @@ -287,7 +287,7 @@ repos: hooks: - id: pyrefly name: pyrefly - entry: bash -c "uv run pyrefly check -c ./.config/pyrefly.toml" + entry: bash -c "uv run --frozen pyrefly check -c ./.config/pyrefly.toml" files: '.+\.py$' exclude: | (?x)^( diff --git a/.prekignore b/.prekignore new file mode 100644 index 00000000..85e2c6aa --- /dev/null +++ b/.prekignore @@ -0,0 +1,8 @@ +# ============== WARNING ============================================================================== +# File is managed by copier template: gh:LabAutomationAndScreening/copier-base-template.git +# See .config/.copier-managed-files.json for details. +# +# You are welcome to make changes to this file in your repo if they are custom to your project, +# but if the change should be shared with other projects, please backport it to the template repo. +# ===================================================================================================== +/template/ diff --git a/extensions/context.py b/extensions/context.py index 6478e646..aa0e15fc 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -25,6 +25,7 @@ def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just context["nvm_version"] = "0.40.5" context["pre_commit_version"] = "==4.6.2" context["identify_version"] = "==2.6.20" + context["prek_version"] = "==0.5.4" context["task_version"] = "==3.53.1" context["pytest_version"] = ">=9.1.1" context["pytest_randomly_version"] = ">=5.0.0" diff --git a/template/.claude/settings/permissions/bash.jsonc b/template/.claude/settings/permissions/bash.jsonc index b6b9d83f..6e59e03d 100644 --- a/template/.claude/settings/permissions/bash.jsonc +++ b/template/.claude/settings/permissions/bash.jsonc @@ -19,6 +19,7 @@ "Bash(aws sts get*)", // Code Quality & Formatting "Bash(pre-commit run *)", + "Bash(prek run *)", // Core Shell Commands "Bash(COMMAND *)", // used in slash commands "Bash(kill *)", @@ -165,6 +166,16 @@ "Bash(task --dir=*)", "Bash(task -g *)", "Bash(task --global *)", + // Same reasoning for the hook runners: they must run the repo's own reviewed .pre-commit-config.yaml, and these flags are how to point them at another config or another repo + "Bash(pre-commit run -c *)", + "Bash(pre-commit run --config *)", + "Bash(pre-commit run --config=*)", + "Bash(prek run -c *)", + "Bash(prek run --config *)", + "Bash(prek run --config=*)", + "Bash(prek run -C *)", + "Bash(prek run --cd *)", + "Bash(prek run --cd=*)", // Destructive File Operations "Bash(chmod -R *)", diff --git a/template/.coderabbit.yaml b/template/.coderabbit.yaml index addc595c..a2932857 100644 --- a/template/.coderabbit.yaml +++ b/template/.coderabbit.yaml @@ -13,7 +13,7 @@ reviews: - 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: "**/*.py" - instructions: "Never express concerns about potential ruff rule violations, even those rules mentioned in other agent instructions; a pre-commit hook already runs a ruff check. Do not warn about unnecessary super().__init__() calls; pyrefly prefers those to be present. Do not warn about missing type hints; a pre-commit hook already checks for that." + instructions: "Never express concerns about potential ruff rule violations, even those rules mentioned in other agent instructions; the CI pipeline already runs a ruff check. Do not warn about unnecessary super().__init__() calls; pyrefly prefers those to be present. Do not warn about missing type hints; the CI pipeline already checks for that." - path: "**/.copier-answers.yml" instructions: "Do not comment about the `_commit` value needing to be a clean release tag. A CI job will fail if that is not the case." - path: ".config/.copier-managed-files.json" @@ -26,11 +26,11 @@ reviews: appears in multiple entries, the last entry is the authoritative owner; use parent_src to trace the full chain and identify the correct template repo for backporting. tools: - eslint: # when the code contains typescript, eslint will be run by pre-commit, and coderabbit often generates false positives + eslint: # when the code contains typescript, eslint will be run in the CI pipeline, and coderabbit often generates false positives enabled: false - ruff: # when the code contains python, ruff will be run by pre-commit, and coderabbit often generates false positives + ruff: # when the code contains python, ruff will be run in the CI pipeline, and coderabbit often generates false positives enabled: false - pylint: # when the code contains python, pylint will be run by pre-commit, and coderabbit often generates false positives + pylint: # when the code contains python, pylint will be run in the CI pipeline, and coderabbit often generates false positives enabled: false flake8: # we use ruff instead (when we use Python) enabled: false diff --git a/template/.devcontainer/install-ci-tooling.py.jinja b/template/.devcontainer/install-ci-tooling.py.jinja index 24a638f3..43fbbedb 100644 --- a/template/.devcontainer/install-ci-tooling.py.jinja +++ b/template/.devcontainer/install-ci-tooling.py.jinja @@ -14,6 +14,7 @@ COPIER_TEMPLATE_EXTENSIONS_VERSION = "{% endraw %}{{ copier_template_extensions_ PRE_COMMIT_VERSION = "{% endraw %}{{ pre_commit_version }}{% raw %}" # identify decides which files each pre-commit hook runs on, so a floating version silently changes what CI checks IDENTIFY_VERSION = "{% endraw %}{{ identify_version }}{% raw %}" +PREK_VERSION = "{% endraw %}{{ prek_version }}{% raw %}" TASK_VERSION = "{% endraw %}{{ task_version }}{% raw %}" DOWNLOAD_TIMEOUT_SECONDS = 90 # Where uv places both itself and the executables of the tools it installs. Resolves from USERPROFILE @@ -275,6 +276,17 @@ def main(): env=uv_env, timeout=DOWNLOAD_TIMEOUT_SECONDS, ) + _ = subprocess.run( # noqa: S603 # this is all our own input + [ + uv_path, + "tool", + "install", + f"prek{PREK_VERSION}", + ], + check=True, + env=uv_env, + timeout=DOWNLOAD_TIMEOUT_SECONDS, + ) if not args.no_node: run_node_cmds(["npm -v", f"npm install -g pnpm@{PNPM_VERSION}", "pnpm -v"], is_windows=is_windows) # Task is installed outside the --no-node branch because CI always passes --no-node (pnpm/setup handles pnpm there), and every job still needs the task runner diff --git a/template/.github/workflows/hash_git_files.py b/template/.github/workflows/hash_git_files.py index be7b172c..4652c32d 100644 --- a/template/.github/workflows/hash_git_files.py +++ b/template/.github/workflows/hash_git_files.py @@ -16,6 +16,10 @@ DEVCONTAINER_COMMENT_LINE_PREFIX = ( " // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): " ) +# Recognized before it is ever written, so that switching DEVCONTAINER_COMMENT_LINE_PREFIX to it later cannot leave a copy of this script that fails to find the line and inserts a duplicate +GIT_HOOK_DEVCONTAINER_COMMENT_LINE_PREFIX = ( + " // Devcontainer context hash (do not manually edit this, it's managed by a git hook): " +) DEVCONTAINER_COMMENT_LINE_SUFFIX = ( " # spellchecker:disable-line" # the typos hook can sometimes mess with the hash without this @@ -116,7 +120,7 @@ def find_devcontainer_hash_line(lines: list[str]) -> tuple[int, str | None]: # Check the line above it if i > 0: above_line = lines[i - 1] - if above_line.startswith(DEVCONTAINER_COMMENT_LINE_PREFIX): + if above_line.startswith((DEVCONTAINER_COMMENT_LINE_PREFIX, GIT_HOOK_DEVCONTAINER_COMMENT_LINE_PREFIX)): part_after_prefix = above_line.split(": ", 1)[1] part_before_suffix = part_after_prefix.split("#")[0] current_hash = part_before_suffix.strip() diff --git a/template/.github/workflows/pre-commit.yaml b/template/.github/workflows/pre-commit.yaml index 34b139d9..e8fa0729 100644 --- a/template/.github/workflows/pre-commit.yaml +++ b/template/.github/workflows/pre-commit.yaml @@ -89,14 +89,7 @@ jobs: restore-keys: ${{ env.CACHE_RESTORE_KEY }} - name: Run pre-commit - run: | - pre-commit run -a || PRE_COMMIT_EXIT_CODE=$? - if [ -n "$PRE_COMMIT_EXIT_CODE" ]; then - echo "Pre-commit failed with exit code $PRE_COMMIT_EXIT_CODE" - echo "Showing git diff:" - git --no-pager diff - exit $PRE_COMMIT_EXIT_CODE - fi + run: pre-commit run -a --show-diff-on-failure - name: Save Pre-commit hooks cache if: ${{ steps.cache-probe.outputs.cache-hit != 'true' && steps.cache-recheck.outputs.cache-hit != 'true' }} diff --git a/template/.pre-commit-config.yaml b/template/.pre-commit-config.yaml index 216cd1a7..ee17c231 100644 --- a/template/.pre-commit-config.yaml +++ b/template/.pre-commit-config.yaml @@ -30,8 +30,8 @@ repos: name: ensure python dependencies are up to date during commits stages: [pre-commit] - # When the install does change things, it exits 0, so needed to check for the phrase 'operations' in stdout in order to cause things pre-commit command to fail - entry: python -c "import subprocess,sys; results=subprocess.run(['uv', 'sync', '--frozen'],timeout=360,capture_output=True); print ('stdout- ' + results.stdout.decode('utf-8', 'strict')); print ('stderr- ' + results.stderr.decode('utf-8', 'strict')); sys.exit(int(results.returncode or int('Installed' in results.stdout.decode('utf-8', 'strict'))));" + # When the install does change things, it exits 0, so needed to check for the phrase 'Installed' in stderr (where uv writes its progress) in order to cause things pre-commit command to fail + entry: python -c "import subprocess,sys; results=subprocess.run(['uv', 'sync', '--frozen'],timeout=360,capture_output=True); print ('stdout- ' + results.stdout.decode('utf-8', 'strict')); print ('stderr- ' + results.stderr.decode('utf-8', 'strict')); sys.exit(int(results.returncode or int('Installed' in results.stderr.decode('utf-8', 'strict'))));" # don't pass filenames else the command line sees them twice pass_filenames: false language: system @@ -287,7 +287,7 @@ repos: hooks: - id: pyrefly name: pyrefly - entry: bash -c "uv run pyrefly check -c ./.config/pyrefly.toml" + entry: bash -c "uv run --frozen pyrefly check -c ./.config/pyrefly.toml" files: '.+\.py$' exclude: | (?x)^( @@ -307,7 +307,7 @@ repos: hooks: - id: pyright-on-tests name: Run pyright on tests of the library # to mimic a downstream consumer of the library who uses pyright as their type checker, see https://pyrefly.org/blog/too-many-type-checkers/ - entry: bash -c "uv run pyright" + entry: bash -c "uv run --frozen pyright" files: '(.+\.py|pyproject\.toml|pyrightconfig\.json)$' exclude: | (?x)^( From 33fe2973214587f171df59789b403453727d06e3 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Tue, 6 Oct 2026 12:52:11 +0000 Subject: [PATCH 3/5] build: copier update from copier-base-template prek-prep Pulls prek 0.5.5, which fixes the conflicted stash restore data loss (j178/prek#2801), and skips installing prek when CI=true since CI still runs hooks through pre-commit. --- .config/.copier-answers.yml | 2 +- .devcontainer/devcontainer.json | 2 +- .devcontainer/install-ci-tooling.py | 26 ++++++++++--------- extensions/context.py | 2 +- .../.devcontainer/install-ci-tooling.py.jinja | 24 +++++++++-------- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/.config/.copier-answers.yml b/.config/.copier-answers.yml index b1036226..6aec2870 100644 --- a/.config/.copier-answers.yml +++ b/.config/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: v0.1.12-8-gf1f0f96d +_commit: v0.1.12-9-g0f7a68c6 _src_path: gh:LabAutomationAndScreening/copier-base-template.git copier_answers_directory: .config description: Copier template for creating Python libraries and executables diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 41f5e4a9..2aebbd05 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -67,5 +67,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): daa2326f # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 68e564ba # spellchecker:disable-line } diff --git a/.devcontainer/install-ci-tooling.py b/.devcontainer/install-ci-tooling.py index e2ce9c7a..be9ec7ee 100644 --- a/.devcontainer/install-ci-tooling.py +++ b/.devcontainer/install-ci-tooling.py @@ -21,7 +21,7 @@ PRE_COMMIT_VERSION = "==4.6.2" # identify decides which files each pre-commit hook runs on, so a floating version silently changes what CI checks IDENTIFY_VERSION = "==2.6.20" -PREK_VERSION = "==0.5.4" +PREK_VERSION = "==0.5.5" TASK_VERSION = "==3.53.1" DOWNLOAD_TIMEOUT_SECONDS = 90 # Where uv places both itself and the executables of the tools it installs. Resolves from USERPROFILE @@ -283,17 +283,19 @@ def main(): env=uv_env, timeout=DOWNLOAD_TIMEOUT_SECONDS, ) - _ = subprocess.run( # noqa: S603 # this is all our own input - [ - uv_path, - "tool", - "install", - f"prek{PREK_VERSION}", - ], - check=True, - env=uv_env, - timeout=DOWNLOAD_TIMEOUT_SECONDS, - ) + # CI still runs hooks through pre-commit, so prek is only needed in devcontainers for now + if os.environ.get("CI") != "true": + _ = subprocess.run( # noqa: S603 # this is all our own input + [ + uv_path, + "tool", + "install", + f"prek{PREK_VERSION}", + ], + check=True, + env=uv_env, + timeout=DOWNLOAD_TIMEOUT_SECONDS, + ) if not args.no_node: run_node_cmds(["npm -v", f"npm install -g pnpm@{PNPM_VERSION}", "pnpm -v"], is_windows=is_windows) # Task is installed outside the --no-node branch because CI always passes --no-node (pnpm/setup handles pnpm there), and every job still needs the task runner diff --git a/extensions/context.py b/extensions/context.py index aa0e15fc..7d79657b 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -25,7 +25,7 @@ def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just context["nvm_version"] = "0.40.5" context["pre_commit_version"] = "==4.6.2" context["identify_version"] = "==2.6.20" - context["prek_version"] = "==0.5.4" + context["prek_version"] = "==0.5.5" context["task_version"] = "==3.53.1" context["pytest_version"] = ">=9.1.1" context["pytest_randomly_version"] = ">=5.0.0" diff --git a/template/.devcontainer/install-ci-tooling.py.jinja b/template/.devcontainer/install-ci-tooling.py.jinja index 43fbbedb..aeaba71d 100644 --- a/template/.devcontainer/install-ci-tooling.py.jinja +++ b/template/.devcontainer/install-ci-tooling.py.jinja @@ -276,17 +276,19 @@ def main(): env=uv_env, timeout=DOWNLOAD_TIMEOUT_SECONDS, ) - _ = subprocess.run( # noqa: S603 # this is all our own input - [ - uv_path, - "tool", - "install", - f"prek{PREK_VERSION}", - ], - check=True, - env=uv_env, - timeout=DOWNLOAD_TIMEOUT_SECONDS, - ) + # CI still runs hooks through pre-commit, so prek is only needed in devcontainers for now + if os.environ.get("CI") != "true": + _ = subprocess.run( # noqa: S603 # this is all our own input + [ + uv_path, + "tool", + "install", + f"prek{PREK_VERSION}", + ], + check=True, + env=uv_env, + timeout=DOWNLOAD_TIMEOUT_SECONDS, + ) if not args.no_node: run_node_cmds(["npm -v", f"npm install -g pnpm@{PNPM_VERSION}", "pnpm -v"], is_windows=is_windows) # Task is installed outside the --no-node branch because CI always passes --no-node (pnpm/setup handles pnpm there), and every job still needs the task runner From 7022586745c3cc3e625c5129c352f249396099c6 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Wed, 7 Oct 2026 12:34:55 +0000 Subject: [PATCH 4/5] build: copier update from copier-base-template v0.1.13 Moves from the prek-prep branch ref to the released tag. Pulls prek installed in CI too (so downstream repos can trial it there), uv 0.12.23, pnpm 12.9.1 and faker 40.41.0. Restored the template's pyright_version context var that the update's reject dropped; relocked faker. --- .config/.copier-answers.yml | 2 +- .devcontainer/install-ci-tooling.py | 28 +++++++++---------- .github/actions/install_deps/action.yml | 2 +- extensions/context.py | 6 ++-- pyproject.toml | 2 +- .../.devcontainer/install-ci-tooling.py.jinja | 24 ++++++++-------- .../.github/actions/install_deps/action.yml | 2 +- uv.lock | 8 +++--- 8 files changed, 35 insertions(+), 39 deletions(-) diff --git a/.config/.copier-answers.yml b/.config/.copier-answers.yml index 6aec2870..1efdb3f0 100644 --- a/.config/.copier-answers.yml +++ b/.config/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: v0.1.12-9-g0f7a68c6 +_commit: v0.1.13 _src_path: gh:LabAutomationAndScreening/copier-base-template.git copier_answers_directory: .config description: Copier template for creating Python libraries and executables diff --git a/.devcontainer/install-ci-tooling.py b/.devcontainer/install-ci-tooling.py index be9ec7ee..fed5ccc1 100644 --- a/.devcontainer/install-ci-tooling.py +++ b/.devcontainer/install-ci-tooling.py @@ -14,8 +14,8 @@ import tempfile from pathlib import Path -UV_VERSION = "0.12.21" -PNPM_VERSION = "12.8.1" +UV_VERSION = "0.12.23" +PNPM_VERSION = "12.9.1" COPIER_VERSION = "==9.18.2" COPIER_TEMPLATE_EXTENSIONS_VERSION = "==0.3.3" PRE_COMMIT_VERSION = "==4.6.2" @@ -283,19 +283,17 @@ def main(): env=uv_env, timeout=DOWNLOAD_TIMEOUT_SECONDS, ) - # CI still runs hooks through pre-commit, so prek is only needed in devcontainers for now - if os.environ.get("CI") != "true": - _ = subprocess.run( # noqa: S603 # this is all our own input - [ - uv_path, - "tool", - "install", - f"prek{PREK_VERSION}", - ], - check=True, - env=uv_env, - timeout=DOWNLOAD_TIMEOUT_SECONDS, - ) + _ = subprocess.run( # noqa: S603 # this is all our own input + [ + uv_path, + "tool", + "install", + f"prek{PREK_VERSION}", + ], + check=True, + env=uv_env, + timeout=DOWNLOAD_TIMEOUT_SECONDS, + ) if not args.no_node: run_node_cmds(["npm -v", f"npm install -g pnpm@{PNPM_VERSION}", "pnpm -v"], is_windows=is_windows) # Task is installed outside the --no-node branch because CI always passes --no-node (pnpm/setup handles pnpm there), and every job still needs the task runner diff --git a/.github/actions/install_deps/action.yml b/.github/actions/install_deps/action.yml index 9b2286fd..8f684782 100644 --- a/.github/actions/install_deps/action.yml +++ b/.github/actions/install_deps/action.yml @@ -92,7 +92,7 @@ runs: uses: pnpm/setup@v2.1.0 with: # an empty version makes pnpm/setup read it from the manifest in working-directory instead. Passing both a version and a package.json with a conflicting `packageManager` field is a hard error in pnpm/setup. - version: ${{ inputs.working-directory == 'notUsing' && '12.8.1' || '' }} + version: ${{ inputs.working-directory == 'notUsing' && '12.9.1' || '' }} working-directory: ${{ steps.pnpm-project.outputs.dir }} # cache-dependency-path is left at its default, which is the lock file inside working-directory -- the same one the probe above checks runtime: node@${{ inputs.node-version }} diff --git a/extensions/context.py b/extensions/context.py index 7d79657b..fb9cea24 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -19,8 +19,8 @@ class ContextUpdater(ContextHook): def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just creating the dict self, context: dict[Any, Any] ) -> dict[Any, Any]: - context["uv_version"] = "0.12.21" - context["pnpm_version"] = "12.8.1" + context["uv_version"] = "0.12.23" + context["pnpm_version"] = "12.9.1" context["npm_version"] = "11.13.0" context["nvm_version"] = "0.40.5" context["pre_commit_version"] = "==4.6.2" @@ -64,7 +64,7 @@ def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just context["pytest_asyncio_version"] = ">=1.4.0" context["pytest_timeout_version"] = ">=2.4.0" context["pytest_reserial_version"] = ">=0.6.1" - context["python_faker_version"] = ">=40.40.0" + context["python_faker_version"] = ">=40.41.0" context["mutmut_version"] = ">=3.8.0" context["pyright_version"] = ">=1.1.414" context["pyrefly_version"] = ">=1.3.2" diff --git a/pyproject.toml b/pyproject.toml index 86f7ee40..930312fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ dependencies = [ "pytest>=9.1.1", "pytest-cov>=7.1.0", "pytest-randomly>=5.0.0", - "faker>=40.40.0", + "faker>=40.41.0", "pyrefly>=1.3.2", "copier==9.18.2", "copier-template-extensions==0.3.3" diff --git a/template/.devcontainer/install-ci-tooling.py.jinja b/template/.devcontainer/install-ci-tooling.py.jinja index aeaba71d..43fbbedb 100644 --- a/template/.devcontainer/install-ci-tooling.py.jinja +++ b/template/.devcontainer/install-ci-tooling.py.jinja @@ -276,19 +276,17 @@ def main(): env=uv_env, timeout=DOWNLOAD_TIMEOUT_SECONDS, ) - # CI still runs hooks through pre-commit, so prek is only needed in devcontainers for now - if os.environ.get("CI") != "true": - _ = subprocess.run( # noqa: S603 # this is all our own input - [ - uv_path, - "tool", - "install", - f"prek{PREK_VERSION}", - ], - check=True, - env=uv_env, - timeout=DOWNLOAD_TIMEOUT_SECONDS, - ) + _ = subprocess.run( # noqa: S603 # this is all our own input + [ + uv_path, + "tool", + "install", + f"prek{PREK_VERSION}", + ], + check=True, + env=uv_env, + timeout=DOWNLOAD_TIMEOUT_SECONDS, + ) if not args.no_node: run_node_cmds(["npm -v", f"npm install -g pnpm@{PNPM_VERSION}", "pnpm -v"], is_windows=is_windows) # Task is installed outside the --no-node branch because CI always passes --no-node (pnpm/setup handles pnpm there), and every job still needs the task runner diff --git a/template/.github/actions/install_deps/action.yml b/template/.github/actions/install_deps/action.yml index 9b2286fd..8f684782 100644 --- a/template/.github/actions/install_deps/action.yml +++ b/template/.github/actions/install_deps/action.yml @@ -92,7 +92,7 @@ runs: uses: pnpm/setup@v2.1.0 with: # an empty version makes pnpm/setup read it from the manifest in working-directory instead. Passing both a version and a package.json with a conflicting `packageManager` field is a hard error in pnpm/setup. - version: ${{ inputs.working-directory == 'notUsing' && '12.8.1' || '' }} + version: ${{ inputs.working-directory == 'notUsing' && '12.9.1' || '' }} working-directory: ${{ steps.pnpm-project.outputs.dir }} # cache-dependency-path is left at its default, which is the lock file inside working-directory -- the same one the probe above checks runtime: node@${{ inputs.node-version }} diff --git a/uv.lock b/uv.lock index 9e85d457..a3fc2c75 100644 --- a/uv.lock +++ b/uv.lock @@ -62,7 +62,7 @@ dependencies = [ requires-dist = [ { name = "copier", specifier = "==9.18.2" }, { name = "copier-template-extensions", specifier = "==0.3.3" }, - { name = "faker", specifier = ">=40.40.0" }, + { name = "faker", specifier = ">=40.41.0" }, { name = "pyrefly", specifier = ">=1.3.2" }, { name = "pytest", specifier = ">=9.1.1" }, { name = "pytest-cov", specifier = ">=7.1.0" }, @@ -159,14 +159,14 @@ wheels = [ [[package]] name = "faker" -version = "40.40.0" +version = "40.41.0" source = { registry = "https://pypi.org/simple/" } dependencies = [ { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/43/43/7f5870d05331cb1649704040f51332d37f2468ed857de1e226482e2948b0/faker-40.40.0.tar.gz", hash = "sha256:803ee7f920679e7367c3f7b7f97752f5a9780aa5566c71723fbe57d591beafe1", size = 2029985, upload-time = "2026-09-29T00:56:19.983Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0c/f5/cf09c597bac1c2600e4f77200a7abb73e20fb2a542c11d0c557c1c4220f5/faker-40.41.0.tar.gz", hash = "sha256:5383e4ebba7061491530ae5952a33dcf8f161a250c89717fa0ac856602dcfaf3", size = 2031440, upload-time = "2026-10-05T22:08:14.767Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/d2/58beb2b8355f89b483fa21b99fe9934ee7312e3ccf228bb7cefe9e8d979c/faker-40.40.0-py3-none-any.whl", hash = "sha256:cd45ebdd1363f92a45740ac49945e49fa18f7e10771884a83c796a235550d7b7", size = 2066663, upload-time = "2026-09-29T00:56:17.952Z" }, + { url = "https://files.pythonhosted.org/packages/07/52/9ae853e8c70d6b77fe81b1563378d8ee49aa316cf19502a2e0bf1e4a873e/faker-40.41.0-py3-none-any.whl", hash = "sha256:35a7f66282990698c20c3e6dd57180900206b760c2f777112c085cc217e7de92", size = 2067633, upload-time = "2026-10-05T22:08:12.554Z" }, ] [[package]] From 02962caded4204f1c87e2439648a0be59619f138 Mon Sep 17 00:00:00 2001 From: Eli Fine Date: Wed, 7 Oct 2026 12:38:39 +0000 Subject: [PATCH 5/5] build: update devcontainer context hash --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 2aebbd05..822cf25b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -67,5 +67,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): 68e564ba # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 3db73231 # spellchecker:disable-line }