Move directory
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: update_docs_file
|
||||
description: Insert upgrade content into BUILD-README.md for a target chart version.
|
||||
user-invokable: false
|
||||
---
|
||||
|
||||
# update_docs_file (Skill)
|
||||
|
||||
Update a chart version directory's BUILD-README.md by inserting upgrade content.
|
||||
|
||||
## Input schema
|
||||
```json
|
||||
{
|
||||
"repo_path": "string",
|
||||
"docs_file": "string (default: BUILD-README.md)",
|
||||
"version": "string",
|
||||
"content": "string",
|
||||
"overwrite": "boolean"
|
||||
}
|
||||
```
|
||||
|
||||
## Output schema
|
||||
```json
|
||||
{
|
||||
"success": "boolean",
|
||||
"file_path": "string",
|
||||
"already_existed": "boolean"
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
DEFAULT_REPO = None
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--repo-path", required=True)
|
||||
parser.add_argument("--docs-file", default="BUILD-README.md")
|
||||
parser.add_argument("--version", required=True)
|
||||
parser.add_argument("--content-file", required=True)
|
||||
parser.add_argument("--overwrite", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
repo_root = os.environ.get("UPDATE_CATALOG_ROOT")
|
||||
if repo_root:
|
||||
sys.path.insert(0, str(Path(repo_root) / "src"))
|
||||
else:
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
|
||||
from update_catalog.update_docs_file import update_docs_file # type: ignore
|
||||
|
||||
content = Path(args.content_file).read_text(encoding="utf-8")
|
||||
out = update_docs_file({
|
||||
"repo_path": args.repo_path,
|
||||
"docs_file": args.docs_file,
|
||||
"version": args.version,
|
||||
"content": content,
|
||||
"overwrite": bool(args.overwrite),
|
||||
})
|
||||
print(json.dumps(out, ensure_ascii=False, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1 @@
|
||||
__all__ = ["skill_interface"]
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+145
@@ -0,0 +1,145 @@
|
||||
"""Skill Interface v1.0 for Helm upgrade automation."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, List, Literal, Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
SKILL_INTERFACE_VERSION = "1.0"
|
||||
|
||||
|
||||
# -------------------------
|
||||
# Common Error Schema
|
||||
# -------------------------
|
||||
class SkillError(BaseModel):
|
||||
code: str
|
||||
message: str
|
||||
retryable: bool = False
|
||||
details: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class ErrorResponse(BaseModel):
|
||||
error: SkillError
|
||||
|
||||
|
||||
# -------------------------
|
||||
# Shared Types
|
||||
# -------------------------
|
||||
Severity = Literal["critical", "high", "medium", "warning"]
|
||||
|
||||
|
||||
class BreakingReason(BaseModel):
|
||||
type: str
|
||||
resource: Optional[str] = None
|
||||
key: Optional[str] = None
|
||||
detail: Optional[str] = None
|
||||
|
||||
|
||||
# -------------------------
|
||||
# helm_diff
|
||||
# -------------------------
|
||||
class HelmDiffInput(BaseModel):
|
||||
chart: str
|
||||
repo: Optional[str] = None
|
||||
chart_path: Optional[str] = None
|
||||
from_version: str
|
||||
to_version: str
|
||||
values_override: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class HelmDiffOutput(BaseModel):
|
||||
chart: str
|
||||
from_version: str
|
||||
to_version: str
|
||||
generated_at: str
|
||||
values: Dict[str, Any]
|
||||
templates: Dict[str, Any]
|
||||
crd: Dict[str, Any]
|
||||
dependencies: Dict[str, Any]
|
||||
errors: List[Dict[str, Any]] = Field(default_factory=list)
|
||||
|
||||
|
||||
# -------------------------
|
||||
# breaking_change_check
|
||||
# -------------------------
|
||||
class BreakingCheckInput(BaseModel):
|
||||
diff_json: Dict[str, Any]
|
||||
|
||||
|
||||
class BreakingCheckOutput(BaseModel):
|
||||
breaking: bool
|
||||
severity: Severity
|
||||
breaking_reasons: List[BreakingReason] = Field(default_factory=list)
|
||||
warnings: List[BreakingReason] = Field(default_factory=list)
|
||||
|
||||
|
||||
# -------------------------
|
||||
# generate_upgrade_doc
|
||||
# -------------------------
|
||||
class GenerateDocInput(BaseModel):
|
||||
diff_json: Dict[str, Any]
|
||||
breaking_result: Dict[str, Any]
|
||||
docs_context: Optional[Dict[str, str]] = None
|
||||
max_tokens: int = 50000
|
||||
|
||||
|
||||
class GenerateDocOutput(BaseModel):
|
||||
markdown: str
|
||||
truncated: bool = False
|
||||
|
||||
|
||||
# -------------------------
|
||||
# update_docs_file
|
||||
# -------------------------
|
||||
class UpdateDocsInput(BaseModel):
|
||||
repo_path: str
|
||||
docs_file: str # 예: "manifests/helm/<chart>/<to_version>/CUSTOM-README.md"
|
||||
version: str
|
||||
content: str
|
||||
overwrite: bool = False
|
||||
|
||||
|
||||
class UpdateDocsOutput(BaseModel):
|
||||
success: bool
|
||||
file_path: str
|
||||
already_existed: bool = False
|
||||
|
||||
|
||||
# -------------------------
|
||||
# create_pr
|
||||
# -------------------------
|
||||
class CreatePRInput(BaseModel):
|
||||
chart: str
|
||||
from_version: str
|
||||
to_version: str
|
||||
repo_path: str
|
||||
doc_content: str
|
||||
breaking: bool
|
||||
severity: Severity
|
||||
|
||||
|
||||
class CreatePROutput(BaseModel):
|
||||
pr_url: str
|
||||
branch_name: str
|
||||
labels: List[str]
|
||||
|
||||
|
||||
# -------------------------
|
||||
# deploy_validate
|
||||
# -------------------------
|
||||
class DeployValidateInput(BaseModel):
|
||||
chart: str
|
||||
repo: Optional[str] = None
|
||||
chart_path: Optional[str] = None
|
||||
version: str
|
||||
values_override: Optional[Dict[str, Any]] = None
|
||||
namespace: str
|
||||
timeout: int = 300
|
||||
|
||||
|
||||
class DeployValidateOutput(BaseModel):
|
||||
success: bool
|
||||
dry_run_passed: bool
|
||||
pod_status: Dict[str, int]
|
||||
events: List[Dict[str, Any]] = Field(default_factory=list)
|
||||
logs: Optional[str] = None
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
"""update_docs_file skill implementation."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
||||
from .skill_interface import UpdateDocsInput, UpdateDocsOutput
|
||||
|
||||
|
||||
HEADER = "# Upgrade History"
|
||||
|
||||
|
||||
def _insert_section(text: str, version: str, content: str) -> tuple[str, bool]:
|
||||
marker = f"## {version}"
|
||||
if marker in text:
|
||||
return text, True
|
||||
|
||||
if HEADER in text:
|
||||
parts = text.split(HEADER, 1)
|
||||
head = parts[0] + HEADER
|
||||
rest = parts[1].lstrip("\n")
|
||||
new_section = f"\n\n{marker}\n{content.strip()}\n"
|
||||
return head + new_section + "\n" + rest, False
|
||||
|
||||
# If no header, prepend
|
||||
new_text = f"{HEADER}\n\n{marker}\n{content.strip()}\n\n{text}"
|
||||
return new_text, False
|
||||
|
||||
|
||||
def update_docs_file(payload: Dict[str, Any]) -> Dict[str, Any]:
|
||||
inp = UpdateDocsInput(**payload)
|
||||
repo_path = Path(inp.repo_path)
|
||||
docs_path = repo_path / inp.docs_file
|
||||
|
||||
text = ""
|
||||
if docs_path.exists():
|
||||
text = docs_path.read_text(encoding="utf-8")
|
||||
|
||||
new_text, existed = _insert_section(text, inp.version, inp.content)
|
||||
if existed and not inp.overwrite:
|
||||
out = UpdateDocsOutput(success=True, file_path=str(docs_path), already_existed=True)
|
||||
return json.loads(out.model_dump_json())
|
||||
|
||||
if existed and inp.overwrite:
|
||||
# overwrite: replace section between marker and next header
|
||||
marker = f"## {inp.version}"
|
||||
parts = new_text.split(marker, 1)
|
||||
if len(parts) > 1:
|
||||
after = parts[1]
|
||||
tail_idx = after.find("\n## ")
|
||||
if tail_idx != -1:
|
||||
after = after[tail_idx:]
|
||||
else:
|
||||
after = ""
|
||||
new_text = parts[0] + marker + "\n" + inp.content.strip() + "\n" + after
|
||||
|
||||
docs_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
docs_path.write_text(new_text, encoding="utf-8")
|
||||
|
||||
out = UpdateDocsOutput(success=True, file_path=str(docs_path), already_existed=existed)
|
||||
return json.loads(out.model_dump_json())
|
||||
Reference in New Issue
Block a user