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
12 changes: 6 additions & 6 deletions .github/rulesets/main-branch-protection.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
"parameters": {
"strict_required_status_checks_policy": false,
"required_status_checks": [
{ "context": "Pre-commit hooks", "integration_id": 15368 },
{ "context": "Check dependencies with deptry", "integration_id": 15368 },
{ "context": "docs-coverage", "integration_id": 15368 },
{ "context": "Security scanning", "integration_id": 15368 },
{ "context": "License compliance scan", "integration_id": 15368 },
{ "context": "CI gate", "integration_id": 15368 }
{ "context": "ci / Pre-commit hooks", "integration_id": 15368 },
{ "context": "ci / Check dependencies with deptry", "integration_id": 15368 },
{ "context": "ci / docs-coverage", "integration_id": 15368 },
{ "context": "ci / Security scanning", "integration_id": 15368 },
{ "context": "ci / License compliance scan", "integration_id": 15368 },
{ "context": "ci / CI gate", "integration_id": 15368 }
]
}
}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rhiza_benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ on:

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.0
secrets: inherit
2 changes: 1 addition & 1 deletion .github/workflows/rhiza_book.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ on:

jobs:
book:
uses: jebel-quant/rhiza/.github/workflows/rhiza_book.yml@v1.2.5
uses: jebel-quant/rhiza/.github/workflows/rhiza_book.yml@v1.3.0
secrets: inherit
permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rhiza_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ on:

jobs:
ci:
uses: jebel-quant/rhiza/.github/workflows/rhiza_ci.yml@v1.2.5
uses: jebel-quant/rhiza/.github/workflows/rhiza_ci.yml@v1.3.0
secrets: inherit
2 changes: 1 addition & 1 deletion .github/workflows/rhiza_codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ on:

jobs:
codeql:
uses: jebel-quant/rhiza/.github/workflows/rhiza_codeql.yml@v1.2.5
uses: jebel-quant/rhiza/.github/workflows/rhiza_codeql.yml@v1.3.0
secrets: inherit
permissions:
security-events: write # Upload CodeQL results to code scanning
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rhiza_marimo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ on:

jobs:
marimo:
uses: jebel-quant/rhiza/.github/workflows/rhiza_marimo.yml@v1.2.5
uses: jebel-quant/rhiza/.github/workflows/rhiza_marimo.yml@v1.3.0
secrets: inherit
2 changes: 1 addition & 1 deletion .github/workflows/rhiza_mutation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
# this repo sets the `MUTATION_ENABLED` variable to 'true'. Gating here in
# the caller keeps it optional regardless of the pinned reusable workflow.
if: ${{ vars.MUTATION_ENABLED == 'true' }}
uses: jebel-quant/rhiza/.github/workflows/rhiza_mutation.yml@v1.2.5
uses: jebel-quant/rhiza/.github/workflows/rhiza_mutation.yml@v1.3.0
secrets: inherit
permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rhiza_paper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ on:

jobs:
paper:
uses: jebel-quant/rhiza/.github/workflows/rhiza_paper.yml@v1.2.5
uses: jebel-quant/rhiza/.github/workflows/rhiza_paper.yml@v1.3.0
secrets: inherit
permissions:
contents: write
42 changes: 42 additions & 0 deletions .github/workflows/rhiza_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,48 @@ jobs:
fi
fi

- name: Ensure the tagged commit is reachable from a branch
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.set_tag.outputs.tag }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
# Backstop for issue #1454: a release cut on a branch that is then
# squash-merged leaves the tag on the pre-squash commit, and the squash
# puts the same content on the default branch under a new SHA. The tag is
# then permanently orphaned — no branch contains it, `git describe` skips
# the release, and a git-cliff regeneration silently deletes that version's
# CHANGELOG section because it cannot place a boundary at an unreachable
# tag. Publishing from such a tag is never intended, so refuse it.
# The checkout above uses fetch-depth: 0; this fetch only adds the remote
# branch refs, which a tag-push checkout does not need otherwise.
git fetch --no-tags --quiet origin '+refs/heads/*:refs/remotes/origin/*'

if [ -z "$DEFAULT_BRANCH" ]; then
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')
fi
if ! git rev-parse --verify --quiet "refs/remotes/origin/$DEFAULT_BRANCH" >/dev/null; then
echo "::error::Cannot resolve the default branch 'origin/$DEFAULT_BRANCH' — refusing to release without a reachability check."
exit 1
fi

COMMIT=$(git rev-parse "$TAG^{commit}")
if git merge-base --is-ancestor "$COMMIT" "refs/remotes/origin/$DEFAULT_BRANCH"; then
echo "✅ $TAG ($COMMIT) is an ancestor of $DEFAULT_BRANCH"
exit 0
fi

