katalon-cli 0.1.6__tar.gz → 0.1.8__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: katalon-cli
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Installer & Updater CLI für Katalon Production-Instanzen
5
5
  Author: Karl Krägelin
6
6
  Author-email: Karl Krägelin <karlkraegelin@gmail.com>
@@ -30,6 +30,7 @@ uv tool install katalon-cli
30
30
  ```bash
31
31
  katalon install # interaktiver Setup-Wizard (Rich-Prompts + Progress)
32
32
  katalon start / stop / status
33
+ katalon check-updates # prüft nur, ob ein neues Release verfügbar ist
33
34
  katalon update # interaktives Update, Backup zuerst immer
34
35
  katalon rollback # letztes Backup einspielen
35
36
  katalon doctor # Docker, Diskspace, Ports prüfen
@@ -16,6 +16,7 @@ uv tool install katalon-cli
16
16
  ```bash
17
17
  katalon install # interaktiver Setup-Wizard (Rich-Prompts + Progress)
18
18
  katalon start / stop / status
19
+ katalon check-updates # prüft nur, ob ein neues Release verfügbar ist
19
20
  katalon update # interaktives Update, Backup zuerst immer
20
21
  katalon rollback # letztes Backup einspielen
21
22
  katalon doctor # Docker, Diskspace, Ports prüfen
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "katalon-cli"
3
- version = "0.1.6"
3
+ version = "0.1.8"
4
4
  description = "Installer & Updater CLI für Katalon Production-Instanzen"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "katalon-cli"
3
- version = "0.1.6"
3
+ version = "0.1.8"
4
4
  description = "Installer & Updater CLI für Katalon Production-Instanzen"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -69,6 +69,55 @@ def _fetch_release_asset(tag: str | None) -> dict:
69
69
  asset_resp.raise_for_status()
70
70
  return asset_resp.json()
71
71
 
72
+ def _fetch_releases() -> list[dict]:
73
+ """Lädt alle veröffentlichten Katalon-Releases."""
74
+ releases: list[dict] = []
75
+ url: str | None = f"https://api.github.com/repos/{GITHUB_REPO}/releases"
76
+ params: dict[str, int] | None = {"per_page": 100}
77
+ with httpx.Client(timeout=15) as client:
78
+ while url:
79
+ response = client.get(url, params=params)
80
+ response.raise_for_status()
81
+ data = response.json()
82
+ if not isinstance(data, list):
83
+ raise ValueError("GitHub-Releases-Antwort ist keine Liste.")
84
+ releases.extend(data)
85
+ url = response.links.get("next", {}).get("url")
86
+ params = None
87
+ return releases
88
+
89
+
90
+ def _version_key(version: str) -> tuple[int, int, int]:
91
+ parts = version.lstrip("v").split(".")
92
+ if len(parts) != 3 or not all(part.isdigit() for part in parts):
93
+ raise ValueError(f"Ungültige Release-Version: {version}")
94
+ return int(parts[0]), int(parts[1]), int(parts[2])
95
+
96
+
97
+ def get_releases_between(installed_version: str, target_version: str) -> list[ReleaseMetadata]:
98
+ """Lädt Metadaten aller veröffentlichten Releases im Update-Pfad."""
99
+ lower = _version_key(installed_version)
100
+ upper = _version_key(target_version)
101
+ if upper <= lower:
102
+ return []
103
+
104
+ releases: list[tuple[tuple[int, int, int], str]] = []
105
+ for release in _fetch_releases():
106
+ if release.get("draft") or release.get("prerelease"):
107
+ continue
108
+ tag = str(release.get("tag_name", ""))
109
+ try:
110
+ version = _version_key(tag)
111
+ except ValueError:
112
+ continue
113
+ if lower < version <= upper:
114
+ releases.append((version, tag))
115
+
116
+ return [
117
+ ReleaseMetadata.model_validate(_fetch_release_asset(tag))
118
+ for _, tag in sorted(releases)
119
+ ]
120
+
72
121
 
73
122
  def get_latest_release(*, use_cache: bool = True) -> ReleaseMetadata:
74
123
  if use_cache and CACHE_PATH.exists():
@@ -481,6 +481,23 @@ def doctor(dir: Path = typer.Option(DEFAULT_DIR, "--dir")):
481
481
  )
482
482
  docker.compose(dir, "ps")
483
483
 
484
+ @app.command()
485
+ def check_updates(dir: Path = typer.Option(DEFAULT_DIR, "--dir")):
486
+ """Prüft, ob eine neue Katalon-Version verfügbar ist."""
487
+ instance_dir_or_raise(dir)
488
+ state = InstallationState.load(dir)
489
+ try:
490
+ meta = release.get_latest_release()
491
+ except Exception as exc:
492
+ console.print(f"[red]✖ Release-Metadaten konnten nicht geladen werden: {exc}[/]")
493
+ raise typer.Exit(1) from exc
494
+
495
+ if meta.version == state.version:
496
+ console.print(f"[green]✔[/] Bereits auf aktueller Version {meta.version}.")
497
+ return
498
+ console.print(f"Update verfügbar: [bold]{state.version}[/] → [bold]{meta.version}[/]")
499
+
500
+
484
501
  @app.command()
485
502
  def update(
486
503
  dir: Path = typer.Option(DEFAULT_DIR, "--dir"),
@@ -500,6 +517,17 @@ def update(
500
517
  console.print(f"[green]✔[/] Bereits auf aktueller Version {meta.version}.")
501
518
  return
502
519
 
520
+ try:
521
+ update_releases = release.get_releases_between(state.version, meta.version)
522
+ except Exception as exc:
523
+ console.print(f"[red]✖ Release-Metadaten konnten nicht geladen werden: {exc}[/]")
524
+ raise typer.Exit(1) from exc
525
+ env_vars = [var for item in update_releases for var in item.env_vars]
526
+ deprecated_env_vars = [
527
+ var for item in update_releases for var in item.deprecated_env_vars
528
+ ]
529
+
530
+
503
531
  console.rule("Update")
504
532
  console.print(f"Aktuell: [bold]{state.version}[/] → Ziel: [bold]{meta.version}[/]")
505
533
  if meta.breaking:
@@ -513,12 +541,12 @@ def update(
513
541
  )
514
542
 
515
543
  env_existing = _parse_env_file((dir / ".env").read_text() if (dir / ".env").exists() else "")
516
- _print_new_env_vars(env_existing, meta.env_vars)
517
- _print_deprecated_env_vars(env_existing, meta.deprecated_env_vars)
544
+ _print_new_env_vars(env_existing, env_vars)
545
+ _print_deprecated_env_vars(env_existing, deprecated_env_vars)
518
546
 
519
547
  if not yes and not Confirm.ask("Update durchführen?"):
520
548
  raise typer.Exit(0)
521
- provided = _collect_required_env_vars(env_existing, meta.env_vars, yes=yes)
549
+ provided = _collect_required_env_vars(env_existing, env_vars, yes=yes)
522
550
  _ensure_db_running(dir, yes=yes)
523
551
 
524
552
  steps = [
@@ -526,7 +554,7 @@ def update(
526
554
  (
527
555
  "Env-Vars ergänzen",
528
556
  lambda: _ensure_env_vars(
529
- dir, state.base_url, release_env_vars=meta.env_vars, provided=provided
557
+ dir, state.base_url, release_env_vars=env_vars, provided=provided
530
558
  ),
531
559
  ),
532
560
  (