Maintainer toolkit for the Ichava Laravel icon-pack ecosystem.
A Docker-first Python tool that polls upstream registries (npm /
GitHub releases / GitHub tags), refreshes the bundled SVGs in each
pack repo, bumps current_version, commits to a branch, and opens a
PR. Replaces the per-pack php artisan ichava:update* command (which
couldn't persist anything because vendor/ is regenerated on every
composer install).
End-user side of the same story: see
ichava/documentation/icon-pack-upstream-tracking.md.
This repo is the maintainer side.
git clone git@github.com:ichava/maintainer-toolkit.git
cd dev
make build # builds the docker image
make help # shows available targetsYou don't need Python, Node, gh, or any system deps locally -- the
docker image bundles all of them. The image mounts the parent of this
repo at /work so it can read sibling pack repos.
# Interactive menu (default Docker CMD)
make menu
# Check upstream status across every pack (no writes)
make check
# Sync one pack: pulls latest, refreshes assets, opens a PR
make sync PACK=tabler-icons
# Dry-run every pack (no commits)
make sync-allEach pack has a JSON config under config/:
config/
├── packs.json # the registry: which packs to manage
├── tabler-icons.json
├── flag-icons.json
├── bundled-icons.json
└── emoji-sets.json
A pack config:
{
"name": "tabler-icons",
"pack": "ichava/tabler-icons",
"pack_root": "/work/tabler-icons",
"current_version": "3.0.0",
"version_check_url": "https://registry.npmjs.org/@tabler/icons/latest",
"source": {
"type": "npm",
"package": "@tabler/icons",
"source_path": "icons"
},
"sinks": [
{"type": "filesystem", "root": "{pack_root}/resources/assets/svg/files"},
{"type": "git-branch", "repo_root": "{pack_root}", "branch": "chore/sync-upstream-{version}"}
]
}source.type recognises: npm, github-archive, github-release,
github-tag, script (pack-supplied refresh recipe), url.
The tool is built around three composable primitives:
Source (where SVGs come from)
↓
Transform (zero or more: sanitise, subset, slugify, categorise, indexer)
↓
Sink (where SVGs land: filesystem, git-branch)
Fluent + chainable:
from ichava_maintainer_toolkit import Pipeline, sources, transforms, sinks
(
Pipeline.named("tabler-icons@3.44.0")
.source(sources.NpmTarball("@tabler/icons", version="3.44.0"))
.transform(transforms.SubsetTo("icons"))
.transform(transforms.Sanitise())
.sink(sinks.Filesystem(root="/work/tabler-icons/resources/assets/svg/files"))
.sink(sinks.GitBranch(repo_root="/work/tabler-icons", branch="chore/sync-upstream-{version}"))
.run()
)Layout:
src/ichava_maintainer_toolkit/
├── cli.py typer + questionary interactive menu
├── core/
│ ├── pipeline.py Pipeline / Stage / StageContext primitives
│ ├── config.py JSON config loader (pydantic)
│ ├── http.py tenacity-wrapped requests session
│ ├── git.py git + gh-pr-create helpers
│ ├── checker.py upstream version polling (PHP parity)
│ ├── sources/ NpmTarball, GithubArchive, UnicodeCldr
│ ├── transforms/ Sanitise, SubsetTo, Slugify, Categorise, Indexer
│ ├── sinks/ Filesystem, GitBranch
│ └── reporters/ rich-based TTY reporter
└── recipes/ per-pack pre-baked pipelines
- Create
config/<slug>.jsondescribing the upstream + sinks. - Add
<slug>topacksinconfig/packs.json. - If the pack needs custom ETL (multi-source, CLDR taxonomy, etc.),
write a recipe under
src/ichava_maintainer_toolkit/recipes/<slug>.pyand wire it intocli._run_recipe. make check-pack PACK=<slug>to confirm the upstream poll resolves.
make shell # bash inside the container
make test # pytest
make lint # ruff check
make typecheck # mypy strict
make format # ruff formatOr, locally without Docker:
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
ichava-maintainer-toolkit --helpAlpha (v0.1.0). Core primitives + npm strategy + simple_npm
recipe shipping. script-typed packs (emoji-sets, bundled-icons)
need their dedicated recipes ported from the legacy
emoji-sets/scripts/build_emoji_assets.py. See CHANGELOG.md.
MIT. Copyright (c) Simtabi LLC.