homeconsole-cli 0.0.3__tar.gz → 0.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/PKG-INFO +1 -1
  2. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/deploy.py +31 -3
  3. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/env.py +35 -3
  4. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/update.py +29 -2
  5. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/constants.py +1 -1
  6. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/core_ops.py +9 -2
  7. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/homeconsole_cli.egg-info/PKG-INFO +1 -1
  8. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/pyproject.toml +1 -1
  9. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/README.md +0 -0
  10. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/__init__.py +0 -0
  11. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/api.py +0 -0
  12. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/capabilities.py +0 -0
  13. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/client.py +0 -0
  14. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/__init__.py +0 -0
  15. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/_client_helpers.py +0 -0
  16. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/_compose_helpers.py +0 -0
  17. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/auth.py +0 -0
  18. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/connect.py +0 -0
  19. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/core.py +0 -0
  20. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/install.py +0 -0
  21. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/logs.py +0 -0
  22. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/marketplace.py +0 -0
  23. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/module.py +0 -0
  24. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/ping.py +0 -0
  25. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/plugin.py +0 -0
  26. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/recovery/__init__.py +0 -0
  27. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/recovery/compose.py +0 -0
  28. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/recovery/config.py +0 -0
  29. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/recovery/core.py +0 -0
  30. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/recovery/db.py +0 -0
  31. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/recovery/mode.py +0 -0
  32. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/recovery/redis.py +0 -0
  33. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/recovery/ui.py +0 -0
  34. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/remove.py +0 -0
  35. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/reset.py +0 -0
  36. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/search.py +0 -0
  37. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/secrets.py +0 -0
  38. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/setup.py +0 -0
  39. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/setup_wizard.py +0 -0
  40. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/commands/status.py +0 -0
  41. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/config.py +0 -0
  42. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/core_source.py +0 -0
  43. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/env_bootstrap.py +0 -0
  44. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/errors.py +0 -0
  45. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/main.py +0 -0
  46. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/marketplace_operation.py +0 -0
  47. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/native_core.py +0 -0
  48. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/repl.py +0 -0
  49. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/setup_runner.py +0 -0
  50. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/hc/shell.py +0 -0
  51. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/homeconsole_cli.egg-info/SOURCES.txt +0 -0
  52. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/homeconsole_cli.egg-info/dependency_links.txt +0 -0
  53. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/homeconsole_cli.egg-info/entry_points.txt +0 -0
  54. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/homeconsole_cli.egg-info/requires.txt +0 -0
  55. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/homeconsole_cli.egg-info/top_level.txt +0 -0
  56. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/setup.cfg +0 -0
  57. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/tests/test_config_roundtrip.py +0 -0
  58. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/tests/test_core_ops.py +0 -0
  59. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/tests/test_env_bootstrap.py +0 -0
  60. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/tests/test_main_root_callback.py +0 -0
  61. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/tests/test_marketplace_operation_parse.py +0 -0
  62. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/tests/test_native_core_helpers.py +0 -0
  63. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/tests/test_nav_cli.py +0 -0
  64. {homeconsole_cli-0.0.3 → homeconsole_cli-0.0.4}/tests/test_setup_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: homeconsole-cli
3
- Version: 0.0.3
3
+ Version: 0.0.4
4
4
  Summary: HomeConsole CLI (hc) — управление платформой через HTTP API
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -52,11 +52,15 @@ _STACK_ENV_COMPOSE: dict[str, str] = {
52
52
  }
53
53
 
54
54
 
55
+ _MONOREPO_SIBLINGS = frozenset({"home-console-cli", "packages", "platform-home-console"})
56
+
57
+
55
58
  def _find_repo_root() -> Path | None:
56
59
  here = Path(__file__).resolve()
57
60
  for p in [here, *here.parents]:
58
61
  if (p / "core-runtime-service").exists():
59
- return p
62
+ if any((p / s).exists() for s in _MONOREPO_SIBLINGS):
63
+ return p
60
64
  return None
61
65
 
62
66
 
