Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
python-version: "3.14"

- name: Run ruff check
run: uvx ruff check src tests
run: uvx ruff@0.15.0 check src tests
Comment thread
mnriem marked this conversation as resolved.

pytest:
runs-on: ${{ matrix.os }}
Expand Down
5 changes: 4 additions & 1 deletion src/specify_cli/bundler/services/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ class InstallResult:

@property
def changed(self) -> bool:
return bool(self.installed or self.refreshed)
# `uninstalled` is a mutating outcome too: a `bundle update` whose new
# manifest drops components (removing them via the refresh path) with no
# new install/refresh must still report changed=True, not a no-op.
return bool(self.installed or self.refreshed or self.uninstalled)


def install_bundle(
Expand Down
13 changes: 13 additions & 0 deletions tests/integration/test_bundler_install_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,3 +491,16 @@ def test_update_keeps_component_still_needed_by_sibling_bundle(tmp_path: Path):
assert ("extensions", "ext-b") not in {
(c.kind, c.id) for c in rec.contributed_components
}


def test_install_result_changed_reports_uninstalled():
# A `bundle update` that only DROPS components (new manifest reduces
# provides) populates uninstalled with nothing installed/refreshed; that is
# still a mutating change, so `changed` must be True — not a false no-op.
from specify_cli.bundler.services.installer import InstallResult
from specify_cli.bundler.models.manifest import ComponentRef

result = InstallResult(bundle_id="x")
assert result.changed is False # empty == no change
result.uninstalled.append(ComponentRef(kind="presets", id="p1"))
assert result.changed is True