feat: add UpdateVersionAction

This commit is contained in:
cătălin 2025-03-05 12:40:19 +01:00
commit 839f67ad0a
No known key found for this signature in database
8 changed files with 260 additions and 139 deletions

View file

@ -4,6 +4,7 @@ from loguru import logger
from typer import Typer
from huesoporro.actions.import_from_vod import ImportFromVODAction
from huesoporro.actions.misc.update_version_action import UpdateVersionAction
from huesoporro.settings import Settings
from huesoporro.svc.clean_cc_svc import CleanCCSvc
from huesoporro.svc.download_closed_captions import DownloadClosedCaptionsSvc
@ -22,3 +23,8 @@ def import_vod_cc(channel_name: str, youtube_url: str, db_path: Path | None = No
)
for cc_filepath in import_from_vod_action.run(channel_name, youtube_url):
logger.info(f"Closed captions imported from {cc_filepath}")
@app.command()
def update_version(version: str, dry_run: bool = False):
UpdateVersionAction().run(version, dry_run)

View file

View file

@ -0,0 +1,198 @@
import re
from collections.abc import Callable
from difflib import unified_diff
from pathlib import Path
import yaml
from loguru import logger
from pydantic import BaseModel, ConfigDict
from rich import print # noqa: A004
from rich.console import Console
from rich.panel import Panel
from rich.syntax import Syntax
class UpdateVersionAction(BaseModel):
project_root: Path = Path(__file__).parents[4]
files_to_update: dict[str, Callable]
console: Console = Console()
model_config = ConfigDict(arbitrary_types_allowed=True)
def __init__(self, **data):
files_to_update = {
"pyproject.toml": self._update_pyproject_toml,
"charts/huesoporro/values.yaml": self._update_values_yaml,
"charts/huesoporro/Chart.yaml": self._update_chart_yaml,
}
super().__init__(**data, files_to_update=files_to_update)
def _read_file(self, filepath: Path) -> str:
"""
Read the contents of a file.
Args:
filepath (Path): Path to the file to read.
Returns:
str: File contents
"""
with filepath.open("r") as f:
return f.read()
def _write_file(self, filepath: Path, content: str):
"""
Write content to a file.
Args:
filepath (Path): Path to the file to write.
content (str): Content to write to the file.
"""
with filepath.open("w") as f:
f.write(content)
def _update_pyproject_toml(self, filepath: Path, new_version: str) -> str:
"""
Update version in pyproject.toml.
Args:
filepath (Path): Path to pyproject.toml
new_version (str): New version to set
Returns:
str: Updated file content
"""
content = self._read_file(filepath)
version_pattern = r'(version\s*=\s*)[\'"](.+?)[\'"]'
return re.sub(version_pattern, rf'\1"{new_version}"', content)
def _update_values_yaml(self, filepath: Path, new_version: str) -> str:
"""
Update image tag in values.yaml.
Args:
filepath (Path): Path to values.yaml
new_version (str): New version to set
Returns:
str: Updated file content
"""
with filepath.open("r") as file:
values = yaml.safe_load(file)
# Assumes image.tag exists in the values.yaml
values["image"]["tag"] = new_version
return yaml.dump(values, default_flow_style=False)
def _update_chart_yaml(self, filepath: Path, new_version: str) -> str:
"""
Update version and appVersion in Chart.yaml.
Args:
filepath (Path): Path to Chart.yaml
new_version (str): New version to set
Returns:
str: Updated file content
"""
with filepath.open("r") as file:
chart_data = yaml.safe_load(file)
chart_data["version"] = new_version
chart_data["appVersion"] = new_version
return yaml.dump(chart_data, default_flow_style=False)
def _generate_diff(self, original: str, updated: str, filename: str) -> str:
"""
Generate a unified diff between original and updated content.
Args:
original (str): Original file content
updated (str): Updated file content
filename (str): Name of the file
Returns:
str: Unified diff representation
"""
# Split content into lines
original_lines = original.splitlines(keepends=True)
updated_lines = updated.splitlines(keepends=True)
# Generate unified diff
diff_lines = list(
unified_diff(
original_lines,
updated_lines,
fromfile=f"a/{filename}",
tofile=f"b/{filename}",
lineterm="",
)
)
return "\n".join(diff_lines)
def _rich_display_diff(self, diff: str):
"""
Display diff using rich for colorful output.
Args:
diff (str): Unified diff to display
"""
if not diff:
return
# Use Syntax for syntax highlighting
syntax = Syntax(diff, "diff", theme="ansi_dark")
# Create a panel with the diff
panel = Panel(
syntax, title="Version Update Diff", border_style="cyan", expand=False
)
# Display the panel
self.console.print(panel)
def run(self, new_version: str, dry_run: bool = False):
"""
Update version across all specified files.
Args:
new_version (str): New version to set
dry_run (bool): Dry run mode with diff display
"""
for relative_path, update_func in self.files_to_update.items():
filepath = self.project_root / relative_path
if not filepath.exists():
logger.warning(f"Warning: {filepath} not found. Skipping.")
continue
try:
# Read original content
original_content = self._read_file(filepath)
# Generate updated content
updated_content = update_func(filepath, new_version)
if dry_run:
# Generate and display diff
diff = self._generate_diff(
original_content, updated_content, str(relative_path)
)
# Display the diff
if diff:
print(f"\nDiff for {relative_path}:")
self._rich_display_diff(diff)
else:
# Write updated content
self._write_file(filepath, updated_content)
print(f"Updated {relative_path}")
except Exception as exc: # noqa: BLE001
logger.error(f"Error updating {relative_path}: {exc}")
if dry_run:
print("\nDry run complete. No files were modified.")