Copier update: release job - #64
Conversation
|
Warning Review limit reached
Next review available in: 45 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR synchronizes Copier-managed repository files, adds Claude review and mutation-testing workflows, updates development tooling and devcontainer configuration, and introduces GitHub Actions for ECR authentication, tagging, CI validation, and releases. ChangesRepository tooling and automation
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.claude/skills/address-pr-comments/fetch-pr-comments.py:
- Around line 323-330: Move the copier-managed warning header block to the very
beginning of fetch-pr-comments.py, before all imports, comments, and executable
content, while preserving its existing text unchanged.
In @.claude/skills/address-pr-comments/verify-env.py:
- Line 99: Update the on_protected_branch condition to use explicit checks for
“main” and “master” in separate branches instead of membership testing, while
preserving the same boolean result and allowing each condition to be covered
independently.
In @.claude/skills/fix-mutants/utils.py:
- Around line 56-59: Update the emit function’s docstring to comply with the
project guideline: either remove it because the function name and implementation
are self-explanatory, or expand it into a substantive multi-line explanation of
its stdout JSON serialization behavior.
- Around line 209-212: Update the run_mutmut docstring to remove it or expand it
into a multiline docstring documenting the function’s behavior, arguments, and
possible exceptions; preserve the existing implementation and signature.
In @.github/workflows/git_tag.py:
- Line 12: Update ensure_tag_not_present so tag and remote are keyword-only
parameters by adding * to its signature, then revise both call sites in the
surrounding workflow code to pass these arguments by name.
In @.github/workflows/release.yaml:
- Around line 40-44: Prevent shell injection in the release workflow by moving
all GitHub Actions expression values out of run-script interpolation and into
step-level environment variables. Update .github/workflows/release.yaml lines
40-44 for “Fail if real release is not on main,” lines 88-99 for “Check version
tag does not already exist,” lines 118-121 for both “Confirm tag not already
present” and “Create tag,” lines 143-145 for “Package executable (ubuntu-24.04
py3.13.9),” and lines 154-156 for “Package executable (windows-2025-vs2026
py3.13.9)”; use the env variables inside each script for github.ref,
steps.get-version.outputs.version, inputs.dry_run, and
needs.guard.outputs.version respectively.
In `@pyinstaller.spec`:
- Line 23: Update the datas entries in the PyInstaller configuration to satisfy
the spellchecker suppression requirement: add preceding comments explaining that
datas is PyInstaller’s API name, or remove the spellchecker suppressions if they
are unnecessary. Apply this consistently to both occurrences.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 77483d7a-8981-4765-a490-3afd2f426835
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (117)
.claude/.beads/.gitignore.claude/.beads/config.yaml.claude/CLAUDE.md.claude/commands/add-command.md.claude/commands/commit.md.claude/commands/create-adr.md.claude/commands/create-issues.md.claude/commands/gap.md.claude/commands/green.md.claude/commands/issue.md.claude/commands/polish.md.claude/commands/red.md.claude/commands/refactor.md.claude/commands/research.md.claude/commands/simplify.md.claude/commands/spike.md.claude/commands/summarize.md.claude/commands/tdd-review.md.claude/commands/tdd.md.claude/helpers/merge-claude-settings.sh.claude/hooks/bash-chain-guard.js.claude/hooks/caveman-activate.js.claude/hooks/caveman-config.js.claude/hooks/caveman-mode-tracker.js.claude/settings/basics.jsonc.claude/settings/hooks.jsonc.claude/settings/permissions/additional-dirs.jsonc.claude/settings/permissions/bash.jsonc.claude/settings/permissions/read.jsonc.claude/settings/permissions/write.jsonc.claude/skills/address-pr-comments/SKILL.md.claude/skills/address-pr-comments/check-footer.py.claude/skills/address-pr-comments/commit-link.py.claude/skills/address-pr-comments/fetch-pr-comments.py.claude/skills/address-pr-comments/post-reply.py.claude/skills/address-pr-comments/utils.py.claude/skills/address-pr-comments/verify-env.py.claude/skills/caveman/SKILL.md.claude/skills/fix-mutants/SKILL.md.claude/skills/fix-mutants/check-results.py.claude/skills/fix-mutants/group-by-line.py.claude/skills/fix-mutants/list-survived.py.claude/skills/fix-mutants/run-mutmut.py.claude/skills/fix-mutants/show-mutant.py.claude/skills/fix-mutants/utils.py.claude/skills/fix-mutants/verify-mutant.py.coderabbit.yaml.config/.copier-answers.yml.config/.copier-managed-files.json.config/.coveragerc.config/.prettierrc.config/_typos.toml.config/pylintrc.toml.config/pyrefly.mutmut.toml.config/pyrefly.toml.config/ruff-non-src.toml.config/ruff.toml.devcontainer/Dockerfile.devcontainer/code-artifact-auth.sh.devcontainer/create-aws-profile.sh.devcontainer/devcontainer.json.devcontainer/docker-compose.yml.devcontainer/initialize-command.sh.devcontainer/install-ci-tooling.py.devcontainer/manual-setup-deps.py.devcontainer/on-create-command-boilerplate.sh.devcontainer/on-create-command.sh.devcontainer/post-start-command.sh.devcontainer/windows-host-helper.sh.github/.codecov.yml.github/CODE_OF_CONDUCT.md.github/CONTRIBUTING.md.github/ISSUE_TEMPLATE/bug-report.yml.github/ISSUE_TEMPLATE/config.yml.github/ISSUE_TEMPLATE/feature-request.yml.github/ISSUE_TEMPLATE/tech-debt.yml.github/actions/check-skip-duplicates/action.yml.github/actions/ecr-auth/action.yml.github/actions/install_deps/action.yml.github/actions/update-devcontainer-hash/action.yml.github/dependabot.yml.github/pull_request_template.md.github/workflows/ci.yaml.github/workflows/confirm-on-tagged-copier-template.yaml.github/workflows/extract_project_version.py.github/workflows/get-values.yaml.github/workflows/git_tag.py.github/workflows/hash_git_files.py.github/workflows/pre-commit.yaml.github/workflows/release.yaml.gitignore.pre-commit-config.yaml.python-version.readthedocs.yamlAGENTS.mdCHANGELOG.mdCLAUDE.mdLICENSEREADME.mdbiome.jsoncdocs/Makefiledocs/_static/.gitkeepdocs/conf.pydocs/index.rstdocs/make.batdocs/requirements.txtpyinstaller.specpyproject.tomlpyrightconfig.jsonpytest.iniscripts/delete_false_positive_rej.pysh.batsrc/cloud_courier/main.pysrc/entrypoint.pytests/unit/__init__.pytests/unit/conftest.pyty.toml
💤 Files with no reviewable changes (2)
- CLAUDE.md
- ty.toml
|
|
||
| # ============== 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. | ||
| # ===================================================================================================== |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Move the warning header to the top of the file.
Copier-managed file warning headers should be placed at the very beginning of the file. Placing it at the bottom defeats its purpose, as developers modifying the file might not scroll down to see it before making changes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/address-pr-comments/fetch-pr-comments.py around lines 323 -
330, Move the copier-managed warning header block to the very beginning of
fetch-pr-comments.py, before all imports, comments, and executable content,
while preserving its existing text unchanged.
| args = parser.parse_args() | ||
|
|
||
| branch = current_branch() | ||
| on_protected_branch = branch in {"main", "master"} |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Avoid list-style membership tests for conditions.
As per coding guidelines, avoid list-style membership tests such as x in ['a', 'b'] in implementation code; use separate branches so coverage tools can measure each condition independently.
♻️ Proposed refactor
- on_protected_branch = branch in {"main", "master"}
+ if branch == "main":
+ on_protected_branch = True
+ elif branch == "master":
+ on_protected_branch = True
+ else:
+ on_protected_branch = False📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| on_protected_branch = branch in {"main", "master"} | |
| if branch == "main": | |
| on_protected_branch = True | |
| elif branch == "master": | |
| on_protected_branch = True | |
| else: | |
| on_protected_branch = False |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/address-pr-comments/verify-env.py at line 99, Update the
on_protected_branch condition to use explicit checks for “main” and “master” in
separate branches instead of membership testing, while preserving the same
boolean result and allowing each condition to be covered independently.
Source: Coding guidelines
| def emit(obj: Any) -> None: # noqa: ANN401 — serializes arbitrary JSON-shaped result objects | ||
| """Write a JSON result to stdout (the scripts' machine-readable output).""" | ||
| _ = sys.stdout.write(json.dumps(obj, indent=2) + "\n") | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Remove or expand the one-line docstring.
As per coding guidelines, never write one-line Python docstrings; either the name is sufficient or the behavior warrants a full explanation.
♻️ Proposed fix
-def emit(obj: Any) -> None: # noqa: ANN401 — serializes arbitrary JSON-shaped result objects
- """Write a JSON result to stdout (the scripts' machine-readable output)."""
- _ = sys.stdout.write(json.dumps(obj, indent=2) + "\n")
+def emit(obj: Any) -> None: # noqa: ANN401 — serializes arbitrary JSON-shaped result objects
+ _ = sys.stdout.write(json.dumps(obj, indent=2) + "\n")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def emit(obj: Any) -> None: # noqa: ANN401 — serializes arbitrary JSON-shaped result objects | |
| """Write a JSON result to stdout (the scripts' machine-readable output).""" | |
| _ = sys.stdout.write(json.dumps(obj, indent=2) + "\n") | |
| def emit(obj: Any) -> None: # noqa: ANN401 — serializes arbitrary JSON-shaped result objects | |
| _ = sys.stdout.write(json.dumps(obj, indent=2) + "\n") |
🧰 Tools
🪛 ast-grep (0.44.1)
[info] 57-57: use jsonify instead of json.dumps for JSON output
Context: json.dumps(obj, indent=2)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/fix-mutants/utils.py around lines 56 - 59, Update the emit
function’s docstring to comply with the project guideline: either remove it
because the function name and implementation are self-explanatory, or expand it
into a substantive multi-line explanation of its stdout JSON serialization
behavior.
Source: Coding guidelines
| def run_mutmut( | ||
| args: list[str], backend_root: Path, *, timeout: int = SUBPROCESS_TIMEOUT_SECONDS | ||
| ) -> subprocess.CompletedProcess[str]: | ||
| """Invoke the project's mutmut via uv, with cwd at the backend root.""" |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Remove or expand the one-line docstring.
As per coding guidelines, never write one-line Python docstrings. Consider removing it or expanding it to fully document the behavior, parameters, and exceptions.
♻️ Proposed fix
def run_mutmut(
args: list[str], backend_root: Path, *, timeout: int = SUBPROCESS_TIMEOUT_SECONDS
) -> subprocess.CompletedProcess[str]:
- """Invoke the project's mutmut via uv, with cwd at the backend root."""
try:📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def run_mutmut( | |
| args: list[str], backend_root: Path, *, timeout: int = SUBPROCESS_TIMEOUT_SECONDS | |
| ) -> subprocess.CompletedProcess[str]: | |
| """Invoke the project's mutmut via uv, with cwd at the backend root.""" | |
| def run_mutmut( | |
| args: list[str], backend_root: Path, *, timeout: int = SUBPROCESS_TIMEOUT_SECONDS | |
| ) -> subprocess.CompletedProcess[str]: |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/fix-mutants/utils.py around lines 209 - 212, Update the
run_mutmut docstring to remove it or expand it into a multiline docstring
documenting the function’s behavior, arguments, and possible exceptions;
preserve the existing implementation and signature.
Source: Coding guidelines
| raise KeyError(f"No version field found in {path!r}") | ||
|
|
||
|
|
||
| def ensure_tag_not_present(tag: str, remote: str) -> None: |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Prefer keyword-only parameters.
As per coding guidelines, prefer keyword-only parameters in Python by using * in function signatures.
♻️ Proposed refactor for the signature and its call sites
Update the signature:
-def ensure_tag_not_present(tag: str, remote: str) -> None:
+def ensure_tag_not_present(*, tag: str, remote: str) -> None:Update the call on line 57:
- ensure_tag_not_present(tag, args.remote)
+ ensure_tag_not_present(tag=tag, remote=args.remote)Update the call on line 63:
- ensure_tag_not_present(tag, args.remote)
+ ensure_tag_not_present(tag=tag, remote=args.remote)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/git_tag.py at line 12, Update ensure_tag_not_present so
tag and remote are keyword-only parameters by adding * to its signature, then
revise both call sites in the surrounding workflow code to pass these arguments
by name.
Source: Coding guidelines
| - name: Fail if real release is not on main | ||
| if: ${{ !inputs.dry_run && github.ref != 'refs/heads/main' }} | ||
| run: | | ||
| echo "Real releases must run from main. Current ref: ${{ github.ref }}" | ||
| exit 1 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Prevent script injection via template expansion.
Using GitHub Actions expressions like ${{ github.ref }} or ${{ steps.get-version.outputs.version }} directly within a bash run block allows for script injection if the interpolated value contains malicious shell metacharacters (e.g., if a manipulated pyproject.toml version string is surfaced to an active action runner). Pass these values securely via environment variables instead.
.github/workflows/release.yaml#L40-L44: pass${{ github.ref }}via anenvvariable in the "Fail if real release is not on main" step..github/workflows/release.yaml#L88-L99: pass${{ steps.get-version.outputs.version }}and${{ inputs.dry_run }}viaenvvariables in the "Check version tag does not already exist" step..github/workflows/release.yaml#L118-L121: pass${{ needs.guard.outputs.version }}via anenvvariable for both the "Confirm tag not already present" and "Create tag" steps..github/workflows/release.yaml#L143-L145: pass${{ needs.guard.outputs.version }}via anenvvariable in the "Package executable (ubuntu-24.04 py3.13.9)" step..github/workflows/release.yaml#L154-L156: pass${{ needs.guard.outputs.version }}via anenvvariable in the "Package executable (windows-2025-vs2026 py3.13.9)" step.
🧰 Tools
🪛 zizmor (1.26.1)
[error] 43-43: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
📍 Affects 1 file
.github/workflows/release.yaml#L40-L44(this comment).github/workflows/release.yaml#L88-L99.github/workflows/release.yaml#L118-L121.github/workflows/release.yaml#L143-L145.github/workflows/release.yaml#L154-L156
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release.yaml around lines 40 - 44, Prevent shell injection
in the release workflow by moving all GitHub Actions expression values out of
run-script interpolation and into step-level environment variables. Update
.github/workflows/release.yaml lines 40-44 for “Fail if real release is not on
main,” lines 88-99 for “Check version tag does not already exist,” lines 118-121
for both “Confirm tag not already present” and “Create tag,” lines 143-145 for
“Package executable (ubuntu-24.04 py3.13.9),” and lines 154-156 for “Package
executable (windows-2025-vs2026 py3.13.9)”; use the env variables inside each
script for github.ref, steps.get-version.outputs.version, inputs.dry_run, and
needs.guard.outputs.version respectively.
Source: Linters/SAST tools
Pull in upstream changes
Summary by CodeRabbit
New Features
Improvements