# Reachable from some other branch: a maintenance/hotfix release. Legitimate,
# but a changelog regenerated from the default branch still cannot see it.
BRANCHES=$(git branch -r --contains "$COMMIT" --format='%(refname:short)')
if [ -n "$BRANCHES" ]; then
echo "::warning::Tag $TAG is not an ancestor of $DEFAULT_BRANCH; it is contained in: $(echo "$BRANCHES" | tr '\n' ' '). A CHANGELOG regenerated from $DEFAULT_BRANCH will not include this release."
exit 0
fi

echo "::error::Tag $TAG points at $COMMIT, which no branch contains. It is most likely a pre-squash commit from a squash-merged release branch: re-tag the merged commit on $DEFAULT_BRANCH and delete this tag (issue #1454)."
exit 1

- name: Install uv
uses: astral-sh/setup-uv@v7.6.0

Expand Down
15 changes: 6 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,9 @@ local.mk

.bandit-baseline.json

report.html
/demo_report.py
/positions.csv
/prices.csv
LICENSES.md
/test_output/

# local planning file
plan.md

# Rust (rust-core bundle). Kept in core rather than the language layer because
# .gitignore has one owner and git opens it with O_NOFOLLOW, so it cannot be a
# per-layer file. These entries are inert in a Python repo.
target/
**/*.rs.bk
13 changes: 9 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ repos:
pass_filenames: false

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.16.0'
rev: 'v0.16.1'
hooks:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix, --unsafe-fixes ]
Expand Down Expand Up @@ -71,12 +71,12 @@ repos:
args: ["--ini", ".bandit", "--exclude", ".venv,tests,.rhiza/tests,.git,.pytest_cache"]

- repo: https://github.com/betterleaks/betterleaks
rev: v1.7.2
rev: v1.7.3
hooks:
- id: betterleaks

- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.12.0
rev: 0.12.1
hooks:
- id: uv-lock

Expand All @@ -88,7 +88,7 @@ repos:
files: ^src/

- repo: https://github.com/Jebel-Quant/rhiza-hooks
rev: v0.7.0 # Use the latest release
rev: v0.7.1 # Use the latest release
hooks:
# Migrated from rhiza
- id: check-rhiza-workflow-names
Expand All @@ -97,4 +97,9 @@ repos:
- id: check-rhiza-config
- id: check-makefile-targets
- id: check-python-version-consistency
# check-bumpversion-config asserts that bump-my-version can actually discover
# this repo's version config (issue #1453). Enable it once rhiza-hooks ships a
# release containing it — v0.7.1 does not. Until then .rhiza/tests/test_pyproject.py
# enforces the same invariant, one gate later.
# - id: check-bumpversion-config
# - id: check-template-bundles
62 changes: 0 additions & 62 deletions .rhiza/.cfg.toml

This file was deleted.

61 changes: 7 additions & 54 deletions .rhiza/make.d/bootstrap.mk
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
## .rhiza/make.d/bootstrap.mk - Bootstrap and Installation
# This file provides targets for setting up the development environment,
# installing dependencies, and cleaning project artifacts.
# This file provides the language-neutral half of setup: it puts uv/uvx on the
# path (rhiza runs pre-commit, mkdocs and semgrep through uvx whatever the
# project is written in), declares the install hooks, and cleans artifacts.
#
# `install` itself belongs to the language layer, because what it means differs:
# python.mk (bundle python-core) creates a virtualenv and runs `uv sync`.

# Declare phony targets (they don't produce files)
.PHONY: install-uv install clean pre-install post-install

UV_SYNC_ARGS ?= --all-extras --all-groups
.PHONY: install-uv clean pre-install post-install

# Hook targets (double-colon rules allow multiple definitions)
pre-install:: ; @:
Expand All @@ -29,55 +31,6 @@ install-uv: ## ensure uv/uvx is installed
fi; \
fi

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; }; \
fi; \
else \
printf "${YELLOW}[WARN] No pyproject.toml found, skipping install${RESET}\n"; \
fi

# Install pre-commit hooks (skip when core.hooksPath is set, e.g. by an
# external hook manager — pre-commit refuses to install in that case)
@if [ -f ".pre-commit-config.yaml" ]; then \
if [ -n "$$(git config --get core.hooksPath 2>/dev/null)" ]; then \
printf "${BLUE}[INFO] Skipping pre-commit hook install: core.hooksPath is set${RESET}\n"; \
else \
printf "${BLUE}[INFO] Installing pre-commit hooks...${RESET}\n"; \
${UVX_BIN} -p ${PYTHON_VERSION} pre-commit install || { printf "${YELLOW}[WARN] Failed to install pre-commit hooks${RESET}\n"; }; \
fi; \
fi

@$(MAKE) post-install

# Display success message with activation instructions
@printf "\n${GREEN}[SUCCESS] Installation complete!${RESET}\n\n"
@printf "${BLUE}To activate the virtual environment, run:${RESET}\n"
@printf "${YELLOW} source ${VENV}/bin/activate${RESET}\n\n"

clean: ## Clean project artifacts and stale local branches
@printf "%bCleaning project...%b\n" "$(BLUE)" "$(RESET)"

Expand Down
Loading