Files
pkgmgr/tests/integration/test_update_silent_continues.py
Kevin Veen-Birkenbach dcda23435d
Some checks failed
Mark stable commit / test-unit (push) Has been cancelled
Mark stable commit / test-integration (push) Has been cancelled
Mark stable commit / test-env-virtual (push) Has been cancelled
Mark stable commit / test-env-nix (push) Has been cancelled
Mark stable commit / test-e2e (push) Has been cancelled
Mark stable commit / test-virgin-user (push) Has been cancelled
Mark stable commit / test-virgin-root (push) Has been cancelled
Mark stable commit / lint-shell (push) Has been cancelled
Mark stable commit / lint-python (push) Has been cancelled
Mark stable commit / mark-stable (push) Has been cancelled
git commit -m "feat(update): add --silent mode with continue-on-failure and unified summary
- Introduce --silent flag for install/update to downgrade per-repo errors to warnings
- Continue processing remaining repositories on pull/install failures
- Emit a single summary at the end (suppress per-repo summaries during update)
- Preserve interactive verification behavior when not silent
- Add integration test covering silent vs non-silent update behavior
- Update e2e tests to use --silent for stability"

https://chatgpt.com/share/693ffcca-f680-800f-9f95-9d8c52a9a678
2025-12-15 13:19:14 +01:00

111 lines
4.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
import unittest
from unittest.mock import patch
from pkgmgr.actions.update.manager import UpdateManager
class TestUpdateSilentContinues(unittest.TestCase):
def test_update_continues_on_failures_and_silent_controls_exit_code(self) -> None:
"""
Integration test for UpdateManager:
- pull failure on repo A should not stop repo B/C
- install failure on repo B should not stop repo C
- without silent -> SystemExit(1) at end if any failures
- with silent -> no SystemExit even if there are failures
"""
repos = [
{"provider": "github", "account": "example", "repository": "repo-a"},
{"provider": "github", "account": "example", "repository": "repo-b"},
{"provider": "github", "account": "example", "repository": "repo-c"},
]
# We patch the internal calls used by UpdateManager:
# - pull_with_verification is called once per repo
# - install_repos is called once per repo that successfully pulled
#
# We simulate:
# repo-a: pull fails
# repo-b: pull ok, install fails
# repo-c: pull ok, install ok
pull_calls = []
install_calls = []
def pull_side_effect(selected_repos, *_args, **_kwargs):
# selected_repos is a list with exactly one repo in our implementation.
repo = selected_repos[0]
pull_calls.append(repo["repository"])
if repo["repository"] == "repo-a":
raise SystemExit(2)
return None
def install_side_effect(selected_repos, *_args, **kwargs):
repo = selected_repos[0]
install_calls.append((repo["repository"], kwargs.get("silent"), kwargs.get("emit_summary")))
if repo["repository"] == "repo-b":
raise SystemExit(3)
return None
# Patch at the exact import locations used inside UpdateManager.run()
with patch("pkgmgr.actions.repository.pull.pull_with_verification", side_effect=pull_side_effect), patch(
"pkgmgr.actions.install.install_repos", side_effect=install_side_effect
):
# 1) silent=True: should NOT raise (even though failures happened)
UpdateManager().run(
selected_repos=repos,
repositories_base_dir="/tmp/repos",
bin_dir="/tmp/bin",
all_repos=repos,
no_verification=True,
system_update=False,
preview=True,
quiet=True,
update_dependencies=False,
clone_mode="shallow",
silent=True,
force_update=True,
)
# Ensure it tried all pulls, and installs happened for B and C only.
self.assertEqual(pull_calls, ["repo-a", "repo-b", "repo-c"])
self.assertEqual([r for r, _silent, _emit in install_calls], ["repo-b", "repo-c"])
# Ensure UpdateManager suppressed install summary spam by passing emit_summary=False.
for _repo_name, _silent, emit_summary in install_calls:
self.assertFalse(emit_summary)
# Reset tracking for the non-silent run
pull_calls.clear()
install_calls.clear()
# 2) silent=False: should raise SystemExit(1) at end due to failures
with self.assertRaises(SystemExit) as cm:
UpdateManager().run(
selected_repos=repos,
repositories_base_dir="/tmp/repos",
bin_dir="/tmp/bin",
all_repos=repos,
no_verification=True,
system_update=False,
preview=True,
quiet=True,
update_dependencies=False,
clone_mode="shallow",
silent=False,
force_update=True,
)
self.assertEqual(cm.exception.code, 1)
# Still must have processed all repos (continue-on-failure behavior).
self.assertEqual(pull_calls, ["repo-a", "repo-b", "repo-c"])
self.assertEqual([r for r, _silent, _emit in install_calls], ["repo-b", "repo-c"])
if __name__ == "__main__":
unittest.main()