Releases: KingPin/hoist
Release list
v1.9.2
Full Changelog: v1.9.1...v1.9.2
v1.9.1
What's Changed
Full Changelog: v1.9.0...v1.9.1
v1.9.0
What's Changed
Full Changelog: v1.8.3...v1.9.0
v1.8.3
Highlights
Fix: orphaned docker compose children no longer wedge the per-project lock.
Symptom
Runs hang at <container>: Checking... on the same containers every time. The run's workers sit parked on flock, while stale docker compose pull processes from earlier runs linger reparented to PID 1.
Root cause
_with_project_lock opened the per-project flock fd without close-on-exec, so every docker compose pull/up child inherited it. Because flock is held against the open file description (not the process), a Ctrl+C — or any worker death — mid-pull orphaned that child to init while it kept the fd open forever, holding the lock and wedging every later run that touched the same compose project. Each killed run leaked another orphan, ratcheting the problem worse. This is the per-project analogue of the run-lock fd-inheritance bug fixed in v1.8.2.
Fix
Close the lock fd for the wrapped command only ({fd}>&-). The worker keeps its own copy open so the lock still holds for the duration of the pull/up, but the docker child can no longer pin it — an orphaned child no longer outlives its worker.
Upgrade note
This prevents new wedges. If a host is already stuck from a pre-1.8.3 run, clear the existing orphans once:
```bash
pkill -f '/usr/local/bin/hoist'
pkill -f 'docker.*compose pull'
```
What's Changed
Full Changelog: v1.8.2...v1.8.3
v1.8.2 — Fix run-lock surviving Ctrl+C
Bug fix: a Ctrl+C'd run no longer wedges future runs
Symptom
Pressing Ctrl+C during a run — typically while docker compose pull was in flight under --parallel — left the flock run-lock permanently held. Every subsequent run then bailed out immediately with:
Another hoist run holds the lock (/tmp/hoist.lock); exiting.
The only recovery was to find and kill the stray process or reboot.
Root cause
The run-lock is a flock held against the open file description, which the kernel releases only when the last copy of that file descriptor closes. Bash sets no close-on-exec flag on the {_LOCK_FD} redirection fd, so every docker/docker compose child and every &-spawned parallel worker inherited it. A Ctrl+C mid-pull could orphan a docker subprocess (the signal handler's pkill -P reaches only direct children, and races the worker's death), and that orphan kept the inherited fd — and therefore the lock — alive long after hoist itself had exited.
Fix
After acquiring the lock, hoist now hands the held fd to a single childless holder process and closes its own copy, so nothing it later forks or exec's can pin the lock:
- The holder is
disowned, keeping it out of the job table so the parallel pool'swait/wait -nignore it. - An
EXITtrap — also reached via theINT/TERMhandler'sexit— kills the holder, releasing the lock the instant hoist truly exits, regardless of any orphaned docker children left behind.
The result: serial and parallel runs release the lock cleanly on Ctrl+C, SIGTERM, or normal exit. The mkdir-fallback lock path (used when flock is absent) was already covered by its stale-PID detection and is unchanged.
No configuration or label changes. Drop-in upgrade — run hoist --update.
v1.8.1
What's Changed
Changed
- Quieter parallel pulls — under
--parallel N(N > 1), hoist now passes--quiettodocker compose pull. Previously, sibling containers' compose-pull progress bars interleaved into unreadable output. Hoist's own per-containerChecking.../Pulling image...log lines still print, so a parallel run never looks hung. Serial runs (--parallel 1, the default) are unchanged and keep Docker's verbose progress output.
Notes
- This is a cosmetic/output change only — update, notify, digest-comparison, and summary behavior are all unaffected.
- A
Pulledline fromdocker compose pullmeans "registry checked, local copy verified current" — not "a new version was downloaded." The authoritative result is always hoist's end-of-run summary line.
Full Changelog: v1.8.0...v1.8.1
v1.8.0
What's Changed
Full Changelog: v1.7.1...v1.8.0
v1.7.1
v1.7.0
Highlights
- New
--docker-host <uri>flag for--cron install --scope user. PinsDOCKER_HOSTinto the generatedhoist.serviceregardless of whether the calling shell has it set. Useful for non-interactive automation (Ansible, CI) and when auto-detect would pick the wrong rootless docker socket.
Behaviour
- Precedence: explicit
--docker-hostwins over the existing auto-detect path. With no flag, the v1.6.0 auto-pin behaviour is unchanged (looks atDOCKER_HOST,systemctl --user show-environment, and docker context). - Scope guard:
--docker-hostis rejected with--scope system— the system unit doesn't go through the pinning path. - Logs disambiguate source: install logs now show
(--docker-host flag)vs(rootless docker detected)so the origin of the pin is obvious in journalctl.
Example
hoist --cron install --scope user --schedule hourly \
--docker-host unix:///run/user/1000/docker.sockDocs
docs/scheduling.mdgains a "User scope and rootless docker" section covering both auto-pin and explicit override.README.mdandCLAUDE.mdupdated with the new flag.
Full Changelog: v1.6.0...v1.7.0