@@ -106,6 +110,28 @@ def _run_env(cmd: list[str], *, cwd: Path | None = None, env: dict[str, str] | N
106
110
  raise typer.Exit(code=p.returncode)
107
111
 
108
112
 
113
+ def _run_pull(
114
+ cmd: list[str],
115
+ *,
116
+ cwd: Path | None = None,
117
+ env: dict[str, str] | None = None,
118
+ image: str,
119
+ ) -> None:
120
+ """docker compose pull с понятной подсказкой при ошибке авторизации."""
121
+ p = subprocess.run(cmd, cwd=str(cwd) if cwd else None, env=env, check=False) # noqa: S603
122
+ if p.returncode != 0:
123
+ registry = image.split("/")[0] if "/" in image else "ghcr.io"
124
+ raise HcCliError(
125
+ message=f"Не удалось загрузить образ {image}",
126
+ hint=(
127
+ f"Образ недоступен (denied / unauthorized).\n"
128
+ f" Авторизуйся в реестре:\n"
129
+ f" docker login {registry} -u <github_username> -p <PAT_read:packages>"
130
+ ),
131
+ exit_code=p.returncode,
132
+ )
133
+
134
+
109
135
  def _copy_dir_contents(src: Path, dst: Path) -> None:
110
136
  if dst.exists():
111
137
  shutil.rmtree(dst)
@@ -707,10 +733,11 @@ def register(app: typer.Typer) -> None:
707
733
  env = {**os.environ, "PLATFORM_IMAGE": full_image}
708
734
  console.print(f"[cyan]→[/cyan] Deploy platform image [bold]{full_image}[/bold]")
709
735
  if start:
710
- _run_env(
736
+ _run_pull(
711
737
  ["docker", "compose", "-f", str(compose_file), "pull", "platform-web"],
712
738
  cwd=platform_root,
713
739
  env=env,
740
+ image=full_image,
714
741
  )
715
742
  _run_env(
716
743
  ["docker", "compose", "-f", str(compose_file), "up", "-d"],
@@ -1477,10 +1504,11 @@ def register(app: typer.Typer) -> None:
1477
1504
  console.print(f"Local rollout: [bold]{full}[/bold]")
1478
1505
  env = {**os.environ, "CORE_RUNTIME_IMAGE": full, **_compose_env_overrides(db=db, cache=cache)}
1479
1506
  if do_pull:
1480
- _run_env(
1507
+ _run_pull(
1481
1508
  ["docker", "compose", "-f", str(project.compose_file), "pull", "core-runtime"],
1482
1509
  cwd=project.cwd,
1483
1510
  env=env,
1511
+ image=full,
1484
1512
  )
1485
1513
  _run_env(
1486
1514
  ["docker", "compose", "-f", str(project.compose_file), "up", "-d"],
@@ -11,7 +11,7 @@ from rich.console import Console
11
11
  from rich.table import Table
12
12
 
13
13
  from hc.core_ops import compose_project_from_source, require_docker
14
- from hc.core_source import CoreSource, get_core_source_from_repo, get_core_source_local
14
+ from hc.core_source import CoreSource, get_core_source_from_repo, get_core_source_local, init_core_source
15
15
  from hc.errors import CoreSourcesNotFoundError, HcCliError
16
16
 
17
17
 
@@ -105,11 +105,17 @@ _DB_HELP = "sqlite | postgres (без --db: интерактивный выбо
105
105
 
106
106
  # ─── Helpers ──────────────────────────────────────────────────────────────────
107
107
 
108
+ # Known siblings of core-runtime-service that confirm we're in the monorepo root.
109
+ # Without them, a standalone core-runtime-service clone in any parent dir would be mistaken for monorepo.
110
+ _MONOREPO_SIBLINGS = frozenset({"home-console-cli", "packages", "platform-home-console"})
111
+
112
+
108
113
  def _find_repo_root() -> Path | None:
109
114
  here = Path(__file__).resolve()
110
115
  for p in [here, *here.parents]:
111
116
  if (p / "core-runtime-service").exists():
112
- return p
117
+ if any((p / s).exists() for s in _MONOREPO_SIBLINGS):
118
+ return p
113
119
  return None
114
120
 
115
121
 
@@ -122,10 +128,36 @@ def _resolve_source(console: Console) -> CoreSource:
122
128
  src = get_core_source_local()
123
129
  if src:
124
130
  return src
131
+
132
+ # On a fresh machine: offer to auto-clone core-runtime-service.
133
+ from hc.constants import CORE_SRC_DIR, DEFAULT_CORE_REPO
134
+ console.print(f"[yellow]Исходники Core не найдены.[/yellow] ({CORE_SRC_DIR})")
135
+
136
+ if sys.stdin.isatty():
137
+ try:
138
+ import questionary
139
+ answer = questionary.confirm(
140
+ f"Скачать core-runtime-service в {CORE_SRC_DIR}?",
141
+ default=True,
142
+ ).ask()
143
+ except ImportError:
144
+ answer = None
145
+
146
+ if answer is None:
147
+ raise typer.Abort()
148
+ if not answer:
149
+ raise CoreSourcesNotFoundError(
150
+ message="Исходники Core не найдены.",
151
+ exit_code=1,
152
+ hint=f"Запусти: hc core init (клонирует {DEFAULT_CORE_REPO})",
153
+ )
154
+
155
+ return init_core_source(console, None, None)
156
+
125
157
  raise CoreSourcesNotFoundError(
126
158
  message="Исходники Core не найдены.",
127
159
  exit_code=1,
128
- hint="Сделай `hc core init` или запусти из монорепы HomeConsole.",
160
+ hint=f"Запусти: hc core init (клонирует {DEFAULT_CORE_REPO})",
129
161
  )
130
162
 
131
163
 
@@ -23,11 +23,15 @@ from hc.errors import (
23
23
  )
24
24
 
25
25
 
26
+ _MONOREPO_SIBLINGS = frozenset({"home-console-cli", "packages", "platform-home-console"})
27
+
28
+
26
29
  def _find_repo_root() -> Path | None:
27
30
  here = Path(__file__).resolve()
28
31
  for p in [here, *here.parents]:
29
32
  if (p / "core-runtime-service").exists():
30
- return p
33
+ if any((p / s).exists() for s in _MONOREPO_SIBLINGS):
34
+ return p
31
35
  return None
32
36
 
33
37
 
@@ -81,6 +85,28 @@ def _run(cmd: list[str], *, cwd: Path | None = None, env: dict[str, str] | None
81
85
  raise typer.Exit(code=p.returncode)
82
86
 
83
87
 
88
+ def _run_pull(
89
+ cmd: list[str],
90
+ *,
91
+ cwd: Path | None = None,
92
+ env: dict[str, str] | None = None,
93
+ image: str,
94
+ ) -> None:
95
+ """docker compose pull с понятной подсказкой при ошибке авторизации."""
96
+ p = subprocess.run(cmd, cwd=str(cwd) if cwd else None, env=env, check=False) # noqa: S603
97
+ if p.returncode != 0:
98
+ registry = image.split("/")[0] if "/" in image else "ghcr.io"
99
+ raise HcCliError(
100
+ message=f"Не удалось загрузить образ {image}",
101
+ hint=(
102
+ f"Образ недоступен (denied / unauthorized).\n"
103
+ f" Авторизуйся в реестре:\n"
104
+ f" docker login {registry} -u <github_username> -p <PAT_read:packages>"
105
+ ),
106
+ exit_code=p.returncode,
107
+ )
108
+
109
+
84
110
  def _fmt_s(seconds: float) -> str:
85
111
  if seconds < 60:
86
112
  return f"{seconds:.1f}s"
@@ -307,10 +333,11 @@ def register(app: typer.Typer) -> None:
307
333
  project = compose_project_from_source(console, src, mode=deploy_mode)
308
334
  env = {**os.environ, "CORE_RUNTIME_IMAGE": full}
309
335
  t0 = time.monotonic()
310
- _run(
336
+ _run_pull(
311
337
  ["docker", "compose", "-f", str(project.compose_file), "pull", "core-runtime"],
312
338
  cwd=project.cwd,
313
339
  env=env,
340
+ image=full,
314
341
  )
315
342
  _run(["docker", "compose", "-f", str(project.compose_file), "up", "-d"], cwd=project.cwd, env=env)
316
343
  dt = time.monotonic() - t0
@@ -23,7 +23,7 @@ DEFAULT_CORE_REPO = "https://github.com/home-console/core-runtime-service"
23
23
  DEFAULT_CORE_REF = "master"
24
24
 
25
25
  # Образ для prod / dev-image rollout (Ghcr). Локально собранный тег задаёт через --image.
26
- DEFAULT_CORE_IMAGE = "ghcr.io/home-console/core-runtime"
26
+ DEFAULT_CORE_IMAGE = "ghcr.io/home-console/core-runtime-service"
27
27
 
28
28
  DEFAULT_HOST = "localhost"
29
29
  DEFAULT_PORT = 8080
@@ -9,7 +9,7 @@ import typer
9
9
  from rich.console import Console
10
10
 
11
11
  from hc.config import Config
12
- from hc.core_source import VALID_MODES, CoreSource
12
+ from hc.core_source import COMPOSE_MODES, VALID_MODES, CoreSource
13
13
  from hc.env_bootstrap import ensure_core_env
14
14
  from hc.errors import DockerNotFoundError, HcCliError
15
15
 
@@ -46,10 +46,17 @@ def compose_project_from_source(console: Console, src: CoreSource, mode: str | N
46
46
  hint=f"Допустимые режимы: {valid}",
47
47
  ) from exc
48
48
  if not compose.exists():
49
+ available = [m for m, rel in COMPOSE_MODES.items() if (src.path / rel).exists()]
50
+ hint = f"Режим {mode!r} → {src.compose_rel(mode)}. Файл не найден в {src.path}."
51
+ if available:
52
+ hint += f"\n Доступные режимы: {' | '.join(available)}"
53
+ hint += f"\n Попробуй: hc env up --mode {available[0]}"
54
+ else:
55
+ hint += "\n Сделай `hc core init` для загрузки исходников Core."
49
56
  raise HcCliError(
50
57
  message=f"Не найден compose-файл: {compose}",
51
58
  exit_code=1,
52
- hint=f"Режим {mode!r} → {src.compose_rel(mode)}. Проверь наличие файла в core-runtime-service.",
59
+ hint=hint,
53
60
  )
54
61
  return ComposeProject(compose_file=compose)
55
62
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: homeconsole-cli
3
- Version: 0.0.3
3
+ Version: 0.0.4
4
4
  Summary: HomeConsole CLI (hc) — управление платформой через HTTP API
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "homeconsole-cli"
3
- version = "0.0.3"
3
+ version = "0.0.4"
4
4
  description = "HomeConsole CLI (hc) — управление платформой через HTTP API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"