chore: update rhiza to v1.3.2 - #758
Conversation
📝 WalkthroughWalkthroughThe PR synchronizes Rhiza workflows to ChangesRhiza synchronization
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant GitHubActions
participant GitRemote
participant BranchRefs
GitHubActions->>GitRemote: Fetch remote branch references
GitHubActions->>BranchRefs: Resolve default branch and branch containment
BranchRefs-->>GitHubActions: Return tag reachability
GitHubActions->>GitHubActions: Continue or reject release validation
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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.
Pull request overview
Updates this repository’s Rhiza template sync from jebel-quant/rhiza v1.2.5 → v1.3.2, refreshing the template-managed build/test tooling, release safeguards, and the synced “rhiza tests” suite.
Changes:
- Adds/reshapes synced Rhiza tests (README bash-fence parsing, release-tag reachability checks, and a packaging/version invariant smoke test).
- Refactors Makefile fragments to introduce a Python language-layer (
.rhiza/make.d/python.mk) and moves core vs. language-specific gates accordingly. - Updates tooling pins and CI/reusable workflow references (pre-commit hook revisions, workflow stubs, and branch-protection required check contexts).
Reviewed changes
Copilot reviewed 29 out of 31 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
tests/test_rhiza_packaging.py |
Adds a baseline packaging/version-invariant test to ensure installed distribution version matches pyproject.toml. |
cliff.toml |
Refines git-cliff commit skipping rules to avoid dropping dependency bump commits. |
.rhiza/tests/test_release_tags.py |
Adds a core test asserting the newest tag’s commit is reachable from at least one branch. |
.rhiza/tests/test_readme.py |
Adds language-neutral README checks (existence/readability + bash fence syntax parsing). |
.rhiza/tests/test_readme_validation.py |
Narrows this module to Python-fence execution/validation; removes bash-fence responsibilities now covered by core tests. |
.rhiza/tests/test_pyproject.py |
Expands pyproject invariants (notably bump-my-version discoverability and config correctness) and delegates tag reachability to core tests. |
.rhiza/tests/README.md |
Updates suite documentation to reflect bundle ownership and new/relocated test modules. |
.rhiza/tests/conftest.py |
Adds shared latest_tag fixture and clarifies “core-owned” fixture responsibility. |
.rhiza/template.yml |
Bumps template ref to v1.3.2. |
.rhiza/template.lock |
Updates template lock sha/ref, file list (adds python.mk + new tests; removes .rhiza/.cfg.toml from template-owned list), and sync timestamp. |
.rhiza/rhiza.mk |
Clarifies uv/uvx role in core, adjusts help target parsing, and removes python-specific venv concerns from core. |
.rhiza/make.d/test.mk |
Converts this fragment to optional testing “extras” only (benchmarks, hypothesis, stress, mutation), with core gates moved to the language layer. |
.rhiza/make.d/quality.mk |
Moves to prek, refocuses to language-neutral quality gates, and reinstates a single rhiza-test runner owned by core. |
.rhiza/make.d/python.mk |
Introduces Python language-layer: defines install, all, and core Python gates (test, typecheck, security, docs-coverage, deps, license). |
.rhiza/make.d/doctor.mk |
Switches to doctor:: (layer-extensible) and standardizes output formatting. |
.rhiza/make.d/bootstrap.mk |
Keeps only language-neutral bootstrapping (uv/uvx install, hooks, clean); removes Python-specific install implementation. |
.rhiza/CONTRIBUTING.md |
Updates contributor guidance (notably removal of a non-existent lint group). |
.pre-commit-config.yaml |
Bumps hook revisions (ruff, betterleaks, uv-pre-commit, rhiza-hooks) and documents disabled hooks. |
.gitignore |
Adds Rust bundle ignore patterns at core level. |
.github/workflows/rhiza_weekly.yml |
Updates reusable workflow pin to v1.3.2. |
.github/workflows/rhiza_scorecard.yml |
Updates reusable workflow pin to v1.3.2. |
.github/workflows/rhiza_release.yml |
Adds a tag reachability backstop step and updates reusable workflow pin to v1.3.2. |
.github/workflows/rhiza_mutation.yml |
Updates reusable workflow pin to v1.3.2. |
.github/workflows/rhiza_marimo.yml |
Updates reusable workflow pin to v1.3.2. |
.github/workflows/rhiza_fuzzing.yml |
Updates reusable workflow pin to v1.3.2. |
.github/workflows/rhiza_codeql.yml |
Updates reusable workflow pin to v1.3.2. |
.github/workflows/rhiza_ci.yml |
Updates reusable workflow pin to v1.3.2. |
.github/workflows/rhiza_book.yml |
Updates reusable workflow pin to v1.3.2. |
.github/workflows/rhiza_benchmark.yml |
Updates reusable workflow pin to v1.3.2. |
.github/rulesets/main-branch-protection.json |
Updates required status check context names to match the reusable-workflow job context format. |
.github/pull_request_template.md |
Updates checklist to reflect make deps (renamed from make deptry). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - .gitignore | ||
| - .pre-commit-config.yaml | ||
| - .python-version | ||
| - .rhiza/.cfg.toml | ||
| - .rhiza/.env | ||
| - .rhiza/.gitignore |
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 @.github/workflows/rhiza_benchmark.yml:
- Line 23: Replace the mutable `@v1.3.2` references in
.github/workflows/rhiza_benchmark.yml at lines 23-23 and
.github/workflows/rhiza_book.yml at lines 32-32 with reviewed immutable commit
SHAs for the reusable workflow, then regenerate or synchronize both workflow
files.
In @.rhiza/make.d/python.mk:
- Around line 51-76: Configure uv to use the virtual environment created by the
install target by setting UV_PROJECT_ENVIRONMENT to ${VENV} near the existing uv
configuration, so both locked and unlocked ${UV_BIN} sync invocations target the
overridden VENV consistently.
In @.rhiza/tests/conftest.py:
- Around line 63-71: Update the Git tag lookup in the fixture around
subprocess.run to check result.returncode before evaluating tags; when the
command fails, fail the test using result.stderr, and retain the existing skip
behavior only when a successful command returns no tags.
In @.rhiza/tests/test_pyproject.py:
- Around line 287-298: Update test_config_does_not_duplicate_the_version so any
present [tool.bumpversion].current_version is rejected, including values equal
to declared_version; require declared_in_config to be None and adjust the
assertion message to reflect that all redundant values must be removed.
- Around line 53-59: Update _has_bumpversion_section for .cfg files to parse the
file with configparser and determine presence using has_section("bumpversion"),
replacing the raw text search so commented headers are not accepted. Preserve
the existing TOML parsing path for non-.cfg files.
In @.rhiza/tests/test_release_tags.py:
- Around line 52-53: Update the template source that generates the release-tag
test so the git branch check uses only remote branches via branch -r rather than
branch -a. Then regenerate or synchronize .rhiza/tests/test_release_tags.py from
that template; do not edit the template-managed file directly, and preserve the
existing --contains commit and refname formatting arguments.
In `@tests/test_rhiza_packaging.py`:
- Around line 87-90: Update the PackageNotFoundError handling around
installed_version(name) to skip only when pyproject.toml positively identifies
the project as virtual or non-package; otherwise let the missing distribution
fail the test so build and package-discovery defects are detected.
🪄 Autofix
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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 110e3268-a2d8-4e03-abed-69ba31e01621
⛔ Files ignored due to path filters (1)
.rhiza/template.lockis excluded by!**/*.lock
📒 Files selected for processing (30)
.github/pull_request_template.md.github/rulesets/main-branch-protection.json.github/workflows/rhiza_benchmark.yml.github/workflows/rhiza_book.yml.github/workflows/rhiza_ci.yml.github/workflows/rhiza_codeql.yml.github/workflows/rhiza_fuzzing.yml.github/workflows/rhiza_marimo.yml.github/workflows/rhiza_mutation.yml.github/workflows/rhiza_release.yml.github/workflows/rhiza_scorecard.yml.github/workflows/rhiza_weekly.yml.gitignore.pre-commit-config.yaml.rhiza/CONTRIBUTING.md.rhiza/make.d/bootstrap.mk.rhiza/make.d/doctor.mk.rhiza/make.d/python.mk.rhiza/make.d/quality.mk.rhiza/make.d/test.mk.rhiza/rhiza.mk.rhiza/template.yml.rhiza/tests/README.md.rhiza/tests/conftest.py.rhiza/tests/test_pyproject.py.rhiza/tests/test_readme.py.rhiza/tests/test_readme_validation.py.rhiza/tests/test_release_tags.pycliff.tomltests/test_rhiza_packaging.py
| jobs: | ||
| benchmark: | ||
| uses: jebel-quant/rhiza/.github/workflows/rhiza_benchmark.yml@v1.2.5 | ||
| uses: jebel-quant/rhiza/.github/workflows/rhiza_benchmark.yml@v1.3.2 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow references =="
for f in .github/workflows/rhiza_benchmark.yml .github/workflows/rhiza_book.yml; do
if [ -f "$f" ]; then
echo "-- $f --"
nl -ba "$f" | sed -n '1,80p'
else
echo "MISSING $f"
fi
done
echo
echo "== rhiza repo tag ref data =="
if command -v gh >/dev/null 2>&1; then
echo "-- ref --"
git ls-remote --tags https://github.com/jebel-quant/rhiza.git 'refs/tags/v1.3.2' || true
echo "-- tag object --"
gh api repos/jebel-quant/rhiza/git/refs/tags/v1.3.2 --jq '{ref,.object}' || true
else
echo "gh command unavailable"
fi
echo
echo "== repository references and permissions relevant lines =="
rg -n "secrets: inherit|permissions:|pages:|OIDC|id-token|pull_request_target|push:|workflow_dispatch:" .github/workflows 2>/dev/null || trueRepository: tschm/pyhrp
Length of output: 259
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow references =="
for f in .github/workflows/rhiza_benchmark.yml .github/workflows/rhiza_book.yml; do
if [ -f "$f" ]; then
echo "-- $f --"
awk '{printf "%6d\t%s\n", NR, $0}' "$f" | sed -n '1,90p'
else
echo "MISSING $f"
fi
done
echo
echo "== rhiza repo tag ref data =="
if command -v gh >/dev/null 2>&1; then
echo "-- tag ref --"
git ls-remote --tags https://github.com/jebel-quant/rhiza.git 'refs/tags/v1.3.2' || true
echo "-- ref object --"
gh api repos/jebel-quant/rhiza/git/refs/tags/v1.3.2 --jq '{ref,.object}' || true
echo "-- tag object dereference --"
tag_object="$(gh api repos/jebel-quant/rhiza/git/refs/tags/v1.3.2 --jq '.object.sha' 2>/dev/null || true)"
if [ -n "${tag_object:-}" ]; then
gh api repos/jebel-quant/rhiza/git/tags/"$tag_object" --jq '{object}' || true
fi
else
echo "gh command unavailable"
fi
echo
echo "== repository references and permissions relevant lines =="
rg -n "secrets: inherit|permissions:|pages:|OIDC|id-token|pull_request_target|push:|workflow_dispatch:" .github/workflows 2>/dev/null || trueRepository: tschm/pyhrp
Length of output: 6752
Security Misconfiguration (CWE-829): Inclusion of Functionality from Untrusted Control Sphere
Pin reusable workflows to immutable commit SHAs.
Both workflows call jebel-quant/rhiza/...@v1.3.2. GitHub tags are mutable at the upstream repository, so retargeting that tag can change executed workflow code while retaining inherited secrets and the Book job’s Pages/OIDC permissions. Replace both @v1.3.2 references with reviewed commit SHAs and regenerate/synchronize the workflow files.
.github/workflows/rhiza_benchmark.yml#L23.github/workflows/rhiza_book.yml#L32
🧰 Tools
🪛 zizmor (1.29.0)
[warning] 23-23: secrets unconditionally inherited by called workflow (secrets-inherit): this reusable workflow
(secrets-inherit)
📍 Affects 2 files
.github/workflows/rhiza_benchmark.yml#L23-L23(this comment).github/workflows/rhiza_book.yml#L32-L32
🤖 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/rhiza_benchmark.yml at line 23, Replace the mutable
`@v1.3.2` references in .github/workflows/rhiza_benchmark.yml at lines 23-23 and
.github/workflows/rhiza_book.yml at lines 32-32 with reviewed immutable commit
SHAs for the reusable workflow, then regenerate or synchronize both workflow
files.
Source: Linters/SAST tools
| install: pre-install install-uv ## install | ||
| # Create the virtual environment only if it doesn't exist | ||
| @if [ ! -d "${VENV}" ]; then \ | ||
| ${UV_BIN} venv $(if $(PYTHON_VERSION),--python $(PYTHON_VERSION)) ${VENV} || { printf "${RED}[ERROR] Failed to create virtual environment${RESET}\n"; exit 1; }; \ | ||
| else \ | ||
| printf "${BLUE}[INFO] Using existing virtual environment at ${VENV}, skipping creation${RESET}\n"; \ | ||
| fi | ||
|
|
||
| # Install the dependencies from pyproject.toml (if it exists). | ||
| # --inexact leaves packages uv did not manage in place instead of pruning them each | ||
| # run, so repeated 'make' targets don't churn the environment. Per-target tooling | ||
| # (pytest, interrogate, mutmut, ...) is provisioned on the fly via `uv run --with` | ||
| # in the individual targets, so there is no separate dependency-install step here. | ||
| @if [ -f "pyproject.toml" ]; then \ | ||
| if [ -f "uv.lock" ]; then \ | ||
| if ! ${UV_BIN} lock --check >/dev/null 2>&1; then \ | ||
| printf "${YELLOW}[WARN] uv.lock is out of sync with pyproject.toml${RESET}\n"; \ | ||
| printf "${YELLOW} Run 'uv sync' to update your lock file and environment${RESET}\n"; \ | ||
| printf "${YELLOW} Or run 'uv lock' to update only the lock file${RESET}\n"; \ | ||
| exit 1; \ | ||
| fi; \ | ||
| printf "${BLUE}[INFO] Installing dependencies from lock file${RESET}\n"; \ | ||
| ${UV_BIN} sync $(UV_SYNC_ARGS) --inexact --frozen || { printf "${RED}[ERROR] Failed to install dependencies${RESET}\n"; exit 1; }; \ | ||
| else \ | ||
| printf "${YELLOW}[WARN] uv.lock not found. Generating lock file and installing dependencies...${RESET}\n"; \ | ||
| ${UV_BIN} sync $(UV_SYNC_ARGS) --inexact || { printf "${RED}[ERROR] Failed to install dependencies${RESET}\n"; exit 1; }; \ |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== file excerpt =="
sed -n '1,120p' .rhiza/make.d/python.mk
echo
echo "== uv references =="
rg -n "UV_PROJECT_ENVIRONMENT|uv sync|uv venv|VENV|doctor" -S .rhiza . 2>/dev/null | head -200
echo
echo "== lock/tool files with uv =="
git ls-files | rg '(^|/)(uv\.lock|pyproject\.toml|\.github/workflows/.*\.ya?ml|README\.md)$|(^|/)uv$' | head -200Repository: tschm/pyhrp
Length of output: 9102
🌐 Web query:
uv sync environment variable UV_PROJECT_ENVIRONMENT project environment default .venv
💡 Result:
The environment variable UV_PROJECT_ENVIRONMENT is used to configure the path to the virtual environment used by uv for its project operations [1][2]. By default, uv uses a.venv directory located in the project root [3][4]. Key details regarding UV_PROJECT_ENVIRONMENT: - Purpose: It allows you to override the default.venv path, which is especially useful in continuous integration (CI) or Docker environments [2][5]. - Behavior: - If a relative path is provided, it is resolved relative to the workspace root [2][6]. - If an absolute path is provided, it is used as-is [2]. - System Environments: You can target a system Python environment by setting UV_PROJECT_ENVIRONMENT to the prefix of that installation (e.g., /usr/local) [2][6]. This is not recommended for general development because uv sync will remove extraneous packages, potentially breaking the system environment [2][6]. - Caveats: - If you set this variable to an absolute path shared across multiple projects, those projects will overwrite each other's environments [2][6]. - uv does not automatically read this variable from.env files [7]. - By default, uv does not respect the VIRTUAL_ENV environment variable during project operations; it prefers the path specified by UV_PROJECT_ENVIRONMENT or the default.venv [2][8]. If VIRTUAL_ENV points elsewhere, a warning may be displayed [2][8]. When using uv, it is generally recommended to rely on the default.venv structure to ensure compatibility with editor tooling and to maintain the isolation that uv's project management model provides [3][4][9].
Citations:
- 1: https://docs.astral.sh/uv/reference/environment/
- 2: https://docs.astral.sh/uv/concepts/projects/config/
- 3: https://docs.astral.sh/uv/concepts/projects/layout/
- 4: https://docs.astral.sh/uv/guides/projects/
- 5: uv add and uv sync doesn't install packages in virtual env created by uv venv <custom venv name> but creates the default .venv astral-sh/uv#8878
- 6: https://github.com/astral-sh/uv/blob/262a50bb/docs/concepts/projects/config.md
- 7:
uvdoes not respect theUV_PROJECT_ENVIRONMENTenvironment variable anymore astral-sh/uv#19792 - 8: phantom UV_PROJECT_ENVIRONMENT value astral-sh/uv#9834
- 9: Allow customizing the project environment path with
UV_PROJECT_ENVIRONMENTastral-sh/uv#6834
Route uv sync through the configured virtualenv.
VENV creates the activation target, but uv sync does not receive it. When VENV is overridden, the sync may target the default .venv while the success message points to ${VENV}. Set UV_PROJECT_ENVIRONMENT := ${VENV}, or use the default virtualenv consistently.
🤖 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 @.rhiza/make.d/python.mk around lines 51 - 76, Configure uv to use the
virtual environment created by the install target by setting
UV_PROJECT_ENVIRONMENT to ${VENV} near the existing uv configuration, so both
locked and unlocked ${UV_BIN} sync invocations target the overridden VENV
consistently.
| result = subprocess.run( # nosec B603 | ||
| [_GIT, "tag", "--list", "v*", "--sort=-version:refname"], | ||
| capture_output=True, | ||
| text=True, | ||
| cwd=root, | ||
| ) | ||
| tags = [line.strip() for line in result.stdout.splitlines() if line.strip()] | ||
| if not tags: | ||
| pytest.skip("No version tags found in repository") |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Fail when Git cannot list tags.
If git tag fails, result.stdout is empty and this fixture skips the release and version checks as if the repository had no tags. Check result.returncode before testing tags, then fail with result.stderr.
Proposed fix
result = subprocess.run(
[_GIT, "tag", "--list", "v*", "--sort=-version:refname"],
capture_output=True,
text=True,
cwd=root,
)
+ if result.returncode != 0:
+ pytest.fail(f"git tag --list failed: {result.stderr.strip()}")
tags = [line.strip() for line in result.stdout.splitlines() if line.strip()]📝 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.
| result = subprocess.run( # nosec B603 | |
| [_GIT, "tag", "--list", "v*", "--sort=-version:refname"], | |
| capture_output=True, | |
| text=True, | |
| cwd=root, | |
| ) | |
| tags = [line.strip() for line in result.stdout.splitlines() if line.strip()] | |
| if not tags: | |
| pytest.skip("No version tags found in repository") | |
| result = subprocess.run( # nosec B603 | |
| [_GIT, "tag", "--list", "v*", "--sort=-version:refname"], | |
| capture_output=True, | |
| text=True, | |
| cwd=root, | |
| ) | |
| if result.returncode != 0: | |
| pytest.fail(f"git tag --list failed: {result.stderr.strip()}") | |
| tags = [line.strip() for line in result.stdout.splitlines() if line.strip()] | |
| if not tags: | |
| pytest.skip("No version tags found in repository") |
🧰 Tools
🪛 Ruff (0.16.1)
[error] 63-63: subprocess call: check for execution of untrusted input
(S603)
🤖 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 @.rhiza/tests/conftest.py around lines 63 - 71, Update the Git tag lookup in
the fixture around subprocess.run to check result.returncode before evaluating
tags; when the command fails, fail the test using result.stderr, and retain the
existing skip behavior only when a successful command returns no tags.
| if path.suffix == ".cfg": | ||
| return "[bumpversion]" in path.read_text(encoding="utf-8") | ||
| try: | ||
| with path.open("rb") as handle: | ||
| data = tomllib.load(handle) | ||
| except tomllib.TOMLDecodeError: | ||
| return False |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate files =="
git ls-files .rhiza/tests/test_pyproject.py pyproject.toml setup.cfg setup.py requirements*.txt | sed -n '1,120p'
echo
echo "== test file outline/size =="
wc -l .rhiza/tests/test_pyproject.py 2>/dev/null || true
ast-grep outline .rhiza/tests/test_pyproject.py --view expanded 2>/dev/null | sed -n '1,220p' || true
echo
echo "== relevant test.py lines =="
cat -n .rhiza/tests/test_pyproject.py | sed -n '1,120p'Repository: tschm/pyhrp
Length of output: 8469
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== bump-relevant test bodies =="
cat -n .rhiza/tests/test_pyproject.py | sed -n '221,310p'
echo
echo "== repo bump refs =="
rg -n "bumpversion|bump-my-version|tool\.bumpversion" .rhiza pyproject.toml 2>/dev/null || true
echo
echo "== static config files list =="
for f in setup.cfg setup.py .bumpversion.toml .bumpversion.cfg pyproject.toml; do
if [ -f "$f" ]; then
echo "--- $f ---"
sed -n '1,160p' "$f" | nl -ba
fi
done
echo
echo "== Python parser probe for INI-like substring acceptance =="
python3 - <<'PY'
text = "# [bumpversion]"
print("[bumpversion] in text:", "[bumpversion]" in text)
# Equivalent to tomllib.load(b'''# [bumpversion]''') semantics: file is valid TOML, no table.
import tomllib
data = tomllib.loads("# [bumpversion]\n")
print("TOML parsed tables:", list(data.keys()))
print("tool.bumpversion present:", isinstance(data.get("tool", {}).get("bumpversion"), dict))
PYRepository: tschm/pyhrp
Length of output: 9851
🌐 Web query:
bump-my-version configuration file formats INI .cfg [bumpversion] configuration syntax
💡 Result:
Bump My Version supports both INI-style (.cfg,.ini) and TOML (.toml) configuration file formats [1]. While legacy support exists for INI formats, TOML is the recommended format, and the maintainers have indicated that INI-style support may be dropped in the future [1]. In INI-style configuration files (such as.bumpversion.cfg or setup.cfg), the global configuration is defined under the [bumpversion] section [2][3]. File-specific configurations are defined under [bumpversion:file:] or [bumpversion:glob:] sections [4][5]. Key syntax points for INI configuration include: Global Settings: The [bumpversion] section contains parameters such as current_version, parse, serialize, commit, tag, and search/replace templates [2][3]. These values are defined using standard INI key-value pairs [3]. File-specific Settings: For files, the section header itself specifies the target [4]. For example: [bumpversion:file:path/to/file.txt] search = {current_version} replace = {new_version} If you need to process the same file multiple times (e.g., to replace different parts of a changelog), you can differentiate sections by adding a description in parentheses: [bumpversion:file(description):path/to/file.txt] [4][5]. TOML is the preferred format and offers a more structured approach, typically using the [tool.bumpversion] section for global settings and an array of tables for file configurations [2][6]. Due to the potential for future deprecation of INI support, migrating to TOML is advised for long-term compatibility [1].
Citations:
- 1: https://callowayproject.github.io/bump-my-version/reference/configuration/
- 2: https://callowayproject.github.io/bump-my-version/reference/configuration/global/
- 3: https://github.com/callowayproject/bump-my-version/blob/master/docs/reference/configuration/global.md
- 4: https://callowayproject.github.io/bump-my-version/reference/configuration/file/
- 5: https://github.com/callowayproject/bump-my-version/blob/master/docs/reference/configuration/file.md
- 6: https://callowayproject.github.io/bump-my-version/tutorials/getting-started/
🌐 Web query:
bump-my-version source read configuration INI configparser [bumpversion]
💡 Result:
bump-my-version supports INI-style configuration files (such as.bumpversion.cfg or setup.cfg) [1]. When using an INI file, configuration is organized under the [bumpversion] section [2][3]. Specific file configurations are handled by appending the file path or glob pattern to the section header, using the syntax [bumpversion:file:] or [bumpversion:glob:] [4]. Example of INI configuration: [bumpversion] current_version = 0.1.0 [bumpversion:file:README.md] search = version {current_version} replace = version {new_version} Note that while bump-my-version supports INI-style formats, TOML is the recommended configuration format, and future support for INI files may be deprecated [1]. For TOML files, the configuration is placed under the [tool.bumpversion] section [2][5]. Configuration files are automatically detected in a specific order of precedence, or can be specified explicitly using the --config-file command-line argument [6][1].
Citations:
- 1: https://callowayproject.github.io/bump-my-version/reference/configuration/
- 2: https://callowayproject.github.io/bump-my-version/reference/configuration/global/
- 3: https://github.com/callowayproject/bump-my-version/blob/master/docs/reference/configuration/global.md
- 4: https://github.com/callowayproject/bump-my-version/blob/master/docs/reference/configuration/file.md
- 5: https://callowayproject.github.io/bump-my-version/tutorials/getting-started/
- 6: https://callowayproject.github.io/bump-my-version/reference/cli/
🌐 Web query:
"bump-my-version" "Current,Version" "INI" "configparser" source
💡 Result:
Bump My Version is a maintained refactor of the original bumpversion tool, designed to support modern configuration standards [1][2]. Regarding INI-style configuration files: 1. Support Status: Bump My Version supports legacy INI-style configuration files, specifically .bumpversion.cfg and setup.cfg [1][2]. 2. Recommendations: The project explicitly recommends using TOML-formatted configuration files (e.g., pyproject.toml or .bumpversion.toml) over INI-style formats [1][2]. This preference is due to better type handling in TOML compared to the parsing and formatting issues associated with INI-style files [1][2]. 3. Future Outlook: The developers have indicated they may drop support for INI-style formats in the future [1][2]. If you are currently using an INI-style file, it is advisable to migrate your configuration to a TOML-based format to ensure long-term compatibility [1][2]. While the tool uses Pydantic for validation and Python's standard libraries for underlying operations, the reliance on older INI formats is being phased out in favor of modern, standard formats [1][3][2].
Citations:
- 1: https://pypi.org/project/bump-my-version/0.17.2/
- 2: https://pypi.org/project/bump-my-version/0.15.4/
- 3: https://github.com/callowayproject/bump-my-version/blob/master/CHANGELOG.md
Parse INI files before accepting a bumpversion section.
The raw "[bumpversion]" in text check also matches comments such as # [bumpversion], so a .cfg or setup.cfg file can pass _has_bumpversion_section() without declaring the required INI section. Use configparser and has_section("bumpversion") for .cfg files.
🤖 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 @.rhiza/tests/test_pyproject.py around lines 53 - 59, Update
_has_bumpversion_section for .cfg files to parse the file with configparser and
determine presence using has_section("bumpversion"), replacing the raw text
search so commented headers are not accepted. Preserve the existing TOML parsing
path for non-.cfg files.
| def test_config_does_not_duplicate_the_version(self, pyproject: dict, declared_version: str) -> None: | ||
| """``current_version`` is redundant in pyproject.toml, and drifts once stale.""" | ||
| section = pyproject.get("tool", {}).get("bumpversion") | ||
| if not isinstance(section, dict): | ||
| pytest.skip("no [tool.bumpversion] table — reported by test_a_discoverable_config_exists") | ||
| declared_in_config = section.get("current_version") | ||
| assert declared_in_config in (None, declared_version), ( | ||
| f"[tool.bumpversion].current_version is {declared_in_config!r} but " | ||
| f"[project].version is {declared_version!r}; bumping from the stale value cannot " | ||
| f"match the version in the file. Drop current_version — bump-my-version reads " | ||
| f"[project].version natively." | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Locate file =="
fd -a 'test_pyproject.py' . || true
echo "== Relevant assertions around current_version =="
if [ -f .rhiza/tests/test_pyproject.py ]; then
sed -n '250,315p' .rhiza/tests/test_pyproject.py | cat -n
fi
echo "== Search current_version tests/usages =="
rg -n "current_version|declared_version|read.*tool\.bumpversion|bump-my-version|bumpversion" .rhiza/tests/test_pyproject.py .rhiza 2>/dev/null | head -200Repository: tschm/pyhrp
Length of output: 13882
🌐 Web query:
bump-my-version pyproject.toml tool bumpversion current_version reads project.version
💡 Result:
Yes, bump-my-version supports reading the version from project.version as defined in PEP 621 [1][2]. If the current_version is not explicitly set in the [tool.bumpversion] configuration, bump-my-version will attempt to fall back to the version specified in project.version within your pyproject.toml [3][4][1]. Key details regarding this functionality: - Statically set version: This fallback mechanism only functions if project.version is statically defined [3][4]. If project.version is marked as dynamic (i.e., listed in project.dynamic), the tool will not use it and will instead proceed to query SCM tags [1][5]. - Automatic updates: When bumping the version, if bump-my-version successfully retrieved the current version from project.version, it will automatically update that field in your pyproject.toml to the new version [1]. - Configuration precedence: While you can use pyproject.toml for your configuration, if you omit current_version in the [tool.bumpversion] table, the tool automatically checks the [project] table for the version [1].
Citations:
- 1: https://callowayproject.github.io/bump-my-version/CHANGELOG/
- 2: Support PEP 621 version? callowayproject/bump-my-version#66
- 3: https://github.com/callowayproject/bump-my-version/blob/master/docs/reference/configuration/global.md
- 4: https://callowayproject.github.io/bump-my-version/reference/configuration/global/
- 5: https://callowayproject.github.io/bump-my-version/reference/api/bumpversion/config/files/
Reject every redundant current_version value.
Allowing current_version equal to project.version still creates duplicate version sources; treat a present current_version as stale. Require declared_in_config is None.
🤖 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 @.rhiza/tests/test_pyproject.py around lines 287 - 298, Update
test_config_does_not_duplicate_the_version so any present
[tool.bumpversion].current_version is rejected, including values equal to
declared_version; require declared_in_config to be None and adjust the assertion
message to reflect that all redundant values must be removed.
| contains = subprocess.run( # nosec B603 | ||
| [_GIT, "branch", "-a", "--contains", commit.stdout.strip(), "--format=%(refname:short)"], |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Match the release workflow remote-branch check.
Line 53 uses git branch -a, which also accepts local branches. .github/workflows/rhiza_release.yml lines 192-195 accept only remote branches. A stale local branch can make this test pass although the release workflow rejects the same tag.
Update the Rhiza template source to use git branch -r --contains ..., then synchronize this file. As per coding guidelines, “Do not edit files under .rhiza/ directly because they are template-managed configuration.”
Proposed template change
- [_GIT, "branch", "-a", "--contains", commit.stdout.strip(), "--format=%(refname:short)"],
+ [_GIT, "branch", "-r", "--contains", commit.stdout.strip(), "--format=%(refname:short)"],📝 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.
| contains = subprocess.run( # nosec B603 | |
| [_GIT, "branch", "-a", "--contains", commit.stdout.strip(), "--format=%(refname:short)"], | |
| contains = subprocess.run( # nosec B603 | |
| [_GIT, "branch", "-r", "--contains", commit.stdout.strip(), "--format=%(refname:short)"], |
🧰 Tools
🪛 Ruff (0.16.1)
[error] 52-52: subprocess call: check for execution of untrusted input
(S603)
🤖 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 @.rhiza/tests/test_release_tags.py around lines 52 - 53, Update the template
source that generates the release-tag test so the git branch check uses only
remote branches via branch -r rather than branch -a. Then regenerate or
synchronize .rhiza/tests/test_release_tags.py from that template; do not edit
the template-managed file directly, and preserve the existing --contains commit
and refname formatting arguments.
Source: Coding guidelines
| try: | ||
| found = installed_version(name) | ||
| except PackageNotFoundError: | ||
| pytest.skip(f"{name!r} is not installed as a distribution (a virtual project has no metadata)") |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Fail for a missing distribution in buildable projects.
PackageNotFoundError can indicate the packaging defect this test is meant to detect. The current unconditional skip also hides a broken build backend or package-discovery configuration.
Skip only when pyproject.toml positively identifies a virtual or non-package project. Otherwise fail when installed_version(name) cannot find the distribution.
🤖 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 `@tests/test_rhiza_packaging.py` around lines 87 - 90, Update the
PackageNotFoundError handling around installed_version(name) to skip only when
pyproject.toml positively identifies the project as virtual or non-package;
otherwise let the missing distribution fail the test so build and
package-discovery defects are detected.
Template:
jebel-quant/rhiza—v1.2.5→v1.3.2What changed
30 template-owned files staged (28 merged, 1 deleted upstream). New this bump:
.rhiza/make.d/python.mk,.rhiza/tests/test_readme.py,.rhiza/tests/test_release_tags.py,tests/test_rhiza_packaging.py.Conflicts
1 file conflicted and was resolved by taking the upstream (template) side:
.rhiza/tests/test_pyproject.py(2 blocks)Left unstaged (working tree only, not template-owned)
.rhiza/.cfg.toml— the sync deleted it, but it isn't in the template lock's filelist, so the deletion was not committed. Decide separately whether it should go.
No gates were run — run
/rhiza:qualityfor a scorecard.Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Chores