Files
ai-training-skills/gitea-issues/scripts/gitea_common.py
T

155 lines
5.2 KiB
Python

#!/usr/bin/env python3
"""Shared Gitea configuration helpers for issue scripts."""
from __future__ import annotations
import os
import re
import shlex
import subprocess
from pathlib import Path
from urllib.parse import urlparse
DEFAULT_ENV_FILE = Path("~/.config/gitea/gitea.env").expanduser()
SECRETS_ENV_FILE = Path("~/.config/secrets/gitea.env").expanduser()
LEGACY_ENV_FILE = Path("~/.config/gitea/data-analysis-agent.env").expanduser()
REQUIRED_ENV = ("GITEA_BASE_URL", "GITEA_OWNER", "GITEA_REPO", "GITEA_TOKEN")
def load_env_file(path: Path) -> dict[str, str]:
values: dict[str, str] = {}
if not path.exists():
return values
for raw_line in path.read_text(encoding="utf-8").splitlines():
line = raw_line.strip()
if not line or line.startswith("#"):
continue
if line.startswith("export "):
line = line[len("export ") :]
if "=" not in line:
continue
key, raw_value = line.split("=", 1)
key = key.strip()
try:
parsed = shlex.split(raw_value.strip(), comments=False, posix=True)
except ValueError as exc:
raise SystemExit(f"Could not parse {path}: {exc}") from exc
values[key] = parsed[0] if parsed else ""
return values
def discover_origin_config() -> dict[str, str]:
try:
remote = subprocess.run(
["git", "remote", "get-url", "origin"],
capture_output=True,
text=True,
check=True,
).stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError):
return {}
if not remote:
return {}
parsed = urlparse(remote)
host = ""
path = ""
if parsed.scheme in {"http", "https", "ssh"} and parsed.netloc:
host = parsed.hostname or parsed.netloc.split("@")[-1].split(":")[0]
path = parsed.path.lstrip("/")
else:
match = re.match(r"(?:(?P<user>[^@]+)@)?(?P<host>[^:]+):(?P<path>.+)$", remote)
if match:
host = match.group("host")
path = match.group("path")
if not host or not path:
return {}
if path.endswith(".git"):
path = path[:-4]
parts = [part for part in path.split("/") if part]
if len(parts) < 2:
return {}
return {
"GITEA_BASE_URL": f"https://{host}",
"GITEA_OWNER": parts[-2],
"GITEA_REPO": parts[-1],
}
def config(env_file: Path | None = None) -> dict[str, str]:
env_path = (env_file or DEFAULT_ENV_FILE).expanduser()
file_values = load_env_file(env_path)
if env_path == DEFAULT_ENV_FILE:
secrets_values = load_env_file(SECRETS_ENV_FILE)
legacy_values = load_env_file(LEGACY_ENV_FILE)
file_values = {**legacy_values, **secrets_values, **file_values}
origin_values = discover_origin_config()
base_url = (
os.environ.get("GITEA_BASE_URL")
or os.environ.get("GITEA_URL")
or origin_values.get("GITEA_BASE_URL")
or file_values.get("GITEA_BASE_URL")
or file_values.get("GITEA_URL", "")
)
values = {
"GITEA_BASE_URL": base_url,
"GITEA_OWNER": os.environ.get("GITEA_OWNER")
or origin_values.get("GITEA_OWNER")
or file_values.get("GITEA_OWNER", ""),
"GITEA_REPO": os.environ.get("GITEA_REPO")
or origin_values.get("GITEA_REPO")
or file_values.get("GITEA_REPO", ""),
"GITEA_TOKEN": os.environ.get("GITEA_TOKEN") or file_values.get("GITEA_TOKEN", ""),
}
missing = [key for key, value in values.items() if not value]
if missing:
raise SystemExit(
"Missing required Gitea configuration: "
+ ", ".join(missing)
+ f"\nSet them in the shell, {env_path}, {SECRETS_ENV_FILE}, "
+ "or run from a git repo with a Gitea origin."
)
return values
def auth_config(env_file: Path | None = None) -> dict[str, str]:
"""Return Gitea API auth config without requiring a repository context."""
env_path = (env_file or DEFAULT_ENV_FILE).expanduser()
file_values = load_env_file(env_path)
if env_path == DEFAULT_ENV_FILE:
secrets_values = load_env_file(SECRETS_ENV_FILE)
legacy_values = load_env_file(LEGACY_ENV_FILE)
file_values = {**legacy_values, **secrets_values, **file_values}
origin_values = discover_origin_config()
base_url = (
os.environ.get("GITEA_BASE_URL")
or os.environ.get("GITEA_URL")
or origin_values.get("GITEA_BASE_URL")
or file_values.get("GITEA_BASE_URL")
or file_values.get("GITEA_URL", "")
)
values = {
"GITEA_BASE_URL": base_url,
"GITEA_OWNER": os.environ.get("GITEA_OWNER")
or origin_values.get("GITEA_OWNER")
or file_values.get("GITEA_OWNER", ""),
"GITEA_TOKEN": os.environ.get("GITEA_TOKEN") or file_values.get("GITEA_TOKEN", ""),
}
missing = [key for key in ("GITEA_BASE_URL", "GITEA_TOKEN") if not values[key]]
if missing:
raise SystemExit(
"Missing required Gitea configuration: "
+ ", ".join(missing)
+ f"\nSet them in the shell, {env_path}, {SECRETS_ENV_FILE}, "
+ "or run from a git repo with a Gitea origin."
)
return values