✨ feat(playbook): add no_backup deploy controls
remove obsolete main_language placeholders and language summary template text limit generated .agents guidance to configured langs and normalize AGENT_RULES trailing newlines document install_skills no_backup behavior and refresh tests for deployment links and sync flows
This commit is contained in:
+28
-79
@@ -320,29 +320,7 @@ def resolve_docs_prefix(context: dict) -> str:
|
||||
return join_deploy_subpath(resolve_deploy_root(context), "docs")
|
||||
|
||||
|
||||
def resolve_main_language(config: dict, context: dict) -> str:
|
||||
raw = config.get("main_language")
|
||||
if raw is not None and str(raw).strip():
|
||||
return str(raw).strip()
|
||||
|
||||
full_config = context.get("config", {})
|
||||
if isinstance(full_config, dict):
|
||||
sync_conf = full_config.get("sync_standards")
|
||||
if isinstance(sync_conf, dict):
|
||||
langs_raw = sync_conf.get("langs")
|
||||
if langs_raw is not None:
|
||||
try:
|
||||
langs = normalize_langs(langs_raw)
|
||||
except ValueError:
|
||||
langs = []
|
||||
if langs:
|
||||
return langs[0]
|
||||
|
||||
return "tsl"
|
||||
|
||||
|
||||
def resolve_playbook_scripts(project_root: Path, context: dict) -> str:
|
||||
_ = project_root
|
||||
def resolve_playbook_scripts(context: dict) -> str:
|
||||
return join_deploy_subpath(resolve_deploy_root(context), "scripts")
|
||||
|
||||
|
||||
@@ -541,14 +519,11 @@ def replace_placeholders(
|
||||
text: str,
|
||||
project_name: str | None,
|
||||
date_value: str,
|
||||
main_language: str | None,
|
||||
playbook_scripts: str | None,
|
||||
) -> str:
|
||||
result = text.replace("{{DATE}}", date_value)
|
||||
if project_name:
|
||||
result = result.replace("{{PROJECT_NAME}}", project_name)
|
||||
if main_language:
|
||||
result = result.replace("{{MAIN_LANGUAGE}}", main_language)
|
||||
if playbook_scripts:
|
||||
result = result.replace("{{PLAYBOOK_SCRIPTS}}", playbook_scripts)
|
||||
return result
|
||||
@@ -563,41 +538,16 @@ def backup_path(path: Path, no_backup: bool) -> None:
|
||||
log(f"Backed up: {path} -> {backup}")
|
||||
|
||||
|
||||
def rename_template_files(root: Path) -> None:
|
||||
for template in root.rglob("*.template.md"):
|
||||
target = template.with_name(template.name.replace(".template.md", ".md"))
|
||||
template.rename(target)
|
||||
|
||||
|
||||
def replace_placeholders_in_dir(
|
||||
root: Path,
|
||||
project_name: str | None,
|
||||
date_value: str,
|
||||
main_language: str | None,
|
||||
playbook_scripts: str | None,
|
||||
) -> None:
|
||||
for file_path in root.rglob("*.md"):
|
||||
text = file_path.read_text(encoding="utf-8")
|
||||
updated = replace_placeholders(
|
||||
text, project_name, date_value, main_language, playbook_scripts
|
||||
)
|
||||
if updated != text:
|
||||
file_path.write_text(updated, encoding="utf-8")
|
||||
|
||||
|
||||
def replace_placeholders_in_file(
|
||||
file_path: Path,
|
||||
project_name: str | None,
|
||||
date_value: str,
|
||||
main_language: str | None,
|
||||
playbook_scripts: str | None,
|
||||
) -> None:
|
||||
if file_path.suffix != ".md":
|
||||
return
|
||||
text = file_path.read_text(encoding="utf-8")
|
||||
updated = replace_placeholders(
|
||||
text, project_name, date_value, main_language, playbook_scripts
|
||||
)
|
||||
updated = replace_placeholders(text, project_name, date_value, playbook_scripts)
|
||||
if updated != text:
|
||||
file_path.write_text(updated, encoding="utf-8")
|
||||
|
||||
@@ -616,7 +566,6 @@ def sync_directory(
|
||||
target_dir: Path,
|
||||
project_name: str | None,
|
||||
date_value: str,
|
||||
main_language: str | None,
|
||||
playbook_scripts: str | None,
|
||||
force: bool,
|
||||
no_backup: bool,
|
||||
@@ -637,7 +586,6 @@ def sync_directory(
|
||||
target_file,
|
||||
project_name,
|
||||
date_value,
|
||||
main_language,
|
||||
playbook_scripts,
|
||||
)
|
||||
|
||||
@@ -665,12 +613,11 @@ def update_agents_section(
|
||||
end_marker: str,
|
||||
project_name: str | None,
|
||||
date_value: str,
|
||||
main_language: str | None,
|
||||
playbook_scripts: str | None,
|
||||
) -> None:
|
||||
template_text = template_path.read_text(encoding="utf-8")
|
||||
template_text = replace_placeholders(
|
||||
template_text, project_name, date_value, main_language, playbook_scripts
|
||||
template_text, project_name, date_value, playbook_scripts
|
||||
)
|
||||
block = extract_block_lines(template_text, start_marker, end_marker)
|
||||
if not block:
|
||||
@@ -746,8 +693,7 @@ def sync_agents_template(context: dict) -> int:
|
||||
return 0
|
||||
|
||||
project_name = resolve_project_name(context)
|
||||
main_language = resolve_main_language({}, context)
|
||||
playbook_scripts = resolve_playbook_scripts(project_root, context)
|
||||
playbook_scripts = resolve_playbook_scripts(context)
|
||||
date_value = resolve_template_date(context)
|
||||
|
||||
agents_dst = project_root / "AGENTS.md"
|
||||
@@ -773,7 +719,6 @@ def sync_agents_template(context: dict) -> int:
|
||||
end_marker,
|
||||
project_name,
|
||||
date_value,
|
||||
main_language,
|
||||
playbook_scripts,
|
||||
)
|
||||
return 0
|
||||
@@ -805,17 +750,14 @@ def sync_rules_action(config: dict, context: dict) -> int:
|
||||
return 0
|
||||
|
||||
project_name = resolve_project_name(context)
|
||||
main_language = resolve_main_language(config, context)
|
||||
playbook_scripts = resolve_playbook_scripts(project_root, context)
|
||||
playbook_scripts = resolve_playbook_scripts(context)
|
||||
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
||||
no_backup = bool(config.get("no_backup", False))
|
||||
|
||||
backup_path(rules_dst, no_backup)
|
||||
text = rules_src.read_text(encoding="utf-8")
|
||||
text = replace_placeholders(
|
||||
text, project_name, date_value, main_language, playbook_scripts
|
||||
)
|
||||
rules_dst.write_text(text + "\n", encoding="utf-8")
|
||||
text = replace_placeholders(text, project_name, date_value, playbook_scripts)
|
||||
rules_dst.write_text(text.rstrip("\n") + "\n", encoding="utf-8")
|
||||
log("Synced: AGENT_RULES.md")
|
||||
return 0
|
||||
|
||||
@@ -833,8 +775,7 @@ def sync_memory_bank_action(config: dict, context: dict) -> int:
|
||||
return 2
|
||||
|
||||
project_name = config.get("project_name")
|
||||
main_language = resolve_main_language(config, context)
|
||||
playbook_scripts = resolve_playbook_scripts(project_root, context)
|
||||
playbook_scripts = resolve_playbook_scripts(context)
|
||||
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
||||
force = bool(config.get("force", False))
|
||||
no_backup = bool(config.get("no_backup", False))
|
||||
@@ -846,7 +787,6 @@ def sync_memory_bank_action(config: dict, context: dict) -> int:
|
||||
memory_dst,
|
||||
project_name,
|
||||
date_value,
|
||||
main_language,
|
||||
playbook_scripts,
|
||||
force,
|
||||
no_backup,
|
||||
@@ -868,8 +808,7 @@ def sync_prompts_action(config: dict, context: dict) -> int:
|
||||
return 2
|
||||
|
||||
project_name = resolve_project_name(context)
|
||||
main_language = resolve_main_language(config, context)
|
||||
playbook_scripts = resolve_playbook_scripts(project_root, context)
|
||||
playbook_scripts = resolve_playbook_scripts(context)
|
||||
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
||||
force = bool(config.get("force", False))
|
||||
no_backup = bool(config.get("no_backup", False))
|
||||
@@ -882,7 +821,6 @@ def sync_prompts_action(config: dict, context: dict) -> int:
|
||||
prompts_dst,
|
||||
project_name,
|
||||
date_value,
|
||||
main_language,
|
||||
playbook_scripts,
|
||||
force,
|
||||
no_backup,
|
||||
@@ -945,6 +883,13 @@ def update_agents_block(agents_md: Path, block_lines: list[str]) -> None:
|
||||
|
||||
def create_agents_index(agents_root: Path, langs: list[str], docs_prefix: str | None) -> None:
|
||||
agents_index = agents_root / "index.md"
|
||||
lang_descriptions = {
|
||||
"tsl": "TSL 相关规则集(由 playbook 同步;适用于 `.tsl`/`.tsf`)",
|
||||
"cpp": "C++ 相关规则集(由 playbook 同步;适用于 C++23/Modules)",
|
||||
"python": "Python 相关规则集(由 playbook 同步)",
|
||||
"typescript": "TypeScript/JavaScript 相关规则集(由 playbook 同步)",
|
||||
"markdown": "Markdown 相关规则集(仅代码格式化)",
|
||||
}
|
||||
lines = [
|
||||
"# .agents(多语言)",
|
||||
"",
|
||||
@@ -952,11 +897,11 @@ def create_agents_index(agents_root: Path, langs: list[str], docs_prefix: str |
|
||||
"",
|
||||
"建议约定:",
|
||||
"",
|
||||
"- `.agents/tsl/`:TSL 相关规则集(由 playbook 同步;适用于 `.tsl`/`.tsf`)",
|
||||
"- `.agents/cpp/`:C++ 相关规则集(由 playbook 同步;适用于 C++23/Modules)",
|
||||
"- `.agents/python/`:Python 相关规则集(由 playbook 同步)",
|
||||
"- `.agents/typescript/`:TypeScript/JavaScript 相关规则集(由 playbook 同步)",
|
||||
"- `.agents/markdown/`:Markdown 相关规则集(仅代码格式化)",
|
||||
]
|
||||
for lang in langs:
|
||||
description = lang_descriptions.get(lang, "相关规则集(由 playbook 同步)")
|
||||
lines.append(f"- `.agents/{lang}/`:{description}")
|
||||
lines += [
|
||||
"",
|
||||
"规则发生冲突时,建议以“更靠近代码的目录规则更具体”为准。",
|
||||
"",
|
||||
@@ -1220,6 +1165,7 @@ def install_skills_action(config: dict, context: dict) -> int:
|
||||
return 2
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
no_backup = bool(config.get("no_backup", False))
|
||||
for name in skills:
|
||||
src = skills_src_root / name
|
||||
if not src.is_dir():
|
||||
@@ -1227,9 +1173,12 @@ def install_skills_action(config: dict, context: dict) -> int:
|
||||
return 2
|
||||
dst = skills_dst_root / name
|
||||
if dst.exists():
|
||||
backup = skills_dst_root / f"{name}.bak.{timestamp}"
|
||||
dst.rename(backup)
|
||||
log(f"Backed up existing skill: {name} -> {backup.name}")
|
||||
if no_backup:
|
||||
rmtree(dst)
|
||||
else:
|
||||
backup = skills_dst_root / f"{name}.bak.{timestamp}"
|
||||
dst.rename(backup)
|
||||
log(f"Backed up existing skill: {name} -> {backup.name}")
|
||||
copytree(src, dst)
|
||||
rewrite_skill_docs_links(dst, resolve_docs_prefix(context))
|
||||
log(f"Installed: {name}")
|
||||
|
||||
Reference in New Issue
Block a user