diff --git a/NEWS b/NEWS index 287602ec..709ae6c8 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ * #1258: Fix a "codec can't decode byte" error when running commands that output multi-byte unicode characters. * #1260: Fix for SSH warnings from Borg showing up as JSON logs even without the "--log-json" flag. + * #1252: Work around Borg returning a warning exit code when a repository/archive check fails. Now, + borgmatic interprets such failures as errors. 2.1.1 * #1241: For the "recreate" action, actually pass the "--dry-run" flag through to Borg instead of diff --git a/borgmatic/borg/check.py b/borgmatic/borg/check.py index ef160417..a74c9b5c 100644 --- a/borgmatic/borg/check.py +++ b/borgmatic/borg/check.py @@ -149,8 +149,10 @@ def check_archives( max_duration = check_arguments.max_duration or repository_check_config.get('max_duration') + # If not configured, elevate Borg's exit code 1 (an ostensible warning) to error, because Borg + # returns exit code 1 for repository check errors! + borg_exit_codes = config.get('borg_exit_codes', []) + [{'code': 1, 'treat_as': 'error'}] umask = config.get('umask') - borg_exit_codes = config.get('borg_exit_codes') working_directory = borgmatic.config.paths.get_working_directory(config) if 'data' in checks: diff --git a/tests/unit/borg/test_check.py b/tests/unit/borg/test_check.py index fb4acc32..d68c89e0 100644 --- a/tests/unit/borg/test_check.py +++ b/tests/unit/borg/test_check.py @@ -24,7 +24,7 @@ def insert_execute_command_mock( environment=None, working_directory=working_directory, borg_local_path=command[0], - borg_exit_codes=borg_exit_codes, + borg_exit_codes=(borg_exit_codes or []) + [{'code': 1, 'treat_as': 'error'}], ).once() @@ -335,7 +335,7 @@ def test_check_archives_with_progress_passes_through_to_borg(): environment=None, working_directory=None, borg_local_path='borg', - borg_exit_codes=None, + borg_exit_codes=[{'code': 1, 'treat_as': 'error'}], ).once() module.check_archives( @@ -371,7 +371,7 @@ def test_check_archives_with_log_json_and_progress_passes_through_both_to_borg() environment=None, working_directory=None, borg_local_path='borg', - borg_exit_codes=None, + borg_exit_codes=[{'code': 1, 'treat_as': 'error'}], ).once() module.check_archives( @@ -407,7 +407,7 @@ def test_check_archives_with_repair_passes_through_to_borg(): environment=None, working_directory=None, borg_local_path='borg', - borg_exit_codes=None, + borg_exit_codes=[{'code': 1, 'treat_as': 'error'}], ).once() module.check_archives( @@ -443,7 +443,7 @@ def test_check_archives_with_log_json_and_repair_passes_through_both_to_borg(): environment=None, working_directory=None, borg_local_path='borg', - borg_exit_codes=None, + borg_exit_codes=[{'code': 1, 'treat_as': 'error'}], ).once() module.check_archives( @@ -479,7 +479,7 @@ def test_check_archives_with_max_duration_flag_passes_through_to_borg(): environment=None, working_directory=None, borg_local_path='borg', - borg_exit_codes=None, + borg_exit_codes=[{'code': 1, 'treat_as': 'error'}], ).once() module.check_archives( @@ -515,7 +515,7 @@ def test_check_archives_with_max_duration_option_passes_through_to_borg(): environment=None, working_directory=None, borg_local_path='borg', - borg_exit_codes=None, + borg_exit_codes=[{'code': 1, 'treat_as': 'error'}], ).once() module.check_archives( @@ -689,7 +689,7 @@ def test_check_archives_with_max_duration_flag_overrides_max_duration_option(): environment=None, working_directory=None, borg_local_path='borg', - borg_exit_codes=None, + borg_exit_codes=[{'code': 1, 'treat_as': 'error'}], ).once() module.check_archives( @@ -854,7 +854,7 @@ def test_check_archives_with_local_path_calls_borg_via_local_path(): def test_check_archives_with_exit_codes_calls_borg_using_them(): checks = {'repository'} - borg_exit_codes = flexmock() + borg_exit_codes = [{'code': 101, 'treat_as': 'error'}] config = {'borg_exit_codes': borg_exit_codes} flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(()) flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) @@ -1026,7 +1026,7 @@ def test_check_archives_with_match_archives_passes_through_to_borg(): environment=None, working_directory=None, borg_local_path='borg', - borg_exit_codes=None, + borg_exit_codes=[{'code': 1, 'treat_as': 'error'}], ).once() module.check_archives(