rhiza 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/actions/setup-project/action.yml +2 -24
- rhiza-0.4.0/.github/scripts/sync.sh +310 -0
- rhiza-0.4.0/.github/template.yml +16 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/deptry.yml +1 -1
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/marimo.yml +1 -1
- rhiza-0.4.0/.github/workflows/structure.yml +73 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/sync.yml +1 -1
- rhiza-0.4.0/PKG-INFO +35 -0
- rhiza-0.4.0/README.md +2 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/pyproject.toml +17 -5
- rhiza-0.4.0/src/rhiza/__init__.py +5 -0
- rhiza-0.4.0/src/rhiza/__main__.py +10 -0
- rhiza-0.4.0/src/rhiza/cli.py +47 -0
- rhiza-0.4.0/src/rhiza/commands/__init__.py +5 -0
- rhiza-0.4.0/src/rhiza/commands/hello.py +9 -0
- rhiza-0.4.0/src/rhiza/commands/inject.py +160 -0
- rhiza-0.4.0/tests/test_cli_commands.py +482 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/uv.lock +92 -4
- rhiza-0.3.0/.devcontainer/bootstrap.sh +0 -38
- rhiza-0.3.0/.devcontainer/devcontainer.json +0 -48
- rhiza-0.3.0/.github/workflows/devcontainer.yml +0 -137
- rhiza-0.3.0/.github/workflows/docker.yml +0 -63
- rhiza-0.3.0/PKG-INFO +0 -709
- rhiza-0.3.0/README.md +0 -679
- rhiza-0.3.0/assets/rhiza-logo.svg +0 -81
- rhiza-0.3.0/book/marimo/df.py +0 -37
- rhiza-0.3.0/book/minibook-templates/custom.html.jinja2 +0 -210
- rhiza-0.3.0/book/pdoc-templates/module.html.jinja2 +0 -19
- rhiza-0.3.0/docker/Dockerfile +0 -64
- rhiza-0.3.0/docker/Dockerfile.dockerignore +0 -17
- rhiza-0.3.0/docker/README.md +0 -31
- {rhiza-0.3.0 → rhiza-0.4.0}/.editorconfig +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/renovate.json +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/book.sh +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/bump.sh +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/customisations/build-extras.sh +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/customisations/post-release.sh +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/marimushka.sh +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/release.sh +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/scripts/update-readme-help.sh +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/book.yml +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/ci.yml +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/pre-commit.yml +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/release.yml +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/scripts/version_matrix.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.github/workflows/scripts/version_max.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.gitignore +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/.pre-commit-config.yaml +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/CONTRIBUTING.md +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/LICENSE +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/Makefile +0 -0
- {rhiza-0.3.0/src/rhiza → rhiza-0.4.0/book/marimo}/.gitkeep +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/pytest.ini +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/ruff.toml +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/README.md +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/conftest.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_bump_script.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_docstrings.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_git_repo_fixture.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_makefile.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_marimushka_script.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_readme.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_release_script.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_structure.py +0 -0
- {rhiza-0.3.0 → rhiza-0.4.0}/tests/test_rhiza/test_updatereadme_script.py +0 -0
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
# Action: Setup Project (composite action)
|
|
5
5
|
#
|
|
6
6
|
# Purpose: Bootstrap a Python project in GitHub Actions by:
|
|
7
|
-
# - Installing Task, uv, and uvx
|
|
8
|
-
# - Optionally rendering the repository from a Copier template for tests
|
|
7
|
+
# - Installing Task, uv, and uvx
|
|
9
8
|
# - Detecting presence of pyproject.toml and exposing it as an output
|
|
10
9
|
# - Creating a virtual environment with uv and syncing dependencies
|
|
11
10
|
#
|
|
@@ -43,28 +42,7 @@ runs:
|
|
|
43
42
|
- name: Install uv
|
|
44
43
|
uses: astral-sh/setup-uv@v7
|
|
45
44
|
with:
|
|
46
|
-
version: "0.9.
|
|
47
|
-
|
|
48
|
-
- name: Render the project
|
|
49
|
-
if: hashFiles('tests/resources/render.yml') != ''
|
|
50
|
-
shell: bash
|
|
51
|
-
run: |
|
|
52
|
-
pip install copier
|
|
53
|
-
|
|
54
|
-
# Render the current folder in-place
|
|
55
|
-
copier copy . . \
|
|
56
|
-
--data-file ./tests/resources/render.yml \
|
|
57
|
-
--force \
|
|
58
|
-
--overwrite \
|
|
59
|
-
--quiet
|
|
60
|
-
|
|
61
|
-
# Delete all remaining .jinja files
|
|
62
|
-
find . -type f -name "*.jinja" -exec rm -f {} +
|
|
63
|
-
|
|
64
|
-
# Delete all folders that still contain {{ ... }}
|
|
65
|
-
find . -depth -type d -name "*{{*}}*" -exec rm -rf {} +
|
|
66
|
-
|
|
67
|
-
ls -R
|
|
45
|
+
version: "0.9.18"
|
|
68
46
|
|
|
69
47
|
- name: Check for pyproject.toml
|
|
70
48
|
id: check_pyproject
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Sync configuration files from template repository
|
|
3
|
+
# - Reads configuration from .github/template.yml
|
|
4
|
+
# - Downloads specified files from the template repository
|
|
5
|
+
# - Copies them to the current repository
|
|
6
|
+
#
|
|
7
|
+
# This script is POSIX-sh compatible and provides manual sync capability
|
|
8
|
+
# for repositories that use jebel-quant/rhiza as a template.
|
|
9
|
+
|
|
10
|
+
set -e
|
|
11
|
+
|
|
12
|
+
BLUE="\033[36m"
|
|
13
|
+
RED="\033[31m"
|
|
14
|
+
GREEN="\033[32m"
|
|
15
|
+
YELLOW="\033[33m"
|
|
16
|
+
RESET="\033[0m"
|
|
17
|
+
|
|
18
|
+
TEMPLATE_CONFIG=".github/template.yml"
|
|
19
|
+
TEMP_DIR="/tmp/rhiza-sync-$$"
|
|
20
|
+
|
|
21
|
+
show_usage() {
|
|
22
|
+
printf "Usage: %s [OPTIONS]\n\n" "$0"
|
|
23
|
+
printf "Sync configuration files from the template repository.\n\n"
|
|
24
|
+
printf "Options:\n"
|
|
25
|
+
printf " -h, --help Show this help message\n"
|
|
26
|
+
printf " --dry-run Show what would be synced without making changes\n\n"
|
|
27
|
+
printf "Configuration:\n"
|
|
28
|
+
printf " Reads from %s to determine:\n" "$TEMPLATE_CONFIG"
|
|
29
|
+
printf " - template-repository: Source repository (e.g., 'jebel-quant/rhiza')\n"
|
|
30
|
+
printf " - template-branch: Branch to sync from (e.g., 'main')\n"
|
|
31
|
+
printf " - include: Files/directories to sync\n"
|
|
32
|
+
printf " - exclude: Files/directories to skip (optional)\n\n"
|
|
33
|
+
printf "Example %s:\n" "$TEMPLATE_CONFIG"
|
|
34
|
+
printf " template-repository: \"jebel-quant/rhiza\"\n"
|
|
35
|
+
printf " template-branch: \"main\"\n"
|
|
36
|
+
printf " include: |\n"
|
|
37
|
+
printf " .github\n"
|
|
38
|
+
printf " Makefile\n"
|
|
39
|
+
printf " ruff.toml\n"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
DRY_RUN=""
|
|
43
|
+
while [ $# -gt 0 ]; do
|
|
44
|
+
case "$1" in
|
|
45
|
+
-h|--help)
|
|
46
|
+
show_usage
|
|
47
|
+
exit 0
|
|
48
|
+
;;
|
|
49
|
+
--dry-run)
|
|
50
|
+
DRY_RUN="true"
|
|
51
|
+
shift
|
|
52
|
+
;;
|
|
53
|
+
*)
|
|
54
|
+
printf "%b[ERROR] Unknown option: %s%b\n" "$RED" "$1" "$RESET"
|
|
55
|
+
show_usage
|
|
56
|
+
exit 1
|
|
57
|
+
;;
|
|
58
|
+
esac
|
|
59
|
+
done
|
|
60
|
+
|
|
61
|
+
# Check if template.yml exists
|
|
62
|
+
if [ ! -f "$TEMPLATE_CONFIG" ]; then
|
|
63
|
+
printf "%b[ERROR] Template configuration not found: %s%b\n" "$RED" "$TEMPLATE_CONFIG" "$RESET"
|
|
64
|
+
printf "\nThis repository is not configured for template syncing.\n"
|
|
65
|
+
printf "Create %s with the following content:\n\n" "$TEMPLATE_CONFIG"
|
|
66
|
+
printf " template-repository: \"jebel-quant/rhiza\"\n"
|
|
67
|
+
printf " template-branch: \"main\"\n"
|
|
68
|
+
printf " include: |\n"
|
|
69
|
+
printf " .github\n"
|
|
70
|
+
printf " Makefile\n"
|
|
71
|
+
printf " ruff.toml\n"
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Parse template.yml to extract configuration
|
|
76
|
+
# This is a simple parser that works with basic YAML structure
|
|
77
|
+
printf "%b[INFO] Reading configuration from %s...%b\n" "$BLUE" "$TEMPLATE_CONFIG" "$RESET"
|
|
78
|
+
|
|
79
|
+
TEMPLATE_REPO=""
|
|
80
|
+
TEMPLATE_BRANCH=""
|
|
81
|
+
INCLUDE_LIST=""
|
|
82
|
+
EXCLUDE_LIST=""
|
|
83
|
+
|
|
84
|
+
# Simple YAML parser
|
|
85
|
+
in_multiline=""
|
|
86
|
+
|
|
87
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
88
|
+
# Skip comments and empty lines
|
|
89
|
+
case "$line" in
|
|
90
|
+
\#*|"") continue ;;
|
|
91
|
+
esac
|
|
92
|
+
|
|
93
|
+
# Check if line starts with spaces by looking at first character
|
|
94
|
+
first_char=$(printf '%s' "$line" | cut -c1)
|
|
95
|
+
|
|
96
|
+
if [ "$first_char" = " " ] || [ "$first_char" = "$(printf '\t')" ]; then
|
|
97
|
+
# This is indented content (part of a multiline block)
|
|
98
|
+
if [ -n "$in_multiline" ]; then
|
|
99
|
+
# Remove leading spaces
|
|
100
|
+
item=$(echo "$line" | sed 's/^[[:space:]]*//')
|
|
101
|
+
if [ -n "$item" ]; then
|
|
102
|
+
if [ "$in_multiline" = "include" ]; then
|
|
103
|
+
INCLUDE_LIST="${INCLUDE_LIST}${item}
|
|
104
|
+
"
|
|
105
|
+
elif [ "$in_multiline" = "exclude" ]; then
|
|
106
|
+
EXCLUDE_LIST="${EXCLUDE_LIST}${item}
|
|
107
|
+
"
|
|
108
|
+
fi
|
|
109
|
+
fi
|
|
110
|
+
fi
|
|
111
|
+
else
|
|
112
|
+
# This is a key line (not indented)
|
|
113
|
+
case "$line" in
|
|
114
|
+
template-repository:*)
|
|
115
|
+
TEMPLATE_REPO=$(echo "$line" | sed 's/^template-repository:[[:space:]]*//' | sed 's/"//g' | sed "s/'//g")
|
|
116
|
+
in_multiline=""
|
|
117
|
+
;;
|
|
118
|
+
template-branch:*)
|
|
119
|
+
TEMPLATE_BRANCH=$(echo "$line" | sed 's/^template-branch:[[:space:]]*//' | sed 's/"//g' | sed "s/'//g")
|
|
120
|
+
in_multiline=""
|
|
121
|
+
;;
|
|
122
|
+
include:*)
|
|
123
|
+
in_multiline="include"
|
|
124
|
+
;;
|
|
125
|
+
exclude:*)
|
|
126
|
+
in_multiline="exclude"
|
|
127
|
+
;;
|
|
128
|
+
esac
|
|
129
|
+
fi
|
|
130
|
+
done < "$TEMPLATE_CONFIG"
|
|
131
|
+
|
|
132
|
+
# Validate required fields
|
|
133
|
+
if [ -z "$TEMPLATE_REPO" ]; then
|
|
134
|
+
printf "%b[ERROR] template-repository not found in %s%b\n" "$RED" "$TEMPLATE_CONFIG" "$RESET"
|
|
135
|
+
exit 1
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
if [ -z "$TEMPLATE_BRANCH" ]; then
|
|
139
|
+
printf "%b[WARN] template-branch not specified, using 'main'%b\n" "$YELLOW" "$RESET"
|
|
140
|
+
TEMPLATE_BRANCH="main"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
if [ -z "$INCLUDE_LIST" ]; then
|
|
144
|
+
printf "%b[ERROR] include list is empty in %s%b\n" "$RED" "$TEMPLATE_CONFIG" "$RESET"
|
|
145
|
+
exit 1
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
printf "%b[INFO] Template repository: %s%b\n" "$GREEN" "$TEMPLATE_REPO" "$RESET"
|
|
149
|
+
printf "%b[INFO] Template branch: %s%b\n" "$GREEN" "$TEMPLATE_BRANCH" "$RESET"
|
|
150
|
+
printf "%b[INFO] Files to sync:%b\n" "$GREEN" "$RESET"
|
|
151
|
+
echo "$INCLUDE_LIST" | while IFS= read -r item; do
|
|
152
|
+
[ -n "$item" ] && printf " - %s\n" "$item"
|
|
153
|
+
done || true
|
|
154
|
+
|
|
155
|
+
if [ -n "$EXCLUDE_LIST" ]; then
|
|
156
|
+
printf "%b[INFO] Files to exclude:%b\n" "$YELLOW" "$RESET"
|
|
157
|
+
echo "$EXCLUDE_LIST" | while IFS= read -r item; do
|
|
158
|
+
[ -n "$item" ] && printf " - %s\n" "$item"
|
|
159
|
+
done || true
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
if [ -n "$DRY_RUN" ]; then
|
|
163
|
+
printf "\n%b[DRY RUN] No changes will be made%b\n" "$YELLOW" "$RESET"
|
|
164
|
+
exit 0
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Create temporary directory
|
|
168
|
+
mkdir -p "$TEMP_DIR"
|
|
169
|
+
trap 'rm -rf "$TEMP_DIR"' EXIT INT TERM
|
|
170
|
+
|
|
171
|
+
# Backup this script to avoid being overwritten during sync
|
|
172
|
+
SELF_SCRIPT=".github/scripts/sync.sh"
|
|
173
|
+
if [ -f "$SELF_SCRIPT" ]; then
|
|
174
|
+
cp "$SELF_SCRIPT" "$TEMP_DIR/sync.sh.bak"
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# Clone the template repository
|
|
178
|
+
printf "\n%b[INFO] Cloning template repository...%b\n" "$BLUE" "$RESET"
|
|
179
|
+
REPO_URL="https://github.com/${TEMPLATE_REPO}.git"
|
|
180
|
+
|
|
181
|
+
if ! git clone --depth 1 --branch "$TEMPLATE_BRANCH" "$REPO_URL" "$TEMP_DIR/template" 2>/dev/null; then
|
|
182
|
+
printf "%b[ERROR] Failed to clone template repository from %s%b\n" "$RED" "$REPO_URL" "$RESET"
|
|
183
|
+
exit 1
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
# Function to check if a file path should be excluded
|
|
187
|
+
is_file_excluded() {
|
|
188
|
+
file_path="$1"
|
|
189
|
+
if [ -z "$EXCLUDE_LIST" ]; then
|
|
190
|
+
return 1 # Not excluded (false)
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
while IFS= read -r exclude_item || [ -n "$exclude_item" ]; do
|
|
194
|
+
[ -z "$exclude_item" ] && continue
|
|
195
|
+
if [ "$file_path" = "$exclude_item" ]; then
|
|
196
|
+
return 0 # Is excluded (true)
|
|
197
|
+
fi
|
|
198
|
+
done <<EOF_EXCLUDE_CHECK
|
|
199
|
+
$EXCLUDE_LIST
|
|
200
|
+
EOF_EXCLUDE_CHECK
|
|
201
|
+
|
|
202
|
+
return 1 # Not excluded (false)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
# Copy files from template to current directory
|
|
206
|
+
printf "%b[INFO] Syncing files...%b\n" "$BLUE" "$RESET"
|
|
207
|
+
|
|
208
|
+
synced_count=0
|
|
209
|
+
skipped_count=0
|
|
210
|
+
# Track whether .github (containing this script) was synced and whether a direct self update was requested
|
|
211
|
+
synced_dotgithub="false"
|
|
212
|
+
deferred_self_update="false"
|
|
213
|
+
|
|
214
|
+
# Use here-document instead of pipeline to avoid subshell
|
|
215
|
+
while IFS= read -r item || [ -n "$item" ]; do
|
|
216
|
+
[ -z "$item" ] && continue
|
|
217
|
+
|
|
218
|
+
# Check if this item is in the exclude list
|
|
219
|
+
if is_file_excluded "$item"; then
|
|
220
|
+
printf " %b[SKIP]%b %s (excluded)\n" "$YELLOW" "$RESET" "$item"
|
|
221
|
+
skipped_count=$((skipped_count + 1))
|
|
222
|
+
continue
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
# Defer updating this script to the very end to avoid mid-run overwrite
|
|
226
|
+
if [ "$item" = ".github/scripts/sync.sh" ]; then
|
|
227
|
+
deferred_self_update="true"
|
|
228
|
+
printf " %b[DEFER]%b %s (will update at end)\n" "$YELLOW" "$RESET" "$item"
|
|
229
|
+
continue
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
src_path="$TEMP_DIR/template/$item"
|
|
233
|
+
dest_path="./$item"
|
|
234
|
+
|
|
235
|
+
if [ -e "$src_path" ]; then
|
|
236
|
+
# Create parent directory if needed
|
|
237
|
+
dest_dir=$(dirname "$dest_path")
|
|
238
|
+
mkdir -p "$dest_dir"
|
|
239
|
+
|
|
240
|
+
# Copy the file or directory
|
|
241
|
+
if [ -d "$src_path" ]; then
|
|
242
|
+
# Ensure destination directory exists
|
|
243
|
+
mkdir -p "$dest_path"
|
|
244
|
+
# Copy contents of the source directory into the destination directory
|
|
245
|
+
# to avoid nesting (e.g., .github/.github or tests/tests)
|
|
246
|
+
cp -R "$src_path"/. "$dest_path"/
|
|
247
|
+
# Mark if we synced the .github directory so we can safely update sync.sh at the end
|
|
248
|
+
if [ "$item" = ".github" ]; then
|
|
249
|
+
synced_dotgithub="true"
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
# Remove excluded files from the copied directory
|
|
253
|
+
if [ -n "$EXCLUDE_LIST" ]; then
|
|
254
|
+
while IFS= read -r exclude_item || [ -n "$exclude_item" ]; do
|
|
255
|
+
[ -z "$exclude_item" ] && continue
|
|
256
|
+
# Check if the excluded item is a child of the current item
|
|
257
|
+
# e.g., if item=".github" and exclude_item=".github/workflows/docker.yml"
|
|
258
|
+
case "$exclude_item" in
|
|
259
|
+
"$item"/*)
|
|
260
|
+
# This is a nested file that should be excluded
|
|
261
|
+
excluded_file_path="./$exclude_item"
|
|
262
|
+
if [ -e "$excluded_file_path" ]; then
|
|
263
|
+
rm -rf "$excluded_file_path"
|
|
264
|
+
printf " %b[EXCLUDE]%b %s (removed from synced directory)\n" "$YELLOW" "$RESET" "$exclude_item"
|
|
265
|
+
fi
|
|
266
|
+
;;
|
|
267
|
+
esac
|
|
268
|
+
done <<EOF_EXCLUDE_NESTED
|
|
269
|
+
$EXCLUDE_LIST
|
|
270
|
+
EOF_EXCLUDE_NESTED
|
|
271
|
+
fi
|
|
272
|
+
|
|
273
|
+
# If we just synced the .github directory, restore this script immediately to avoid mid-run overwrite issues
|
|
274
|
+
if [ "$item" = ".github" ] && [ -f "$TEMP_DIR/sync.sh.bak" ]; then
|
|
275
|
+
cp "$TEMP_DIR/sync.sh.bak" "$SELF_SCRIPT"
|
|
276
|
+
fi
|
|
277
|
+
printf " %b[SYNC]%b %s (directory contents)\n" "$GREEN" "$RESET" "$item"
|
|
278
|
+
else
|
|
279
|
+
cp "$src_path" "$dest_path"
|
|
280
|
+
printf " %b[SYNC]%b %s\n" "$GREEN" "$RESET" "$item"
|
|
281
|
+
fi
|
|
282
|
+
synced_count=$((synced_count + 1))
|
|
283
|
+
else
|
|
284
|
+
printf " %b[WARN]%b %s (not found in template)\n" "$YELLOW" "$RESET" "$item"
|
|
285
|
+
skipped_count=$((skipped_count + 1))
|
|
286
|
+
fi
|
|
287
|
+
done <<EOF_INCLUDE
|
|
288
|
+
$INCLUDE_LIST
|
|
289
|
+
EOF_INCLUDE
|
|
290
|
+
|
|
291
|
+
# Finalize self-update of sync.sh if applicable
|
|
292
|
+
TEMPLATE_SELF_SH="$TEMP_DIR/template/.github/scripts/sync.sh"
|
|
293
|
+
if [ -f "$TEMPLATE_SELF_SH" ] && { [ "$deferred_self_update" = "true" ] || [ "$synced_dotgithub" = "true" ]; }; then
|
|
294
|
+
if is_file_excluded ".github/scripts/sync.sh"; then
|
|
295
|
+
printf " %b[SKIP]%b .github/scripts/sync.sh (excluded from final update)\n" "$YELLOW" "$RESET"
|
|
296
|
+
else
|
|
297
|
+
cp "$TEMPLATE_SELF_SH" "$SELF_SCRIPT"
|
|
298
|
+
chmod +x "$SELF_SCRIPT" 2>/dev/null || true
|
|
299
|
+
printf " %b[SYNC]%b .github/scripts/sync.sh (finalized)\n" "$GREEN" "$RESET"
|
|
300
|
+
fi
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
printf "\n%b[INFO] Sync complete!%b\n" "$GREEN" "$RESET"
|
|
304
|
+
printf " Synced: %d files/directories\n" "$synced_count"
|
|
305
|
+
if [ "$skipped_count" -gt 0 ]; then
|
|
306
|
+
printf " Skipped: %d files/directories\n" "$skipped_count"
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
printf "\n%b[INFO] Review the changes with: git status%b\n" "$BLUE" "$RESET"
|
|
310
|
+
printf "%b[INFO] Commit the changes with: git add . && git commit -m 'chore: sync template files'%b\n" "$BLUE" "$RESET"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
template-repository: "jebel-quant/rhiza"
|
|
2
|
+
template-branch: "main"
|
|
3
|
+
include:
|
|
4
|
+
- .github
|
|
5
|
+
- tests
|
|
6
|
+
- .editorconfig
|
|
7
|
+
- .gitignore
|
|
8
|
+
- .pre-commit-config.yaml
|
|
9
|
+
- CODE_OF_CONDUCT.md
|
|
10
|
+
- CONTRIBUTING.md
|
|
11
|
+
- Makefile
|
|
12
|
+
- ruff.toml
|
|
13
|
+
- pytest.ini
|
|
14
|
+
exclude:
|
|
15
|
+
- .github/workflows/docker.yml
|
|
16
|
+
- .github/workflows/devcontainer.yml
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# This file is part of the jebel-quant/rhiza repository
|
|
2
|
+
# (https://github.com/jebel-quant/rhiza).
|
|
3
|
+
#
|
|
4
|
+
# GitHub Actions workflow: repository structure advisory checks
|
|
5
|
+
# Purpose: Soft-check the presence of common scaffolding (src/, tests/, and key dotfiles)
|
|
6
|
+
# and print WARN messages if something is missing. This workflow is advisory:
|
|
7
|
+
# it never fails the job based on these checks; it only surfaces helpful hints
|
|
8
|
+
# for template consumers.
|
|
9
|
+
#
|
|
10
|
+
# Triggers: on push and pull requests targeting main/master.
|
|
11
|
+
# Permissions: read-only; no writes or tokens required. LFS enabled to support
|
|
12
|
+
# repositories that track large files.
|
|
13
|
+
# Notes: The shell steps use printf with optional color variables (e.g., YELLOW,
|
|
14
|
+
# RESET). If these env vars are unset in the runner, the parameter expansion
|
|
15
|
+
# defaults ensure plain text output without ANSI colors.
|
|
16
|
+
name: "STRUCTURE"
|
|
17
|
+
|
|
18
|
+
# Minimal read permission is sufficient; the workflow does not modify the repo
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
# Run on pushes and pull requests to the default branches
|
|
23
|
+
on:
|
|
24
|
+
push:
|
|
25
|
+
pull_request:
|
|
26
|
+
branches: [ main, master ]
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
# Single job that performs presence checks and emits WARN lines (warn-only)
|
|
30
|
+
structure_check:
|
|
31
|
+
runs-on: "ubuntu-latest"
|
|
32
|
+
|
|
33
|
+
permissions:
|
|
34
|
+
contents: read
|
|
35
|
+
|
|
36
|
+
steps:
|
|
37
|
+
# Check out the repository code (with Git LFS files, if any)
|
|
38
|
+
- uses: actions/checkout@v6
|
|
39
|
+
with:
|
|
40
|
+
lfs: true
|
|
41
|
+
|
|
42
|
+
# Check there is a src folder
|
|
43
|
+
- name: Check src folder exists
|
|
44
|
+
run: |
|
|
45
|
+
if [ ! -d "src" ]; then
|
|
46
|
+
printf "${YELLOW:-}[WARN] No src folder found, skipping structure check${RESET:-}\n"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Check there is a tests folder
|
|
50
|
+
- name: Check tests folder exists
|
|
51
|
+
run: |
|
|
52
|
+
if [ ! -d "tests" ]; then
|
|
53
|
+
printf "${YELLOW:-}[WARN] No tests folder found, skipping structure check${RESET:-}\n"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Check there is a .editorconfig, .gitignore, .pre-commit-config.yaml and Makefile file
|
|
57
|
+
- name: Check .editorconfig and .gitignore files exist
|
|
58
|
+
run: |
|
|
59
|
+
if [ ! -f ".editorconfig" ]; then
|
|
60
|
+
printf "${YELLOW:-}[WARN] No .editorconfig file found, skipping structure check${RESET:-}\n"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
if [ ! -f ".gitignore" ]; then
|
|
64
|
+
printf "${YELLOW:-}[WARN] No .gitignore file found, skipping structure check${RESET:-}\n"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
if [ ! -f ".pre-commit-config.yaml" ]; then
|
|
68
|
+
printf "${YELLOW:-}[WARN] No .pre-commit-config file found, skipping structure check${RESET:-}\n"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
if [ ! -f "Makefile" ]; then
|
|
72
|
+
printf "${YELLOW:-}[WARN] No Makefile found, skipping structure check${RESET:-}\n"
|
|
73
|
+
fi
|
rhiza-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rhiza
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Reusable configuration templates for modern Python projects
|
|
5
|
+
Project-URL: Homepage, https://github.com/jebel-quant/rhiza-cli
|
|
6
|
+
Project-URL: Repository, https://github.com/jebel-quant/rhiza-cli
|
|
7
|
+
Project-URL: Issues, https://github.com/jebel-quant/rhiza/issues-cli
|
|
8
|
+
Author: Thomas Schmelzer
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ci,configuration,ruff,taskfile,templates
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: loguru>=0.7.3
|
|
23
|
+
Requires-Dist: pyyaml==6.0.3
|
|
24
|
+
Requires-Dist: typer>=0.20.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: marimo==0.18.4; extra == 'dev'
|
|
27
|
+
Requires-Dist: pdoc>=16.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pre-commit==4.5.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-html>=4.1.1; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest==9.0.2; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# rhiza-cli
|
|
35
|
+
Command line interface for Rhiza
|
rhiza-0.4.0/README.md
ADDED
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rhiza"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "Reusable configuration templates for modern Python projects"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -12,7 +12,7 @@ license = { text = "MIT" }
|
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = "Thomas Schmelzer" }
|
|
14
14
|
]
|
|
15
|
-
keywords = ["templates", "configuration", "ci", "ruff"]
|
|
15
|
+
keywords = ["templates", "configuration", "taskfile", "ci", "ruff"]
|
|
16
16
|
classifiers = [
|
|
17
17
|
"Programming Language :: Python :: 3",
|
|
18
18
|
"Programming Language :: Python :: 3 :: Only",
|
|
@@ -25,10 +25,16 @@ classifiers = [
|
|
|
25
25
|
"Topic :: Software Development :: Build Tools",
|
|
26
26
|
]
|
|
27
27
|
|
|
28
|
+
dependencies = [
|
|
29
|
+
"loguru>=0.7.3",
|
|
30
|
+
"typer>=0.20.0",
|
|
31
|
+
"PyYAML==6.0.3"
|
|
32
|
+
]
|
|
33
|
+
|
|
28
34
|
[project.urls]
|
|
29
|
-
Homepage = "https://github.com/jebel-quant/rhiza"
|
|
30
|
-
Repository = "https://github.com/jebel-quant/rhiza"
|
|
31
|
-
Issues = "https://github.com/jebel-quant/rhiza/issues"
|
|
35
|
+
Homepage = "https://github.com/jebel-quant/rhiza-cli"
|
|
36
|
+
Repository = "https://github.com/jebel-quant/rhiza-cli"
|
|
37
|
+
Issues = "https://github.com/jebel-quant/rhiza/issues-cli"
|
|
32
38
|
|
|
33
39
|
|
|
34
40
|
[project.optional-dependencies]
|
|
@@ -49,5 +55,11 @@ packages = ["src/rhiza"]
|
|
|
49
55
|
# see https://deptry.com/usage/#pep-621-dev-dependency-groups
|
|
50
56
|
pep621_dev_dependency_groups = ["dev"]
|
|
51
57
|
|
|
58
|
+
[tool.deptry.package_module_name_map]
|
|
59
|
+
PyYAML = "yaml"
|
|
60
|
+
|
|
52
61
|
[tool.marimo.runtime]
|
|
53
62
|
pythonpath = ["src"]
|
|
63
|
+
|
|
64
|
+
[project.scripts]
|
|
65
|
+
rhiza = "rhiza.__main__:app"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Rhiza command-line interface (CLI).
|
|
2
|
+
|
|
3
|
+
This module defines the Typer application entry points exposed by Rhiza.
|
|
4
|
+
Commands are thin wrappers around implementations in `rhiza.commands.*`.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import typer
|
|
10
|
+
|
|
11
|
+
from rhiza.commands.hello import hello as hello_cmd
|
|
12
|
+
from rhiza.commands.inject import inject as inject_cmd
|
|
13
|
+
|
|
14
|
+
app = typer.Typer(help="rhiza — configuration materialization tools")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@app.command()
|
|
18
|
+
def hello():
|
|
19
|
+
"""Sanity check command."""
|
|
20
|
+
hello_cmd()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@app.command()
|
|
24
|
+
def materialize(
|
|
25
|
+
target: Path = typer.Argument(
|
|
26
|
+
default=Path("."), # default to current directory
|
|
27
|
+
exists=True,
|
|
28
|
+
file_okay=False,
|
|
29
|
+
dir_okay=True,
|
|
30
|
+
help="Target git repository (defaults to current directory)",
|
|
31
|
+
),
|
|
32
|
+
branch: str = typer.Option("main", "--branch", "-b", help="Rhiza branch to use"),
|
|
33
|
+
force: bool = typer.Option(False, "--force", "-y", help="Overwrite existing files"),
|
|
34
|
+
):
|
|
35
|
+
"""Inject Rhiza configuration into a target repository.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
target:
|
|
40
|
+
Path to the target Git repository directory. Defaults to the
|
|
41
|
+
current working directory.
|
|
42
|
+
branch:
|
|
43
|
+
Name of the Rhiza branch to use when sourcing templates.
|
|
44
|
+
force:
|
|
45
|
+
If True, overwrite existing files without prompting.
|
|
46
|
+
"""
|
|
47
|
+
inject_cmd(target, branch, force)
|