Files
restic-backup-docker/CHANGELOG.md
T
Tobias KaupatandClaude Sonnet 5.5 be7d426f78 test: move container test suites to pytest (#112)
* test: scaffold pytest suite with mise, uv and Task

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci: run the pytest suite via mise and task

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix: make test cleanup survive repeated SIGINT

A group Ctrl-C reaches pytest a second time via task and uv while the
session fixture tears down, aborting the volume cleanup. Ignore SIGINT
and SIGTERM during cleanup, remove volumes in finally, and tolerate
already-removed objects.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix: pin Python 3.13 for uv without mise

Add .python-version (read by mise and uv) and cap requires-python at
<3.14 so bare uv uses 3.13 or fails instead of picking 3.14.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix: clean up test containers on SIGTERM

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: port compat tests to pytest

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: assert the success message first in the corruption test

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: assert the empty-tag snapshot carries no tags

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: remove anonymous volumes with short-lived test containers

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: port feature-gated tests to pytest

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: port sabotage self-test to task test:sabotage

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix: create parent directories in put_file

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: move structure.yml to tests and remove cst volume leak

container-structure-test left one anonymous volume per test container.
tests/structure.py runs it with --save and removes the new containers
with their volumes afterwards.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: remove the Bash suite

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci: run only the Python suite in the test job

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* docs: describe the Python test suite

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: isolate scenario steps, share helpers, use restore_latest, HEAD dir probe

Scenario fixtures record each step; a failing step fails only the tests
that assert on it. running() and raise_interrupt() live in helpers.py.
put_file probes parent directories with a HEAD request instead of a
get_archive stream. stream_run uses restore_latest and asserts its result.
Docstrings no longer refer to the removed Bash suite.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: sabotage check rejects errors and malformed reports

Only <failure> of the expected tests counts as red; errors in them and a
malformed JUnit report exit 2 (invalid) instead of passing or exiting 1.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test: structure wrapper removes only its own containers

Restrict cleanup to containers of the image under test without the
rbd-test-run label and ignore NotFound.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* build: run all test suites and aggregate the exit code

task test no longer stops at the first failing suite.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix: sabotage check treats failed scenario steps as INVALID

StepFailed is no AssertionError any more; sabotage.py counts a JUnit failure
named StepFailed as error, so an expected-red test only counts when its own
assertion fails.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix: hard timeout for container-structure-test

CST_TIMEOUT (default 300 s) kills a hanging run; existing cleanup removes the
containers; exit code 124 with a clear message.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix: shorten sabotage message for lint

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix: handle JUnit failures without message in sabotage check

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 20:47:03 +02:00

2.2 KiB

Changelog

Unreleased

Added

  • Test suites in tests/ (compat, features, structure) that run the image as a real container, plus a Test GitHub Actions workflow running them on every pull request. The suites are written in Python (pytest) and run via mise install and task test; task test:sabotage proves they detect a broken backup
  • .gitattributes pinning shell scripts, the Dockerfile and YAML files to LF line endings. With a Windows checkout (core.autocrlf=true) the scripts were checked out with CRLF, which made the built image fail to start with exec /entry.sh: no such file or directory

Removed

  • config-broken.yml and docker-compose.test.broken.yml, replaced by tests/structure.yml and the test workflow

v1.4.2

Removed

  • Execute a repository check after prune was passed as a parameter in the forget call - use RESTIC_CHECK_CRON Var instead

v1.4.1

Changed

  • Execute a repository check after prune was passed as a parameter in the forget call

v1.4.0

Added

  • Option to set the target folder backup
  • Multi-platform image build

v1.3.2 (restic 0.16.0)

Changed

  • Base image directly on official restic image
  • Semver aligned version naming including restic version
  • Updated to restic 0.16.0

Added

  • rclone to docker image
  • Implemented a simple mail notification after backups using mailx
  • MAILX_ARGS environment variable

v1.3.1-0.9.6

Changed

  • Update to Restic v0.9.5
  • Reduced the number of layers in the Docker image

Fixed

  • Check if a repo already exists works now for all repository types

Added

  • shh added to container
  • fuse added to container
  • support to send mails using external SMTP server after backups

v1.2-0.9.4

Added

  • AWS Support

v1.1

Fixed

  • --prune must be passed to RESTIC_FORGET_ARGS to execute prune after forget.

Changed

  • Switch to base Docker container to golang:1.7-alpine to support latest restic build.

v1.0

Initial release.

The container has proper logs now and was running for over a month in production. There are still some features missing. Sticking to semantic versioning we do not expect any breaking changes in the 1.x releases.