Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .copier-answers.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Changes here will be overwritten by Copier
_commit: v0.0.85
_commit: v0.0.90
_src_path: gh:LabAutomationAndScreening/copier-base-template.git
description: Copier template for creating Python libraries and executables
install_claude_cli: false
Expand All @@ -12,6 +12,8 @@ repo_org_name: LabAutomationAndScreening
repo_org_name_for_copyright: Lab Automation & Screening
ssh_port_number: 55874
template_might_want_to_install_aws_ssm_port_forwarding_plugin: true
template_might_want_to_use_python_asyncio: true
template_might_want_to_use_vcrpy: true
template_uses_javascript: false
template_uses_pulumi: false
template_uses_python: true
Expand Down
9 changes: 2 additions & 7 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
"service": "devcontainer",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
"features": {
"ghcr.io/devcontainers/features/aws-cli:1.1.2": {
// https://github.com/devcontainers/features/blob/main/src/aws-cli/devcontainer-feature.json
// view latest version https://raw.githubusercontent.com/aws/aws-cli/v2/CHANGELOG.rst
"version": "2.31.11"
},
"ghcr.io/devcontainers/features/python:1.7.1": {
// https://github.com/devcontainers/features/blob/main/src/python/devcontainer-feature.json
"version": "3.12.7",
Expand All @@ -21,7 +16,7 @@
"extensions": [
// 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",
Expand Down Expand Up @@ -63,5 +58,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): eeccb984 # spellchecker:disable-line
// Devcontainer context hash (do not manually edit this, it's managed by a pre-commit hook): 99b3f7c4 # spellchecker:disable-line
}
4 changes: 2 additions & 2 deletions .devcontainer/install-ci-tooling.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import tempfile
from pathlib import Path

UV_VERSION = "0.9.11"
PNPM_VERSION = "10.23.0"
UV_VERSION = "0.9.17"
PNPM_VERSION = "10.25.0"
COPIER_VERSION = "9.11.0"
COPIER_TEMPLATE_EXTENSIONS_VERSION = "0.3.3"
PRE_COMMIT_VERSION = "4.5.0"
Expand Down
44 changes: 18 additions & 26 deletions .devcontainer/windows-host-helper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,30 @@ repoName=$(basename "$gitUrl" .git)

echo "Repo name extracted as '$repoName'"

# Remove any existing subfolder with the repository name and recreate it
rm -rf "./$repoName" || true # sometimes deleting the .venv folder fails
rm -rf "./$repoName/*.md" # for some reason, sometimes md files are left behind
sudo rm -rf "./$repoName" || true
sudo rm -rf "./$repoName/*.md"
mkdir -p "./$repoName"
sudo chown -R "$(whoami):$(whoami)" "./$repoName" # TODO: see if this alone is enough to fix everything
Comment on lines +30 to +33
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Rsync-based sync is a nice simplification; drop redundant rm line

The new flow (fresh clone into a tmp dir, rsync -av into ./$repoName with excludes, then cleanup) is much simpler and safer than the previous manual copy logic. One nit:

  • sudo rm -rf "./$repoName" already removes the entire target directory; the subsequent sudo rm -rf "./$repoName/*.md" is redundant, and the quotes prevent glob expansion anyway. It can be removed to avoid confusion.

Also applies to: 38-50, 52-56

🤖 Prompt for AI Agents
.devcontainer/windows-host-helper.sh around lines 30 to 33: the second removal
command `sudo rm -rf "./$repoName/*.md"` is redundant because `sudo rm -rf
"./$repoName"` already deletes the directory and the quotes prevent glob
expansion; remove that redundant line here and also remove the identical
redundant rm lines in the other ranges (lines 38-50 and 52-56) referenced in the
comment; if you actually intended to only remove markdown files instead of the
whole directory, replace the whole-dir rm with a properly unquoted glob-aware
command or use find to target *.md, but per the review just delete the redundant
`rm -rf "./$repoName/*.md"` occurrences.


# Create a temporary directory for cloning
tmpdir=$(mktemp -d)

# Clone the repository into a subfolder inside the temporary directory.
# This creates "$tmpdir/$repoName" with the repository's contents.
# Clone the repository into a subfolder inside the temporary directory
git clone "$gitUrl" "$tmpdir/$repoName"


SRC="$(realpath "$tmpdir/$repoName")"
DST="$(realpath "./$repoName")"

# 1) Recreate directory tree under $DST
while IFS= read -r -d '' dir; do
rel="${dir#$SRC/}" # strip leading $SRC/ → e.g. "sub/dir"
mkdir -p "$DST/$rel"
done < <(find "$SRC" -type d -print0)

# 2) Move all files into that mirror
while IFS= read -r -d '' file; do
rel="${file#$SRC/}" # e.g. "sub/dir/file.txt"
# ensure parent exists (though step 1 already did)
mkdir -p "$(dirname "$DST/$rel")"
mv "$file" "$DST/$rel"
done < <(find "$SRC" -type f -print0)

# 3) Clean up now‑empty dirs and the tmp clone
find "$SRC" -depth -type d -empty -delete
# Use rsync to merge all contents (including hidden files) from cloned repo to target
# -a: archive mode (preserves permissions, timestamps, etc.)
# -v: verbose
# --exclude: skip volume mount directories that should not be overwritten
echo "Syncing repository contents..."
rsync -av \
--exclude='node_modules' \
--exclude='.pnpm-store' \
--exclude='.venv' \
"$tmpdir/$repoName/" "./$repoName/"

# Clean up: remove the temporary directory
rm -rf "$tmpdir"

echo "Repository '$repoName' has been synced into '$DST'."
echo "Repository '$repoName' has been updated."
echo "Note: Volume mounts (node_modules, .pnpm-store, .venv) were preserved."
6 changes: 3 additions & 3 deletions .github/actions/install_deps/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ runs:

- name: Setup python
if: ${{ inputs.python-version != 'notUsing' }}
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v6.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Setup node
if: ${{ inputs.node-version != 'notUsing' }}
uses: actions/setup-node@v6.0.0
uses: actions/setup-node@v6.1.0
with:
node-version: ${{ inputs.node-version }}

Expand All @@ -75,7 +75,7 @@ runs:

- name: OIDC Auth for CodeArtifact
if: ${{ inputs.code-artifact-auth-role-name != 'no-code-artifact' }}
uses: aws-actions/configure-aws-credentials@v5.1.0
uses: aws-actions/configure-aws-credentials@v5.1.1
with:
role-to-assume: arn:aws:iam::${{ inputs.code-artifact-auth-role-account-id }}:role/${{ inputs.code-artifact-auth-role-name }}
aws-region: ${{ inputs.code-artifact-auth-region }}
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/update-devcontainer-hash/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ runs:
shell: bash

- name: Checkout code
uses: actions/checkout@v5.0.0
uses: actions/checkout@v6.0.1
with:
persist-credentials: true
fetch-depth: 1
Expand Down
4 changes: 2 additions & 2 deletions .github/reusable_workflows/build-docker-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ jobs:
shell: bash

- name: Checkout code
uses: actions/checkout@v5.0.0
uses: actions/checkout@v6.0.1
with:
persist-credentials: false

- name: OIDC Auth for ECR
if: ${{ inputs.push-role-name != 'no-push' }}
uses: aws-actions/configure-aws-credentials@v5.1.0
uses: aws-actions/configure-aws-credentials@v5.1.1
with:
role-to-assume: arn:aws:iam::${{ steps.parse_ecr_url.outputs.aws_account_id }}:role/${{ inputs.push-role-name }}
aws-region: ${{ steps.parse_ecr_url.outputs.aws_region }}
Expand Down
22 changes: 16 additions & 6 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ jobs:
contents: write # needed for updating dependabot branches

pre-commit:
needs: [ get-values ]
needs:
- get-values
uses: ./.github/workflows/pre-commit.yaml
permissions:
contents: write # needed for mutex
Expand All @@ -29,7 +30,8 @@ jobs:
python-version: 3.12.7

lint-matrix:
needs: [ pre-commit ]
needs:
- pre-commit
strategy:
matrix:
os:
Expand All @@ -54,7 +56,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v5.0.0
uses: actions/checkout@v6.0.1
with:
persist-credentials: false

Expand Down Expand Up @@ -111,7 +113,7 @@ jobs:
timeout-minutes: 8 # 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:
Expand All @@ -123,7 +125,13 @@ 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
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

- name: Upload pre-commit log if failure
if: ${{ failure() }}
Expand All @@ -135,7 +143,9 @@ jobs:
required-check:
runs-on: ubuntu-24.04
timeout-minutes: 2
needs: [ lint-matrix, get-values ]
needs:
- lint-matrix
- get-values
permissions:
statuses: write # needed for updating status on Dependabot PRs
if: always()
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/get-values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ on:
dependabot-commit-created:
description: whether or not a commit was created on a dependabot branch
value: ${{ jobs.get-values.outputs.dependabot-commit-created }}
pr-short-num:
description: the last two digits of the PR number (to be used for fixed width naming, like Pulumi stacks)
value: ${{ jobs.get-values.outputs.pr-short-num }}

env:
PYTHONUNBUFFERED: True
Expand All @@ -32,7 +35,7 @@ jobs:
JSON

- name: Checkout code
uses: actions/checkout@v5.0.0
uses: actions/checkout@v6.0.1
with:
persist-credentials: false

Expand Down
11 changes: 4 additions & 7 deletions .github/workflows/hash_git_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,16 @@ def compute_adler32(repo_path: Path, files: list[str]) -> int:
if not chunk:
break
checksum = zlib.adler32(chunk, checksum)
except Exception as e:
if "[Errno 21] Is a directory" in str(e):
# Ignore symlinks that on windows sometimes get confused as being directories
continue
print(f"Error reading file {file}: {e}", file=sys.stderr) # noqa: T201 # this just runs as a simple script, so using print instead of log
raise
except IsADirectoryError:
# Ignore symlinks that on windows sometimes get confused as being directories
continue

return checksum


def find_devcontainer_hash_line(lines: list[str]) -> tuple[int, str | None]:
"""Find the line index and current hash in the devcontainer.json file."""
for i in range(len(lines) - 1, -1, -1):
for i in reversed(range(len(lines))):
if lines[i].strip() == "}":
# Check the line above it
if i > 0:
Expand Down
15 changes: 11 additions & 4 deletions .github/workflows/pre-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ jobs:
steps:
- name: Checkout code during push
if: ${{ github.event_name == 'push' }}
uses: actions/checkout@v5.0.0
uses: actions/checkout@v6.0.1
with:
ref: ${{ github.ref_name }} # explicitly get the head of the branch, which will include any new commits pushed if this is a dependabot branch
persist-credentials: false

- name: Checkout code not during push
if: ${{ github.event_name != 'push' }}
uses: actions/checkout@v5.0.0
uses: actions/checkout@v6.0.1
with:
persist-credentials: false

Expand All @@ -59,7 +59,7 @@ jobs:
timeout-minutes: 8 # 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:
Expand All @@ -69,4 +69,11 @@ jobs:
ubuntu-24.04-py${{ inputs.python-version }}-node-${{ inputs.node-version}}-${{ env.cache-name }}-

- name: Run pre-commit
run: pre-commit run -a
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
Comment on lines 71 to +79
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Quote PRE_COMMIT_EXIT_CODE when exiting to satisfy shellcheck

The new failure-handling block is sensible, but shellcheck’s SC2086 warning is likely about unquoted $PRE_COMMIT_EXIT_CODE in the exit command. Quoting it avoids word-splitting/globbing warnings and keeps linters happy without changing behavior.

You can address this with a minimal tweak:

-          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"
+          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
+            exit "$PRE_COMMIT_EXIT_CODE"
           fi
🧰 Tools
🪛 actionlint (1.7.9)

72-72: shellcheck reported issue in this script: SC2086:info:6:8: Double quote to prevent globbing and word splitting

(shellcheck)

🤖 Prompt for AI Agents
In .github/workflows/pre-commit.yaml around lines 71 to 79, the exit command
uses an unquoted shell variable which triggers shellcheck SC2086; update the
exit invocation to quote the variable (exit "$PRE_COMMIT_EXIT_CODE") so the
value is passed safely without word-splitting or globbing while preserving
behavior.

2 changes: 1 addition & 1 deletion .github/workflows/tag-on-merge.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ dist
**/logs/*.log.*

# macOS dev cleanliness
*.DS_Store
.DS_Store
**/.DS_Store

# Ignores specific to this repository
Loading