Skip to content

Commit 0415378

Browse files
committed
added output mode json
1 parent 9869209 commit 0415378

File tree

3 files changed

+330
-181
lines changed

3 files changed

+330
-181
lines changed

src/workato_platform_cli/cli/commands/profiles.py

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -394,29 +394,58 @@ def _update_workatoenv_files(old_name: str, new_name: str) -> list[Path]:
394394
@profiles.command()
395395
@click.argument("old_name")
396396
@click.argument("new_name")
397+
@click.option(
398+
"--output-mode",
399+
type=click.Choice(["table", "json"]),
400+
default="table",
401+
help="Output format: table (default) or json",
402+
)
403+
@click.option(
404+
"--yes",
405+
is_flag=True,
406+
help="Skip confirmation prompt",
407+
)
397408
@handle_cli_exceptions
398409
@inject
399410
async def rename(
400411
old_name: str,
401412
new_name: str,
413+
output_mode: str = "table",
414+
yes: bool = False,
402415
config_manager: ConfigManager = Provide[Container.config_manager],
403416
) -> None:
404417
"""Rename a profile"""
405418
# Check if old profile exists
406419
old_profile = config_manager.profile_manager.get_profile(old_name)
407420
if not old_profile:
408-
click.echo(f"❌ Profile '{old_name}' not found")
409-
click.echo("💡 Use 'workato profiles list' to see available profiles")
421+
if output_mode == "json":
422+
error_msg = f"Profile '{old_name}' not found"
423+
output_data: dict[str, Any] = {"status": "error", "error": error_msg}
424+
click.echo(json.dumps(output_data))
425+
else:
426+
click.echo(f"❌ Profile '{old_name}' not found")
427+
click.echo("💡 Use 'workato profiles list' to see available profiles")
410428
return
411429

412430
# Check if new name already exists
413431
if config_manager.profile_manager.get_profile(new_name):
414-
click.echo(f"❌ Profile '{new_name}' already exists")
415-
click.echo("💡 Choose a different name or delete the existing profile first")
432+
if output_mode == "json":
433+
error_msg = f"Profile '{new_name}' already exists"
434+
output_data = {"status": "error", "error": error_msg}
435+
click.echo(json.dumps(output_data))
436+
else:
437+
click.echo(f"❌ Profile '{new_name}' already exists")
438+
click.echo(
439+
"💡 Choose a different name or delete the existing profile first"
440+
)
416441
return
417442

418-
# Show confirmation prompt
419-
if not click.confirm(f"Rename profile '{old_name}' to '{new_name}'?"):
443+
# Show confirmation prompt (skip in JSON mode or if --yes flag)
444+
if (
445+
not yes
446+
and output_mode != "json"
447+
and not click.confirm(f"Rename profile '{old_name}' to '{new_name}'?")
448+
):
420449
click.echo("❌ Rename cancelled")
421450
return
422451

