chore: auto release commit (2026-07-03 18:50:07)
All checks were successful
技能自动化发布 / release (push) Successful in 6s

This commit is contained in:
2026-07-03 18:50:08 +08:00
parent 7136689efe
commit 48a86e56f1
31 changed files with 1605 additions and 549 deletions

View File

@@ -174,6 +174,84 @@ class TestDocsStandards(unittest.TestCase):
self.assertIn("RpaVideoSession", text)
self.assertIn("1.0.17", text)
def test_rpa_md_forbids_rpa_helpers_import(self) -> None:
text = self._read("development/RPA.md")
self.assertIn("rpa_helpers", text)
self.assertTrue(
"不要 import" in text or "不要" in text and "import" in text,
msg="RPA.md must document forbidding rpa_helpers import",
)
def test_rpa_md_covers_simulator_playwright_layering(self) -> None:
text = self._read("development/RPA.md")
self.assertTrue(
"simulator_playwright" in text
or ("薄 adapter" in text and "playwright.py" in text),
msg="RPA.md must describe thin adapter + *_playwright.py layering",
)
def test_rpa_md_covers_industry_simulator_portal(self) -> None:
text = self._read("development/RPA.md")
self.assertTrue(
any(marker in text for marker in ("jc2009", "行业仿真", "门户")),
msg="RPA.md must mention jc2009 / industry simulator / portal gate",
)
def test_simulator_example_readme_covers_async_and_account_manager(self) -> None:
text = self._read("examples/simulator_browser_rpa/README.md")
self.assertIn("async", text.lower())
self.assertTrue(
"account-manager" in text.lower() or "pick-web" in text or "pick_web_account" in text,
msg="simulator_browser_rpa README must mention async and account-manager",
)
def test_development_md_documents_scaffold_and_git_cleanup(self) -> None:
text = self._read("development/DEVELOPMENT.md")
self.assertTrue(
"scaffold_skill" in text or "scaffold_skill.ps1" in text,
msg="DEVELOPMENT.md must document scaffold_skill",
)
self.assertTrue(
("Remove-Item" in text and ".git" in text)
or ("删除" in text and ".git" in text),
msg="DEVELOPMENT.md must document deleting .git",
)
def test_naming_md_copy_flow_documents_scaffold_or_git_cleanup(self) -> None:
text = self._read("development/NAMING.md")
self.assertTrue(
"scaffold" in text.lower() or ("清理" in text and ".git" in text),
msg="NAMING.md §9 must mention scaffold or Git cleanup",
)
def test_scaffold_ps1_exists(self) -> None:
path = os.path.join(get_skill_root(), "tools", "scaffold_skill.ps1")
self.assertTrue(os.path.isfile(path), msg="tools/scaffold_skill.ps1 must exist")
def test_guarded_docs_do_not_reference_amazon_implementation(self) -> None:
forbidden = (
"download-settlement-report-amazon",
"amazon_sim",
"#amz-email",
)
guarded_docs = (
"development/RPA.md",
"development/ADAPTER.md",
"development/DEVELOPMENT.md",
"development/CONFIG.md",
"development/TESTING.md",
"examples/README.md",
"examples/simulator_browser_rpa/README.md",
)
for rel in guarded_docs:
text = self._read(rel)
for fragment in forbidden:
self.assertNotIn(
fragment,
text,
msg=f"{rel} must not reference Amazon implementation {fragment!r}",
)
def test_adapter_md_covers_four_tiers_and_config_get(self) -> None:
text = self._read("development/ADAPTER.md")
for marker in (

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
"""禁止在模板主骨架 scripts/ 中 import account-manager 内部 RPA 辅助模块。"""
from __future__ import annotations
import os
import re
import unittest
from _support import get_skill_root
FORBIDDEN_PATTERNS = (
re.compile(r"\brpa_helpers\b"),
re.compile(r"\binject_account_manager_scripts_path\b"),
re.compile(r"\bget_account_credential\b"),
)
class TestNoRpaHelpersImport(unittest.TestCase):
def test_scripts_tree_has_no_forbidden_account_manager_imports(self) -> None:
scripts_dir = os.path.join(get_skill_root(), "scripts")
violations: list[str] = []
for root, _dirs, files in os.walk(scripts_dir):
for name in files:
if not name.endswith(".py"):
continue
rel = os.path.relpath(os.path.join(root, name), scripts_dir)
text = open(os.path.join(root, name), encoding="utf-8").read()
for pattern in FORBIDDEN_PATTERNS:
if pattern.search(text):
violations.append(f"{rel}: {pattern.pattern}")
self.assertEqual(
violations,
[],
msg="Forbidden account-manager internal imports in scripts/:\n" + "\n".join(violations),
)
if __name__ == "__main__":
unittest.main()

View File

@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
"""skill-template 脚手架与 Git 防串库守护。"""
from __future__ import annotations
import os
import unittest
from _support import get_skill_root
TEMPLATE_MARKER = ".openclaw-skill-template"
TEMPLATE_SLUG = "your-skill-slug"
def _read_skill_slug() -> str:
constants_path = os.path.join(get_skill_root(), "scripts", "util", "constants.py")
with open(constants_path, encoding="utf-8") as f:
for line in f:
if line.strip().startswith("SKILL_SLUG"):
_, _, value = line.partition("=")
return value.strip().strip('"').strip("'")
return ""
class TestScaffoldGuard(unittest.TestCase):
def test_template_repo_has_marker(self) -> None:
slug = _read_skill_slug()
if slug != TEMPLATE_SLUG:
self.skipTest(f"当前 SKILL_SLUG={slug!r},非模板占位,跳过 template marker 断言")
marker = os.path.join(get_skill_root(), TEMPLATE_MARKER)
self.assertTrue(
os.path.isfile(marker),
msg=f"skill-template 源仓库根目录必须存在 {TEMPLATE_MARKER}",
)
def test_business_skill_must_not_keep_template_marker(self) -> None:
slug = _read_skill_slug()
if slug == TEMPLATE_SLUG:
self.skipTest("当前仍为模板占位 slug由 test_template_repo_has_marker 守护")
marker = os.path.join(get_skill_root(), TEMPLATE_MARKER)
self.assertFalse(
os.path.isfile(marker),
msg=(
"业务技能不得保留 .openclaw-skill-template"
"请使用 tools/scaffold_skill 或删除标记文件并检查是否误复制了模板 .git"
),
)
def test_development_md_documents_git_cleanup(self) -> None:
path = os.path.join(get_skill_root(), "development", "DEVELOPMENT.md")
with open(path, encoding="utf-8") as f:
text = f.read()
self.assertIn(".git", text)
self.assertTrue(
"scaffold_skill" in text or "scaffold" in text.lower(),
msg="DEVELOPMENT.md must document scaffold_skill",
)
self.assertTrue(
"remote" in text.lower() or "git remote" in text.lower(),
msg="DEVELOPMENT.md must mention git remote self-check",
)
if __name__ == "__main__":
unittest.main()