Skip to content

Commit c87081a

Browse files
authored
fix(integration): clarify multi-install guidance (#2549)
1 parent e6afba9 commit c87081a

2 files changed

Lines changed: 50 additions & 7 deletions

File tree

src/specify_cli/__init__.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,10 +1740,18 @@ def integration_install(
17401740

17411741
if key in installed_keys:
17421742
console.print(f"[yellow]Integration '{key}' is already installed.[/yellow]")
1743+
if default_key == key:
1744+
console.print("It is already the default integration.")
1745+
else:
1746+
console.print(
1747+
f"To make it the default integration, run "
1748+
f"[cyan]specify integration use {key}[/cyan]."
1749+
)
17431750
console.print(
1744-
f"Run [cyan]specify integration upgrade {key}[/cyan] to reinstall managed files, "
1745-
f"or [cyan]specify integration uninstall {key}[/cyan] first."
1751+
f"To refresh its managed files or options, run "
1752+
f"[cyan]specify integration upgrade {key}[/cyan]."
17461753
)
1754+
console.print("No files were changed.")
17471755
raise typer.Exit(0)
17481756

17491757
if installed_keys and not force:
@@ -1763,8 +1771,12 @@ def integration_install(
17631771
"integrations are declared multi-install safe."
17641772
)
17651773
console.print(
1766-
f"Run [cyan]specify integration switch {key}[/cyan] to replace the default "
1767-
f"integration, or retry with [cyan]--force[/cyan] to opt in."
1774+
f"To replace the default integration, run "
1775+
f"[cyan]specify integration switch {key}[/cyan]."
1776+
)
1777+
console.print(
1778+
f"To install '{key}' alongside the existing integrations anyway, "
1779+
"retry the same install command with [cyan]--force[/cyan]."
17681780
)
17691781
raise typer.Exit(1)
17701782

tests/integrations/test_integration_subcommand.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,30 @@ def test_install_already_installed(self, tmp_path):
163163
assert "already installed" in result.output
164164
normalized = " ".join(result.output.split())
165165
assert "specify integration upgrade copilot" in normalized
166-
assert "specify integration uninstall copilot" in normalized
166+
assert "already the default integration" in normalized
167+
assert "No files were changed" in normalized
168+
assert "specify integration uninstall copilot" not in normalized
169+
170+
def test_install_already_installed_non_default_guides_use(self, tmp_path):
171+
project = _init_project(tmp_path, "claude")
172+
old_cwd = os.getcwd()
173+
try:
174+
os.chdir(project)
175+
install = runner.invoke(app, [
176+
"integration", "install", "codex",
177+
"--script", "sh",
178+
], catch_exceptions=False)
179+
assert install.exit_code == 0, install.output
180+
181+
result = runner.invoke(app, ["integration", "install", "codex"])
182+
finally:
183+
os.chdir(old_cwd)
184+
assert result.exit_code == 0
185+
normalized = " ".join(result.output.split())
186+
assert "already installed" in normalized
187+
assert "specify integration use codex" in normalized
188+
assert "specify integration upgrade codex" in normalized
189+
assert "specify integration uninstall codex" not in normalized
167190

168191
def test_install_different_when_one_exists(self, tmp_path):
169192
project = _init_project(tmp_path, "copilot")
@@ -176,7 +199,11 @@ def test_install_different_when_one_exists(self, tmp_path):
176199
assert result.exit_code != 0
177200
assert "Installed integrations: copilot" in result.output
178201
assert "Default integration: copilot" in result.output
179-
assert "--force" in result.output
202+
normalized = " ".join(result.output.split())
203+
assert "To replace the default integration" in normalized
204+
assert "specify integration switch claude" in normalized
205+
assert "To install 'claude' alongside" in normalized
206+
assert "retry the same install command with --force" in normalized
180207

181208
def test_install_multi_safe_integration(self, tmp_path):
182209
project = _init_project(tmp_path, "claude")
@@ -261,7 +288,11 @@ def test_install_multi_unsafe_requires_force(self, tmp_path):
261288
assert result.exit_code != 0
262289
assert "Installed integrations: copilot" in result.output
263290
assert "multi-install safe" in result.output
264-
assert "--force" in result.output
291+
normalized = " ".join(result.output.split())
292+
assert "To replace the default integration" in normalized
293+
assert "specify integration switch claude" in normalized
294+
assert "To install 'claude' alongside" in normalized
295+
assert "retry the same install command with --force" in normalized
265296

266297
def test_install_multi_unsafe_allowed_with_force(self, tmp_path):
267298
project = _init_project(tmp_path, "copilot")

0 commit comments

Comments
 (0)