diff --git a/.config/.copier-answers.yml b/.config/.copier-answers.yml index 1edeaf1f..6dc5626d 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.7 +_commit: v0.1.9 _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 803fb84a..ec9e6a90 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -22,17 +22,17 @@ "extensions": [ // basic tooling // "eamodio.gitlens@15.5.1", - "coderabbit.coderabbit-vscode@0.21.8", + "coderabbit.coderabbit-vscode@0.21.9", "ms-vscode.live-server@0.5.2025051301", "MS-vsliveshare.vsliveshare@1.0.5905", - "anthropic.claude-code@2.1.278", + "anthropic.claude-code@2.1.283", // Python "-ms-python.vscode-pylance", // pyrefly is the language server for this project; ms-python.python auto-installs Pylance via its extension pack, and Pylance then warns on every boot that it's disabled "ms-python.python@2026.5.2026052901", "meta.pyrefly@1.3.1", "ms-vscode-remote.remote-containers@0.414.0", - "charliermarsh.ruff@2026.68.0", + "charliermarsh.ruff@2026.84.0", // Misc file formats "bierner.markdown-mermaid@1.29.0", @@ -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): 079f70d6 # spellchecker:disable-line + // Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 6950b8fc # spellchecker:disable-line } diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 5b3d083a..99bb5a36 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -15,7 +15,7 @@ services: REPO_NAME: copier-python-package-template # You can run `devcontainer-info content-url` in codespaces to see what image base is volumes: - - ..:/workspaces/copier-python-package-template:cached + - ..:${WORKSPACE_MOUNT_TARGET:-/workspaces/copier-python-package-template} # Break out the venv folder as a separate docker volume for better performance on Windows hosts - python_venv:/workspaces/copier-python-package-template/.venv command: sleep infinity diff --git a/.devcontainer/initialize-command.sh b/.devcontainer/initialize-command.sh index aefe24a8..52c2b030 100644 --- a/.devcontainer/initialize-command.sh +++ b/.devcontainer/initialize-command.sh @@ -7,6 +7,15 @@ if [ -n "$CODESPACES" ] && [ "$CODESPACES" = "true" ]; then docker image prune --all --force fi +# "Clone Repository in Container Volume" runs this inside a bootstrap container that has the cloned volume mounted at /workspaces. +# The compose bind mount of `..` then points at a path the Docker host doesn't have, so it gets retargeted onto /workspaces where VS Code's own volume mount replaces it. +workspace_mount_type=$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/workspaces"}}{{.Type}}{{end}}{{end}}' "$HOSTNAME" 2>/dev/null || true) +if [ "$workspace_mount_type" = "volume" ]; then + echo "WORKSPACE_MOUNT_TARGET=/workspaces" > .devcontainer/.env +else + : > .devcontainer/.env +fi + # ============== WARNING ============================================================================== # File is managed by copier template: gh:LabAutomationAndScreening/copier-base-template.git # See .config/.copier-managed-files.json for details. diff --git a/.devcontainer/install-ci-tooling.py b/.devcontainer/install-ci-tooling.py index 424071ae..9fac24cb 100644 --- a/.devcontainer/install-ci-tooling.py +++ b/.devcontainer/install-ci-tooling.py @@ -18,8 +18,10 @@ PNPM_VERSION = "12.4.2" COPIER_VERSION = "==9.18.2" COPIER_TEMPLATE_EXTENSIONS_VERSION = "==0.3.3" -PRE_COMMIT_VERSION = "4.6.2" -TASK_VERSION = "3.53.1" +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" +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 # on Windows, so it matches the runner's home directory without assuming its user name. Already on @@ -112,7 +114,7 @@ def install_task(uv_path: str, uv_env: dict[str, str], *, is_windows: bool) -> N """ LOCAL_BIN_DIR.mkdir(parents=True, exist_ok=True) _ = subprocess.run( # noqa: S603 # this is all our own input - [uv_path, "tool", "install", f"go-task-bin=={TASK_VERSION}"], + [uv_path, "tool", "install", f"go-task-bin{TASK_VERSION}"], check=True, env=uv_env, timeout=DOWNLOAD_TIMEOUT_SECONDS, @@ -272,7 +274,9 @@ def main(): uv_path, "tool", "install", - f"pre-commit=={PRE_COMMIT_VERSION}", + f"pre-commit{PRE_COMMIT_VERSION}", + "--with", + f"identify{IDENTIFY_VERSION}", ], check=True, env=uv_env, diff --git a/.gitignore b/.gitignore index 4916f46e..d61c5f34 100644 --- a/.gitignore +++ b/.gitignore @@ -126,5 +126,7 @@ dist # Devcontainer # The devcontainer CLI writes this lock file to pin feature digests, but we are not using it yet .devcontainer/devcontainer-lock.json +# Written by initialize-command.sh on every devcontainer start +.devcontainer/.env # Ignores specific to this repository diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 30a885ad..96be46df 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -136,6 +136,7 @@ repos: .*/__snapshots__/.*| .*/vendor_files/.*| .*\.svg| + .*\.wxs| # formatter sorts attributes and joins multi-line ones, making the Windows installer files hard to read )$ # Invalid File Checks diff --git a/extensions/context.py b/extensions/context.py index d69c4815..81bbf500 100644 --- a/extensions/context.py +++ b/extensions/context.py @@ -23,8 +23,9 @@ def hook( # noqa: PLR0915 # yes, this is a lot of statements, but it's all just context["pnpm_version"] = "12.4.2" context["npm_version"] = "11.13.0" context["nvm_version"] = "0.40.5" - context["pre_commit_version"] = "4.6.2" - context["task_version"] = "3.53.1" + context["pre_commit_version"] = "==4.6.2" + context["identify_version"] = "==2.6.20" + context["task_version"] = "==3.53.1" context["pytest_version"] = ">=9.1.1" context["pytest_randomly_version"] = ">=5.0.0" context["pytest_cov_version"] = ">=7.1.0" diff --git a/template/.devcontainer/devcontainer.json.jinja b/template/.devcontainer/devcontainer.json.jinja index 7edbd22a..93c0cbef 100644 --- a/template/.devcontainer/devcontainer.json.jinja +++ b/template/.devcontainer/devcontainer.json.jinja @@ -34,17 +34,17 @@ "-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.21.8", + "coderabbit.coderabbit-vscode@0.21.9", "ms-vscode.live-server@0.5.2025051301", "MS-vsliveshare.vsliveshare@1.0.5905",{% endraw %}{% if install_claude_cli %}{% raw %} - "anthropic.claude-code@2.1.278",{% endraw %}{% endif %}{% raw %}{% endraw %}{% if (is_child_of_copier_base_template is defined and is_child_of_copier_base_template is sameas(true)) or (is_child_of_copier_base_template is not defined and template_uses_python is defined and template_uses_python is sameas(true)) %}{% raw %} + "anthropic.claude-code@2.1.283",{% endraw %}{% endif %}{% raw %}{% endraw %}{% if (is_child_of_copier_base_template is defined and is_child_of_copier_base_template is sameas(true)) or (is_child_of_copier_base_template is not defined and template_uses_python is defined and template_uses_python is sameas(true)) %}{% raw %} // Python "-ms-python.vscode-pylance", // pyrefly is the language server for this project; ms-python.python auto-installs Pylance via its extension pack, and Pylance then warns on every boot that it's disabled "ms-python.python@2026.5.2026052901", "meta.pyrefly@1.3.1", "ms-vscode-remote.remote-containers@0.414.0", - "charliermarsh.ruff@2026.68.0",{% endraw %}{% endif %}{% raw %} + "charliermarsh.ruff@2026.84.0",{% endraw %}{% endif %}{% raw %} {% endraw %}{% if is_child_of_copier_base_template is not defined and template_uses_vuejs is defined and template_uses_vuejs is sameas(true) %}{% raw %} // VueJS "vue.volar@3.2.5", diff --git a/template/.devcontainer/docker-compose.yml.jinja b/template/.devcontainer/docker-compose.yml.jinja index edbad299..04abec45 100644 --- a/template/.devcontainer/docker-compose.yml.jinja +++ b/template/.devcontainer/docker-compose.yml.jinja @@ -8,7 +8,7 @@ REPO_NAME: {% endraw %}{{ repo_name }}{% raw %} # You can run `devcontainer-info content-url` in codespaces to see what image base is volumes: - - ..:/workspaces/{% endraw %}{{ repo_name }}{% raw %}:cached + - ..:${WORKSPACE_MOUNT_TARGET:-/workspaces/{% endraw %}{{ repo_name }}{% raw %}} # Break out the venv folder as a separate docker volume for better performance on Windows hosts - python_venv:/workspaces/{% endraw %}{{ repo_name }}{% raw %}/.venv command: sleep infinity diff --git a/template/.devcontainer/initialize-command.sh b/template/.devcontainer/initialize-command.sh index aefe24a8..52c2b030 100644 --- a/template/.devcontainer/initialize-command.sh +++ b/template/.devcontainer/initialize-command.sh @@ -7,6 +7,15 @@ if [ -n "$CODESPACES" ] && [ "$CODESPACES" = "true" ]; then docker image prune --all --force fi +# "Clone Repository in Container Volume" runs this inside a bootstrap container that has the cloned volume mounted at /workspaces. +# The compose bind mount of `..` then points at a path the Docker host doesn't have, so it gets retargeted onto /workspaces where VS Code's own volume mount replaces it. +workspace_mount_type=$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/workspaces"}}{{.Type}}{{end}}{{end}}' "$HOSTNAME" 2>/dev/null || true) +if [ "$workspace_mount_type" = "volume" ]; then + echo "WORKSPACE_MOUNT_TARGET=/workspaces" > .devcontainer/.env +else + : > .devcontainer/.env +fi + # ============== WARNING ============================================================================== # File is managed by copier template: gh:LabAutomationAndScreening/copier-base-template.git # See .config/.copier-managed-files.json for details. diff --git a/template/.devcontainer/install-ci-tooling.py.jinja b/template/.devcontainer/install-ci-tooling.py.jinja index 61b69455..24a638f3 100644 --- a/template/.devcontainer/install-ci-tooling.py.jinja +++ b/template/.devcontainer/install-ci-tooling.py.jinja @@ -12,6 +12,8 @@ PNPM_VERSION = "{% endraw %}{{ pnpm_version }}{% raw %}" COPIER_VERSION = "{% endraw %}{{ copier_version }}{% raw %}" COPIER_TEMPLATE_EXTENSIONS_VERSION = "{% endraw %}{{ copier_template_extensions_version }}{% raw %}" 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 %}" 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 @@ -105,7 +107,7 @@ def install_task(uv_path: str, uv_env: dict[str, str], *, is_windows: bool) -> N """ LOCAL_BIN_DIR.mkdir(parents=True, exist_ok=True) _ = subprocess.run( # noqa: S603 # this is all our own input - [uv_path, "tool", "install", f"go-task-bin=={TASK_VERSION}"], + [uv_path, "tool", "install", f"go-task-bin{TASK_VERSION}"], check=True, env=uv_env, timeout=DOWNLOAD_TIMEOUT_SECONDS, @@ -265,7 +267,9 @@ def main(): uv_path, "tool", "install", - f"pre-commit=={PRE_COMMIT_VERSION}", + f"pre-commit{PRE_COMMIT_VERSION}", + "--with", + f"identify{IDENTIFY_VERSION}", ], check=True, env=uv_env, diff --git a/template/.gitignore b/template/.gitignore index 4916f46e..d61c5f34 100644 --- a/template/.gitignore +++ b/template/.gitignore @@ -126,5 +126,7 @@ dist # Devcontainer # The devcontainer CLI writes this lock file to pin feature digests, but we are not using it yet .devcontainer/devcontainer-lock.json +# Written by initialize-command.sh on every devcontainer start +.devcontainer/.env # Ignores specific to this repository diff --git a/template/.pre-commit-config.yaml b/template/.pre-commit-config.yaml index 288bebb2..216cd1a7 100644 --- a/template/.pre-commit-config.yaml +++ b/template/.pre-commit-config.yaml @@ -136,6 +136,7 @@ repos: .*/__snapshots__/.*| .*/vendor_files/.*| .*\.svg| + .*\.wxs| # formatter sorts attributes and joins multi-line ones, making the Windows installer files hard to read )$ # Invalid File Checks