@@ -427,24 +456,43 @@ async def rename(
427456
try:
428457
config_manager.profile_manager.set_profile(new_name, old_profile, old_token)
429458
except ValueError as e:
430-
click.echo(f"❌ Failed to create new profile: {e}")
459+
if output_mode == "json":
460+
output_data = {"status": "error", "error": str(e)}
461+
click.echo(json.dumps(output_data))
462+
else:
463+
click.echo(f"❌ Failed to create new profile: {e}")
431464
return
432465

433466
# If old profile was current, set new profile as current
434467
current_profile = config_manager.profile_manager.get_current_profile_name()
435-
if current_profile == old_name:
468+
was_current = current_profile == old_name
469+
if was_current:
436470
config_manager.profile_manager.set_current_profile(new_name)
437471

438472
# Delete old profile
439473
config_manager.profile_manager.delete_profile(old_name)
440474

441475
# Update all .workatoenv files that reference the old profile
442-
click.echo("🔄 Updating project configurations...")
476+
if output_mode == "table":
477+
click.echo("🔄 Updating project configurations...")
443478
updated_files = _update_workatoenv_files(old_name, new_name)
444479

445-
# Show success message
480+
# JSON output mode
481+
if output_mode == "json":
482+
output_data = {
483+
"status": "success",
484+
"old_name": old_name,
485+
"new_name": new_name,
486+
"was_current_profile": was_current,
487+
"updated_files": [str(f) for f in updated_files],
488+
"updated_files_count": len(updated_files),
489+
}
490+
click.echo(json.dumps(output_data))
491+
return
492+
493+
# Table output mode (default)
446494
click.echo("✅ Profile renamed successfully")
447-
if current_profile == old_name:
495+
if was_current:
448496
click.echo(f"✅ Set '{new_name}' as the active profile")
449497

450498
# Display updated files

tests/conftest.py

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
"""Pytest configuration and shared fixtures."""
22

3+
import json
34
import tempfile
45

5-
from collections.abc import Generator
6+
from collections.abc import Callable, Generator
67
from pathlib import Path
78
from typing import Any
89
from unittest.mock import MagicMock, Mock, patch
@@ -144,3 +145,80 @@ def prevent_keyring_errors() -> None:
144145
minimal_keyring.delete_password.return_value = None
145146

146147
sys.modules["keyring"] = minimal_keyring
148+
149+
150+
# Shared test helpers
151+
152+
153+
def parse_json_output(capsys: pytest.CaptureFixture[str]) -> dict[str, Any]:
154+
"""Parse JSON output from capsys."""
155+
output = capsys.readouterr().out
156+
result: dict[str, Any] = json.loads(output)
157+
return result
158+
159+
160+
def create_workatoenv_file(
161+
tmp_path: Path,
162+
dir_name: str,
163+
profile: str,
164+
project_id: int = 123,
165+
**extra_fields: Any,
166+
) -> Path:
167+
"""Create a test .workatoenv file.
168+
169+
Args:
170+
tmp_path: Temporary directory path
171+
dir_name: Name of the project directory to create
172+
profile: Profile name to set in the workatoenv file
173+
project_id: Project ID (default: 123)
174+
**extra_fields: Additional fields to include in the workatoenv file
175+
"""
176+
project_dir = tmp_path / dir_name
177+
project_dir.mkdir()
178+
workatoenv = project_dir / ".workatoenv"
179+
180+
data = {"project_id": project_id, "profile": profile}
181+
data.update(extra_fields)
182+
183+
workatoenv.write_text(json.dumps(data))
184+
return workatoenv
185+
186+
187+
def _make_workatoenv_updater(tmp_path: Path) -> Callable[[str, str], list[Path]]:
188+
"""Create a mock _update_workatoenv_files function for testing.
189+
190+
Returns a function that searches tmp_path instead of home directory.
191+
"""
192+
193+
def mock_update(old_name: str, new_name: str) -> list[Path]:
194+
updated_files = []
195+
for workatoenv_file in tmp_path.rglob(".workatoenv"):
196+
try:
197+
with open(workatoenv_file, "r+") as f:
198+
data = json.load(f)
199+
if data.get("profile") == old_name:
200+
data["profile"] = new_name
201+
f.seek(0)
202+
f.truncate()
203+
json.dump(data, f, indent=2)
204+
f.write("\n")
205+
updated_files.append(workatoenv_file)
206+
except (OSError, json.JSONDecodeError):
207+
continue
208+
return updated_files
209+
210+
return mock_update
211+
212+
213+
def mock_workatoenv_updates(tmp_path: Path) -> Any:
214+
"""Context manager for mocking workatoenv file updates.
215+
216+
Use this to mock the _update_workatoenv_files function in profiles module.
217+
Must import profiles_module in your test file to use this helper.
218+
"""
219+
from workato_platform_cli.cli.commands import profiles as profiles_module
220+
221+
mock_update = _make_workatoenv_updater(tmp_path)
222+
return patch.object(
223+
profiles_module, "_update_workatoenv_files", side_effect=mock_update
224+
)

0 commit comments

Comments
 (0)