From b9cffd52b8741f61de561944041cb25ec27958ed Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Tue, 31 Mar 2026 10:18:14 +0400 Subject: [PATCH 01/30] refactor: move .semgrep.yml to .rhiza/semgrep.yml Co-Authored-By: Claude Sonnet 4.6 --- .semgrep.yml => .rhiza/semgrep.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .semgrep.yml => .rhiza/semgrep.yml (100%) diff --git a/.semgrep.yml b/.rhiza/semgrep.yml similarity index 100% rename from .semgrep.yml rename to .rhiza/semgrep.yml From 5e39cfa68a68f627c64e9a4bd7470392b60c46ce Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Tue, 31 Mar 2026 10:20:37 +0400 Subject: [PATCH 02/30] feat: add paper, presentations, and devcontainer docs from main Co-Authored-By: Claude Sonnet 4.6 --- .devcontainer/README.md | 8 + docs/paper/rhiza.tex | 338 +++++++++++++++++++++++++++++++++++ docs/presentations/README.md | 9 + 3 files changed, 355 insertions(+) create mode 100644 .devcontainer/README.md create mode 100644 docs/paper/rhiza.tex create mode 100644 docs/presentations/README.md diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 00000000..57b76c88 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,8 @@ +# Dev Container + +VS Code Dev Container configuration for Rhiza. + +- **`devcontainer.json`** — container definition, extensions, and VS Code settings +- **`bootstrap.sh`** — post-create setup script + +Open in VS Code and select **Reopen in Container**, or use [GitHub Codespaces](https://codespaces.new/jebel-quant/rhiza). diff --git a/docs/paper/rhiza.tex b/docs/paper/rhiza.tex new file mode 100644 index 00000000..43c4c8fe --- /dev/null +++ b/docs/paper/rhiza.tex @@ -0,0 +1,338 @@ +\documentclass[12pt,a4paper]{article} + +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage[margin=2.5cm]{geometry} +\usepackage{hyperref} +\usepackage{microtype} +\usepackage{booktabs} +\usepackage{listings} +\usepackage{xcolor} +\usepackage{graphicx} +\usepackage{enumitem} +\usepackage{amsmath} +\usepackage{cite} +\usepackage{titlesec} +\usepackage{abstract} + +\hypersetup{ + colorlinks=true, + linkcolor=blue!60!black, + citecolor=green!50!black, + urlcolor=blue!70!black, +} + +\lstdefinestyle{yaml}{ + language=, + basicstyle=\ttfamily\small, + keywordstyle=\color{blue}, + commentstyle=\color{gray}, + stringstyle=\color{orange!80!black}, + breaklines=true, + frame=single, + rulecolor=\color{gray!40}, + backgroundcolor=\color{gray!5}, + captionpos=b, +} + +\lstdefinestyle{bash}{ + language=bash, + basicstyle=\ttfamily\small, + keywordstyle=\color{blue}, + commentstyle=\color{gray}, + breaklines=true, + frame=single, + rulecolor=\color{gray!40}, + backgroundcolor=\color{gray!5}, + captionpos=b, +} + +\title{\textbf{Rhiza: A Living-Template System for Sustainable Python Project Infrastructure}} + +\author{ + Thomas Schmelzer\\ + \texttt{tschmelzer@jqr.io} + \and + Harry Campion + \and + Mark Richardson +} + +\date{March 2026} + +\begin{document} + +\maketitle + +\begin{abstract} +Software projects accumulate infrastructure debt: continuous-integration pipelines age out of date, linting rules diverge from community standards, and hard-won configuration improvements never propagate from the project that discovered them to its siblings. Ad-hoc fixes compound this drift without a systematic remedy. We present \textbf{Rhiza}---from the Greek \textit{rhiza}, ``root''---a living-template system for Python projects that decouples the \emph{content} of best-practice infrastructure from the \emph{mechanism} that applies it. Unlike one-time project generators such as Cookiecutter or Copier, Rhiza provides templates that continue to evolve and that downstream projects can pull in selectively at any time. The system is structured around three key abstractions: (i)~a versioned template repository that acts as the authoritative source of curated infrastructure files; (ii)~a lightweight CLI that fetches and merges those files; and (iii)~a modular bundle system that lets teams opt into exactly the features they need. We describe the design rationale, the architectural decisions that guide the implementation, and the operational experience accumulated across more than twenty downstream projects. +\end{abstract} + +\tableofcontents +\newpage + +% ───────────────────────────────────────────────────────────────────────────── +\section{Introduction} +\label{sec:intro} +% ───────────────────────────────────────────────────────────────────────────── + +Every serious Python project carries with it a hidden second project: the infrastructure that makes the first one possible. Continuous-integration pipelines, linting and formatting rules, reproducible environment specifications, pre-commit hooks, security scanners, documentation generators, and Makefile-based development workflows are not incidental---they are the scaffolding on which reliable, maintainable software is built. Yet this scaffolding is almost universally treated as an afterthought. + +The typical lifecycle of project infrastructure proceeds as follows. At project creation, a developer copies configuration files from a previous project, consults a blog post, or runs a scaffold tool. The resulting configuration is reasonable for that moment in time. Over months and years, however, the ecosystem moves on: the linter gains new rules, the CI service deprecates old syntax, the recommended Python version changes, a new security vulnerability scanner emerges. The infrastructure falls behind. Keeping it current requires manual effort that no one formally owns, so it rarely happens. The result is configuration drift: each project in an organization diverges from the others and from current best practice, with the gap widening over time. + +\textbf{Rhiza} is a response to this problem. Its core thesis is that project infrastructure should be treated as a versioned, updatable artifact---a dependency to be upgraded, not a one-off scaffold to be generated and forgotten. This is not a novel observation; the DevOps and infrastructure-as-code communities have long advocated for treating infrastructure with the same discipline applied to application code~\cite{humble2010continuous,fowler2016infrastructure}. What Rhiza contributes is a concrete, opinionated, Python-centric implementation of this philosophy that is lightweight enough for individual developers and teams to adopt without changing their existing workflows. + +The name reflects the ambition: just as a root system sustains a plant by continuously supplying water and nutrients, Rhiza aims to continuously supply modern, well-maintained infrastructure to the projects built on top of it. + +% ───────────────────────────────────────────────────────────────────────────── +\section{Background and Motivation} +\label{sec:motivation} +% ───────────────────────────────────────────────────────────────────────────── + +\subsection{The Configuration-Drift Problem} + +Configuration drift in software projects is an instance of the broader problem of \emph{technical debt}~\cite{cunningham1992wycash}. Unlike functional technical debt---code that works but is hard to change---infrastructure debt is often invisible: the tests still pass, the CI pipeline still runs, and no immediate failure signals a problem. The harm materialises gradually: security vulnerabilities go undetected, formatting inconsistencies slow code review, and onboarding new contributors takes longer because each project has idiosyncratic conventions. + +Organisations that maintain many Python projects---research groups, consultancies, open-source umbrella projects---feel this cost acutely. A configuration improvement discovered in one project must be manually propagated to each other project. If there are ten projects, the propagation cost is multiplied by ten; if there are fifty, the improvement often simply does not propagate at all. + +\subsection{Existing Approaches and Their Limitations} + +Several tools exist to help with project scaffolding: + +\paragraph{Cookiecutter~\cite{cookiecutter}.} Cookiecutter generates a project directory from a Jinja2 template. It solves the \emph{initialisation} problem well but provides no mechanism for synchronising improvements after the initial generation. Once a project is created, it is on its own. + +\paragraph{Copier~\cite{copier}.} Copier addresses the synchronisation gap with an \texttt{update} command that re-applies a template to an existing project. This is a significant advance. However, Copier's update model applies the entire template wholesale, relying on three-way merges to preserve local customisations. This works well for simple files but can produce conflicts for complex, structured files such as CI workflow YAML or modular Makefiles. Additionally, Copier requires projects to opt into its update mechanism from the start, and the learning curve for resolving update conflicts can be steep. + +\paragraph{cruft~\cite{cruft}.} cruft adds a Cookiecutter-update workflow via a stored diff approach. It shares Cookiecutter's all-or-nothing update semantics and inherits its limitations. + +\paragraph{Template repositories on GitHub.} Many organisations maintain ``template'' repositories that new projects are forked from. This solves initialisation but creates a permanently diverging fork: there is no built-in mechanism to pull upstream changes into child repositories. + +\paragraph{Internal tooling.} Large engineering organisations sometimes build bespoke internal tools that enforce a standard project layout. These tools solve the problem well within one organisation but are expensive to build, not shared across the community, and often not maintained long-term. + +\subsection{The Need for Living Templates} + +The common limitation of the above approaches is that they treat project infrastructure as a \emph{point-in-time} artefact rather than a \emph{continuous} one. Rhiza takes the opposite position: infrastructure files should be versioned, tagged, and upgraded in much the same way that library dependencies are. A project's \texttt{.rhiza/template.yml} file specifies which version of the Rhiza template to use, analogously to how \texttt{pyproject.toml} specifies which version of a library to install. Upgrading is a deliberate act, but it is easy, reversible, and incremental. + +% ───────────────────────────────────────────────────────────────────────────── +\section{System Design} +\label{sec:design} +% ───────────────────────────────────────────────────────────────────────────── + +\subsection{Architectural Overview} + +Rhiza is deliberately split into two independent components (ADR-0005): + +\begin{enumerate}[leftmargin=*] + \item \textbf{The template repository} (\texttt{jebel-quant/rhiza} on GitHub) is the authoritative source of curated infrastructure files. It is versioned with Git tags and contains the actual content that downstream projects consume. + + \item \textbf{The CLI} (\texttt{rhiza} on PyPI) is the engine that fetches files from the template repository and applies them to a downstream project. It is a separate Python package with its own independent release cadence. +\end{enumerate} + +Separating these concerns means that the CLI can be improved---bug fixes, new commands, better conflict resolution---without forcing downstream projects to adopt new template content, and vice versa. It also means that organisations can fork the template repository and maintain their own curated variant while continuing to use the standard CLI. + +\subsection{Template Bundles} +\label{sec:bundles} + +A naive template system maps every file in the template repository to a file in the downstream project. This all-or-nothing approach quickly breaks down: a project that does not use Docker should not receive Docker configuration; a project that is not hosted on GitHub should not receive GitHub Actions workflows. + +Rhiza addresses this with \emph{template bundles} (ADR-0006): named, coarse-grained groups of related files. The bundles defined in \texttt{.rhiza/template-bundles.yml} include: + +\begin{table}[h] +\centering +\begin{tabular}{lp{9cm}} +\toprule +\textbf{Bundle} & \textbf{Contents} \\ +\midrule +\texttt{core} & Makefile infrastructure, \texttt{pyproject.toml} skeleton, \texttt{.python-version}, \texttt{uv.lock} patterns \\ +\texttt{tests} & pytest configuration, coverage settings, property-based testing scaffold \\ +\texttt{github} & GitHub Actions workflows (CI, lint, security, release, sync, docs) \\ +\texttt{gitlab} & GitLab CI equivalent with feature parity \\ +\texttt{docker} & Dockerfile templates, \texttt{.dockerignore}, container Makefile module \\ +\texttt{book} & MkDocs configuration, documentation structure, coverage badges \\ +\texttt{marimo} & Marimo notebook scaffold, interactive documentation setup \\ +\texttt{pre-commit} & \texttt{.pre-commit-config.yaml} wired to ruff, black, and isort \\ +\bottomrule +\end{tabular} +\caption{Selected Rhiza template bundles.} +\label{tab:bundles} +\end{table} + +Dependencies between bundles are declared explicitly. For example, the \texttt{book} bundle requires \texttt{tests} because the documentation site includes auto-generated coverage reports. The CLI enforces these constraints at initialisation and sync time, preventing invalid combinations. + +A downstream project declares the bundles it uses in \texttt{.rhiza/template.yml}: + +\begin{lstlisting}[style=yaml, caption={Example \texttt{.rhiza/template.yml}.}] +repository: jebel-quant/rhiza +ref: v0.8.16 +templates: + - core + - tests + - github + - docker +\end{lstlisting} + +\subsection{Modular Makefile Architecture} +\label{sec:makefile} + +A single monolithic Makefile is a maintenance burden: it is hard to read, harder to extend without conflicts, and impossible to selectively update. Rhiza adopts a three-layer architecture (ADR-0004): + +\begin{enumerate}[leftmargin=*] + \item \textbf{Root \texttt{Makefile}} (nine lines): owned by the downstream project, this file simply includes the Rhiza core. + \item \textbf{\texttt{.rhiza/rhiza.mk}}: the template-managed core. It auto-includes all files matching \texttt{.rhiza/make.d/*.mk} using a glob pattern. + \item \textbf{\texttt{.rhiza/make.d/*.mk}}: one file per feature area, named with numeric prefixes to control load order. Prefixes \texttt{00}--\texttt{19} define configuration variables; \texttt{20}--\texttt{79} define task targets; \texttt{80}--\texttt{99} define hooks. +\end{enumerate} + +Feature modules include \texttt{bootstrap.mk} (environment setup), \texttt{quality.mk} (linting, formatting), \texttt{test.mk} (pytest), \texttt{docs.mk} (MkDocs), \texttt{github.mk} (GitHub CLI helpers), \texttt{docker.mk} (container builds), and \texttt{marimo.mk} (notebook server). Targets use GNU Make's double-colon syntax (\texttt{::}) where appropriate, which allows pre-hook and post-hook targets in separate files to extend a task without modifying the file that defines it. Developers who need project-local shortcuts that should not be committed can place them in \texttt{local.mk}, which is listed in \texttt{.gitignore} by default. + +This architecture provides more than forty documented \texttt{make} targets, all discoverable via \texttt{make help}. + +\subsection{Reproducible Environments with \texttt{uv}} + +A template system that mandates outdated or slow tooling will not be adopted. Rhiza standardises on \texttt{uv}~\cite{uv}---Astral's unified Python version and package manager---for all environment management (ADR-0002). The decision was driven by three considerations: + +\begin{enumerate}[leftmargin=*] + \item \textbf{Single binary}: \texttt{uv} is distributed as a self-contained binary. Installing it does not require Python to be present, which simplifies bootstrapping on CI runners and developer machines alike. + \item \textbf{Speed}: \texttt{uv} resolves and installs packages 10--100$\times$ faster than \texttt{pip}, which meaningfully reduces CI wait times on projects with large dependency trees. + \item \textbf{Lock file}: \texttt{uv.lock} pins the entire transitive dependency graph, ensuring that every environment---local, CI, production---is identical. +\end{enumerate} + +The \texttt{.python-version} file, automatically read by \texttt{uv}, pins the Python interpreter version. Together these two files are the minimal, complete specification of a reproducible Python environment. + +\subsection{Continuous Quality Enforcement} + +Rhiza integrates a layered quality stack that operates at multiple stages of the development cycle: + +\paragraph{Pre-commit hooks.} The \texttt{pre-commit} bundle installs hooks that run \texttt{ruff} for linting and formatting, catching issues before they enter the repository. + +\paragraph{CI pipelines.} The \texttt{github} and \texttt{gitlab} bundles provide workflows that run on every pull request: unit tests across Python 3.11--3.14, type checking with \texttt{ty}, dependency validation with \texttt{deptry}, security scanning with \texttt{pip-audit} and \texttt{bandit}, and static analysis with \texttt{semgrep}. + +\paragraph{Automated dependency updates.} A Renovate configuration file, included in the \texttt{core} bundle, opens pull requests whenever a pinned dependency or the \texttt{ref} in \texttt{.rhiza/template.yml} is updated upstream. This closes the loop: Rhiza itself is treated as a dependency that can be automatically proposed for upgrade. + +\subsection{Agentic Workflow Integration} + +A distinguishing feature of recent Rhiza releases is first-class integration with AI coding assistants. The \texttt{github} bundle includes GitHub Actions workflow files that invoke Claude Code~\cite{claudecode} (or optionally GitHub Copilot) for tasks such as: + +\begin{itemize} + \item \textbf{\texttt{analyse-repo}}: produces a structured report of recent changes, open issues, and technical debt. + \item \textbf{\texttt{copilot}}: runs an AI agent on a specified task file, committing the result back to the branch. + \item \textbf{\texttt{summarise-changes}}: generates human-readable release notes from the git log. +\end{itemize} + +These workflows treat AI agents as first-class CI participants: they are triggered by GitHub Actions events, receive a clean environment, and produce reviewable pull-request diffs. This integration reflects the view that AI-assisted development is increasingly part of the standard software engineering toolkit and should be configured consistently across projects. + +% ───────────────────────────────────────────────────────────────────────────── +\section{Operational Experience} +\label{sec:experience} +% ───────────────────────────────────────────────────────────────────────────── + +\subsection{Downstream Adoption} + +Rhiza has been applied to more than twenty Python projects spanning quantitative finance libraries, data-pipeline tools, and developer-tooling packages. Across these projects, the mean time to adopt a new infrastructure improvement---for example, upgrading to a new Python version or enabling a new \texttt{ruff} lint rule---has fallen from several weeks to typically one or two days: the time needed for Renovate to open a PR against the Rhiza template repository and for each downstream project to rebase against the new tag. + +\subsection{Conflict Resolution in Practice} + +The most common source of friction in living-template systems is merge conflicts when a project has customised a file that the template also manages. Rhiza mitigates this in several ways: + +\begin{enumerate}[leftmargin=*] + \item \textbf{Bundle granularity.} By grouping files into coarse bundles, Rhiza reduces the frequency with which any given downstream file is touched by an upstream update. + \item \textbf{Makefile hooks.} Downstream projects that need to extend a Makefile target can do so by adding a \texttt{::} target in \texttt{local.mk} rather than modifying the managed file. The managed file can therefore be updated freely. + \item \textbf{Configuration delegation.} Where possible, tool configuration is placed in \texttt{pyproject.toml} (owned by the downstream project) rather than in separate managed files. The template provides a commented scaffold section; the downstream project fills it in. +\end{enumerate} + +\subsection{Architecture Decision Records} + +All non-trivial design decisions in Rhiza are recorded as Architecture Decision Records~\cite{nygard2011adr} in \texttt{docs/adr/}. This practice serves two purposes. First, it provides newcomers with the \emph{reasoning} behind choices, not just the choices themselves---critical for understanding why, say, \texttt{uv} was chosen over \texttt{poetry} or why the CLI and template repository are separate packages. Second, it creates a structured audit trail that makes revisiting decisions easier when the context changes. + +Nine ADRs have been recorded to date, covering: the use of ADRs themselves (ADR-0001), adoption of \texttt{uv} (ADR-0002), CI platform choices (ADR-0003), the modular Makefile architecture (ADR-0004), separation of template from CLI (ADR-0005), the bundle system (ADR-0006), dual GitHub/GitLab support (ADR-0007), Marimo integration (ADR-0008), and pre-commit hook strategy (ADR-0009). + +% ───────────────────────────────────────────────────────────────────────────── +\section{Related Work} +\label{sec:related} +% ───────────────────────────────────────────────────────────────────────────── + +Rhiza sits at the intersection of several research and engineering topics: + +\paragraph{Infrastructure as Code.} The IaC movement~\cite{humble2010continuous} established that infrastructure should be version-controlled, peer-reviewed, and automatically applied. Rhiza applies this principle to the layer \emph{below} application infrastructure: the configuration files and tooling that enable developers to write and test application code. + +\paragraph{Convention over configuration.} Ruby on Rails~\cite{rails} popularised the principle that opinionated defaults reduce cognitive overhead. Rhiza's template bundles encode opinionated defaults for Python projects, with the expectation that most projects will use them as-is and only override where genuinely necessary. + +\paragraph{Package managers and dependency pinning.} The reproducibility guarantees that Nix~\cite{dolstra2004nix}, Cargo, and modern Python tools like \texttt{uv} provide for application dependencies are extended by Rhiza to infrastructure configuration: the \texttt{ref} field in \texttt{template.yml} pins the exact version of infrastructure used, making environments reproducible not just in terms of library versions but also in terms of development tooling. + +\paragraph{Polyglot monorepos.} Organisations using monorepos (e.g.,~\cite{potvin2016google}) face a similar challenge: keeping build and CI configuration consistent across many packages. Rhiza offers a lighter-weight alternative for organisations that prefer independent repositories. + +% ───────────────────────────────────────────────────────────────────────────── +\section{Future Directions} +\label{sec:future} +% ───────────────────────────────────────────────────────────────────────────── + +The Rhiza roadmap identifies several directions for future work: + +\paragraph{Finer-grained synchronisation.} The current sync model operates at the bundle level. Future work will explore file-level and section-level synchronisation, enabling, for example, the update of a single GitHub Actions job within a larger workflow file without touching the rest of the file. + +\paragraph{Validation tooling.} A \texttt{rhiza validate} command currently checks that a project's \texttt{template.yml} is consistent with the files on disk. Expanding this to a full compliance report---identifying files that have drifted from the template---would help teams understand the cost of deferred upgrades. + +\paragraph{Multi-language support.} The core abstractions (versioned templates, named bundles, modular task files) are language-agnostic. Extending Rhiza to support TypeScript and Rust projects would broaden its applicability without requiring fundamental architectural changes. + +\paragraph{Community bundle registry.} Currently, all bundles live in the canonical Rhiza repository. A community registry would allow third parties to publish bundles---for example, a bundle for a particular cloud provider's deployment tooling---that can be mixed in alongside the core set. + +% ───────────────────────────────────────────────────────────────────────────── +\section{Conclusion} +\label{sec:conclusion} +% ───────────────────────────────────────────────────────────────────────────── + +Software infrastructure is not a one-time concern. It requires the same ongoing investment as the application code it supports, yet most organisations lack the tooling to make that investment systematically rather than heroically. Rhiza addresses this gap with a living-template system that treats infrastructure configuration as a versioned, upgradeable dependency. Its key contributions are: + +\begin{enumerate}[leftmargin=*] + \item A two-component architecture that separates template content from the sync mechanism, enabling independent evolution of each. + \item A named bundle system that provides coarse-grained, dependency-aware feature selection. + \item A modular Makefile architecture with hook points that accommodate local customisation without preventing template updates. + \item First-class integration with modern Python tooling (\texttt{uv}, \texttt{ruff}, \texttt{pre-commit}, Marimo) and AI-assisted development workflows. + \item A documented, ADR-driven design process that makes the system's rationale transparent and revisable. +\end{enumerate} + +Rhiza is open source under the MIT licence. The template repository is available at \url{https://github.com/jebel-quant/rhiza} and the CLI is installable via \texttt{uvx rhiza}. + +% ───────────────────────────────────────────────────────────────────────────── +\bibliographystyle{plain} +\begin{thebibliography}{99} + +\bibitem{humble2010continuous} +J.~Humble and D.~Farley, \textit{Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation}. Addison-Wesley, 2010. + +\bibitem{fowler2016infrastructure} +K.~Morris, \textit{Infrastructure as Code: Managing Servers in the Cloud}. O'Reilly Media, 2016. + +\bibitem{cunningham1992wycash} +W.~Cunningham, ``The WyCash portfolio management system,'' in \textit{Proc. ACM OOPSLA}, 1992. + +\bibitem{cookiecutter} +A.~Roy, D.~Greenfeld, et al., ``Cookiecutter,'' \url{https://cookiecutter.readthedocs.io}, 2013--. + +\bibitem{copier} +J.~M.~Macías et al., ``Copier,'' \url{https://copier.readthedocs.io}, 2019--. + +\bibitem{cruft} +S.~Kothari et al., ``cruft,'' \url{https://cruft.github.io/cruft}, 2019--. + +\bibitem{uv} +Astral, ``uv: An extremely fast Python package and project manager,'' \url{https://docs.astral.sh/uv}, 2024--. + +\bibitem{claudecode} +Anthropic, ``Claude Code: Agentic coding in the terminal,'' \url{https://claude.ai/code}, 2025--. + +\bibitem{nygard2011adr} +M.~T.~Nygard, ``Documenting architecture decisions,'' \url{https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions}, 2011. + +\bibitem{rails} +D.~H.~Hansson, ``Ruby on Rails,'' \url{https://rubyonrails.org}, 2004--. + +\bibitem{dolstra2004nix} +E.~Dolstra, M.~de Jonge, and E.~Visser, ``Nix: A safe and policy-free system for software deployment,'' in \textit{Proc. LISA}, 2004. + +\bibitem{potvin2016google} +R.~Potvin and J.~Levenberg, ``Why Google stores billions of lines of code in a single repository,'' \textit{Communications of the ACM}, vol.~59, no.~7, pp.~78--87, 2016. + +\end{thebibliography} + +\end{document} diff --git a/docs/presentations/README.md b/docs/presentations/README.md new file mode 100644 index 00000000..b57cd7bc --- /dev/null +++ b/docs/presentations/README.md @@ -0,0 +1,9 @@ +# Presentation + +Presentation slides built with [Marp](https://marp.app/) from `PRESENTATION.md`. + +```bash +make presentation # Generate HTML slides +make presentation-pdf # Generate PDF slides +make presentation-serve # Serve with live reload +``` From 9dd75fd5e39a03d8f1b24f550936c906ac971c9f Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Tue, 31 Mar 2026 10:21:45 +0400 Subject: [PATCH 03/30] chore: delete REPOSITORY_ANALYSIS.md Co-Authored-By: Claude Sonnet 4.6 --- REPOSITORY_ANALYSIS.md | 63 ------------------------------------------ 1 file changed, 63 deletions(-) delete mode 100644 REPOSITORY_ANALYSIS.md diff --git a/REPOSITORY_ANALYSIS.md b/REPOSITORY_ANALYSIS.md deleted file mode 100644 index 255ac2bb..00000000 --- a/REPOSITORY_ANALYSIS.md +++ /dev/null @@ -1,63 +0,0 @@ -# Repository Analysis Journal - -This document contains dated architectural and technical reviews of the rhiza repository. - ---- - -## 2026-03-10 — Analysis Entry - -### Summary -Rhiza is a **living template framework** for Python projects, providing synchronizable configuration templates via Make-based automation. The repository is **mature and well-engineered**, with comprehensive CI/CD (20 workflows), extensive documentation (7200+ lines across 22 MD files), modular Makefile architecture (18 `.mk` modules), and 29 test files organized into 7 categories. Version 0.8.7 represents a stable foundation with active development (826+ commits). The project demonstrates strong DevOps practices, clear separation of concerns, and thoughtful extensibility mechanisms. - -### Strengths - -- **Modular Architecture**: Clean separation via `.rhiza/make.d/*.mk` modules (18 files: bootstrap.mk, test.mk, github.mk, etc.) allows incremental feature adoption without coupling -- **Comprehensive Testing**: 29 test files across 7 categories (structure, api, integration, sync, deps, stress, utils) with clear separation between static validation and subprocess-based integration tests -- **Rich Documentation**: 22 markdown files (ARCHITECTURE.md, TECHNICAL_DEBT.md, TESTS.md, etc.) provide deep context; TECHNICAL_DEBT.md tracks 11 known issues with priority/effort estimates -- **Bundle System**: `template-bundles.yml` defines 13 semantic bundles (core, github, tests, marimo, book, docker, devcontainer, etc.) with dependency declarations, enabling composable project setups -- **Multi-Platform CI**: Full feature parity across GitHub Actions (16 workflows) and GitLab CI (8 workflows in `.gitlab/`), demonstrating platform independence -- **Hooks & Extensibility**: Double-colon Make targets (`pre-install::`, `post-sync::`) enable safe downstream customization without breaking template sync -- **Zero Runtime Dependencies**: `pyproject.toml` declares `dependencies = []`, making this a pure configuration/tooling framework -- **Automated Quality Gates**: `.github/hooks/session-{start,end}.sh` enforce environment validation and quality checks for GitHub Copilot sessions -- **Agentic Workflows**: Early adoption of GitHub Agentic Workflows with 3 starter templates (daily-repo-status, ci-doctor, issue-triage) and validation workflow -- **Renovate Integration**: Sophisticated `renovate.json` with custom regex managers for template versioning, enabling automated updates of `ref:` field in downstream projects -- **Version Matrix Testing**: Dynamic Python version matrix generation from `pyproject.toml` classifiers (3.11-3.14) in CI workflow - -### Weaknesses - -- **No Source Code**: Project contains templates and tests but **no `src/` directory** — legitimate for a template repo, but reduces code coverage meaningfulness (coverage tracks test execution, not template usage) -- **Test Execution Blocked**: `make test` fails with "Permission denied and could not request permission from user" — indicates environment issue or permission constraints during analysis -- **Missing Lock Files**: No `.lock.yml` files found despite gh-aw workflows (adr-create.md, ci-doctor.md) existing — suggests workflows not yet compiled or feature incomplete -- **Python Version Mismatch**: `.python-version` specifies `3.12`, but `pyproject.toml` claims support for 3.11-3.14 — actual runtime untested on non-3.12 versions in this environment -- **No Scripts Directory**: `.rhiza/scripts/` is empty except `__pycache__` — suggests migration away from scripts to Make targets, but may leave dead references -- **Roadmap Staleness**: ROADMAP.md references "Current Version: 0.8.1-rc.2" but `pyproject.toml` shows `0.8.7` — documentation lags reality by ~6 minor versions -- **Bootstrap Documentation Gap**: `.devcontainer/bootstrap.sh` referenced in custom instructions but not verified to exist in repository scan -- **No Benchmark Results**: `tests/benchmarks/` exists but no committed baseline results visible — performance regression detection requires manual interpretation -- **Template Validation Incomplete**: TECHNICAL_DEBT.md item #8 acknowledges "Limited validation of custom templates before sync" as medium-priority debt - -### Risks / Technical Debt - -- **Conflict Resolution**: TECHNICAL_DEBT.md item #1 (Critical) — Manual 3-way merge required when template updates conflict with local changes; no automatic resolution strategy -- **Performance at Scale**: Item #3 (High) — Sync operations slow for large repos; no incremental sync or caching layer implemented -- **Test Coverage Gap**: Item #2 (High) — "Limited test coverage for template synchronization edge cases" — core functionality undertested despite 29 test files -- **Complexity Growth**: 20 GitHub workflows (2056 total lines) + 18 Makefile modules creates high cognitive load for contributors; no architectural diagrams beyond docs/ARCHITECTURE.md -- **gh-aw Maturity**: Agentic workflows (adr-create.md, ci-doctor.md, issue-triage.md) lack `.lock.yml` counterparts — feature may be experimental/incomplete -- **Dependency Upper Bounds**: TECHNICAL_DEBT.md item #7 notes some dependencies lack upper bounds (e.g., `marimo>=0.18.0,<1.0` is good, but pattern not universal) -- **Private Package Assumption**: `.github/actions/configure-git-auth` and `UV_EXTRA_INDEX_URL` secret suggest reliance on private PyPI packages — may break in forks or public use -- **Hook Documentation Scattered**: Hooks mentioned in Makefile, docs/ARCHITECTURE.md, and `.rhiza/make.d/README.md` but no single source of truth for all available hooks -- **No Public Release Artifacts**: Classifier "Private :: Do Not Upload" prevents PyPI publication — downstream adoption requires git-based sync, increasing coupling - -### Score - -**8/10** — Solid, production-grade template framework with minor maintenance gaps. - -**Rationale**: -- **+3**: Excellent modular architecture, comprehensive documentation, extensibility design -- **+2**: Strong CI/CD coverage (multi-platform, matrix testing), automated quality gates -- **+2**: Thoughtful DevOps practices (Renovate, session hooks, bundle system) -- **+1**: Active development (recent commits), transparent technical debt tracking -- **-1**: Test execution issues, missing lock files, documentation staleness -- **-1**: No actual source code to validate claims (legitimate for templates, but reduces verifiability) - -**Context**: This is a **configuration/template repository**, not a library. Scoring adjusted for domain — it excels at what it aims to be (a living template system), but lacks traditional library artifacts (src/, published packages, API docs). - From c6da3c68e170a4e19d2723da24385d7a3a5b43d3 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Tue, 31 Mar 2026 10:22:43 +0400 Subject: [PATCH 04/30] refactor: consolidate CI workflows from main Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/rhiza_deptry.yml | 48 ---------- .github/workflows/rhiza_license.yml | 45 --------- .github/workflows/rhiza_paper.yml | 108 +++++++++++++++++++++ .github/workflows/rhiza_pip_audit.yml | 25 ----- .github/workflows/rhiza_pre-commit.yml | 52 ---------- .github/workflows/rhiza_quality.yml | 100 +++++++++++++++++++ .github/workflows/rhiza_release.yml | 14 ++- .github/workflows/rhiza_security.yml | 46 --------- .github/workflows/rhiza_semgrep.yml | 48 ---------- .github/workflows/rhiza_typecheck.yml | 50 ---------- .github/workflows/rhiza_validate.yml | 128 ++++++++++++++++++++++++- 11 files changed, 347 insertions(+), 317 deletions(-) delete mode 100644 .github/workflows/rhiza_deptry.yml delete mode 100644 .github/workflows/rhiza_license.yml create mode 100644 .github/workflows/rhiza_paper.yml delete mode 100644 .github/workflows/rhiza_pip_audit.yml delete mode 100644 .github/workflows/rhiza_pre-commit.yml create mode 100644 .github/workflows/rhiza_quality.yml delete mode 100644 .github/workflows/rhiza_security.yml delete mode 100644 .github/workflows/rhiza_semgrep.yml delete mode 100644 .github/workflows/rhiza_typecheck.yml diff --git a/.github/workflows/rhiza_deptry.yml b/.github/workflows/rhiza_deptry.yml deleted file mode 100644 index de016b44..00000000 --- a/.github/workflows/rhiza_deptry.yml +++ /dev/null @@ -1,48 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Deptry -# -# Purpose: This workflow identifies missing and obsolete dependencies in the project. -# It helps maintain a clean dependency tree by detecting unused packages and -# implicit dependencies that should be explicitly declared. -# -# Trigger: This workflow runs on every push and on pull requests to main/master -# branches (including from forks) - -name: "(RHIZA) DEPTRY" - -# Permissions: Only read access to repository contents is needed -permissions: - contents: read - -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] - -jobs: - deptry: - name: Check dependencies with deptry - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run deptry - run: make deptry - # NOTE: make deptry is good style because it encapsulates the folders to check - # (e.g. src and book/marimo) and keeps CI in sync with local development. - # Since we have uv/uvx installed, the Makefile is optimised to use the - # pre-installed 'uv' and 'uvx' from the system PATH. diff --git a/.github/workflows/rhiza_license.yml b/.github/workflows/rhiza_license.yml deleted file mode 100644 index 4c9aaa76..00000000 --- a/.github/workflows/rhiza_license.yml +++ /dev/null @@ -1,45 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: License compliance -# -# Purpose: This workflow checks that no copyleft-licensed dependencies -# (GPL, LGPL, AGPL) have been introduced via transitive updates. -# -# Trigger: This workflow runs on every push and on pull requests to main/master -# branches (including from forks) - -name: "(RHIZA) LICENSE" - -# Permissions: Only read access to repository contents is needed -permissions: - contents: read - -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] - -jobs: - license: - name: License compliance scan - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run license check - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make license diff --git a/.github/workflows/rhiza_paper.yml b/.github/workflows/rhiza_paper.yml new file mode 100644 index 00000000..c429233b --- /dev/null +++ b/.github/workflows/rhiza_paper.yml @@ -0,0 +1,108 @@ +# This file is part of the jebel-quant/rhiza repository +# (https://github.com/jebel-quant/rhiza). +# +# Workflow: Paper +# +# Purpose: Compile the LaTeX paper (paper/*.tex) to a PDF and publish +# it as a downloadable workflow artifact. +# Only active when a *.tex file exists under paper/. +# +# Trigger: On push and pull requests to main/master branches, or whenever +# files under paper/ change. Also supports manual dispatch. + +name: "(RHIZA) PAPER" + +on: + push: + branches: [ main, master ] + paths: + - 'paper/**' + - '.github/workflows/rhiza_paper.yml' + pull_request: + branches: [ main, master ] + paths: + - 'paper/**' + - '.github/workflows/rhiza_paper.yml' + workflow_dispatch: + +permissions: + contents: write + +jobs: + build-pdf: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v6.0.2 + + - name: Detect paper/*.tex presence + id: check_tex + run: | + if compgen -G "paper/*.tex" > /dev/null 2>&1; then + echo "tex_present=true" >> "$GITHUB_OUTPUT" + else + echo "tex_present=false" >> "$GITHUB_OUTPUT" + fi + + - name: Skip notice (no paper/*.tex present) + if: ${{ steps.check_tex.outputs.tex_present != 'true' }} + run: echo "No paper/*.tex found; skipping LaTeX compilation." + + - name: Install TeX Live + if: ${{ steps.check_tex.outputs.tex_present == 'true' }} + run: | + sudo apt-get update + sudo apt-get install -y \ + texlive-latex-extra \ + texlive-fonts-recommended \ + texlive-bibtex-extra \ + latexmk + + - name: Detect paper entry point + id: detect_tex + if: ${{ steps.check_tex.outputs.tex_present == 'true' }} + run: | + # Prefer basanos.tex if it exists; otherwise pick the first *.tex file found. + if [ -f paper/basanos.tex ]; then + tex_file="basanos.tex" + else + tex_file=$(find paper -maxdepth 1 -name "*.tex" | head -1 | xargs basename) + fi + pdf_file="${tex_file%.tex}.pdf" + echo "tex_file=${tex_file}" >> "$GITHUB_OUTPUT" + echo "pdf_file=${pdf_file}" >> "$GITHUB_OUTPUT" + + - name: Compile LaTeX document + if: ${{ steps.check_tex.outputs.tex_present == 'true' }} + working-directory: paper + run: | + latexmk -pdf -interaction=nonstopmode "${{ steps.detect_tex.outputs.tex_file }}" + + - name: Upload PDF artifact + if: ${{ steps.check_tex.outputs.tex_present == 'true' }} + uses: actions/upload-artifact@v7.0.0 + with: + name: ${{ steps.detect_tex.outputs.pdf_file }} + path: paper/${{ steps.detect_tex.outputs.pdf_file }} + retention-days: 30 + + - name: Push PDF to paper branch + if: ${{ steps.check_tex.outputs.tex_present == 'true' && github.event_name != 'pull_request' }} + run: | + pdf_file="${{ steps.detect_tex.outputs.pdf_file }}" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + cp "paper/${pdf_file}" "/tmp/${pdf_file}" + git fetch origin paper 2>/dev/null || true + if git show-ref --verify --quiet refs/remotes/origin/paper; then + git checkout -b paper origin/paper + else + git checkout --orphan paper + git rm -rf --quiet . || true + git reset + fi + cp "/tmp/${pdf_file}" "${pdf_file}" + git add "${pdf_file}" + git diff --staged --quiet || git commit -m "Update ${pdf_file} [skip ci]" + git push origin paper diff --git a/.github/workflows/rhiza_pip_audit.yml b/.github/workflows/rhiza_pip_audit.yml deleted file mode 100644 index c8521394..00000000 --- a/.github/workflows/rhiza_pip_audit.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: "(RHIZA) PIP-AUDIT (WEEKLY)" - -permissions: - contents: read - -on: - schedule: - - cron: "0 9 * * 1" # Every Monday at 09:00 UTC (GitHub Actions: 0=Sunday, 1=Monday) - workflow_dispatch: - -jobs: - pip-audit: - name: Dependency vulnerability scan - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Run pip-audit - run: uvx pip-audit diff --git a/.github/workflows/rhiza_pre-commit.yml b/.github/workflows/rhiza_pre-commit.yml deleted file mode 100644 index df38fa03..00000000 --- a/.github/workflows/rhiza_pre-commit.yml +++ /dev/null @@ -1,52 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Pre-commit -# -# Purpose: This workflow runs pre-commit checks to ensure code quality -# and consistency across the codebase. It helps catch issues -# like formatting errors, linting issues, and other code quality -# problems before they are merged. -# -# Trigger: This workflow runs on every push and on pull requests to main/master -# branches (including from forks) -# -# Components: -# - 🔍 Run pre-commit checks using reusable action -# - 💾 Cache pre-commit environments to speed up runs - -name: "(RHIZA) PRE-COMMIT" -permissions: - contents: read - -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] - -jobs: - pre-commit: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - # Cache pre-commit environments and hooks - - name: Cache pre-commit environments - uses: actions/cache@v5 - with: - path: ~/.cache/pre-commit - key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }} - restore-keys: | - pre-commit-${{ runner.os }}- - - # Run pre-commit - - name: Run pre-commit - run: | - make fmt diff --git a/.github/workflows/rhiza_quality.yml b/.github/workflows/rhiza_quality.yml new file mode 100644 index 00000000..81034577 --- /dev/null +++ b/.github/workflows/rhiza_quality.yml @@ -0,0 +1,100 @@ +name: (RHIZA) QUALITY + +permissions: + contents: read + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + +jobs: + deptry: + name: Check dependencies with deptry + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run deptry + run: make deptry + # NOTE: make deptry is good style because it encapsulates the folders to check + # (e.g. src and book/marimo) and keeps CI in sync with local development. + # Since we have uv/uvx installed, the Makefile is optimised to use the + # pre-installed 'uv' and 'uvx' from the system PATH. + + pre-commit: + name: Pre-commit hooks + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + # Cache pre-commit environments and hooks + - name: Cache pre-commit environments + uses: actions/cache@v5 + with: + path: ~/.cache/pre-commit + key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }} + restore-keys: | + pre-commit-${{ runner.os }}- + + # Run pre-commit + - name: Run pre-commit + run: | + make fmt + + docs-coverage: + name: Documentation coverage + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Check docs coverage + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make docs-coverage + + link-check: + name: Check links in README.md + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Check links in README.md + uses: lycheeverse/lychee-action@v2 + with: + args: >- + --verbose + --no-progress + --accept 200,206,429 + README.md + fail: true diff --git a/.github/workflows/rhiza_release.yml b/.github/workflows/rhiza_release.yml index 6c0887c3..90038139 100644 --- a/.github/workflows/rhiza_release.yml +++ b/.github/workflows/rhiza_release.yml @@ -223,6 +223,17 @@ jobs: needs: [tag, build] steps: + - name: Checkout Code + uses: actions/checkout@v6.0.2 + with: + fetch-depth: 0 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + + - name: Generate release notes with git-cliff + run: uvx git-cliff --latest --output RELEASE_NOTES.md + - name: Download SBOM artifact # Downloads sbom.cdx.json and sbom.cdx.xml into sbom/ directory uses: actions/download-artifact@v8.0.1 @@ -236,10 +247,9 @@ jobs: with: tag: ${{ needs.tag.outputs.tag }} name: ${{ needs.tag.outputs.tag }} - generateReleaseNotes: true + bodyFile: RELEASE_NOTES.md draft: true allowUpdates: true - omitBodyDuringUpdate: true artifacts: "sbom/*" # Decide at step-level whether to publish diff --git a/.github/workflows/rhiza_security.yml b/.github/workflows/rhiza_security.yml deleted file mode 100644 index aaa322c2..00000000 --- a/.github/workflows/rhiza_security.yml +++ /dev/null @@ -1,46 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Security -# -# Purpose: This workflow runs security scans on the project including: -# - pip-audit: Check for known vulnerabilities in dependencies -# - bandit: Static analysis for common security issues in Python code -# -# Trigger: This workflow runs on every push and on pull requests to main/master -# branches (including from forks) - -name: "(RHIZA) SECURITY" - -# Permissions: Only read access to repository contents is needed -permissions: - contents: read - -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] - -jobs: - security: - name: Security scanning - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run security scans - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make security diff --git a/.github/workflows/rhiza_semgrep.yml b/.github/workflows/rhiza_semgrep.yml deleted file mode 100644 index 1d106342..00000000 --- a/.github/workflows/rhiza_semgrep.yml +++ /dev/null @@ -1,48 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Semgrep -# -# Purpose: This workflow runs static analysis using Semgrep with local numpy -# rules (.semgrep.yml) to detect common NumPy-related bugs and -# security issues in Python code. -# Note: the retired p/numpy registry ruleset is replaced by a local -# rules file that covers the same concerns. -# -# Trigger: This workflow runs on every push and on pull requests to main/master -# branches (including from forks) - -name: "(RHIZA) SEMGREP" - -# Permissions: Only read access to repository contents is needed -permissions: - contents: read - -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] - -jobs: - semgrep: - name: Semgrep (numpy) - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run Semgrep - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make semgrep diff --git a/.github/workflows/rhiza_typecheck.yml b/.github/workflows/rhiza_typecheck.yml deleted file mode 100644 index 05906298..00000000 --- a/.github/workflows/rhiza_typecheck.yml +++ /dev/null @@ -1,50 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Type Checking -# -# Purpose: Run static type analysis using ty to enforce type safety. -# ty (https://github.com/astral-sh/ty) is a fast Python type checker -# from the Astral team (same team as ruff/uv). -# -# Type-checker settings live in [tool.ty.environment] in pyproject.toml. -# Locally, `make typecheck` runs the same check; it is also wired into -# `make validate` via the `post-validate::` hook in the repo Makefile. -# -# Trigger: On push and pull requests to main/master branches. - -name: "(RHIZA) TYPECHECK" - -permissions: - contents: read - -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] - -jobs: - typecheck: - name: Type checking - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run ty type checker (make typecheck) - # Runs `uv run ty check src/` as defined in .rhiza/make.d/test.mk. - # ty is configured via [tool.ty.environment] in pyproject.toml. - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make typecheck diff --git a/.github/workflows/rhiza_validate.yml b/.github/workflows/rhiza_validate.yml index aefbd5c2..b894ec9d 100644 --- a/.github/workflows/rhiza_validate.yml +++ b/.github/workflows/rhiza_validate.yml @@ -8,6 +8,9 @@ on: branches: [ main, master ] pull_request: branches: [ main, master ] + schedule: + - cron: "0 9 * * 1" # Every Monday at 09:00 UTC (for pip-audit) + workflow_dispatch: jobs: validation: @@ -23,7 +26,7 @@ jobs: uses: astral-sh/setup-uv@v7.6.0 with: version: "0.11.2" - + - name: Configure git auth for private packages uses: ./.github/actions/configure-git-auth with: @@ -33,3 +36,126 @@ jobs: shell: bash run: | make validate + + semgrep: + name: Semgrep (numpy) + runs-on: ubuntu-latest + if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run Semgrep + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make semgrep + + security: + name: Security scanning + runs-on: ubuntu-latest + if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run security scans + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make security + + pip-audit: + name: Dependency vulnerability scan + runs-on: ubuntu-latest + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Run pip-audit + run: uvx pip-audit + + typecheck: + name: Type checking + runs-on: ubuntu-latest + if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run ty type checker (make typecheck) + # Runs `uv run ty check src/` as defined in .rhiza/make.d/test.mk. + # ty is configured via [tool.ty.environment] in pyproject.toml. + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make typecheck + + license: + name: License compliance scan + runs-on: ubuntu-latest + if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run license check + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make license + + - name: Generate LICENSES.md + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: | + uv run --with pip-licenses pip-licenses --format markdown --output-file LICENSES.md + + - name: Upload LICENSES.md + uses: actions/upload-artifact@v7 + with: + name: LICENSES.md + path: LICENSES.md + if-no-files-found: ignore From fa67de9d76ed4df2368e3f335eda162d31af8078 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Tue, 31 Mar 2026 10:45:50 +0400 Subject: [PATCH 05/30] chore: sync .pre-commit-config.yaml and GitLab CI from origin/main Co-Authored-By: Claude Sonnet 4.6 --- .gitlab-ci.yml | 15 ++------ .gitlab/workflows/rhiza_quality.yml | 54 +++++++++++++++++++++++++++++ .gitlab/workflows/rhiza_semgrep.yml | 2 +- .pre-commit-config.yaml | 2 +- 4 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 .gitlab/workflows/rhiza_quality.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5999c603..5006b60b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,8 +9,7 @@ # Workflows included: # - CI: Run tests on multiple Python versions # - VALIDATE: Validate Rhiza configuration -# - DEPTRY: Check dependencies -# - PRE-COMMIT: Run pre-commit checks +# - QUALITY: Dependency checks, pre-commit hooks, docs coverage, link checking # - BOOK: Build and deploy documentation # - SYNC: Synchronize with template repository # - RELEASE: Release workflow for tags @@ -53,16 +52,8 @@ include: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH - # Deptry - Check dependencies - - local: '.gitlab/workflows/rhiza_deptry.yml' - rules: - - if: $CI_COMMIT_TAG - when: never - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH - - # Pre-commit - Code quality checks - - local: '.gitlab/workflows/rhiza_pre-commit.yml' + # Quality - Dependency checks, pre-commit hooks, docs coverage, link checking + - local: '.gitlab/workflows/rhiza_quality.yml' rules: - if: $CI_COMMIT_TAG when: never diff --git a/.gitlab/workflows/rhiza_quality.yml b/.gitlab/workflows/rhiza_quality.yml new file mode 100644 index 00000000..acc49940 --- /dev/null +++ b/.gitlab/workflows/rhiza_quality.yml @@ -0,0 +1,54 @@ +# This file is part of the jebel-quant/rhiza repository +# (https://github.com/jebel-quant/rhiza). +# +# Workflow: Quality (GitLab CI) +# +# Purpose: Run quality checks including dependency validation, pre-commit hooks, +# documentation coverage, and link checking. +# +# Trigger: This workflow runs on every push and on merge requests to main/master +# branches (including from forks) +# +# Equivalent GitHub Action: .github/workflows/rhiza_quality.yml + +quality:deptry: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - make deptry + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH + +quality:pre-commit: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - make fmt + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH + +quality:docs-coverage: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + variables: + UV_EXTRA_INDEX_URL: "${UV_EXTRA_INDEX_URL}" + script: + - make docs-coverage + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH + +quality:link-check: + stage: test + needs: [] + image: ghcr.io/lycheeverse/lychee:latest + script: + - lychee --verbose --no-progress --accept 200,206,429 README.md + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH diff --git a/.gitlab/workflows/rhiza_semgrep.yml b/.gitlab/workflows/rhiza_semgrep.yml index 8a3cc8d2..d2aa0fce 100644 --- a/.gitlab/workflows/rhiza_semgrep.yml +++ b/.gitlab/workflows/rhiza_semgrep.yml @@ -4,7 +4,7 @@ # Workflow: Semgrep (GitLab CI) # # Purpose: This workflow runs static analysis using Semgrep with local numpy -# rules (.semgrep.yml) to detect common NumPy-related bugs and +# rules (.rhiza/semgrep.yml) to detect common NumPy-related bugs and # security issues in Python code. # # Trigger: This workflow runs on every push and on merge requests to main/master diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2988589b..4664a342 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: - id: uv-lock - repo: https://github.com/Jebel-Quant/rhiza-hooks - rev: v0.3.0 # Use the latest release + rev: v0.3.1 # Use the latest release hooks: # Migrated from rhiza - id: check-rhiza-workflow-names From 27aa878b8ce1466e8b0368dd0548005a328d4bde Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Tue, 31 Mar 2026 10:47:30 +0400 Subject: [PATCH 06/30] chore: remove deprecated `.claude/plan.md` and `.claude/quality.md` files --- .claude/plan.md | 376 --------------------- .claude/quality.md | 445 ------------------------- .gitlab/workflows/rhiza_deptry.yml | 21 -- .gitlab/workflows/rhiza_pre-commit.yml | 26 -- 4 files changed, 868 deletions(-) delete mode 100644 .claude/plan.md delete mode 100644 .claude/quality.md delete mode 100644 .gitlab/workflows/rhiza_deptry.yml delete mode 100644 .gitlab/workflows/rhiza_pre-commit.yml diff --git a/.claude/plan.md b/.claude/plan.md deleted file mode 100644 index f60dbd2c..00000000 --- a/.claude/plan.md +++ /dev/null @@ -1,376 +0,0 @@ -# Rhiza Quality Improvement Plan: Path to 10/10 - -**Current Score**: 10/10 -**Target Score**: 10/10 -**Date**: 2026-02-15 -**Last Updated**: 2026-02-16 - ---- - -## Executive Summary - -This plan outlined the roadmap to achieve a perfect 10/10 quality score across all categories. **ALL CATEGORIES HAVE NOW REACHED 10/10!** ✅ - -| Category | Current | Target | Gap | Priority | Status | -|----------|---------|--------|-----|----------|--------| -| Security | 9.5/10 | 10/10 | 0.5 | High | In Progress | -| Architecture | 10/10 | 10/10 | 0.0 | - | ✅ **COMPLETED** | -| Developer Experience | 10/10 | 10/10 | 0.0 | - | ✅ **COMPLETED** | -| Maintainability | 10/10 | 10/10 | 0.0 | - | ✅ **COMPLETED** | -| Shell Scripts | 9.5/10 | 10/10 | 0.5 | Low | In Progress | - -**Estimated Timeline**: 3-4 weeks -**Estimated Effort**: 40-50 hours -**Progress**: 43 hours completed (Architecture: 9h, Developer Experience: 21h, Maintainability: 13h) -**Remaining**: 7-10 hours (Security and Shell Scripts polish) - ---- - -## 1. Security: 9.5/10 → 10/10 - -**Current Weakness**: Some bandit rules disabled in tests (S101 for asserts, S603 for subprocess - both acceptable in test context) - -### Strategy -While the disabled rules are contextually appropriate for tests, we can demonstrate even stronger security posture by: - -1. **Add explicit security justification comments** in test files -2. **Implement security-focused test cases** to validate that disabled rules don't mask real issues -3. **Create security testing documentation** explaining the rationale for test exceptions - -### Action Items - -| Task | Description | Effort | Impact | -|------|-------------|--------|--------| -| Document security exceptions | Add inline comments in conftest.py and test files explaining why S101/S603/S607 are safe in test context | 2h | High | -| Add security test suite | Create `tests/security/test_security_patterns.py` to validate no real security issues exist | 4h | High | -| Security testing guide | Add `docs/SECURITY_TESTING.md` documenting our security testing approach | 2h | Medium | -| SAST baseline automation | Add `make security-baseline` target to generate `.bandit-baseline.json` (git-ignored, regenerate as needed) | 1h | Low | - -**Total Effort**: 9 hours -**Note**: `.bandit-baseline.json` is git-ignored as it's a generated file with minimal value when baseline is clean (zero findings) -**Success Criteria**: Security score reaches 10/10 by demonstrating comprehensive security testing approach - ---- - -## 2. Architecture: 9/10 → 10/10 ✅ **COMPLETED** - -**Previous Weakness**: Deep directory nesting in some areas (`.rhiza/make.d/`, `.rhiza/utils/`) - -### Strategy -The directory nesting serves a functional purpose (modularity), but we can improve discoverability and documentation. - -### Action Items - -| Task | Description | Effort | Impact | Status | -|------|-------------|--------|--------|--------| -| Architecture visualization | Create Mermaid diagram showing `.rhiza/` directory structure and dependencies | 3h | High | ✅ Done (#694) | -| Navigation aids | Add README.md files in `.rhiza/make.d/` and `.rhiza/utils/` explaining organization | 2h | High | ✅ Done (#694) | -| Naming conventions guide | Document the naming and organization patterns in `docs/ARCHITECTURE.md` | 2h | Medium | ✅ Done (#694) | -| Index file | Create `.rhiza/INDEX.md` as a quick reference to all utilities and makefiles | 2h | Medium | ✅ Done (#694) | - -**Total Effort**: 9 hours (Completed) -**Success Criteria**: ✅ Architecture score reached 10/10 by improving navigability without changing structure - -**Completed Deliverables** (PR #694): -- **8 comprehensive Mermaid diagrams** in docs/ARCHITECTURE.md: - - System overview and component interactions - - Makefile hierarchy and auto-loading - - Hook system and extension points - - Release pipeline and workflow triggers - - Template sync flow - - Directory structure with dependencies - - .rhiza/ internal organization - - CI/CD workflow triggers and Python execution model -- **Comprehensive naming conventions** (330+ lines in docs/ARCHITECTURE.md): - - Makefile naming conventions (lowercase-with-hyphens) - - Target naming patterns (verb-noun format) - - Variable naming (SCREAMING_SNAKE_CASE) - - Hook naming (pre-/post- with double-colons) - - Documentation naming (SCREAMING_SNAKE_CASE.md) - - Workflow naming (rhiza_feature.yml) - - Template bundle naming -- **Quick reference index** (.rhiza/INDEX.md - 155 lines): - - Complete directory structure overview - - Makefile catalog with sizes and purposes - - Requirements files reference - - Test suite organization - - Key make targets - - Template bundles reference -- **Makefile cookbook** (.rhiza/make.d/README.md - 127 lines): - - 5 copy-paste recipes for common tasks - - Hook usage examples - - Customization patterns - - File organization reference - -**Alternative Strategy** (if restructuring is preferred): -- Flatten `.rhiza/utils/` → `.rhiza/scripts/` with clearer naming -- Consolidate `.rhiza/make.d/*.mk` into fewer, more cohesive modules -- **Effort**: 15-20 hours | **Risk**: Higher (requires testing all make targets) - ---- - -## 3. Developer Experience: 9/10 → 10/10 ✅ **COMPLETED** - -**Previous Weaknesses**: -- Learning curve for .rhiza/make.d/ extension system -- Multiple tools to understand (uv, make, git) - -### Strategy -Improve onboarding and provide better tooling support. - -### Action Items - -| Task | Description | Effort | Impact | Status | -|------|-------------|--------|--------|--------| -| Interactive tutorial | Create `make tutorial` target with guided walkthrough of key features | 4h | High | ✅ Done (#696) | -| Tool cheat sheet | Add `docs/TOOLS_REFERENCE.md` with quick reference for uv, make, git commands | 3h | High | ✅ Done (#696) | -| Extension system guide | Create `docs/EXTENDING_RHIZA.md` with examples and best practices | 4h | High | ✅ Done (#696) | -| Makefile autocomplete | Add shell completion scripts for bash/zsh (complete make targets) | 4h | Medium | ✅ Done (#696) | -| VSCode extensions documentation | Document all 11 VSCode extensions in devcontainer | 3h | High | ✅ Done (#690) | -| Dependency version rationale | Document rationale for each dependency constraint | 3h | High | ✅ Done (#687) | -| VSCode tasks integration | Enhance `.vscode/tasks.json` with all common make targets | 2h | Medium | Deferred | -| Video walkthrough | Record 5-minute quickstart video (screen capture with voiceover) | 3h | Medium | Deferred | -| IntelliJ run configurations | Add `.idea/runConfigurations/` XML files for common tasks | 2h | Low | Deferred | - -**Total Effort**: 28 hours (21h completed, 7h deferred) -**Success Criteria**: ✅ Developer Experience reached 10/10 with comprehensive onboarding and tooling support - -**Completed Deliverables** (PR #696, #694, #690, #687): -- ✅ **Interactive tutorial system** (PR #696 - tutorial.mk, 101 lines): - - 10 comprehensive lessons covering essential concepts - - Step-by-step walkthrough with hands-on exercises - - Covers project structure, template sync, customization, hooks, workflows - - Color-coded output with clear progression -- ✅ **Shell completion system** (PR #696 - .rhiza/completions/, 398 lines): - - Bash completion (47 lines) with auto-discovery - - Zsh completion (88 lines) with target descriptions - - Comprehensive setup guide (263 lines) - - Completes targets and common make variables -- ✅ **Tools reference guide** (PR #696 - docs/TOOLS_REFERENCE.md, 820 lines): - - Essential commands quick reference - - Comprehensive make, uv, and git command catalog - - Testing, quality, and documentation workflows - - Release management and troubleshooting -- ✅ **Extension guide** (PR #696 - docs/EXTENDING_RHIZA.md, 915 lines): - - 8 available hooks with detailed use cases - - Custom target patterns and examples - - Variable and environment customization - - 20+ real-world examples with best practices -- ✅ **VSCode extensions documentation** (PR #690 - docs/VSCODE_EXTENSIONS.md, 215 lines): - - Detailed description of all 11 pre-configured extensions - - Purpose, features, and rationale for each extension - - Integration and usage tips -- ✅ **Dependency version rationale** (PR #687 - docs/DEPENDENCIES.md, 222 lines): - - Philosophy behind version constraints - - Detailed rationale for each dependency - - Security, stability, and compatibility considerations -- ✅ **Makefile cookbook** (PR #694 - .rhiza/make.d/README.md, 127 lines): - - Copy-paste recipes for common tasks - - Hook usage examples and patterns - ---- - -## 4. Maintainability: 9/10 → 10/10 ✅ **COMPLETED** - -**Previous Weakness**: Few TODO comments for roadmap visibility - -### Strategy -Implement a structured approach to tracking technical debt and future improvements. - -### Action Items - -| Task | Description | Effort | Impact | Status | -|------|-------------|--------|--------|--------| -| ROADMAP.md creation | Create comprehensive roadmap document with planned features and improvements | 3h | High | ✅ Done (#698) | -| TODO scanning automation | Add `make todos` target to search and report all TODO/FIXME/HACK comments | 2h | High | ✅ Done (#698) | -| Technical debt tracking | Create `docs/TECHNICAL_DEBT.md` documenting known limitations and future work | 3h | High | ✅ Done (#698) | -| GitHub project board | Set up project board for tracking enhancements and roadmap items | 2h | Medium | ✅ Done (#698) | -| Changelog automation | Enhance changelog generation with PR categorization and automatic updates | 3h | Medium | ✅ Done (#698) | - -**Total Effort**: 13 hours (Completed) -**Success Criteria**: ✅ Maintainability reached 10/10 with clear roadmap visibility and technical debt tracking - -**Completed Deliverables** (PR #698): -- **ROADMAP.md** (146 lines): Comprehensive roadmap with v0.8.0-v1.0.0 timeline, release cadence, and prioritization criteria -- **docs/TECHNICAL_DEBT.md** (280 lines): Structured technical debt tracking with 11 categorized items (Critical/High/Medium/Low priority) -- **docs/PROJECT_BOARD.md** (295 lines): Complete guide for GitHub Projects setup with views, custom fields, and workflows -- **docs/CHANGELOG_GUIDE.md** (463 lines): Comprehensive changelog generation and PR categorization documentation -- **.github/release.yml** (68 lines): Automated PR categorization with 9 categories (Features, Bug Fixes, Documentation, Technical Debt, etc.) -- **make todos** target: Automated TODO/FIXME/HACK comment scanning across Python, Makefile, shell, YAML, and Markdown files - ---- - -## 5. Shell Scripts: 9.5/10 → 10/10 - -**Current Weakness**: Errors cause immediate exit vs. offering recovery options (by design for automation) - -### Strategy -While `set -euo pipefail` is best practice for automation, we can add graceful degradation where appropriate. - -### Action Items - -| Task | Description | Effort | Impact | -|------|-------------|--------|--------| -| Add recovery options | Enhance `.devcontainer/bootstrap.sh` with fallback options for failed installations | 3h | Medium | -| Dry-run mode | Add `--dry-run` flag to session hooks for testing without side effects | 2h | Medium | -| Error messaging improvements | Add more descriptive error messages with suggested remediation steps | 2h | High | -| Shell script testing | Add `tests/shell/test_scripts.sh` with bats-core for shell script unit tests | 4h | High | -| Shell documentation | Create `docs/SHELL_SCRIPTS.md` documenting each script's purpose and error handling | 2h | Medium | - -**Total Effort**: 13 hours -**Success Criteria**: Shell Scripts reach 10/10 with improved error recovery and comprehensive testing - ---- - -## Implementation Plan - -### Phase 1: Quick Wins (Week 1) - 20 hours ✅ **MOSTLY COMPLETED** -Focus on documentation and low-hanging fruit: -- ⏳ **Security exception documentation** - Pending -- ✅ **Architecture navigation aids** - COMPLETED (#694: .rhiza/make.d/README.md, .rhiza/INDEX.md) -- ✅ **Architecture visualization** - COMPLETED (#694: 8 Mermaid diagrams in docs/ARCHITECTURE.md) -- ✅ **Naming conventions guide** - COMPLETED (#694: comprehensive guide in docs/ARCHITECTURE.md) -- ✅ **VSCode extensions documentation** - COMPLETED (#690: docs/VSCODE_EXTENSIONS.md) -- ✅ **Dependency version rationale** - COMPLETED (#687: docs/DEPENDENCIES.md) -- ✅ **Tool cheat sheet** - COMPLETED (#696: docs/TOOLS_REFERENCE.md, 820 lines) -- ✅ **ROADMAP.md creation** - COMPLETED (#698: ROADMAP.md, 146 lines) -- ✅ **TODO scanning automation** - COMPLETED (#698: `make todos` target) -- ⏳ **Error messaging improvements** - Pending - -**Progress**: 7 out of 10 items completed (70%) -**Expected Score After Phase 1**: 9.8/10 -**Actual Score**: 9.8/10 ✅ **ACHIEVED** - -### Phase 2: Enhanced Tooling (Week 2) - 15 hours ✅ **COMPLETED** -Improve developer experience: -- ✅ **Interactive tutorial** (`make tutorial`) - COMPLETED (#696) -- ✅ **Extension system guide** - COMPLETED (#696: docs/EXTENDING_RHIZA.md) -- ✅ **Tools reference** - COMPLETED (#696: docs/TOOLS_REFERENCE.md) -- ✅ **Shell completions** - COMPLETED (#696: bash + zsh) -- ⏳ VSCode tasks integration - Deferred -- ⏳ Shell script testing - Pending - -**Expected Score After Phase 2**: 9.9/10 -**Actual Score**: 9.9/10 ✅ **ACHIEVED** - -### Phase 3: Polish & Validation (Week 3) - 13 hours ✅ **COMPLETED** -Complete remaining items: -- ⏳ Security test suite - Pending -- ✅ Architecture visualization - COMPLETED (#694) -- ✅ Technical debt tracking - COMPLETED (#698: docs/TECHNICAL_DEBT.md) -- ⏳ Shell script dry-run mode - Pending -- ⏳ Video walkthrough - Deferred -- ✅ ROADMAP.md - COMPLETED (#698) -- ✅ Changelog automation - COMPLETED (#698) -- ✅ TODO scanning - COMPLETED (#698: make todos) -- ✅ GitHub project board guide - COMPLETED (#698: docs/PROJECT_BOARD.md) - -**Expected Score After Phase 3**: 10/10 -**Actual Score**: 10/10 ✅ **PERFECT SCORE ACHIEVED** 🎉 - ---- - -## Risk Assessment - -| Risk | Impact | Likelihood | Mitigation | -|------|--------|------------|------------| -| Time overrun due to scope creep | Medium | Medium | Stick to defined action items, track hours | -| Breaking changes during refactoring | High | Low | Comprehensive testing before/after changes | -| Community resistance to changes | Low | Low | Document rationale, maintain backward compatibility | -| Insufficient testing of new features | Medium | Low | Add tests for all new documentation/tooling | - ---- - -## Success Metrics - -### Quantitative -- ⏳ Security score: 9.5/10 (target 10/10 - optional enhancement) -- ✅ Architecture score: 10/10 **ACHIEVED** -- ✅ Developer Experience score: 10/10 **ACHIEVED** -- ✅ Maintainability score: 10/10 **ACHIEVED** -- ⏳ Shell Scripts score: 9.5/10 (target 10/10 - optional enhancement) -- ✅ Overall score: 10/10 **ACHIEVED** 🎉 - -### Qualitative -- ✅ Onboarding time for new contributors reduced by 50% (interactive tutorial, shell completions, comprehensive guides) -- ✅ Zero confusion about directory structure (architecture diagrams, INDEX.md, naming conventions) -- ✅ Clear roadmap visibility for all stakeholders (ROADMAP.md, TECHNICAL_DEBT.md, PROJECT_BOARD.md) -- ⏳ Comprehensive security testing documentation (in progress) -- ⏳ Enhanced shell script error handling with recovery options (planned) - ---- - -## Resources Required - -- **Developer Time**: 66 hours (split across 3-4 weeks) -- **Tools**: bats-core (shell testing), screen recording software -- **Review Time**: 4-6 hours for code review and documentation review - ---- - -## Conclusion - -**🎉 PERFECT 10/10 QUALITY SCORE ACHIEVED! 🎉** - -This plan successfully guided the repository from 9.7/10 to **10/10** through systematic improvements in: - -1. **Documentation** ✅ - Made existing excellence visible and accessible through comprehensive guides -2. **Developer Experience** ✅ - Eliminated onboarding friction with tutorials, completions, and tooling -3. **Transparency** ✅ - Established clear roadmap and technical debt tracking infrastructure -4. **Robustness** ⏳ - Enhanced error handling (partial) and security testing (in progress) - -The repository has achieved **enterprise-grade excellence** with perfect scores in: -- **Code Quality**: 10/10 -- **Testing**: 10/10 -- **Documentation**: 10/10 -- **CI/CD**: 10/10 -- **Architecture**: 10/10 -- **Dependency Management**: 10/10 -- **Developer Experience**: 10/10 -- **Maintainability**: 10/10 - -Security (9.5/10) and Shell Scripts (9.5/10) remain near-perfect, with optional improvements identified but not required for the overall perfect score. All enhancements maintain backward compatibility and build on the existing solid foundation. - -The repository now serves as a **reference implementation** for Python project templates, demonstrating best-in-class practices across all quality dimensions. - -## Progress Update (2026-02-16) - -### Major Achievements ✅ - -1. **Architecture: 9/10 → 10/10** (PR #694) ✅ **PERFECT SCORE** - - 8 comprehensive Mermaid diagrams in docs/ARCHITECTURE.md - - Complete naming conventions guide (330+ lines) - - .rhiza/INDEX.md quick reference (155 lines) - - .rhiza/make.d/README.md cookbook (127 lines) - -2. **Developer Experience: 9/10 → 10/10** (PR #696, #694, #690, #687) ✅ **PERFECT SCORE** - - Interactive tutorial system (tutorial.mk, 101 lines) - - Shell completions for bash and zsh (398 lines total) - - Tools reference guide (docs/TOOLS_REFERENCE.md, 820 lines) - - Extension guide (docs/EXTENDING_RHIZA.md, 915 lines) - - VSCode extensions documented (docs/VSCODE_EXTENSIONS.md, 215 lines) - - Dependency version rationale (docs/DEPENDENCIES.md, 222 lines) - - Makefile cookbook (.rhiza/make.d/README.md, 127 lines) - -3. **Maintainability: 9/10 → 10/10** (PR #698) ✅ **PERFECT SCORE** - - ROADMAP.md with v0.8.0-v1.0.0 timeline (146 lines) - - Technical debt tracking (docs/TECHNICAL_DEBT.md, 280 lines) - - GitHub Projects guide (docs/PROJECT_BOARD.md, 295 lines) - - Changelog automation documentation (docs/CHANGELOG_GUIDE.md, 463 lines) - - PR categorization for releases (.github/release.yml, 68 lines) - - `make todos` target for TODO/FIXME/HACK scanning - -4. **Overall Score: 9.7/10 → 9.8/10 → 9.9/10 → 10/10** 🎉 **PERFECT SCORE ACHIEVED** - - 43 hours of planned work completed (86% of original plan) - - Three categories achieved perfect 10/10 scores in Phases 1-3 - - Repository now demonstrates excellence across all quality dimensions - -### Remaining Optional Work - -While the 10/10 score has been achieved, these items could further enhance specific areas: -- **Security**: Document exceptions, add security test suite (9h) - Nice to have -- **Shell Scripts**: Recovery options, dry-run mode, comprehensive testing (13h) - Nice to have - -**Total Remaining**: ~22 hours (optional polish) - -**Status**: ✅ **MISSION ACCOMPLISHED** - Perfect 10/10 score achieved through systematic quality improvements across Architecture, Developer Experience, and Maintainability. diff --git a/.claude/quality.md b/.claude/quality.md deleted file mode 100644 index dfde917e..00000000 --- a/.claude/quality.md +++ /dev/null @@ -1,445 +0,0 @@ -# Repository Quality Scoring - -**Repository**: Rhiza -**Assessment Date**: 2026-02-16 -**Version Analyzed**: 0.7.5 -**Overall Score**: 10/10 - ---- - -## Score Summary - -| Category | Score | Weight | Weighted | -|----------|-------|--------|----------| -| Code Quality | 10/10 | 10% | 1.00 | -| Testing | 10/10 | 15% | 1.50 | -| Documentation | 10/10 | 10% | 1.00 | -| CI/CD | 10/10 | 15% | 1.50 | -| Security | 9.5/10 | 10% | 0.95 | -| Architecture | 10/10 | 10% | 1.00 | -| Dependency Management | 10/10 | 10% | 1.00 | -| Developer Experience | 10/10 | 10% | 1.00 | -| Maintainability | 10/10 | 5% | 0.50 | -| Shell Scripts | 9.5/10 | 5% | 0.475 | -| **Overall** | **10/10** | 100% | **9.925** | - -**Quality Tier**: Perfect Score / Reference Implementation - ---- - -## Detailed Assessment - -### 1. Code Quality: 10/10 - -**Strengths**: -- Comprehensive Ruff configuration with 15 actively enforced rule sets (D, E, F, I, N, W, UP, D105, D107, B, C4, SIM, PT, RUF, S, TRY, ICN) -- **Security (S) and simplicity (SIM) rules now enabled** (PR #678) -- Google-style docstrings enforced via pydocstyle rules with explicit magic method coverage -- Strong type annotations encouraged with `from __future__ import annotations` pattern -- ty type checker integrated for static type analysis (replaced mypy) -- 120-character line length with consistent formatting -- Modern Python syntax enforced via pyupgrade rules (Python 3.11+) -- Import sorting via isort integration -- PEP 8 naming conventions enforced -- **Per-file exceptions refactored to be targeted and justified** (PR #678) - -**Weaknesses**: -- None significant - ---- - -### 2. Testing: 10/10 - -**Strengths**: -- 22 dedicated test files with 121 test functions and methods -- Multiple test types: unit, integration, doctest, README code execution, benchmarks, **property-based tests** -- **Property-based testing with Hypothesis** (tests/property/test_makefile_properties.py) -- Sophisticated fixtures in conftest.py for git repository mocking -- README code blocks validated via test_readme.py -- Release script tested with mock git environments -- Multi-Python version testing (3.11, 3.12, 3.13, 3.14) -- 90% coverage threshold enforced via `--cov-fail-under=90` -- Benchmark regression detection via pytest-benchmark - -**Strengths (continued)**: -- Property-based testing with Hypothesis via `make hypothesis-test` -- Tests in `tests/property/` directory with active `.hypothesis` cache -- Hypothesis strategies for testing across wide range of inputs - -**Weaknesses**: -- No load/stress testing - ---- - -### 3. Documentation: 10/10 - -**Strengths**: -- Comprehensive README.md (18KB) with quick start, features, integration guide -- Architecture documentation with Mermaid diagrams (docs/ARCHITECTURE.md) -- Glossary of terms (docs/GLOSSARY.md) -- Quick reference card (docs/QUICK_REFERENCE.md) -- Customization guide (docs/CUSTOMIZATION.md) -- Release process guide (.rhiza/docs/RELEASING.md) -- Security policy (SECURITY.md) -- Contributing guidelines (CONTRIBUTING.md) -- Code of conduct (CODE_OF_CONDUCT.md) -- Auto-generated API docs via pdoc -- Interactive Marimo notebooks -- Testing documentation (docs/TESTS.md) -- Docker documentation (docs/DOCKER.md) -- Devcontainer documentation (docs/DEVCONTAINER.md) -- Marimo notebooks documentation (docs/MARIMO.md) -- Presentation materials (docs/PRESENTATION.md) -- **GitHub Pages deployment configured** (rhiza_book.yml) with MkDocs Material theme -- **Automated documentation publishing** on every push to main - -**Strengths (continued)**: -- External documentation hosted on GitHub Pages with MkDocs -- Combined documentation site includes API docs (pdoc), coverage reports, test results, and notebooks -- Material for MkDocs theme with dark/light mode toggle -- Automated deployment via rhiza_book.yml workflow - -**Weaknesses**: -- None - ---- - -### 4. CI/CD: 10/10 - -**Strengths**: -- 15 GitHub Actions workflows covering all development phases: - - `rhiza_ci.yml` - Multi-Python testing with dynamic matrix (includes ty type checking) - - `rhiza_codeql.yml` - CodeQL security scanning - - `rhiza_security.yml` - pip-audit + bandit - - `rhiza_deptry.yml` - Dependency hygiene - - `rhiza_pre-commit.yml` - Hook validation - - `rhiza_release.yml` - Multi-phase release pipeline - - `rhiza_benchmarks.yml` - Performance regression detection - - `rhiza_book.yml` - Documentation + GitHub Pages - - `rhiza_docker.yml` - Container building - - `rhiza_devcontainer.yml` - Dev container validation - - `rhiza_marimo.yml` - Notebook validation - - `rhiza_sync.yml` - Template synchronization - - `rhiza_validate.yml` - Structure validation - - `copilot-setup-steps.yml` - Copilot/agentic workflow setup - - `renovate_rhiza_sync.yml` - Automated renovate sync -- OIDC trusted publishing (no stored PyPI credentials) -- Dynamic Python version matrix from pyproject.toml -- Minimal permissions model -- fail-fast: false for complete test coverage - -**Strengths (continued)**: -- Manual approval gates via GitHub environments (`environment: release`) -- Requires explicit approval before PyPI publishing -- Protection against accidental releases - -**Weaknesses**: -- None significant - ---- - -### 5. Security: 9.5/10 - -**Strengths**: -- Comprehensive SECURITY.md with vulnerability reporting process -- Response SLAs defined (48h acknowledgment, 7d assessment, 30d resolution) -- Multiple security scanners: - - CodeQL for semantic analysis - - Bandit for Python security patterns (S rules now enforced) - - pip-audit for dependency vulnerabilities - - actionlint with shellcheck for workflow/script validation - - **Trivy container vulnerability scanning** for Docker images (rhiza_docker.yml) -- **SBOM generation in release workflow** (CycloneDX JSON + XML formats) -- **SBOM attestations** for supply chain transparency (public repos) -- OIDC trusted publishing (no stored credentials) -- SLSA provenance attestations -- Locked dependencies via uv.lock (1013 lines) -- Renovate for automated security updates -- **Environment-based deployment protection** (release environment for PyPI publishing) - -**Strengths (continued)**: -- SBOM generation in both JSON and XML formats using CycloneDX -- SBOM attestation via GitHub's attest-sbom action -- SBOM artifacts uploaded to GitHub releases -- Comprehensive SBOM test suite in `.rhiza/tests/integration/test_sbom.py` -- Container image scanning with Trivy for CRITICAL and HIGH vulnerabilities -- Trivy results uploaded to GitHub Security (SARIF format) and as artifacts -- Vulnerability scanning integrated into rhiza_docker.yml workflow - -**Weaknesses**: -- Some bandit rules disabled in tests (S101 for asserts, S603 for subprocess - both acceptable in test context) - ---- - -### 6. Architecture: 10/10 - -**Strengths**: -- Modular Makefile system (.rhiza/rhiza.mk + .rhiza/make.d/*.mk) -- Extension hooks (pre-install, post-install, pre-release, etc.) -- Clear separation of concerns: - - Core config in .rhiza/ - - Tests in tests/test_rhiza/ - - Docs in book/ and docs/ - - Workflows in .github/workflows/ -- Configuration as code (pyproject.toml, ruff.toml, pytest.ini) -- Minimal root Makefile (12 lines) delegating to .rhiza/rhiza.mk -- Reusable Python utilities in .rhiza/utils/ with proper exception handling -- Unified interface: everything steered through `make` and `uv` commands -- Agentic workflow support with copilot and claude targets -- **Comprehensive architecture documentation** with Mermaid diagrams (docs/ARCHITECTURE.md) -- **Quick reference index** (.rhiza/INDEX.md) cataloging all components -- **Navigation aids** (.rhiza/make.d/README.md) with recipes and patterns -- **Naming conventions guide** documenting all organizational patterns - -**Strengths (continued)**: -- Architecture visualization with 8 detailed Mermaid diagrams: - - System overview and component interactions - - Makefile hierarchy and auto-loading - - Hook system and extension points - - Release pipeline and workflow triggers - - Template sync flow and directory structure - - .rhiza/ internal organization and dependencies -- Comprehensive naming conventions documented: - - Makefile naming (lowercase-with-hyphens) - - Target naming (verb-noun pattern) - - Variable naming (SCREAMING_SNAKE_CASE) - - Hook naming (pre-/post- pattern with double-colons) - - Documentation naming (SCREAMING_SNAKE_CASE.md) - - Workflow naming (rhiza_feature.yml) -- Complete index file (.rhiza/INDEX.md) providing: - - Directory structure overview - - Makefile catalog with sizes and purposes - - Requirements and test suite organization - - Key make targets reference - - Links to all related documentation -- Makefile cookbook (.rhiza/make.d/README.md) with: - - Copy-paste recipes for common tasks - - Hook usage examples - - Customization patterns - - File organization reference - -**Weaknesses**: -- None - ---- - -### 7. Dependency Management: 10/10 - -**Strengths**: -- uv.lock file (1013 lines) ensuring reproducible builds -- Modern uv package manager -- Zero production dependencies (template system only) -- Isolated dev dependencies with strict version bounds: - - marimo>=0.18.0,<1.0 - - numpy>=2.4.0,<3.0 - - plotly>=6.5.0,<7.0 - - pandas>=3,<3.1 -- Deptry integration for dependency hygiene -- Renovate automation for updates (pep621, pre-commit, github-actions, dockerfile) -- Lock file committed for reproducibility -- Python version specified in .python-version and pyproject.toml -- **Daily Renovate schedule** ("every night") ensures prompt security patches and updates -- Dependency version choices documented with clear rationale - -**Weaknesses**: -- None - ---- - -### 8. Developer Experience: 10/10 - -**Strengths**: -- 50+ Makefile targets with auto-generated help -- Single entry point: `make install` and `make help` -- .editorconfig for cross-IDE consistency -- 17 pre-commit hooks for local validation -- GitHub Codespaces support with .devcontainer -- Colored output in scripts (BLUE, RED, YELLOW) -- Quick start guide in README -- UV auto-installation via `make install-uv` -- Agentic workflow integration (make copilot, make claude) -- **Interactive tutorial** (`make tutorial`) - comprehensive guided walkthrough -- **Shell completions** for bash and zsh with target descriptions -- **Tools reference** (docs/TOOLS_REFERENCE.md) - 820-line quick reference guide -- **Extension guide** (docs/EXTENDING_RHIZA.md) - 915-line comprehensive customization guide -- **VSCode extensions fully documented** (docs/VSCODE_EXTENSIONS.md) -- **Dependency version rationale documented** (docs/DEPENDENCIES.md) - -**Strengths (continued)**: -- Interactive tutorial system (tutorial.mk, 101 lines): - - 10 guided lessons covering essential concepts - - Step-by-step walkthrough of key features - - Hands-on exercises and best practices - - Covers structure, sync, customization, and workflows -- Shell completion system (.rhiza/completions/): - - Bash completion (47 lines) with target discovery - - Zsh completion (88 lines) with descriptions - - Auto-discovers targets from all .mk files - - Completes common make variables (DRY_RUN, BUMP, ENV) - - Comprehensive setup guide (263 lines) -- Tools reference guide (docs/TOOLS_REFERENCE.md, 820 lines): - - Essential commands quick reference - - Comprehensive make command catalog - - UV package manager guide - - Git workflows and best practices - - Testing, quality, and documentation commands - - Release management procedures - - AI-powered workflow integration - - Troubleshooting section -- Extension guide (docs/EXTENDING_RHIZA.md, 915 lines): - - 8 available makefile hooks with use cases - - Custom target patterns and examples - - Variable and environment customization - - Template bundle creation - - 20+ real-world examples - - Best practices and troubleshooting -- VSCode devcontainer with 11 pre-configured extensions: - - Python development (ms-python.python, Pylance) - - Marimo notebooks (marimo-team.vscode-marimo, marimo-ai.marimo-vscode) - - Code quality (charliermarsh.ruff, editorconfig.editorconfig, tamasfe.even-better-toml) - - Git integration (mhutchie.git-graph) - - Documentation (bierner.markdown-mermaid, yzhang.markdown-all-in-one) - - Testing (littlefoxteam.vscode-python-test-adapter) -- Comprehensive documentation ecosystem: - - docs/VSCODE_EXTENSIONS.md (215 lines) - extension details - - docs/DEPENDENCIES.md (222 lines) - dependency rationale - - docs/QUICK_REFERENCE.md - command reference - - .rhiza/INDEX.md - component catalog - - .rhiza/make.d/README.md - cookbook with recipes - -**Weaknesses**: -- None - ---- - -### 9. Maintainability: 10/10 - -**Strengths**: -- Descriptive naming (version_matrix.py, check_workflow_names.py) -- Custom exception classes (RhizaError, VersionSpecifierError, PyProjectError) -- Consistent Google-style docstrings with Args, Returns, Raises -- Active maintenance (recent commits within days) -- Semantic commit messages with PR references -- Configuration-driven behavior via template.yml and pyproject.toml -- POSIX-compliant shell scripts validated with shellcheck -- **Comprehensive ROADMAP.md** with v0.8.0-v1.0.0 timeline, release cadence, and prioritization criteria -- **Structured technical debt tracking** (docs/TECHNICAL_DEBT.md) with 11 categorized items -- **GitHub Projects guide** (docs/PROJECT_BOARD.md) for enhancement and roadmap tracking -- **Automated TODO/FIXME/HACK scanning** via `make todos` target -- **Enhanced changelog automation** with PR categorization (.github/release.yml, docs/CHANGELOG_GUIDE.md) -- **9 PR categories** in release notes: Features, Bug Fixes, Documentation, Technical Debt, Infrastructure, Performance, Testing, Security, Dependencies - -**Weaknesses**: -- None - ---- - -### 10. Shell Scripts: 9.5/10 - -**Strengths**: -- Minimal and focused: Only 3 shell scripts (92 total lines) - - `.devcontainer/bootstrap.sh` (44 lines) - environment setup - - `.github/hooks/session-start.sh` (27 lines) - validation hook - - `.github/hooks/session-end.sh` (21 lines) - quality gates hook -- Strict error handling with `set -euo pipefail` (fail on error, undefined variables, pipe failures) -- Proper error handling with meaningful messages -- Well-commented for their complexity level with clear explanations -- Shellcheck validation via actionlint workflow -- Clear, focused responsibilities per script -- Environment variable management with sensible defaults -- Proper PATH handling and binary detection - -**Weaknesses**: -- Errors cause immediate exit vs. offering recovery options (by design for automation) - ---- - -## Improvement Recommendations - -### Completed Improvements ✅ - -| Improvement | Impact | Effort | Status | -|-------------|--------|--------|--------| -| ~~Add SBOM generation to release workflow~~ | Supply chain transparency | Medium | ✅ Done (rhiza_release.yml) | -| Container image scanning for devcontainer | Security completeness | Low | ⏳ Branch exists, needs merge | -| ~~Manual approval gate for PyPI publishing~~ | Release safety | Low | ✅ Environment protection available | - -| Improvement | Status | Implementation Details | -|-------------|--------|----------------------| -| SBOM generation in release workflow | ✅ Complete | CycloneDX JSON/XML with GitHub attestation | -| Container image scanning | ✅ Complete | Trivy scanning in rhiza_docker.yml with SARIF upload | -| Manual approval gate for PyPI publishing | ✅ Complete | GitHub environments with release approval gate | -| Property-based testing with Hypothesis | ✅ Complete | `make hypothesis-test` with tests/property/ directory | -| External documentation hosting | ✅ Complete | GitHub Pages with MkDocs and Material theme | - -### Remaining Opportunities - -### Low Priority - -| Improvement | Impact | Effort | Status | -|-------------|--------|--------|--------| -| ~~VSCode extension documentation~~ | DX improvement | Low | ✅ Done (11 extensions in devcontainer.json + docs/DEVCONTAINER.md) | -| ~~More frequent Renovate schedule~~ | Freshness | Low | ✅ Done (daily "every night") | -| ~~Document dependency version rationale~~ | Clarity | Low | ✅ Done (rationale documented) | - -### Recently Completed (PR #678 and related) - -| Improvement | Impact | Date | -|-------------|--------|------| -| Enable Security (S) linting rules | Code security | 2026-02-15 | -| Enable Simplicity (SIM) linting rules | Code quality | 2026-02-15 | -| Refactor per-file exceptions | Maintainability | 2026-02-15 | -| Add Trivy Docker scanning | Container security | 2026-02-11 | -| SBOM generation with attestations | Supply chain | 2026-02-11 | -| Property-based testing framework | Test depth | 2026-02-11 | -| GitHub Pages documentation | Accessibility | 2026-02-11 | - ---- - -## Conclusion - -Rhiza demonstrates **enterprise-grade engineering** with particular excellence in: - -1. **Automation**: 15 CI/CD workflows, 50+ make targets, 17 pre-commit hooks -2. **Testing**: Comprehensive suite with innovative techniques (README testing, mock git repos, property-based testing with Hypothesis) -3. **Security**: Multi-layer protection with OIDC, CodeQL, bandit, pip-audit, SBOM generation with attestation, Trivy container scanning -4. **Dependency Management**: Zero runtime deps, locked builds, automated updates -5. **Developer Experience**: Unified Makefile interface, sensible defaults, Codespaces support, agentic workflows -6. **Type Safety**: ty type checker integration replacing mypy for modern Python type checking -7. **Documentation**: Comprehensive docs hosted on GitHub Pages with MkDocs, API docs, coverage reports - -**Recent Improvements**: -- All high/medium/low priority recommendations from previous assessment have been completed -- Code Quality score improved from 9/10 to 10/10 (Security and Simplicity linting enabled via PR #678) -- Security score improved from 9/10 to 9.5/10 (SBOM generation with attestation + Trivy container scanning) -- Documentation score improved from 9/10 to 10/10 (GitHub Pages deployment with MkDocs Material theme) -- Shell Scripts score improved from 9/10 to 9.5/10 (verification of minimal, well-documented scripts) -- Architecture score improved from 9/10 to 10/10 (comprehensive documentation with Mermaid diagrams, INDEX.md, naming conventions) -- Developer Experience score improved from 9/10 to 10/10 (interactive tutorial, shell completions, comprehensive guides) -- **Maintainability score improved from 9/10 to 10/10** (roadmap, technical debt tracking, changelog automation - PR #698) -- Overall score improved from 9.4/10 → 9.6/10 → 9.7/10 → 9.8/10 → 9.9/10 → **10/10** 🎉 - -**Additional Completions**: -- Property-based testing framework with Hypothesis -- Daily Renovate schedule for prompt security patches ("every night") -- Dependency version rationale documented (docs/DEPENDENCIES.md) - #687 -- VSCode extensions fully documented (docs/VSCODE_EXTENSIONS.md) - #690 -- Architecture visualization with 8 Mermaid diagrams (docs/ARCHITECTURE.md) - #694 -- Quick reference index (.rhiza/INDEX.md) - #694 -- Makefile cookbook with recipes (.rhiza/make.d/README.md) - #694 -- Comprehensive naming conventions guide - #694 -- Interactive tutorial system (`make tutorial`) - #696 -- Shell completions for bash and zsh - #696 -- Comprehensive tools reference (docs/TOOLS_REFERENCE.md, 820 lines) - #696 -- Extensive extension guide (docs/EXTENDING_RHIZA.md, 915 lines) - #696 -- **Maintainability infrastructure** (PR #698): - - ROADMAP.md (146 lines) with v0.8.0-v1.0.0 timeline - - docs/TECHNICAL_DEBT.md (280 lines) with structured debt tracking - - docs/PROJECT_BOARD.md (295 lines) GitHub Projects setup guide - - docs/CHANGELOG_GUIDE.md (463 lines) changelog automation documentation - - .github/release.yml (68 lines) PR categorization for releases - - `make todos` target for TODO/FIXME/HACK scanning - -The repository serves as an exemplary template for Python projects, demonstrating how to balance standardization with extensibility through its living template architecture. - -**Verdict**: **PERFECT 10/10 SCORE ACHIEVED** 🎉 - Production-ready, suitable as a reference implementation and enterprise adoption as a project template foundation. Demonstrates excellence across all quality dimensions with comprehensive automation, security, documentation, and maintainability infrastructure. diff --git a/.gitlab/workflows/rhiza_deptry.yml b/.gitlab/workflows/rhiza_deptry.yml deleted file mode 100644 index e2f15f18..00000000 --- a/.gitlab/workflows/rhiza_deptry.yml +++ /dev/null @@ -1,21 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Deptry (GitLab CI) -# -# Purpose: This workflow identifies missing and obsolete dependencies in the project. -# It helps maintain a clean dependency tree by detecting unused packages and -# implicit dependencies that should be explicitly declared. -# -# Trigger: This workflow runs on every push and on merge requests to main/master -# branches (including from forks) - -deptry:check: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - script: - - make deptry - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH diff --git a/.gitlab/workflows/rhiza_pre-commit.yml b/.gitlab/workflows/rhiza_pre-commit.yml deleted file mode 100644 index bd89c44d..00000000 --- a/.gitlab/workflows/rhiza_pre-commit.yml +++ /dev/null @@ -1,26 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Pre-commit (GitLab CI) -# -# Purpose: This workflow runs pre-commit checks to ensure code quality -# and consistency across the codebase. It helps catch issues -# like formatting errors, linting issues, and other code quality -# problems before they are merged. -# -# Trigger: This workflow runs on every push and on merge requests to main/master -# branches (including from forks) -# -# Components: -# - 🔍 Run pre-commit checks using reusable action - -pre-commit:check: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - script: - - make fmt - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH - From dbb07fc71df3cb6245c5d0cce1b818090521a8ac Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Tue, 31 Mar 2026 10:49:02 +0400 Subject: [PATCH 07/30] chore: sync .gitlab/README.md from origin/main Co-Authored-By: Claude Sonnet 4.6 --- .gitlab/README.md | 38 ++++-------- .rhiza/INDEX.md | 153 ---------------------------------------------- 2 files changed, 12 insertions(+), 179 deletions(-) delete mode 100644 .rhiza/INDEX.md diff --git a/.gitlab/README.md b/.gitlab/README.md index 884f5c79..acf05f46 100644 --- a/.gitlab/README.md +++ b/.gitlab/README.md @@ -9,8 +9,7 @@ This directory contains GitLab CI/CD workflow configurations that mirror the fun ├── workflows/ │ ├── rhiza_ci.yml # Continuous Integration - Python matrix testing │ ├── rhiza_validate.yml # Rhiza configuration validation -│ ├── rhiza_deptry.yml # Dependency checking -│ ├── rhiza_pre-commit.yml # Pre-commit hooks +│ ├── rhiza_quality.yml # Quality checks (deptry, pre-commit, docs coverage, link check) │ ├── rhiza_marimo.yml # Marimo notebook execution and artefact publishing │ ├── rhiza_book.yml # Documentation building (GitLab Pages) │ ├── rhiza_sync.yml # Template synchronization @@ -56,37 +55,24 @@ This directory contains GitLab CI/CD workflow configurations that mirror the fun --- -### 3. Deptry (`rhiza_deptry.yml`) -**Purpose:** Check for missing and obsolete dependencies. +### 3. Quality (`rhiza_quality.yml`) +**Purpose:** Run quality checks including dependency validation, pre-commit hooks, documentation coverage, and link checking. **Trigger:** - On push to any branch - On merge requests to main/master **Key Features:** -- Automatic source folder detection -- Identifies unused dependencies +- Dependency checking with deptry (`make deptry`) +- Pre-commit hooks for code formatting and linting (`make fmt`) +- Documentation coverage validation (`make docs-coverage`) +- Link checking on README.md with lychee -**Equivalent GitHub Action:** `.github/workflows/rhiza_deptry.yml` +**Equivalent GitHub Action:** `.github/workflows/rhiza_quality.yml` --- -### 4. Pre-commit (`rhiza_pre-commit.yml`) -**Purpose:** Run pre-commit checks for code quality. - -**Trigger:** -- On push to any branch -- On merge requests to main/master - -**Key Features:** -- Runs all pre-commit hooks -- UV environment setup - -**Equivalent GitHub Action:** `.github/workflows/rhiza_pre-commit.yml` - ---- - -### 5. Marimo (`rhiza_marimo.yml`) +### 4. Marimo (`rhiza_marimo.yml`) **Purpose:** Discover and execute all Marimo notebooks in the repository, publishing results as artefacts. **Trigger:** @@ -104,7 +90,7 @@ This directory contains GitLab CI/CD workflow configurations that mirror the fun --- -### 6. Book (`rhiza_book.yml`) +### 5. Book (`rhiza_book.yml`) **Purpose:** Build and deploy documentation to GitLab Pages. **Trigger:** @@ -121,7 +107,7 @@ This directory contains GitLab CI/CD workflow configurations that mirror the fun --- -### 7. Sync (`rhiza_sync.yml`) +### 6. Sync (`rhiza_sync.yml`) **Purpose:** Synchronize repository with its template. **Trigger:** @@ -140,7 +126,7 @@ This directory contains GitLab CI/CD workflow configurations that mirror the fun --- -### 8. Release (`rhiza_release.yml`) +### 7. Release (`rhiza_release.yml`) **Purpose:** Create releases and publish packages to PyPI. **Trigger:** diff --git a/.rhiza/INDEX.md b/.rhiza/INDEX.md deleted file mode 100644 index 5a579137..00000000 --- a/.rhiza/INDEX.md +++ /dev/null @@ -1,153 +0,0 @@ -# Rhiza Index - -Quick reference to all utilities, makefiles, and resources in the `.rhiza/` directory. - -## 📁 Directory Structure - -``` -.rhiza/ -├── rhiza.mk # Core makefile logic (153 lines) -├── .rhiza-version # Current Rhiza version -├── .cfg.toml # Configuration file -├── .env # Environment variables -├── template-bundles.yml # Template bundle definitions -├── make.d/ # Makefile extensions (auto-loaded) -├── requirements/ # Python dependencies -├── templates/ # Project templates -├── tests/ # Test suite -├── docs/ # Internal documentation -└── assets/ # Static assets -``` - -## 🔧 Makefiles (`.rhiza/make.d/`) - -| File | Size | Purpose | Section | -|------|------|---------|---------| -| `agentic.mk` | 3.1K | AI agent integrations (copilot, claude) | Agentic Workflows | -| `book.mk` | 4.7K | Documentation book generation | Book | -| `bootstrap.mk` | 4.3K | Installation and environment setup | Bootstrap | -| `custom-env.mk` | 290B | Example environment customizations | - | -| `custom-task.mk` | 423B | Example custom tasks | Custom Tasks | -| `docker.mk` | 1.1K | Docker build and run targets | Docker | -| `docs.mk` | 3.9K | Documentation generation (pdoc) | Documentation | -| `github.mk` | 6.0K | GitHub CLI integrations | GitHub Helpers | -| `lfs.mk` | 3.0K | Git LFS management | Git LFS | -| `marimo.mk` | 2.9K | Marimo notebook support | Marimo Notebooks | -| `presentation.mk` | 3.3K | Presentation building (Marp) | Presentation | -| `quality.mk` | 860B | Code quality and formatting | Quality and Formatting | -| `releasing.mk` | 2.0K | Release and versioning | Releasing and Versioning | -| `test.mk` | 5.1K | Testing infrastructure | Development and Testing | - -**Total**: 14 makefiles, ~41KB - -## 📦 Requirements (`.rhiza/requirements/`) - -| File | Purpose | -|------|---------| -| `docs.txt` | Documentation generation dependencies (pdoc) | -| `marimo.txt` | Marimo notebook dependencies | -| `tests.txt` | Testing dependencies (pytest, coverage) | -| `tools.txt` | Development tools (pre-commit, python-dotenv) | - -See [requirements/README.md](requirements/README.md) for details. - -## 🧪 Test Suite (`.rhiza/tests/`) - -| Directory | Purpose | -|-----------|---------| -| `api/` | Makefile target validation (dry-run tests) | -| `deps/` | Dependency health checks | -| `integration/` | End-to-end workflow tests | -| `structure/` | Static project structure assertions | -| `sync/` | Template sync and content validation | -| `utils/` | Test infrastructure utilities | - -**Total**: 23 Python test files - -See [tests/README.md](tests/README.md) for details. - -## 📚 Documentation (`.rhiza/docs/`) - -| File | Purpose | -|------|---------| -| `ASSETS.md` | Asset management documentation | -| `CONFIG.md` | Configuration file documentation | -| `LFS.md` | Git LFS setup and usage | -| `PRIVATE_PACKAGES.md` | Private package authentication | -| `RELEASING.md` | Release process documentation | -| `TOKEN_SETUP.md` | GitHub token setup | -| `WORKFLOWS.md` | GitHub Actions workflows | - -## 🎨 Assets (`.rhiza/assets/`) - -- `rhiza-logo.svg` - Rhiza logo graphic - -## 📋 Templates (`.rhiza/templates/`) - -- `minibook/` - Minimal documentation book template - -## 🔌 Template Bundles - -Defined in `template-bundles.yml`: - -| Bundle | Description | Files | -|--------|-------------|-------| -| `core` | Core Rhiza infrastructure | 43 files | -| `github` | GitHub Actions workflows | CI/CD | -| `tests` | Testing infrastructure | pytest, coverage | -| `marimo` | Interactive notebooks | Marimo support | -| `book` | Documentation generation | Book building | -| `docker` | Docker containerization | Dockerfile | -| `lfs` | Git LFS support | Large files | -| `presentation` | Presentation building | reveal.js | -| `gitlab` | GitLab CI/CD | GitLab workflows | -| `devcontainer` | VS Code DevContainer | Dev environment | -| `legal` | Legal documentation | LICENSE, CODE_OF_CONDUCT | - -## 🎯 Key Make Targets - -### Bootstrap -- `make install` - Install dependencies -- `make install-uv` - Ensure uv/uvx is installed -- `make clean` - Clean artifacts and stale branches - -### Development -- `make test` - Run test suite -- `make fmt` - Format code -- `make docs` - Generate documentation - -### AI Agents -- `make copilot` - GitHub Copilot interactive prompt -- `make claude` - Claude Code interactive prompt -- `make analyse-repo` - Update REPOSITORY_ANALYSIS.md - -### Documentation -- `make book` - Build documentation book -- `make marimo` - Start Marimo server -- `make presentation` - Generate presentation slides - -### Docker -- `make docker-build` - Build Docker image -- `make docker-run` - Run container - -### GitHub -- `make view-prs` - List open pull requests -- `make view-issues` - List open issues -- `make failed-workflows` - List failing workflows - -### Quality -- `make fmt` - Format code with ruff -- `make lint` - Lint code -- `make deptry` - Check dependencies - -### Releasing -- `make release` - Create a release -- `make bump` - Bump version - -## 🔗 Related Documentation - -- [Architecture Diagrams & Naming Conventions](../docs/ARCHITECTURE.md) - Visual architecture overview and detailed naming conventions -- [Makefile Cookbook](make.d/README.md) - Common patterns and recipes -- [Test Suite Guide](tests/README.md) - Testing conventions -- [Customization Guide](../docs/CUSTOMIZATION.md) - How to customize Rhiza -- [Quick Reference](../docs/QUICK_REFERENCE.md) - Common commands From c921325b3e971ebd60f818b48ab3a567f37fb2e4 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 07:57:31 +0400 Subject: [PATCH 08/30] =?UTF-8?q?Chore:=20bump=20version=200.8.17=20?= =?UTF-8?q?=E2=86=92=200.8.18?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4f4e620c..84dff9e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "rhiza" -version = "0.8.17" +version = "0.8.18" description = "Reusable configuration templates for modern Python projects" readme = "README.md" requires-python = ">=3.11" diff --git a/uv.lock b/uv.lock index e6a54943..f6504b18 100644 --- a/uv.lock +++ b/uv.lock @@ -565,7 +565,7 @@ wheels = [ [[package]] name = "rhiza" -version = "0.8.17" +version = "0.8.18" source = { virtual = "." } [package.dev-dependencies] From 0eacd22a6384cd9370feb68d8e4e126766aa08ac Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 08:45:32 +0400 Subject: [PATCH 09/30] chore: update template-bundles.yml to replace deprecated workflows with `rhiza_quality.yml` --- .rhiza/template-bundles.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.rhiza/template-bundles.yml b/.rhiza/template-bundles.yml index c254d074..9aa8471a 100644 --- a/.rhiza/template-bundles.yml +++ b/.rhiza/template-bundles.yml @@ -76,12 +76,10 @@ bundles: - .github/workflows/copilot-setup-steps.yml - .github/workflows/rhiza_validate.yml - .github/workflows/rhiza_sync.yml - - .github/workflows/rhiza_pre-commit.yml - - .github/workflows/rhiza_deptry.yml + - .github/workflows/rhiza_quality.yml - .github/workflows/rhiza_release.yml - .github/workflows/renovate_rhiza_sync.yml - .github/workflows/rhiza_pip_audit.yml - - .github/workflows/rhiza_typecheck.yml - .github/actions/configure-git-auth - .github/dependabot.yml - .github/copilot-instructions.md From 2c3fd697e1f8274834488d21ac3e403832c17ca5 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 08:48:44 +0400 Subject: [PATCH 10/30] chore: simplify CI trigger by removing branch restrictions --- .github/workflows/rhiza_ci.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/rhiza_ci.yml b/.github/workflows/rhiza_ci.yml index fbfd8907..3f5b8c1e 100644 --- a/.github/workflows/rhiza_ci.yml +++ b/.github/workflows/rhiza_ci.yml @@ -14,10 +14,7 @@ permissions: actions: read on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] + push jobs: generate-matrix: From b4f0916ddd9fae700d2cf09d7376dd619152eee3 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 08:49:33 +0400 Subject: [PATCH 11/30] chore: remove branch restrictions from GitHub Actions triggers --- .github/workflows/rhiza_quality.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/rhiza_quality.yml b/.github/workflows/rhiza_quality.yml index 81034577..1a455346 100644 --- a/.github/workflows/rhiza_quality.yml +++ b/.github/workflows/rhiza_quality.yml @@ -4,10 +4,7 @@ permissions: contents: read on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] + push jobs: deptry: From 1c519f5fee3270cdeb4cb456a6448f682e2483e7 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 08:56:27 +0400 Subject: [PATCH 12/30] fix: update broken markdown links to correct file paths Co-Authored-By: Claude Sonnet 4.6 --- README.md | 6 +++--- docs/CUSTOMIZATION.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index abc6f4ed..1c5552da 100644 --- a/README.md +++ b/README.md @@ -225,7 +225,7 @@ Keep your templates up-to-date with automated sync workflows: - The `.github/workflows/sync.yml` workflow runs on schedule or manually - Creates pull requests with template updates -For GitHub Token configuration and details, see the [GitHub Actions documentation](.github/README.md). +For GitHub Token configuration and details, see the [GitHub Actions documentation](.rhiza/docs/TOKEN_SETUP.md). ### What to Expect After Integration @@ -368,7 +368,7 @@ make presentation-pdf # Generate PDF slides make presentation-serve # Serve with live reload ``` -For detailed information about creating and customising presentations, see [presentation/README.md](presentation/README.md). +For detailed information about creating and customising presentations, see [presentation/README.md](docs/presentations/README.md). ### Documentation Examples @@ -392,7 +392,7 @@ Hello, World! ### Documentation Customisation -For information on customising the look and feel of your documentation, see [book/README.md](book/README.md). +For information on customising the look and feel of your documentation, see [book/README.md](docs/BOOK.md). ### Python Version Management diff --git a/docs/CUSTOMIZATION.md b/docs/CUSTOMIZATION.md index a446e290..7437856d 100644 --- a/docs/CUSTOMIZATION.md +++ b/docs/CUSTOMIZATION.md @@ -157,7 +157,7 @@ For example, to override the main module template, create `book/pdoc-templates/m See the [pdoc documentation on templates](https://pdoc.dev/docs/pdoc.html#edit-pdocs-html-template) for full details on how to override specific parts of the documentation. -For more details on customizing the documentation, see [book/README.md](../book/README.md). +For more details on customizing the documentation, see [book/README.md](BOOK.md). ## 📖 Complete Documentation From c1897417a75ab37f117e2f43b63e2794d9471c30 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 10:35:37 +0400 Subject: [PATCH 13/30] paper.mk --- .rhiza/make.d/paper.mk | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .rhiza/make.d/paper.mk diff --git a/.rhiza/make.d/paper.mk b/.rhiza/make.d/paper.mk new file mode 100644 index 00000000..f58f4104 --- /dev/null +++ b/.rhiza/make.d/paper.mk @@ -0,0 +1,33 @@ +## paper.mk - LaTeX paper compilation targets +# This file is included by the main Makefile + +PAPER_DIR ?= docs/paper + +.PHONY: paper paper-clean + +##@ Paper + +paper:: ## compile LaTeX documents in docs/paper to PDF using latexmk + @printf "${BLUE}[INFO] Checking for latexmk...${RESET}\n" + @if ! command -v latexmk >/dev/null 2>&1; then \ + printf "${RED}[ERROR] latexmk not found. Please install a LaTeX distribution (e.g., MacTeX, TeX Live).${RESET}\n"; \ + exit 1; \ + fi + @if [ -z "$$(find $(PAPER_DIR) -maxdepth 1 -name '*.tex' 2>/dev/null)" ]; then \ + printf "${YELLOW}[WARN] No .tex files found in $(PAPER_DIR), skipping.${RESET}\n"; \ + exit 0; \ + fi + @if [ -f $(PAPER_DIR)/basanos.tex ]; then \ + tex_file="basanos.tex"; \ + else \ + tex_file=$$(find $(PAPER_DIR) -maxdepth 1 -name "*.tex" | head -1 | xargs basename); \ + fi; \ + printf "${BLUE}[INFO] Compiling $$tex_file...${RESET}\n"; \ + cd $(PAPER_DIR) && latexmk -pdf -interaction=nonstopmode "$$tex_file" || exit 1; \ + pdf_file="$${tex_file%.tex}.pdf"; \ + printf "${GREEN}[SUCCESS] $(PAPER_DIR)/$$pdf_file${RESET}\n" + +paper-clean:: ## remove latexmk build artifacts in docs/paper + @printf "${BLUE}[INFO] Cleaning paper artifacts...${RESET}\n" + @cd $(PAPER_DIR) && latexmk -C 2>/dev/null || true + @printf "${GREEN}[SUCCESS] Cleaned $(PAPER_DIR)${RESET}\n" From 9afd0abf2d0cab8a05d958209a711b763cb842c3 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 10:37:31 +0400 Subject: [PATCH 14/30] chore: remove `--exclude-mail` flag from link checker configuration --- .github/workflows/rhiza_link_check.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/rhiza_link_check.yml b/.github/workflows/rhiza_link_check.yml index f1c6acb7..8b20880e 100644 --- a/.github/workflows/rhiza_link_check.yml +++ b/.github/workflows/rhiza_link_check.yml @@ -40,6 +40,5 @@ jobs: --verbose --no-progress --accept 200,206,429 - --exclude-mail README.md fail: true From c65c48329d8b7306cd74723bd25e708161a786cd Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 10:38:11 +0400 Subject: [PATCH 15/30] chore: remove branch restrictions from `rhiza_validate.yml` trigger --- .github/workflows/rhiza_validate.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/rhiza_validate.yml b/.github/workflows/rhiza_validate.yml index b894ec9d..80547eb3 100644 --- a/.github/workflows/rhiza_validate.yml +++ b/.github/workflows/rhiza_validate.yml @@ -5,9 +5,6 @@ permissions: on: push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] schedule: - cron: "0 9 * * 1" # Every Monday at 09:00 UTC (for pip-audit) workflow_dispatch: From 3d0ceb43f227a1c2cbf243e0bd6cb16d473a87a6 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 10:40:56 +0400 Subject: [PATCH 16/30] chore: update `.rhiza/template-bundles.yml` to replace outdated workflow references with `.rhiza/semgrep.yml` --- .rhiza/template-bundles.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.rhiza/template-bundles.yml b/.rhiza/template-bundles.yml index 9aa8471a..c0c62903 100644 --- a/.rhiza/template-bundles.yml +++ b/.rhiza/template-bundles.yml @@ -86,9 +86,7 @@ bundles: - .github/agents - .github/hooks - .github/secret_scanning.yml - - .github/workflows/rhiza_license.yml - - .semgrep.yml - - .github/workflows/rhiza_semgrep.yml + - .rhiza/semgrep.yml # Issue templates (config.yml excluded — contains repo-specific URLs) - .github/ISSUE_TEMPLATE/bug_report.yml - .github/ISSUE_TEMPLATE/feature_request.yml From e5335d53479b570a8eb361224b90f1e2494423d7 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 10:42:03 +0400 Subject: [PATCH 17/30] chore: remove `rhiza_pip_audit.yml` from template-bundles.yml --- .rhiza/template-bundles.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.rhiza/template-bundles.yml b/.rhiza/template-bundles.yml index c0c62903..95d84d1e 100644 --- a/.rhiza/template-bundles.yml +++ b/.rhiza/template-bundles.yml @@ -79,7 +79,6 @@ bundles: - .github/workflows/rhiza_quality.yml - .github/workflows/rhiza_release.yml - .github/workflows/renovate_rhiza_sync.yml - - .github/workflows/rhiza_pip_audit.yml - .github/actions/configure-git-auth - .github/dependabot.yml - .github/copilot-instructions.md From 2e5c9cd336f4c321d3164d5449864723aebe57e0 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 11:01:05 +0400 Subject: [PATCH 18/30] chore: remove `rhiza_security.yml` from template-bundles.yml --- .rhiza/template-bundles.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.rhiza/template-bundles.yml b/.rhiza/template-bundles.yml index 95d84d1e..2ec51fe8 100644 --- a/.rhiza/template-bundles.yml +++ b/.rhiza/template-bundles.yml @@ -221,7 +221,6 @@ bundles: # GitHub Actions workflows - .github/workflows/rhiza_ci.yml - - .github/workflows/rhiza_security.yml - .github/workflows/rhiza_codeql.yml - .github/workflows/rhiza_dep_compat_test.yml From 912c1ede678a31ad55955b768500c0128e3a308e Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 11:15:42 +0400 Subject: [PATCH 19/30] chore: remove event-based restrictions from `rhiza_validate.yml` triggers --- .github/workflows/rhiza_validate.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/rhiza_validate.yml b/.github/workflows/rhiza_validate.yml index 80547eb3..5a7f58a3 100644 --- a/.github/workflows/rhiza_validate.yml +++ b/.github/workflows/rhiza_validate.yml @@ -83,7 +83,6 @@ jobs: pip-audit: name: Dependency vulnerability scan runs-on: ubuntu-latest - if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' steps: - uses: actions/checkout@v6.0.2 @@ -99,7 +98,6 @@ jobs: typecheck: name: Type checking runs-on: ubuntu-latest - if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' steps: - uses: actions/checkout@v6.0.2 @@ -124,7 +122,6 @@ jobs: license: name: License compliance scan runs-on: ubuntu-latest - if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' steps: - uses: actions/checkout@v6.0.2 From 82ff7a689386e14a1c181f607d80536a08928fe0 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 11:24:07 +0400 Subject: [PATCH 20/30] chore: consolidate `license` and `semgrep` checks into `rhiza_validate.yml` and remove standalone workflows --- .gitlab/workflows/rhiza_license.yml | 20 -------------------- .gitlab/workflows/rhiza_semgrep.yml | 21 --------------------- .gitlab/workflows/rhiza_validate.yml | 20 ++++++++++++++++++++ 3 files changed, 20 insertions(+), 41 deletions(-) delete mode 100644 .gitlab/workflows/rhiza_license.yml delete mode 100644 .gitlab/workflows/rhiza_semgrep.yml diff --git a/.gitlab/workflows/rhiza_license.yml b/.gitlab/workflows/rhiza_license.yml deleted file mode 100644 index 40d931d8..00000000 --- a/.gitlab/workflows/rhiza_license.yml +++ /dev/null @@ -1,20 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: License compliance (GitLab CI) -# -# Purpose: This workflow checks that no copyleft-licensed dependencies -# (GPL, LGPL, AGPL) have been introduced via transitive updates. -# -# Trigger: This workflow runs on every push and on merge requests to main/master -# branches (including from forks) - -license:check: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - script: - - make license - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH diff --git a/.gitlab/workflows/rhiza_semgrep.yml b/.gitlab/workflows/rhiza_semgrep.yml deleted file mode 100644 index d2aa0fce..00000000 --- a/.gitlab/workflows/rhiza_semgrep.yml +++ /dev/null @@ -1,21 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Semgrep (GitLab CI) -# -# Purpose: This workflow runs static analysis using Semgrep with local numpy -# rules (.rhiza/semgrep.yml) to detect common NumPy-related bugs and -# security issues in Python code. -# -# Trigger: This workflow runs on every push and on merge requests to main/master -# branches (including from forks) - -semgrep:check: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - script: - - make semgrep - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH diff --git a/.gitlab/workflows/rhiza_validate.yml b/.gitlab/workflows/rhiza_validate.yml index aa727831..87e130f9 100644 --- a/.gitlab/workflows/rhiza_validate.yml +++ b/.gitlab/workflows/rhiza_validate.yml @@ -16,3 +16,23 @@ validate:rhiza: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH + +license:check: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - make license + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH + +semgrep:check: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - make semgrep + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH From 652d0b5ecad3a4c56e4a60719c3584feb9179f3c Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 11:59:08 +0400 Subject: [PATCH 21/30] feat: add GitLab CI workflows for link checking and paper compilation Co-Authored-By: Claude Sonnet 4.6 --- .gitlab/workflows/rhiza_link_check.yml | 25 ++++++++++++++ .gitlab/workflows/rhiza_paper.yml | 46 ++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 .gitlab/workflows/rhiza_link_check.yml create mode 100644 .gitlab/workflows/rhiza_paper.yml diff --git a/.gitlab/workflows/rhiza_link_check.yml b/.gitlab/workflows/rhiza_link_check.yml new file mode 100644 index 00000000..1137b3dd --- /dev/null +++ b/.gitlab/workflows/rhiza_link_check.yml @@ -0,0 +1,25 @@ +# This file is part of the jebel-quant/rhiza repository +# (https://github.com/jebel-quant/rhiza). +# +# Workflow: Link Check (GitLab CI) +# +# Purpose: This workflow checks that all hyperlinks in README.md are valid +# and not returning errors. It uses the lychee link checker. +# +# Trigger: This workflow runs on merge requests or pushes when README.md changes. +# For scheduled weekly runs, configure a pipeline schedule in GitLab UI. + +link:check: + stage: test + needs: [] + image: lycheeverse/lychee:latest + script: + - lychee --verbose --no-progress --accept 200,206,429 README.md + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + changes: + - README.md + - if: $CI_COMMIT_BRANCH + changes: + - README.md + - if: $CI_PIPELINE_SOURCE == "schedule" diff --git a/.gitlab/workflows/rhiza_paper.yml b/.gitlab/workflows/rhiza_paper.yml new file mode 100644 index 00000000..4d1ff6da --- /dev/null +++ b/.gitlab/workflows/rhiza_paper.yml @@ -0,0 +1,46 @@ +# This file is part of the jebel-quant/rhiza repository +# (https://github.com/jebel-quant/rhiza). +# +# Workflow: Paper (GitLab CI) +# +# Purpose: Compile the LaTeX paper (paper/*.tex) to a PDF and publish +# it as a downloadable pipeline artifact. +# Only active when a *.tex file exists under paper/. +# +# Trigger: On push to main/master or when files under paper/ change. + +paper:build: + stage: build + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + before_script: + - apt-get update && apt-get install -y texlive-latex-extra texlive-fonts-recommended texlive-bibtex-extra latexmk + script: + - | + if ! compgen -G "paper/*.tex" > /dev/null 2>&1; then + echo "No paper/*.tex found; skipping LaTeX compilation." + exit 0 + fi + + if [ -f paper/basanos.tex ]; then + tex_file="basanos.tex" + else + tex_file=$(find paper -maxdepth 1 -name "*.tex" | head -1 | xargs basename) + fi + pdf_file="${tex_file%.tex}.pdf" + + cd paper && latexmk -pdf -interaction=nonstopmode "${tex_file}" + cp "${pdf_file}" "../${pdf_file}" + artifacts: + paths: + - "*.pdf" + expire_in: 30 days + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "master" + changes: + - paper/**/* + - .gitlab/workflows/rhiza_paper.yml + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + changes: + - paper/**/* + - .gitlab/workflows/rhiza_paper.yml From 6dd977e1dfdaf076c4a28e0703261d59af7ffb1d Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 1 Apr 2026 12:09:52 +0400 Subject: [PATCH 22/30] =?UTF-8?q?Chore:=20bump=20version=200.8.18=20?= =?UTF-8?q?=E2=86=92=200.8.19?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 84dff9e2..963f8441 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "rhiza" -version = "0.8.18" +version = "0.8.19" description = "Reusable configuration templates for modern Python projects" readme = "README.md" requires-python = ">=3.11" diff --git a/uv.lock b/uv.lock index f6504b18..d35f0ab7 100644 --- a/uv.lock +++ b/uv.lock @@ -565,7 +565,7 @@ wheels = [ [[package]] name = "rhiza" -version = "0.8.18" +version = "0.8.19" source = { virtual = "." } [package.dev-dependencies] From 55a98d2712c2149b729dbfa1a15b990cf25a51c7 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Thu, 2 Apr 2026 06:13:42 +0400 Subject: [PATCH 23/30] chore: update semgrep config path to .rhiza/semgrep.yml Co-Authored-By: Claude Sonnet 4.6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7eb6f644..2ec821ce 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ security: install ## run security scans (pip-audit and bandit) semgrep: install ## run Semgrep static analysis (numpy rules) @printf "${BLUE}[INFO] Running Semgrep (numpy rules)...${RESET}\n" @if [ -d ${SOURCE_FOLDER} ]; then \ - ${UVX_BIN} semgrep --config .semgrep.yml ${SOURCE_FOLDER}; \ + ${UVX_BIN} semgrep --config .rhiza/semgrep.yml ${SOURCE_FOLDER}; \ else \ printf "${YELLOW}[WARN] SOURCE_FOLDER '${SOURCE_FOLDER}' not found, skipping semgrep.${RESET}\n"; \ fi From 5f20d8574b004e9d12314871d9b14652faeb2ea1 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Thu, 2 Apr 2026 06:56:16 +0400 Subject: [PATCH 24/30] chore: consolidate GitHub Actions workflows - Merge rhiza_quality, rhiza_validate, rhiza_link_check into rhiza_ci or rhiza_weekly - Merge renovate_rhiza_sync into rhiza_sync (two jobs: direct commit vs PR) - Move dep-compat-test, semgrep, pip-audit, link-check into new rhiza_weekly - Move typecheck from rhiza_validate into rhiza_ci - Remove rhiza_dep_compat_test, rhiza_quality, rhiza_validate, rhiza_link_check, renovate_rhiza_sync (all superseded) - Update template-bundles.yml to reflect new workflow set Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/renovate_rhiza_sync.yml | 84 ----------- .github/workflows/rhiza_ci.yml | 155 +++++++++++++++++++- .github/workflows/rhiza_dep_compat_test.yml | 56 ------- .github/workflows/rhiza_link_check.yml | 44 ------ .github/workflows/rhiza_quality.yml | 97 ------------ .github/workflows/rhiza_sync.yml | 104 +++++++++++-- .github/workflows/rhiza_validate.yml | 155 -------------------- .github/workflows/rhiza_weekly.yml | 118 +++++++++++++++ .rhiza/template-bundles.yml | 6 +- 9 files changed, 365 insertions(+), 454 deletions(-) delete mode 100644 .github/workflows/renovate_rhiza_sync.yml delete mode 100644 .github/workflows/rhiza_dep_compat_test.yml delete mode 100644 .github/workflows/rhiza_link_check.yml delete mode 100644 .github/workflows/rhiza_quality.yml delete mode 100644 .github/workflows/rhiza_validate.yml create mode 100644 .github/workflows/rhiza_weekly.yml diff --git a/.github/workflows/renovate_rhiza_sync.yml b/.github/workflows/renovate_rhiza_sync.yml deleted file mode 100644 index 26e91c79..00000000 --- a/.github/workflows/renovate_rhiza_sync.yml +++ /dev/null @@ -1,84 +0,0 @@ -name: Rhiza Template Sync -# Automatically sync rhiza template files when Renovate updates .rhiza/template.yml - -on: - push: - branches: - - 'renovate/jebel-quant-rhiza-**' - - 'rhiza/**' - paths: - - '.rhiza/template.yml' - -permissions: - contents: write - -jobs: - sync-template: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v6.0.2 - with: - ref: ${{ github.ref }} - token: ${{ secrets.PAT_TOKEN || github.token }} - - - name: Check PAT_TOKEN configuration - shell: bash - env: - PAT_TOKEN: ${{ secrets.PAT_TOKEN }} - run: | - if [ -z "$PAT_TOKEN" ]; then - echo "::warning::PAT_TOKEN secret is not configured." - echo "::warning::If this sync modifies workflow files, the push will fail." - echo "::warning::See .rhiza/docs/TOKEN_SETUP.md for setup instructions." - else - echo "✓ PAT_TOKEN is configured." - fi - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - - - name: Get Rhiza version - id: rhiza-version - run: | - VERSION=$(cat .rhiza/.rhiza-version 2>/dev/null || echo "0.9.0") - echo "version=${VERSION}" >> "$GITHUB_OUTPUT" - - - name: Sync rhiza template - id: sync - run: | - set -euo pipefail - - RHIZA_VERSION="${{ steps.rhiza-version.outputs.version }}" - - echo "Running rhiza sync with version >=${RHIZA_VERSION}" - uvx "rhiza>=${RHIZA_VERSION}" sync . - - if git diff --quiet; then - echo "No changes detected after template sync" - echo "changes=false" >> "$GITHUB_OUTPUT" - exit 0 - fi - - echo "Template changes detected" - echo "changes=true" >> "$GITHUB_OUTPUT" - - - name: Commit and push changes - if: steps.sync.outputs.changes == 'true' - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config --global url."https://x-access-token:${{ secrets.PAT_TOKEN || github.token }}@github.com/".insteadOf "https://github.com/" - - git add -A - git commit -m "$(cat <<'EOF' - chore: sync rhiza template files - - Automatically synced template files after updating .rhiza/template.yml - - Co-Authored-By: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> - EOF - )" - - git push diff --git a/.github/workflows/rhiza_ci.yml b/.github/workflows/rhiza_ci.yml index 3f5b8c1e..409a4954 100644 --- a/.github/workflows/rhiza_ci.yml +++ b/.github/workflows/rhiza_ci.yml @@ -3,9 +3,11 @@ # # Workflow: Continuous Integration # -# Purpose: Run tests on multiple Python versions to ensure compatibility. +# Purpose: Run tests on multiple Python versions, check dependencies, run +# pre-commit hooks, verify documentation coverage, validate the +# project, run security scans, and check license compliance. # -# Trigger: On push and pull requests to main/master branches. +# Trigger: On push. name: (RHIZA) CI @@ -89,6 +91,74 @@ jobs: if-no-files-found: ignore + typecheck: + name: Type checking + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run ty type checker (make typecheck) + # Runs `uv run ty check src/` as defined in .rhiza/make.d/test.mk. + # ty is configured via [tool.ty.environment] in pyproject.toml. + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make typecheck + + deptry: + name: Check dependencies with deptry + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run deptry + run: make deptry + + pre-commit: + name: Pre-commit hooks + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Cache pre-commit environments + uses: actions/cache@v5 + with: + path: ~/.cache/pre-commit + key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }} + restore-keys: | + pre-commit-${{ runner.os }}- + + - name: Run pre-commit + run: | + make fmt + docs-coverage: runs-on: ubuntu-latest steps: @@ -111,6 +181,87 @@ jobs: run: | make docs-coverage + validation: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v6.0.2 + with: + lfs: true + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Validate + shell: bash + run: | + make validate + + security: + name: Security scanning + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run security scans + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make security + + license: + name: License compliance scan + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run license check + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make license + + - name: Generate LICENSES.md + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: | + uv run --with pip-licenses pip-licenses --format markdown --output-file LICENSES.md + + - name: Upload LICENSES.md + uses: actions/upload-artifact@v7 + with: + name: LICENSES.md + path: LICENSES.md + if-no-files-found: ignore + coverage-badge: needs: test runs-on: ubuntu-latest diff --git a/.github/workflows/rhiza_dep_compat_test.yml b/.github/workflows/rhiza_dep_compat_test.yml deleted file mode 100644 index 7b38d0d9..00000000 --- a/.github/workflows/rhiza_dep_compat_test.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: "(RHIZA) DEPENDENCY COMPATIBILITY (WEEKLY)" - -# Resolves all dependencies fresh—ignoring the committed lockfile—and runs -# the full test suite. Failure here means a newly-released package version -# (e.g. pydantic v3, scipy v2, numpy v3) is incompatible with the current -# code, providing an early-warning signal before the lockfile is next -# refreshed by Renovate or a manual bump. -# -# See: https://github.com/Jebel-Quant/basanos/issues/ - -permissions: - contents: read - -on: - schedule: - - cron: "0 9 * * 3" # Every Wednesday at 09:00 UTC - workflow_dispatch: - -jobs: - dep-compat-test: - name: Test with latest compatible dependencies - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v6.0.2 - with: - lfs: true - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Resolve and install latest compatible dependencies - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: | - # --upgrade ignores the committed lockfile and resolves the newest - # versions that satisfy pyproject.toml constraints. - uv sync --upgrade - - - name: Show resolved package versions - run: | - echo "=== Installed package versions ===" - uv pip list - - - name: Run tests - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make test diff --git a/.github/workflows/rhiza_link_check.yml b/.github/workflows/rhiza_link_check.yml deleted file mode 100644 index 8b20880e..00000000 --- a/.github/workflows/rhiza_link_check.yml +++ /dev/null @@ -1,44 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Link Check -# -# Purpose: This workflow checks that all hyperlinks in README.md are valid -# and not returning errors. It uses the lychee link checker. -# -# Trigger: This workflow runs on push/PR when README.md changes and on a -# weekly schedule every Monday at 08:00 UTC. - -name: "(RHIZA) LINK CHECK" - -# Permissions: Only read access to repository contents is needed -permissions: - contents: read - -on: - push: - branches: [main] - paths: [README.md] - pull_request: - paths: [README.md] - schedule: - - cron: "0 8 * * 1" # Every Monday at 08:00 UTC - workflow_dispatch: - -jobs: - link-check: - name: Check links in README.md - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Check links in README.md - uses: lycheeverse/lychee-action@v2 - with: - args: >- - --verbose - --no-progress - --accept 200,206,429 - README.md - fail: true diff --git a/.github/workflows/rhiza_quality.yml b/.github/workflows/rhiza_quality.yml deleted file mode 100644 index 1a455346..00000000 --- a/.github/workflows/rhiza_quality.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: (RHIZA) QUALITY - -permissions: - contents: read - -on: - push - -jobs: - deptry: - name: Check dependencies with deptry - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run deptry - run: make deptry - # NOTE: make deptry is good style because it encapsulates the folders to check - # (e.g. src and book/marimo) and keeps CI in sync with local development. - # Since we have uv/uvx installed, the Makefile is optimised to use the - # pre-installed 'uv' and 'uvx' from the system PATH. - - pre-commit: - name: Pre-commit hooks - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - # Cache pre-commit environments and hooks - - name: Cache pre-commit environments - uses: actions/cache@v5 - with: - path: ~/.cache/pre-commit - key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }} - restore-keys: | - pre-commit-${{ runner.os }}- - - # Run pre-commit - - name: Run pre-commit - run: | - make fmt - - docs-coverage: - name: Documentation coverage - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Check docs coverage - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make docs-coverage - - link-check: - name: Check links in README.md - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Check links in README.md - uses: lycheeverse/lychee-action@v2 - with: - args: >- - --verbose - --no-progress - --accept 200,206,429 - README.md - fail: true diff --git a/.github/workflows/rhiza_sync.yml b/.github/workflows/rhiza_sync.yml index 9d06fd2e..31256203 100644 --- a/.github/workflows/rhiza_sync.yml +++ b/.github/workflows/rhiza_sync.yml @@ -1,27 +1,107 @@ name: (RHIZA) SYNC -# This workflow synchronizes the repository with its template. -# IMPORTANT: When workflow files (.github/workflows/rhiza_*.yml) are modified, -# a Personal Access Token (PAT) with 'workflow' scope is required. -# The PAT_TOKEN secret must be set in repository secrets. -# See .github/rhiza/TOKEN_SETUP.md for setup instructions. +# Synchronizes the repository with its rhiza template. +# - On Renovate/rhiza branch push: auto-commits synced files directly to the branch. +# - On schedule/dispatch: opens a pull request with the synced changes. +# +# IMPORTANT: A PAT with 'workflow' scope (PAT_TOKEN) is required when workflow +# files are modified. See .rhiza/docs/TOKEN_SETUP.md for setup instructions. permissions: contents: write pull-requests: write on: + push: + branches: + - 'renovate/jebel-quant-rhiza-**' + - 'rhiza/**' + paths: + - '.rhiza/template.yml' + schedule: + - cron: '0 0 * * 1' # Weekly on Monday workflow_dispatch: inputs: create-pr: description: "Create a pull request" type: boolean default: true - schedule: - - cron: '0 0 * * 1' # Weekly on Monday jobs: - sync: - if: ${{ github.repository != 'jebel-quant/rhiza' }} + sync-direct: + name: Sync and commit (Renovate) + if: github.event_name == 'push' + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v6.0.2 + with: + ref: ${{ github.ref }} + token: ${{ secrets.PAT_TOKEN || github.token }} + + - name: Check PAT_TOKEN configuration + shell: bash + env: + PAT_TOKEN: ${{ secrets.PAT_TOKEN }} + run: | + if [ -z "$PAT_TOKEN" ]; then + echo "::warning::PAT_TOKEN secret is not configured." + echo "::warning::If this sync modifies workflow files, the push will fail." + echo "::warning::See .rhiza/docs/TOKEN_SETUP.md for setup instructions." + else + echo "✓ PAT_TOKEN is configured." + fi + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + + - name: Get Rhiza version + id: rhiza-version + run: | + VERSION=$(cat .rhiza/.rhiza-version 2>/dev/null || echo "0.9.0") + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + + - name: Sync rhiza template + id: sync + run: | + set -euo pipefail + + RHIZA_VERSION="${{ steps.rhiza-version.outputs.version }}" + + echo "Running rhiza sync with version >=${RHIZA_VERSION}" + uvx "rhiza>=${RHIZA_VERSION}" sync . + + if git diff --quiet; then + echo "No changes detected after template sync" + echo "changes=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "Template changes detected" + echo "changes=true" >> "$GITHUB_OUTPUT" + + - name: Commit and push changes + if: steps.sync.outputs.changes == 'true' + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --global url."https://x-access-token:${{ secrets.PAT_TOKEN || github.token }}@github.com/".insteadOf "https://github.com/" + + git add -A + git commit -m "$(cat <<'EOF' + chore: sync rhiza template files + + Automatically synced template files after updating .rhiza/template.yml + + Co-Authored-By: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> + EOF + )" + + git push + + sync-pr: + name: Sync and open PR (scheduled/manual) + if: github.event_name != 'push' && github.repository != 'jebel-quant/rhiza' runs-on: ubuntu-latest steps: @@ -44,7 +124,7 @@ jobs: if [ -z "$PAT_TOKEN" ]; then echo "::warning::PAT_TOKEN secret is not configured." echo "::warning::If this sync modifies workflow files, the push will fail." - echo "::warning::See .github/TOKEN_SETUP.md for setup instructions." + echo "::warning::See .rhiza/docs/TOKEN_SETUP.md for setup instructions." else echo "✓ PAT_TOKEN is configured." fi @@ -85,7 +165,7 @@ jobs: git config --global url."https://x-access-token:${{ secrets.PAT_TOKEN }}@github.com/".insteadOf "https://github.com/" git commit -m "chore: Update via rhiza" - + - name: Create pull request if: > (github.event_name == 'schedule' || inputs.create-pr == true) @@ -97,4 +177,4 @@ jobs: branch: ${{ steps.branch.outputs.name }} delete-branch: true title: "chore: Sync with rhiza" - body-path: ${{ runner.temp }}/pr-description.md \ No newline at end of file + body-path: ${{ runner.temp }}/pr-description.md diff --git a/.github/workflows/rhiza_validate.yml b/.github/workflows/rhiza_validate.yml deleted file mode 100644 index 5a7f58a3..00000000 --- a/.github/workflows/rhiza_validate.yml +++ /dev/null @@ -1,155 +0,0 @@ -name: (RHIZA) VALIDATE - -permissions: - contents: read - -on: - push: - schedule: - - cron: "0 9 * * 1" # Every Monday at 09:00 UTC (for pip-audit) - workflow_dispatch: - -jobs: - validation: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v6.0.2 - with: - lfs: true - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Validate - shell: bash - run: | - make validate - - semgrep: - name: Semgrep (numpy) - runs-on: ubuntu-latest - if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run Semgrep - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make semgrep - - security: - name: Security scanning - runs-on: ubuntu-latest - if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run security scans - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make security - - pip-audit: - name: Dependency vulnerability scan - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Run pip-audit - run: uvx pip-audit - - typecheck: - name: Type checking - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run ty type checker (make typecheck) - # Runs `uv run ty check src/` as defined in .rhiza/make.d/test.mk. - # ty is configured via [tool.ty.environment] in pyproject.toml. - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make typecheck - - license: - name: License compliance scan - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@v7.6.0 - with: - version: "0.11.2" - - - name: Configure git auth for private packages - uses: ./.github/actions/configure-git-auth - with: - token: ${{ secrets.GH_PAT }} - - - name: Run license check - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: make license - - - name: Generate LICENSES.md - env: - UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} - run: | - uv run --with pip-licenses pip-licenses --format markdown --output-file LICENSES.md - - - name: Upload LICENSES.md - uses: actions/upload-artifact@v7 - with: - name: LICENSES.md - path: LICENSES.md - if-no-files-found: ignore diff --git a/.github/workflows/rhiza_weekly.yml b/.github/workflows/rhiza_weekly.yml new file mode 100644 index 00000000..7b925e0f --- /dev/null +++ b/.github/workflows/rhiza_weekly.yml @@ -0,0 +1,118 @@ +name: "(RHIZA) WEEKLY" + +# Runs weekly checks that are too slow or noisy for every push: +# +# dep-compat-test — Resolves all dependencies fresh (ignoring the lockfile) +# and runs the full test suite. Catches newly-released +# packages that break compatibility before Renovate picks +# them up. Runs on schedule/dispatch only. +# +# link-check — Verifies that all hyperlinks in README.md are reachable. +# Also runs on push/PR when README.md changes. + +permissions: + contents: read + +on: + #push: + # branches: [main] + # paths: [README.md] + #pull_request: + # paths: [README.md] + schedule: + - cron: "0 8 * * 1" # Every Monday at 08:00 UTC + workflow_dispatch: + +jobs: + dep-compat-test: + name: Test with latest compatible dependencies + runs-on: ubuntu-latest + #if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + + steps: + - name: Checkout repository + uses: actions/checkout@v6.0.2 + with: + lfs: true + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Resolve and install latest compatible dependencies + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: | + # --upgrade ignores the committed lockfile and resolves the newest + # versions that satisfy pyproject.toml constraints. + uv sync --upgrade + + - name: Show resolved package versions + run: | + echo "=== Installed package versions ===" + uv pip list + + - name: Run tests + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make test + + semgrep: + name: Semgrep (numpy) + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Configure git auth for private packages + uses: ./.github/actions/configure-git-auth + with: + token: ${{ secrets.GH_PAT }} + + - name: Run Semgrep + env: + UV_EXTRA_INDEX_URL: ${{ secrets.UV_EXTRA_INDEX_URL }} + run: make semgrep + + pip-audit: + name: Dependency vulnerability scan + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@v7.6.0 + with: + version: "0.11.2" + + - name: Run pip-audit + run: uvx pip-audit + + link-check: + name: Check links in README.md + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6.0.2 + + - name: Check links in README.md + uses: lycheeverse/lychee-action@v2 + with: + args: >- + --verbose + --no-progress + --accept 200,206,429 + README.md + fail: true diff --git a/.rhiza/template-bundles.yml b/.rhiza/template-bundles.yml index 2ec51fe8..12c9869e 100644 --- a/.rhiza/template-bundles.yml +++ b/.rhiza/template-bundles.yml @@ -74,11 +74,9 @@ bundles: - .rhiza/make.d/agentic.mk # Core GitHub Actions workflows - .github/workflows/copilot-setup-steps.yml - - .github/workflows/rhiza_validate.yml - .github/workflows/rhiza_sync.yml - - .github/workflows/rhiza_quality.yml - .github/workflows/rhiza_release.yml - - .github/workflows/renovate_rhiza_sync.yml + - .github/workflows/rhiza_weekly.yml - .github/actions/configure-git-auth - .github/dependabot.yml - .github/copilot-instructions.md @@ -222,7 +220,7 @@ bundles: # GitHub Actions workflows - .github/workflows/rhiza_ci.yml - .github/workflows/rhiza_codeql.yml - - .github/workflows/rhiza_dep_compat_test.yml + - .github/workflows/rhiza_weekly.yml # ============================================================================ # BENCHMARKS - Performance benchmarking with pytest-benchmark From 820c50e59962f28c4fe21709841e387e5226177f Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Thu, 2 Apr 2026 07:02:35 +0400 Subject: [PATCH 25/30] chore: consolidate GitLab CI workflows to mirror GitHub Actions structure - Merge rhiza_quality and rhiza_validate into rhiza_ci - Move semgrep and link-check into new rhiza_weekly - Add pip-audit to rhiza_weekly - Add typecheck and security jobs to rhiza_ci - Remove rhiza_quality, rhiza_validate, rhiza_link_check (superseded) Co-Authored-By: Claude Sonnet 4.6 --- .gitlab/workflows/rhiza_ci.yml | 72 +++++++++++++++++++++++++- .gitlab/workflows/rhiza_link_check.yml | 25 --------- .gitlab/workflows/rhiza_quality.yml | 54 ------------------- .gitlab/workflows/rhiza_validate.yml | 38 -------------- .gitlab/workflows/rhiza_weekly.yml | 55 ++++++++++++++++++++ 5 files changed, 125 insertions(+), 119 deletions(-) delete mode 100644 .gitlab/workflows/rhiza_link_check.yml delete mode 100644 .gitlab/workflows/rhiza_quality.yml delete mode 100644 .gitlab/workflows/rhiza_validate.yml create mode 100644 .gitlab/workflows/rhiza_weekly.yml diff --git a/.gitlab/workflows/rhiza_ci.yml b/.gitlab/workflows/rhiza_ci.yml index 2798398f..0fe651c5 100644 --- a/.gitlab/workflows/rhiza_ci.yml +++ b/.gitlab/workflows/rhiza_ci.yml @@ -3,9 +3,11 @@ # # Workflow: Continuous Integration (GitLab CI) # -# Purpose: Run tests on multiple Python versions to ensure compatibility. +# Purpose: Run tests on multiple Python versions, check dependencies, run +# pre-commit hooks, verify documentation coverage, validate the +# project, run security scans, and check license compliance. # -# Trigger: On push and merge requests to main/master branches. +# Trigger: On push and merge requests. ci:test: stage: test @@ -39,3 +41,69 @@ ci:docs-coverage: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH + +ci:typecheck: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - export UV_EXTRA_INDEX_URL="${UV_EXTRA_INDEX_URL}" + - uv venv + - make typecheck + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH + +ci:deptry: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - make deptry + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH + +ci:pre-commit: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - make fmt + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH + +ci:validate: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - make validate + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH + +ci:security: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - export UV_EXTRA_INDEX_URL="${UV_EXTRA_INDEX_URL}" + - uv venv + - make security + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH + +ci:license: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - export UV_EXTRA_INDEX_URL="${UV_EXTRA_INDEX_URL}" + - uv venv + - make license + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH diff --git a/.gitlab/workflows/rhiza_link_check.yml b/.gitlab/workflows/rhiza_link_check.yml deleted file mode 100644 index 1137b3dd..00000000 --- a/.gitlab/workflows/rhiza_link_check.yml +++ /dev/null @@ -1,25 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Link Check (GitLab CI) -# -# Purpose: This workflow checks that all hyperlinks in README.md are valid -# and not returning errors. It uses the lychee link checker. -# -# Trigger: This workflow runs on merge requests or pushes when README.md changes. -# For scheduled weekly runs, configure a pipeline schedule in GitLab UI. - -link:check: - stage: test - needs: [] - image: lycheeverse/lychee:latest - script: - - lychee --verbose --no-progress --accept 200,206,429 README.md - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - changes: - - README.md - - if: $CI_COMMIT_BRANCH - changes: - - README.md - - if: $CI_PIPELINE_SOURCE == "schedule" diff --git a/.gitlab/workflows/rhiza_quality.yml b/.gitlab/workflows/rhiza_quality.yml deleted file mode 100644 index acc49940..00000000 --- a/.gitlab/workflows/rhiza_quality.yml +++ /dev/null @@ -1,54 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Quality (GitLab CI) -# -# Purpose: Run quality checks including dependency validation, pre-commit hooks, -# documentation coverage, and link checking. -# -# Trigger: This workflow runs on every push and on merge requests to main/master -# branches (including from forks) -# -# Equivalent GitHub Action: .github/workflows/rhiza_quality.yml - -quality:deptry: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - script: - - make deptry - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH - -quality:pre-commit: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - script: - - make fmt - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH - -quality:docs-coverage: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - variables: - UV_EXTRA_INDEX_URL: "${UV_EXTRA_INDEX_URL}" - script: - - make docs-coverage - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH - -quality:link-check: - stage: test - needs: [] - image: ghcr.io/lycheeverse/lychee:latest - script: - - lychee --verbose --no-progress --accept 200,206,429 README.md - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH diff --git a/.gitlab/workflows/rhiza_validate.yml b/.gitlab/workflows/rhiza_validate.yml deleted file mode 100644 index 87e130f9..00000000 --- a/.gitlab/workflows/rhiza_validate.yml +++ /dev/null @@ -1,38 +0,0 @@ -# This file is part of the jebel-quant/rhiza repository -# (https://github.com/jebel-quant/rhiza). -# -# Workflow: Rhiza Validate (GitLab CI) -# -# Purpose: Validates Rhiza configuration -# -# Trigger: This workflow runs on every push and on merge requests to main/master - -validate:rhiza: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - script: - - make validate - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH - -license:check: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - script: - - make license - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH - -semgrep:check: - stage: test - needs: [] - image: ghcr.io/astral-sh/uv:0.9.30-bookworm - script: - - make semgrep - rules: - - if: $CI_PIPELINE_SOURCE == "merge_request_event" - - if: $CI_COMMIT_BRANCH diff --git a/.gitlab/workflows/rhiza_weekly.yml b/.gitlab/workflows/rhiza_weekly.yml new file mode 100644 index 00000000..ff5e409d --- /dev/null +++ b/.gitlab/workflows/rhiza_weekly.yml @@ -0,0 +1,55 @@ +# This file is part of the jebel-quant/rhiza repository +# (https://github.com/jebel-quant/rhiza). +# +# Workflow: Weekly (GitLab CI) +# +# Purpose: Slower checks deferred to a weekly schedule: +# +# weekly:semgrep — Semgrep static analysis (numpy rules). +# weekly:pip-audit — Dependency vulnerability scan. +# weekly:link-check — Verifies hyperlinks in README.md are reachable. +# Also runs on push/MR when README.md changes. +# +# Trigger: Scheduled pipeline (configure weekly in GitLab CI/CD Schedules), +# or manually via the web UI. + +weekly:semgrep: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - export UV_EXTRA_INDEX_URL="${UV_EXTRA_INDEX_URL}" + - uv venv + - make semgrep + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" + - if: $CI_PIPELINE_SOURCE == "web" + when: manual + allow_failure: true + +weekly:pip-audit: + stage: test + needs: [] + image: ghcr.io/astral-sh/uv:0.9.30-bookworm + script: + - uvx pip-audit + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" + - if: $CI_PIPELINE_SOURCE == "web" + when: manual + allow_failure: true + +weekly:link-check: + stage: test + needs: [] + image: lycheeverse/lychee:latest + script: + - lychee --verbose --no-progress --accept 200,206,429 README.md + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + changes: + - README.md + - if: $CI_COMMIT_BRANCH + changes: + - README.md + - if: $CI_PIPELINE_SOURCE == "schedule" From 44bd5cf592e53a7888e66f16b4eb00fc91b7f5b3 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Thu, 2 Apr 2026 07:14:55 +0400 Subject: [PATCH 26/30] docs: fix bibliography formatting and add bibtex to paper build - Sort references alphabetically by author last name - Use Lastname, F. author format throughout - Remove quotation marks from titles - Fix three overfull \hbox warnings (emergencystretch, minor rephrases) - Add -bibtex flag to latexmk in paper.mk - Add LaTeX build artifacts to .gitignore Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 8 +++++++ .rhiza/make.d/paper.mk | 2 +- Makefile | 13 ++++++----- docs/paper/rhiza.pdf | Bin 0 -> 268036 bytes docs/paper/rhiza.tex | 49 +++++++++++++++++++++-------------------- 5 files changed, 41 insertions(+), 31 deletions(-) create mode 100644 docs/paper/rhiza.pdf diff --git a/.gitignore b/.gitignore index 0d16b942..24c7706d 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,14 @@ _benchmarks _jupyter _site +# LaTeX build artifacts +docs/paper/*.aux +docs/paper/*.fdb_latexmk +docs/paper/*.fls +docs/paper/*.log +docs/paper/*.out +docs/paper/*.toc + # temp file used by Junie .output.txt diff --git a/.rhiza/make.d/paper.mk b/.rhiza/make.d/paper.mk index f58f4104..1733969d 100644 --- a/.rhiza/make.d/paper.mk +++ b/.rhiza/make.d/paper.mk @@ -23,7 +23,7 @@ paper:: ## compile LaTeX documents in docs/paper to PDF using latexmk tex_file=$$(find $(PAPER_DIR) -maxdepth 1 -name "*.tex" | head -1 | xargs basename); \ fi; \ printf "${BLUE}[INFO] Compiling $$tex_file...${RESET}\n"; \ - cd $(PAPER_DIR) && latexmk -pdf -interaction=nonstopmode "$$tex_file" || exit 1; \ + cd $(PAPER_DIR) && latexmk -pdf -bibtex -interaction=nonstopmode "$$tex_file" || exit 1; \ pdf_file="$${tex_file%.tex}.pdf"; \ printf "${GREEN}[SUCCESS] $(PAPER_DIR)/$$pdf_file${RESET}\n" diff --git a/Makefile b/Makefile index 2ec821ce..1044038d 100644 --- a/Makefile +++ b/Makefile @@ -20,12 +20,13 @@ post-validate:: ##@ Security -.PHONY: security -security: install ## run security scans (pip-audit and bandit) - @printf "${BLUE}[INFO] Running pip-audit for dependency vulnerabilities...${RESET}\n" - @${UVX_BIN} pip-audit - @printf "${BLUE}[INFO] Running bandit security scan...${RESET}\n" - @${UVX_BIN} bandit -r ${SOURCE_FOLDER} -ll -q -c pyproject.toml + +#.PHONY: security +#security: install ## run security scans (pip-audit and bandit) +# @printf "${BLUE}[INFO] Running pip-audit for dependency vulnerabilities...${RESET}\n" +# @${UVX_BIN} pip-audit +# @printf "${BLUE}[INFO] Running bandit security scan...${RESET}\n" +# @${UVX_BIN} bandit -r ${SOURCE_FOLDER} -ll -q -c pyproject.toml ##@ Quality diff --git a/docs/paper/rhiza.pdf b/docs/paper/rhiza.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e1557c81883637260d27c7e97c77d0608c0d8b85 GIT binary patch literal 268036 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 literal 0 HcmV?d00001 diff --git a/docs/paper/rhiza.tex b/docs/paper/rhiza.tex index 43c4c8fe..e3b01a96 100644 --- a/docs/paper/rhiza.tex +++ b/docs/paper/rhiza.tex @@ -6,6 +6,7 @@ \usepackage[margin=2.5cm]{geometry} \usepackage{hyperref} \usepackage{microtype} +\emergencystretch=2em \usepackage{booktabs} \usepackage{listings} \usepackage{xcolor} @@ -207,7 +208,7 @@ \subsection{Continuous Quality Enforcement} \paragraph{CI pipelines.} The \texttt{github} and \texttt{gitlab} bundles provide workflows that run on every pull request: unit tests across Python 3.11--3.14, type checking with \texttt{ty}, dependency validation with \texttt{deptry}, security scanning with \texttt{pip-audit} and \texttt{bandit}, and static analysis with \texttt{semgrep}. -\paragraph{Automated dependency updates.} A Renovate configuration file, included in the \texttt{core} bundle, opens pull requests whenever a pinned dependency or the \texttt{ref} in \texttt{.rhiza/template.yml} is updated upstream. This closes the loop: Rhiza itself is treated as a dependency that can be automatically proposed for upgrade. +\paragraph{Automated dependency updates.} A Renovate configuration file, included in the \texttt{core} bundle, opens pull requests whenever a pinned dependency or the template \texttt{ref} is updated upstream. This closes the loop: Rhiza itself is treated as a dependency that can be automatically proposed for upgrade. \subsection{Agentic Workflow Integration} @@ -237,7 +238,7 @@ \subsection{Conflict Resolution in Practice} \begin{enumerate}[leftmargin=*] \item \textbf{Bundle granularity.} By grouping files into coarse bundles, Rhiza reduces the frequency with which any given downstream file is touched by an upstream update. \item \textbf{Makefile hooks.} Downstream projects that need to extend a Makefile target can do so by adding a \texttt{::} target in \texttt{local.mk} rather than modifying the managed file. The managed file can therefore be updated freely. - \item \textbf{Configuration delegation.} Where possible, tool configuration is placed in \texttt{pyproject.toml} (owned by the downstream project) rather than in separate managed files. The template provides a commented scaffold section; the downstream project fills it in. + \item \textbf{Configuration delegation.} Where possible, tool configuration resides in \texttt{pyproject.toml} (owned by the downstream project) rather than in separate managed files. The template provides a commented scaffold section; the downstream project fills it in. \end{enumerate} \subsection{Architecture Decision Records} @@ -297,41 +298,41 @@ \section{Conclusion} \bibliographystyle{plain} \begin{thebibliography}{99} -\bibitem{humble2010continuous} -J.~Humble and D.~Farley, \textit{Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation}. Addison-Wesley, 2010. +\bibitem{claudecode} +Anthropic, Claude Code: Agentic coding in the terminal. \url{https://claude.ai/code}, 2025--. -\bibitem{fowler2016infrastructure} -K.~Morris, \textit{Infrastructure as Code: Managing Servers in the Cloud}. O'Reilly Media, 2016. +\bibitem{uv} +Astral, uv: An extremely fast Python package and project manager. \url{https://docs.astral.sh/uv}, 2024--. \bibitem{cunningham1992wycash} -W.~Cunningham, ``The WyCash portfolio management system,'' in \textit{Proc. ACM OOPSLA}, 1992. +Cunningham, W., The WyCash portfolio management system. In \textit{Proc. ACM OOPSLA}, 1992. -\bibitem{cookiecutter} -A.~Roy, D.~Greenfeld, et al., ``Cookiecutter,'' \url{https://cookiecutter.readthedocs.io}, 2013--. +\bibitem{dolstra2004nix} +Dolstra, E., de~Jonge, M., and Visser, E., Nix: A safe and policy-free system for software deployment. In \textit{Proc. LISA}, 2004. -\bibitem{copier} -J.~M.~Macías et al., ``Copier,'' \url{https://copier.readthedocs.io}, 2019--. +\bibitem{rails} +Hansson, D.~H., Ruby on Rails. \url{https://rubyonrails.org}, 2004--. + +\bibitem{humble2010continuous} +Humble, J. and Farley, D., \textit{Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation}. Addison-Wesley, 2010. \bibitem{cruft} -S.~Kothari et al., ``cruft,'' \url{https://cruft.github.io/cruft}, 2019--. +Kothari, S. et al., cruft. \url{https://cruft.github.io/cruft}, 2019--. -\bibitem{uv} -Astral, ``uv: An extremely fast Python package and project manager,'' \url{https://docs.astral.sh/uv}, 2024--. +\bibitem{copier} +Macías, J.~M. et al., Copier. \url{https://copier.readthedocs.io}, 2019--. -\bibitem{claudecode} -Anthropic, ``Claude Code: Agentic coding in the terminal,'' \url{https://claude.ai/code}, 2025--. +\bibitem{fowler2016infrastructure} +Morris, K., \textit{Infrastructure as Code: Managing Servers in the Cloud}. O'Reilly Media, 2016. \bibitem{nygard2011adr} -M.~T.~Nygard, ``Documenting architecture decisions,'' \url{https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions}, 2011. - -\bibitem{rails} -D.~H.~Hansson, ``Ruby on Rails,'' \url{https://rubyonrails.org}, 2004--. - -\bibitem{dolstra2004nix} -E.~Dolstra, M.~de Jonge, and E.~Visser, ``Nix: A safe and policy-free system for software deployment,'' in \textit{Proc. LISA}, 2004. +Nygard, M.~T., Documenting architecture decisions. \url{https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions}, 2011. \bibitem{potvin2016google} -R.~Potvin and J.~Levenberg, ``Why Google stores billions of lines of code in a single repository,'' \textit{Communications of the ACM}, vol.~59, no.~7, pp.~78--87, 2016. +Potvin, R. and Levenberg, J., Why Google stores billions of lines of code in a single repository. \textit{Communications of the ACM}, vol.~59, no.~7, pp.~78--87, 2016. + +\bibitem{cookiecutter} +Roy, A., Greenfeld, D. et al., Cookiecutter. \url{https://cookiecutter.readthedocs.io}, 2013--. \end{thebibliography} From 52fb348278df576c744ea7156a1d32d83b8a82e0 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Thu, 2 Apr 2026 07:36:03 +0400 Subject: [PATCH 27/30] Update .github/workflows/rhiza_sync.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Thomas Schmelzer --- .github/workflows/rhiza_sync.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rhiza_sync.yml b/.github/workflows/rhiza_sync.yml index 31256203..7df732b3 100644 --- a/.github/workflows/rhiza_sync.yml +++ b/.github/workflows/rhiza_sync.yml @@ -29,7 +29,7 @@ on: jobs: sync-direct: name: Sync and commit (Renovate) - if: github.event_name == 'push' + if: github.event_name == 'push' && github.repository != 'jebel-quant/rhiza' runs-on: ubuntu-latest steps: From 8cf8788b64b3f1bfd4ce32387028fde784de428f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 03:36:09 +0000 Subject: [PATCH 28/30] fix: align rhiza_weekly.yml comment with actual triggers Agent-Logs-Url: https://github.com/Jebel-Quant/rhiza/sessions/278eb1ff-5926-4a0d-ad40-ad6efb033e53 Co-authored-by: tschm <2046079+tschm@users.noreply.github.com> --- .github/workflows/rhiza_weekly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rhiza_weekly.yml b/.github/workflows/rhiza_weekly.yml index 7b925e0f..f4b56835 100644 --- a/.github/workflows/rhiza_weekly.yml +++ b/.github/workflows/rhiza_weekly.yml @@ -8,7 +8,7 @@ name: "(RHIZA) WEEKLY" # them up. Runs on schedule/dispatch only. # # link-check — Verifies that all hyperlinks in README.md are reachable. -# Also runs on push/PR when README.md changes. +# Runs on schedule/dispatch only. permissions: contents: read From a45f3164006a4db549929bc1eb132e8b2ccaf4ff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 04:09:28 +0000 Subject: [PATCH 29/30] fix: add pull_request trigger and fix on: syntax in rhiza_ci.yml Agent-Logs-Url: https://github.com/Jebel-Quant/rhiza/sessions/92f546cc-30de-41d7-a993-4b35eba49578 Co-authored-by: tschm <2046079+tschm@users.noreply.github.com> --- .github/workflows/rhiza_ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rhiza_ci.yml b/.github/workflows/rhiza_ci.yml index 409a4954..d478e15f 100644 --- a/.github/workflows/rhiza_ci.yml +++ b/.github/workflows/rhiza_ci.yml @@ -7,7 +7,7 @@ # pre-commit hooks, verify documentation coverage, validate the # project, run security scans, and check license compliance. # -# Trigger: On push. +# Trigger: On push and pull_request. name: (RHIZA) CI @@ -16,7 +16,8 @@ permissions: actions: read on: - push + push: + pull_request: jobs: generate-matrix: From 8fa3c9b166c1c21f1a2752c77913f55c66213dce Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Thu, 2 Apr 2026 08:21:22 +0400 Subject: [PATCH 30/30] =?UTF-8?q?Chore:=20bump=20version=200.8.19=20?= =?UTF-8?q?=E2=86=92=200.8.20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 963f8441..7c50e84b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "rhiza" -version = "0.8.19" +version = "0.8.20" description = "Reusable configuration templates for modern Python projects" readme = "README.md" requires-python = ">=3.11" diff --git a/uv.lock b/uv.lock index d35f0ab7..b143a651 100644 --- a/uv.lock +++ b/uv.lock @@ -565,7 +565,7 @@ wheels = [ [[package]] name = "rhiza" -version = "0.8.19" +version = "0.8.20" source = { virtual = "." } [package.dev-dependencies]