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
- 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
111 lines
4.3 KiB
Python
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()
|