Repository navigation
v1.1.0
v1.1.0
Bug-fix release. Four defects were found in review, each capable of producing a backup that looked successful while silently missing data, or a notification that silently failed to retry. All four are fixed with new regression tests, including two run against a real Docker daemon — one of them was verified to actually catch the regression by reverting the fix and confirming the test fails.
Fixed
A backup could silently report success while missing data
- A source file Backfort could not read (permission denied, an I/O error) used to disappear quietly from the archive while the run was still logged as
backup-succeeded.tar --createno longer runs with--ignore-failed-read; GNU tar's own exit status now tells a real read failure (fails the job) apart from the tolerated race of a file changing mid-read (still a warning-only success). Applies to file-source jobs and to Compose named-volume/bind-mount snapshots alike. - The archive sanitizer was silently dropping any file or directory whose name merely started with a space — a false positive, since every archive member is transform-prefixed with the literal string
data, which never itself starts with whitespace. That check is removed. A name that genuinely can't be represented (a literal newline, carriage return, tab, or invalid UTF-8) is still excluded, but doing so now fails the job with a clearmessage=unsupported-entries-removedlog line instead of quietly publishing an incomplete backup.
command_timeout_seconds now actually stops the process, not just the client
- Killing the host-side
docker/docker composeclient — all a timeout wrapper alone can do — does not stop a process it started inside the container's own PID namespace. A hungpg_dump, a restore import, or the volume-snapshottarkept running, orphaned, long after Backfort had given up and moved on. The actual command is now also wrapped with an in-containertimeout, so it's reliably reaped. Requires atimeoutbinary in the database service and volume-helper images (present in common Debian- and Alpine-based images).
Telegram's plain-text retry could never fire
curl --faildiscarded the response body on Telegram's own HTTP error status for a rejected HTML message (e.g. a malformed tag in a custom template), so the{"ok":false,...}payload the retry logic needed to inspect never reached it — the designed fallback silently never triggered.notification_curl_postnow reads the HTTP status explicitly via--write-outinstead of leaning oncurl --fail.
Testing
- New:
tests/unreadable-file.sh(unreadable and unsupported source names) andtests/compose-exec-timeout-real.sh(real Docker; proves the in-container process is actually gone, not just detached from a killed client). tests/notify.sh's Telegram-retry scenario now serves a genuine HTTP 400 and exercises the real production code path instead of a canned response.tests/archive-resilience.shandtests/fidelity.shupdated for the new fail-instead-of-silently-warn behavior.- Full suite: 24/24 passing, including
fidelity.shunder root withacl/attr.