Modular, pluggable GitHub updater library for Python-glued projects (release / source / python-source channels with 3-way merge and dependency auto-detection).
Project description
updater-gitplucker
A modular, pluggable GitHub updater library for Python-glued projects. Drop it into any of your apps to keep them up to date from GitHub — with a safety allowlist, a 3-way merge that preserves your local edits, and automatic Python dependency detection/installation.
- Import name:
gitplucker· Package:updater-gitplucker - Zero required dependencies — the core runs on the Python standard library.
- Passive by design — it hands you an inspectable plan; you decide when to apply. Trigger it manually, at startup, or from a background thread.
from gitplucker import Updater, UpdaterConfig, RepoSubscription, Channel
from pathlib import Path
config = UpdaterConfig(
install_root=Path("/path/to/your/app"), # where the app lives on disk
allowed_repos=["your-org/your-app"], # nothing outside this is ever fetched
subscriptions=[
RepoSubscription("your-org/your-app", branches=["main"],
channel=Channel.PYTHON_SOURCE),
],
token="ghp_...", # optional (private repos / rate limits)
)
updater = Updater(config)
for plan in updater.check(): # dry run — nothing written yet
print(plan.summary())
if plan.has_update and not plan.conflicts:
updater.apply(plan) # backup → write → install deps
else:
updater.discard(plan)
Install
pip install updater-gitplucker
Or the latest from source:
pip install "git+https://github.com/uukjtisa/updater-gitplucker.git"
Concepts
Allowlist (security boundary)
allowed_repos is enforced at the network layer: any repo not listed is
rejected before any request. Every subscription's repo must be allowlisted.
Channels — how a repo is updated
| Channel | Source | Best for |
|---|---|---|
Channel.RELEASE |
Latest GitHub Release + assets (.zip, .whl, …) |
Versioned/shipped builds |
Channel.SOURCE |
Raw source at a branch tip (zipball) | Repos without formal releases |
Channel.PYTHON_SOURCE |
SOURCE + 3-way merge + dependency auto-detect |
Python apps held together by scripts (the main use case) |
Apply strategies — what an update replaces (config.apply_strategy)
| Strategy | Effect |
|---|---|
ApplyStrategy.WHOLE_APP (default) |
Add/modify/merge/delete the tracked tree, with backup + rollback |
ApplyStrategy.SELECTIVE |
Only paths matching selective_globs; never deletes |
ApplyStrategy.PACKAGE |
pip install the downloaded wheel/sdist (RELEASE channel) |
Triggers — when it runs
- Manual — just call
updater.check()/updater.apply()(orManualTrigger). - Startup —
StartupTrigger(updater).run(on_update=prompt_fn). - Background —
BackgroundTrigger(updater, interval_seconds=3600).start(...).
All three are optional wrappers; the library never acts on its own.
3-way merge (PYTHON_SOURCE)
After each apply, gitplucker snapshots the exact files it pulled (the base).
On the next update it merges base → your local edits with base → upstream.
Non-overlapping changes merge cleanly; only edits to the same lines produce a
conflict. config.conflict_policy decides what happens then: mark (git-style
markers, default), local, remote, or abort.
Dependency auto-detection (PYTHON_SOURCE)
Every incoming .py is scanned for imports; standard-library and the app's own
packages are filtered out; anything left that isn't installed is surfaced in
plan.dependency_changes and (if auto_install_deps=True) pip install-ed on
apply. Version pins in your requirements.txt are honored. Newly-added modules
are flagged is_new.
Inspecting a plan
plan.summary() # one-line human summary
plan.has_update # bool
plan.file_changes # list[FileChange] (added/modified/merged/conflict/deleted)
plan.conflicts # list[FileChange] (subset needing attention)
plan.dependency_changes # list[DependencyChange]
plan.new_dependencies # subset that are newly referenced
plan.warnings # e.g. "local changes overwritten (no merge available)"
plan.release_notes # release body / source stamp
Events
updater.events.on(lambda name, payload: print(name, payload))
Emitted: check.start/done, download.progress, dep.detected/install,
apply.file, backup, rollback, apply.done. A throwing listener can never
break an update.
State & rollback
Everything lives in install_root/.gitplucker/ (override via state_dir):
manifest.json (installed version + known modules per repo/branch), base/
(merge snapshots), backups/ (timestamped pre-apply copies for manual
rollback). A failed apply auto-rolls-back the current batch.
See docs/INTEGRATION.md for a step-by-step wiring guide
and examples/basic.py for a runnable script.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file updater_gitplucker-0.4.0.tar.gz.
File metadata
- Download URL: updater_gitplucker-0.4.0.tar.gz
- Upload date:
- Size: 37.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3308ca7da2aeae38961b7a27aa75190f581cc054349ca8b0d92e560de439360a
|
|
| MD5 |
bf2f26b4a34930f312ca941917661815
|
|
| BLAKE2b-256 |
8b47f07bcdfe24cb0267bbc8629e8839696d51ec9e174a10a1df379ed61c8c85
|
File details
Details for the file updater_gitplucker-0.4.0-py3-none-any.whl.
File metadata
- Download URL: updater_gitplucker-0.4.0-py3-none-any.whl
- Upload date:
- Size: 41.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7dee75865750cddb375673cb265d9db638c2e74b911895ccf1bb63a3069ee728
|
|
| MD5 |
440856fd2cb02d3b4f442d868c9526a7
|
|
| BLAKE2b-256 |
0311cb28df73a787533d84abbd7e30b8389833440feb344b27cf9e04c116fe15
|