168 lines
5.8 KiB
Python
168 lines
5.8 KiB
Python
import argparse
|
|
import subprocess
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
from core.logger import setup_logging
|
|
|
|
|
|
def create_plugin(args: argparse.Namespace) -> None:
|
|
root = Path(args.root).resolve()
|
|
plugin_path = root / "plugins" / "external" / args.name
|
|
plugin_path.mkdir(parents=True, exist_ok=True)
|
|
(plugin_path / "__init__.py").write_text(
|
|
"from .plugin import *\n",
|
|
encoding="utf-8",
|
|
)
|
|
(plugin_path / "plugin.py").write_text(
|
|
f"from core.plugin import Plugin\n\n\nclass {args.class_name}(Plugin):\n name = \"{args.name}\"\n version = \"0.1.0\"\n author = \"{args.author}\"\n description = \"{args.description}\"\n\n async def on_load(self):\n self.log.info(\"{args.name} loaded\")\n",
|
|
encoding="utf-8",
|
|
)
|
|
(plugin_path / "config.yml").write_text(
|
|
f"{args.name}:\n enabled: true\n settings: {{}}\n",
|
|
encoding="utf-8",
|
|
)
|
|
(plugin_path / "requirements.txt").write_text("", encoding="utf-8")
|
|
(plugin_path / "README.md").write_text(
|
|
f"# {args.name}\n\n{args.description}\n",
|
|
encoding="utf-8",
|
|
)
|
|
print(f"Created plugin at {plugin_path}")
|
|
|
|
|
|
def validate_plugin(args: argparse.Namespace) -> None:
|
|
path = Path(args.path).resolve()
|
|
required = ["__init__.py", "plugin.py"]
|
|
missing = [item for item in required if not (path / item).exists()]
|
|
if missing:
|
|
print(f"Missing files: {', '.join(missing)}")
|
|
raise SystemExit(1)
|
|
print("Plugin structure OK")
|
|
|
|
|
|
def build_plugin(args: argparse.Namespace) -> None:
|
|
path = Path(args.path).resolve()
|
|
output = Path(args.output).resolve()
|
|
shutil.make_archive(str(output), "zip", root_dir=path)
|
|
print(f"Built {output}.zip")
|
|
|
|
|
|
def publish_plugin(args: argparse.Namespace) -> None:
|
|
root = Path(args.root).resolve()
|
|
if not args.name or not args.version:
|
|
print("Publish requires --name and --version")
|
|
raise SystemExit(1)
|
|
plugin_path = Path(args.path).resolve() if args.path else root / "plugins" / "external" / args.name
|
|
if not plugin_path.exists():
|
|
print(f"Plugin path not found: {plugin_path}")
|
|
raise SystemExit(1)
|
|
tag = args.version if args.version.startswith("v") else f"v{args.version}"
|
|
try:
|
|
subprocess.run(["git", "status"], cwd=plugin_path, check=True, capture_output=True, text=True)
|
|
except subprocess.CalledProcessError as exc:
|
|
print(exc.stderr.strip() or "Git status failed")
|
|
raise SystemExit(1) from exc
|
|
try:
|
|
subprocess.run(["git", "tag", "-a", tag, "-m", f"Release {tag}"], cwd=plugin_path, check=True)
|
|
subprocess.run(["git", "push", "origin", tag], cwd=plugin_path, check=True)
|
|
except subprocess.CalledProcessError as exc:
|
|
print(exc.stderr.strip() or "Git tag/push failed")
|
|
raise SystemExit(1) from exc
|
|
try:
|
|
log = subprocess.run(
|
|
["git", "log", "-5", "--pretty=format:- %s"],
|
|
cwd=plugin_path,
|
|
check=True,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
note = log.stdout.strip() or f"Release {tag}"
|
|
subprocess.run(
|
|
[
|
|
"tea",
|
|
"releases",
|
|
"create",
|
|
"--tag",
|
|
tag,
|
|
"--title",
|
|
f"{args.name} {tag}",
|
|
"--note",
|
|
note,
|
|
],
|
|
cwd=plugin_path,
|
|
check=True,
|
|
)
|
|
except subprocess.CalledProcessError as exc:
|
|
print(exc.stderr.strip() or "Tea release creation failed")
|
|
raise SystemExit(1) from exc
|
|
print(f"Published {args.name} {tag}")
|
|
|
|
|
|
def test_plugin(args: argparse.Namespace) -> None:
|
|
import py_compile
|
|
|
|
path = Path(args.path).resolve()
|
|
errors = []
|
|
for file in path.rglob("*.py"):
|
|
try:
|
|
py_compile.compile(str(file), doraise=True)
|
|
except Exception as exc:
|
|
errors.append((file, exc))
|
|
if errors:
|
|
for file, exc in errors:
|
|
print(f"{file}: {exc}")
|
|
raise SystemExit(1)
|
|
print("Plugin tests OK")
|
|
|
|
|
|
def generate_docs(args: argparse.Namespace) -> None:
|
|
path = Path(args.path).resolve()
|
|
(path / "README.md").write_text("# Plugin\n", encoding="utf-8")
|
|
(path / "COMMANDS.md").write_text("# Commands\n", encoding="utf-8")
|
|
(path / "CONFIG.md").write_text("# Config\n", encoding="utf-8")
|
|
(path / "API.md").write_text("# API\n", encoding="utf-8")
|
|
print("Docs generated")
|
|
|
|
|
|
def run_cli() -> None:
|
|
parser = argparse.ArgumentParser(prog="overub")
|
|
parser.add_argument("--root", default=Path(__file__).resolve().parents[1])
|
|
sub = parser.add_subparsers(dest="command")
|
|
|
|
create = sub.add_parser("create-plugin")
|
|
create.add_argument("name")
|
|
create.add_argument("--class-name", default="MyPlugin")
|
|
create.add_argument("--author", default="overub")
|
|
create.add_argument("--description", default="OverUB plugin")
|
|
create.set_defaults(func=create_plugin)
|
|
|
|
validate = sub.add_parser("validate-plugin")
|
|
validate.add_argument("path")
|
|
validate.set_defaults(func=validate_plugin)
|
|
|
|
build = sub.add_parser("build-plugin")
|
|
build.add_argument("path")
|
|
build.add_argument("--output", default="overub-plugin")
|
|
build.set_defaults(func=build_plugin)
|
|
|
|
test = sub.add_parser("test-plugin")
|
|
test.add_argument("path")
|
|
test.set_defaults(func=test_plugin)
|
|
|
|
docs = sub.add_parser("docs-plugin")
|
|
docs.add_argument("path")
|
|
docs.set_defaults(func=generate_docs)
|
|
|
|
publish = sub.add_parser("publish-plugin")
|
|
publish.add_argument("--name", default="")
|
|
publish.add_argument("--version", default="")
|
|
publish.add_argument("--path", default="")
|
|
publish.set_defaults(func=publish_plugin)
|
|
|
|
args = parser.parse_args()
|
|
setup_logging("INFO")
|
|
if not hasattr(args, "func"):
|
|
parser.print_help()
|
|
return
|
|
args.func(args)
|