mirror of
https://github.com/kevinveenbirkenbach/docker-volume-backup-cleanup.git
synced 2026-01-08 16:32:13 +00:00
feat: make cleanup production-safe by separating invalid backups from infra errors
- Delete only truly invalid backups (dirval rc=1) - Treat timeouts and missing dirval as infrastructure errors - Never auto-delete backups affected by timeouts - Return exit code 1 on infrastructure problems - Update unit and E2E tests to reflect new safety semantics - Align README with new deletion and exit-code behavior https://chatgpt.com/share/695d36f6-0000-800f-98e7-f88a798d6e91
This commit is contained in:
@@ -121,13 +121,6 @@ class CleanbackE2EDockerTests(unittest.TestCase):
|
||||
env["PATH"] = f"{self.bin_dir}:{env.get('PATH', '')}"
|
||||
|
||||
# Run: python -m cleanback --id <ID> --yes
|
||||
# We must point BACKUPS_ROOT to our run_root. Easiest: set /Backups = run_root
|
||||
# But code currently has BACKUPS_ROOT = /Backups constant.
|
||||
#
|
||||
# Therefore, we create our test tree under /Backups (done above) and pass --id
|
||||
# relative to that structure by using run_root/<ID>. To do that, we make
|
||||
# run_root the direct child under /Backups, then we pass the composite id:
|
||||
# "<run-folder>/<ID>".
|
||||
composite_id = f"{self.run_root.name}/{self.backup_id}"
|
||||
|
||||
cmd = [
|
||||
@@ -148,14 +141,19 @@ class CleanbackE2EDockerTests(unittest.TestCase):
|
||||
]
|
||||
proc = subprocess.run(cmd, text=True, capture_output=True, env=env)
|
||||
|
||||
self.assertEqual(proc.returncode, 0, msg=proc.stderr or proc.stdout)
|
||||
# New behavior:
|
||||
# - invalid dirs are deleted and do NOT cause failure
|
||||
# - timeouts are treated as infrastructure problems -> exit code 1 and NOT deleted
|
||||
self.assertEqual(proc.returncode, 1, msg=proc.stderr or proc.stdout)
|
||||
|
||||
self.assertTrue(self.good.exists(), "good should remain")
|
||||
self.assertFalse(self.bad.exists(), "bad should be deleted")
|
||||
self.assertFalse(
|
||||
self.assertTrue(
|
||||
self.timeout.exists(),
|
||||
"timeout should be deleted (timeout treated as failure)",
|
||||
"timeout should NOT be deleted (timeouts are infrastructure problems)",
|
||||
)
|
||||
self.assertIn("Summary:", proc.stdout)
|
||||
self.assertIn("validation infrastructure problem", proc.stdout.lower())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -123,12 +123,12 @@ class CleanupBackupsUsingDirvalTests(unittest.TestCase):
|
||||
"--yes",
|
||||
]
|
||||
)
|
||||
self.assertEqual(rc, 0, msg=err or out)
|
||||
self.assertEqual(rc, 1, msg=err or out)
|
||||
self.assertTrue(self.goodA.exists(), "goodA should remain")
|
||||
self.assertFalse(self.badB.exists(), "badB should be deleted")
|
||||
self.assertFalse(
|
||||
self.assertTrue(
|
||||
self.timeoutC.exists(),
|
||||
"timeoutC should be deleted (timeout treated as failure)",
|
||||
"timeoutC should NOT be deleted (timeout is infra error)",
|
||||
)
|
||||
self.assertIn("Summary:", out)
|
||||
|
||||
@@ -147,10 +147,10 @@ class CleanupBackupsUsingDirvalTests(unittest.TestCase):
|
||||
"--yes",
|
||||
]
|
||||
)
|
||||
self.assertEqual(rc, 0, msg=err or out)
|
||||
self.assertEqual(rc, 1, msg=err or out)
|
||||
self.assertTrue(self.goodA.exists())
|
||||
self.assertFalse(self.badB.exists())
|
||||
self.assertFalse(self.timeoutC.exists())
|
||||
self.assertTrue(self.timeoutC.exists())
|
||||
self.assertTrue(self.goodX.exists())
|
||||
self.assertFalse(self.badY.exists())
|
||||
|
||||
@@ -198,8 +198,8 @@ class CleanupBackupsUsingDirvalTests(unittest.TestCase):
|
||||
"--yes",
|
||||
]
|
||||
)
|
||||
self.assertEqual(rc, 0, msg=err or out)
|
||||
self.assertIn("dirval not found", out + err)
|
||||
self.assertEqual(rc, 1, msg=err or out)
|
||||
self.assertIn("dirval missing", out + err)
|
||||
|
||||
def test_no_targets_message(self):
|
||||
empty = self.backups_root / "EMPTY" / "backup-docker-to-local"
|
||||
|
||||
Reference in New Issue
Block a user