Skip to content
Merged

sync #229

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
9 changes: 7 additions & 2 deletions .github/workflows/rhiza_validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ on:
jobs:
validation:
runs-on: ubuntu-latest
# don't run this in rhiza itself. Rhiza has no template.yml file.
if: ${{ github.repository != 'jebel-quant/rhiza' }}
container:
image: ghcr.io/astral-sh/uv:0.9.30-bookworm

Expand All @@ -27,6 +25,13 @@ jobs:
token: ${{ secrets.GH_PAT }}

- name: Validate Rhiza config
# don't run this in rhiza itself. Rhiza has no template.yml file.
if: ${{ github.repository != 'jebel-quant/rhiza' }}
shell: bash
run: |
uvx "rhiza>=0.8.0" validate .

- name: Run Rhiza Tests
shell: bash
run: |
make rhiza-test
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ repos:
args: ["--skip", "B101", "--exclude", ".venv,tests,.rhiza/tests,.git,.pytest_cache", "-c", "pyproject.toml"]

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

Expand Down
5 changes: 5 additions & 0 deletions .rhiza/.cfg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ values = [
filename = "pyproject.toml"
search = 'version = "{current_version}"'
replace = 'version = "{new_version}"'

# [[tool.bumpversion.files]]
# filename = ".rhiza/template-bundles.yml"
# search = 'version: "{current_version}"'
# replace = 'version: "{new_version}"'
31 changes: 14 additions & 17 deletions .rhiza/history
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,17 @@
.rhiza/docs/CONFIG.md
.rhiza/docs/PRIVATE_PACKAGES.md
.rhiza/docs/TOKEN_SETUP.md
.rhiza/make.d/00-custom-env.mk
.rhiza/make.d/01-test.mk
.rhiza/make.d/02-book.mk
.rhiza/make.d/05-github.mk
.rhiza/make.d/06-agentic.mk
.rhiza/make.d/08-docs.mk
.rhiza/make.d/10-custom-task.mk
.rhiza/make.d/README.md
.rhiza/make.d/agentic.mk
.rhiza/make.d/book.mk
.rhiza/make.d/bootstrap.mk
.rhiza/make.d/custom-env.mk
.rhiza/make.d/custom-task.mk
.rhiza/make.d/docs.mk
.rhiza/make.d/github.mk
.rhiza/make.d/quality.mk
.rhiza/make.d/releasing.mk
.rhiza/make.d/test.mk
.rhiza/requirements/README.md
.rhiza/requirements/docs.txt
.rhiza/requirements/tests.txt
Expand All @@ -48,33 +51,27 @@
.rhiza/scripts/release.sh
.rhiza/templates/minibook/custom.html.jinja2
.rhiza/tests/README.md
.rhiza/tests/__init__.py
.rhiza/tests/api/__init__.py
.rhiza/tests/api/conftest.py
.rhiza/tests/api/test_github_targets.py
.rhiza/tests/api/test_makefile_api.py
.rhiza/tests/api/test_makefile_targets.py
.rhiza/tests/conftest.py
.rhiza/tests/deps/__init__.py
.rhiza/tests/deps/test_dependency_health.py
.rhiza/tests/integration/__init__.py
.rhiza/tests/integration/test_book_targets.py
.rhiza/tests/integration/test_lfs.py
.rhiza/tests/integration/test_marimushka.py
.rhiza/tests/integration/test_notebook_execution.py
.rhiza/tests/integration/test_release.py
.rhiza/tests/structure/__init__.py
.rhiza/tests/integration/test_test_mk.py
.rhiza/tests/structure/test_lfs_structure.py
.rhiza/tests/structure/test_project_layout.py
.rhiza/tests/structure/test_requirements.py
.rhiza/tests/sync/__init__.py
.rhiza/tests/sync/conftest.py
.rhiza/tests/sync/test_docstrings.py
.rhiza/tests/sync/test_readme_validation.py
.rhiza/tests/sync/test_rhiza_version.py
.rhiza/tests/utils/__init__.py
.rhiza/tests/utils/conftest.py
.rhiza/tests/test_utils.py
.rhiza/tests/utils/test_git_repo_fixture.py
.rhiza/tests/utils/test_version_matrix.py
.rhiza/utils/version_matrix.py
CODE_OF_CONDUCT.md
CONTRIBUTING.md
LICENSE
Expand Down
32 changes: 20 additions & 12 deletions .rhiza/make.d/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Makefile Cookbook

This directory (`.rhiza/make.d/`) is the designated place for **repository-specific build logic**. Any `.mk` file added here is automatically absorbed by the main Makefile.
This directory (`.rhiza/make.d/`) contains **template-managed build logic**. Files here are synced from the Rhiza template and should not be modified directly.

**For project-specific customizations, use your root `Makefile`** (before the `include .rhiza/rhiza.mk` line).

Use this cookbook to find copy-paste patterns for common development needs.

Expand All @@ -9,37 +11,43 @@ Use this cookbook to find copy-paste patterns for common development needs.
### 1. Add a Simple Task
**Goal**: Run a script with `make train-model`.

Create `.rhiza/make.d/50-model.mk`:
Add to your root `Makefile`:
```makefile
##@ Machine Learning
train: ## Train the model using local data
@echo "Training model..."
@uv run python scripts/train.py

# Include the Rhiza API (template-managed)
include .rhiza/rhiza.mk
```

### 2. Inject Code into Standard Workflows (Hooks)
**Goal**: Apply task after `make sync`.

Create `.rhiza/make.d/90-hooks.mk`:
Add to your root `Makefile`:
```makefile
post-sync::
@echo "Applying something..."
```
*Note: Use double-colons (`::`) for hooks to avoid conflicts.*
*Note: Use double-colons (`::`) for hooks to allow accumulation.*

### 3. Define Global Variables
**Goal**: Set a default timeout for all test runs.

Create `.rhiza/make.d/01-config.mk`:
Add to your root `Makefile` (before the include line):
```makefile
# Override default timeout (defaults to 60s)
export TEST_TIMEOUT := 120

# Include the Rhiza API (template-managed)
include .rhiza/rhiza.mk
```

### 4. Create a Private Shortcut
**Goal**: Create a command that only exists on my machine (not committed).

Do not use `.rhiza/make.d/`. Instead, create a `local.mk` in the project root:
Create a `local.mk` in the project root:
```makefile
deploy-dev:
@./scripts/deploy-to-my-sandbox.sh
Expand All @@ -48,7 +56,7 @@ deploy-dev:
### 5. Install System Dependencies
**Goal**: Ensure `graphviz` is installed for Marimo notebooks using a hook.

Create `.rhiza/make.d/20-dependencies.mk`:
Add to your root `Makefile`:
```makefile
pre-install::
@if ! command -v dot >/dev/null 2>&1; then \
Expand All @@ -68,13 +76,13 @@ pre-install::

## ℹ️ Reference

### Execution Order
Files are loaded alphabetically. We use numeric prefixes to ensure dependencies resolve correctly:
- `00-19`: Configuration & Variables
- `20-79`: Custom Tasks & Rules
- `80-99`: Hooks & Lifecycle logic
### File Organization
- **`.rhiza/make.d/`**: Template-managed files (do not edit)
- **Root `Makefile`**: Project-specific customizations (variables, hooks, custom targets)
- **`local.mk`**: Developer-local shortcuts (not committed)

### Available Hooks
Add these to your root `Makefile` using double-colon syntax (`::`):
- `pre-install` / `post-install`: Runs around `make install`.
- `pre-sync` / `post-sync`: Runs around repository synchronization.
- `pre-validate` / `post-validate`: Runs around validation checks.
Expand Down
11 changes: 4 additions & 7 deletions .rhiza/make.d/06-agentic.mk → .rhiza/make.d/agentic.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
.PHONY: install-copilot install-claude analyse-repo summarise-changes

COPILOT_BIN ?= $(shell command -v copilot 2>/dev/null || echo "$(INSTALL_DIR)/copilot")
CLAUDE_BIN ?= $(shell command -v claude 2>/dev/null || echo "$(INSTALL_DIR)/claude")
CLAUDE_BIN ?= $(shell command -v claude 2>/dev/null || echo "$(HOME)/.local/bin/claude")
DEFAULT_AI_MODEL ?= gpt-4.1

##@ Agentic Workflows
Expand Down Expand Up @@ -52,16 +52,13 @@ install-copilot: ## checks for copilot and prompts to install
install-claude: ## checks for claude and prompts to install
@if command -v claude >/dev/null 2>&1; then \
printf "${GREEN}[INFO] claude already installed in PATH, skipping install.${RESET}\n"; \
elif [ -x "${INSTALL_DIR}/claude" ]; then \
printf "${SUCCESS}[INFO] claude already installed in ${INSTALL_DIR}, skipping install.${RESET}\n"; \
else \
printf "${YELLOW}[WARN] Claude Code CLI not found in ${INSTALL_DIR}.${RESET}\n"; \
printf "${YELLOW}[WARN] Claude Code CLI not found in PATH.${RESET}\n"; \
printf "${BLUE}Do you want to install Claude Code CLI? [y/N] ${RESET}"; \
read -r response; \
if [ "$$response" = "y" ] || [ "$$response" = "Y" ]; then \
printf "${BLUE}[INFO] Installing Claude Code CLI to ${INSTALL_DIR}...${RESET}\n"; \
mkdir -p "${INSTALL_DIR}"; \
if curl -fsSL https://claude.ai/install.sh | CLAUDE_INSTALL_DIR="${INSTALL_DIR}" bash; then \
printf "${BLUE}[INFO] Installing Claude Code CLI to default location (~/.local/bin/claude)...${RESET}\n"; \
if curl -fsSL https://claude.ai/install.sh | bash; then \
printf "${GREEN}[INFO] Claude Code CLI installed successfully.${RESET}\n"; \
else \
printf "${RED}[ERROR] Failed to install Claude Code CLI.${RESET}\n"; \
Expand Down
2 changes: 1 addition & 1 deletion .rhiza/make.d/02-book.mk → .rhiza/make.d/book.mk
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ marimushka:: install-uv
fi

# Define a default no-op mkdocs-build target that will be used
# when .rhiza/make.d/08-docs.mk doesn't exist or doesn't define mkdocs-build
# when .rhiza/make.d/docs.mk doesn't exist or doesn't define mkdocs-build
mkdocs-build:: install-uv
@if [ ! -f "docs/mkdocs.yml" ]; then \
printf "${BLUE}[INFO] No mkdocs.yml found, skipping MkDocs${RESET}\n"; \
Expand Down
95 changes: 95 additions & 0 deletions .rhiza/make.d/bootstrap.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
## .rhiza/make.d/bootstrap.mk - Bootstrap and Installation
# This file provides targets for setting up the development environment,
# installing dependencies, and cleaning project artifacts.

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

# Hook targets (double-colon rules allow multiple definitions)
pre-install:: ; @:
post-install:: ; @:

##@ Bootstrap
install-uv: ## ensure uv/uvx is installed
# Ensure the ${INSTALL_DIR} folder exists
@mkdir -p ${INSTALL_DIR}

# Install uv/uvx only if they are not already present in PATH or in the install dir
@if command -v uv >/dev/null 2>&1 && command -v uvx >/dev/null 2>&1; then \
:; \
elif [ -x "${INSTALL_DIR}/uv" ] && [ -x "${INSTALL_DIR}/uvx" ]; then \
printf "${BLUE}[INFO] uv and uvx already installed in ${INSTALL_DIR}, skipping.${RESET}\n"; \
else \
printf "${BLUE}[INFO] Installing uv and uvx into ${INSTALL_DIR}...${RESET}\n"; \
if ! curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR="${INSTALL_DIR}" sh >/dev/null 2>&1; then \
printf "${RED}[ERROR] Failed to install uv${RESET}\n"; \
exit 1; \
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)
@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 --all-extras --all-groups --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 --all-extras || { 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 dev dependencies from .rhiza/requirements/*.txt files
@if [ -d ".rhiza/requirements" ] && ls .rhiza/requirements/*.txt >/dev/null 2>&1; then \
for req_file in .rhiza/requirements/*.txt; do \
if [ -f "$$req_file" ]; then \
printf "${BLUE}[INFO] Installing requirements from $$req_file${RESET}\n"; \
${UV_BIN} pip install -r "$$req_file" || { printf "${RED}[ERROR] Failed to install requirements from $$req_file${RESET}\n"; exit 1; }; \
fi; \
done; \
fi

# Check if there is requirements.txt file in the tests folder (legacy support)
@if [ -f "tests/requirements.txt" ]; then \
printf "${BLUE}[INFO] Installing requirements from tests/requirements.txt${RESET}\n"; \
${UV_BIN} pip install -r tests/requirements.txt || { printf "${RED}[ERROR] Failed to install test requirements${RESET}\n"; exit 1; }; \
fi
@$(MAKE) post-install

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

# Remove ignored files/directories, but keep .env files, tested with futures project
@git clean -d -X -f \
-e '!.env' \
-e '!.env.*'

# Remove build & test artifacts
@rm -rf \
dist \
build \
*.egg-info \
.coverage \
.pytest_cache \
.benchmarks

@printf "%bRemoving local branches with no remote counterpart...%b\n" "$(BLUE)" "$(RESET)"

@git fetch --prune

@git branch -vv | awk '/: gone]/{print $$1}' | xargs -r git branch -D
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## .rhiza/make.d/01-custom-env.mk - Custom Environment Configuration
## .rhiza/make.d/custom-env.mk - Custom Environment Configuration
# This file example shows how to set variables for the project.

# Custom variables for this repository
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## .rhiza/make.d/10-custom-task.mk - Custom Repository Tasks
## .rhiza/make.d/custom-task.mk - Custom Repository Tasks
# This file example shows how to add new targets.

.PHONY: hello-rhiza
Expand Down
File renamed without changes.
File renamed without changes.
27 changes: 27 additions & 0 deletions .rhiza/make.d/quality.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## .rhiza/make.d/quality.mk - Quality and Formatting
# This file provides targets for code quality checks, linting, and formatting.

# Declare phony targets (they don't produce files)
.PHONY: deptry fmt mypy

##@ Quality and Formatting
deptry: install-uv ## Run deptry
@if [ -d ${SOURCE_FOLDER} ]; then \
$(UVX_BIN) -p ${PYTHON_VERSION} deptry ${SOURCE_FOLDER}; \
fi

@if [ -d ${MARIMO_FOLDER} ]; then \
if [ -d ${SOURCE_FOLDER} ]; then \
$(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} ${SOURCE_FOLDER} --ignore DEP004; \
else \
$(UVX_BIN) -p ${PYTHON_VERSION} deptry ${MARIMO_FOLDER} --ignore DEP004; \
fi \
fi

fmt: install-uv ## check the pre-commit hooks and the linting
@${UVX_BIN} -p ${PYTHON_VERSION} pre-commit run --all-files

mypy: install ## run mypy analysis
@if [ -d ${SOURCE_FOLDER} ]; then \
${UV_BIN} run mypy ${SOURCE_FOLDER} --strict --config-file=pyproject.toml; \
fi
27 changes: 27 additions & 0 deletions .rhiza/make.d/releasing.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## .rhiza/make.d/releasing.mk - Releasing and Versioning
# This file provides targets for version bumping and release management.

# Declare phony targets (they don't produce files)
.PHONY: bump release pre-bump post-bump pre-release post-release

# Hook targets (double-colon rules allow multiple definitions)
pre-bump:: ; @:
post-bump:: ; @:
pre-release:: ; @:
post-release:: ; @:

##@ Releasing and Versioning
bump: pre-bump ## bump version
@if [ -f "pyproject.toml" ]; then \
$(MAKE) install; \
${UVX_BIN} "rhiza[tools]>=0.8.6" tools bump; \
printf "${BLUE}[INFO] Updating uv.lock file...${RESET}\n"; \
${UV_BIN} lock; \
else \
printf "${YELLOW}[WARN] No pyproject.toml found, skipping bump${RESET}\n"; \
fi
@$(MAKE) post-bump

release: pre-release install-uv ## create tag and push to remote with prompts
@UV_BIN="${UV_BIN}" /bin/sh ".rhiza/scripts/release.sh"
@$(MAKE) post-release
Loading