diff --git a/.github/workflows/reusable-release-skill.yaml b/.github/workflows/reusable-release-skill.yaml index 6847a7a..7c853a7 100644 --- a/.github/workflows/reusable-release-skill.yaml +++ b/.github/workflows/reusable-release-skill.yaml @@ -108,6 +108,13 @@ jobs: ' shutil.copytree(src, dst, ignore=ignore_fn, dirs_exist_ok=True)' \ '' \ "shutil.copy2('SKILL.md', os.path.join(PACKAGE, 'SKILL.md'))" \ + "readme_src = os.path.abspath('README.md')" \ + "readme_dst = os.path.join(PACKAGE, 'README.md')" \ + 'if os.path.isfile(readme_src):' \ + " shutil.copy2(readme_src, readme_dst)" \ + " print('Copied README.md')" \ + 'if os.path.isfile(readme_src) and not os.path.isfile(readme_dst):' \ + " raise RuntimeError('README.md exists in skill root but was not packaged')" \ "copy_dir('references', os.path.join(PACKAGE, 'references'), references_ignore)" \ "copy_dir('assets', os.path.join(PACKAGE, 'assets'), common_ignore)" \ "copy_dir('tests', os.path.join(PACKAGE, 'tests'), common_ignore)" \ @@ -144,7 +151,7 @@ jobs: skill_readme_md = (post.content or '').strip() skill_description = metadata.get('description') metadata['readme_md'] = skill_readme_md - readme_path = os.path.join('references', 'README.md') + readme_path = 'README.md' if os.path.isfile(readme_path): try: readme_post = frontmatter.load(readme_path) diff --git a/pyproject.toml b/pyproject.toml index c35ac78..d8db934 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "jiangchang-platform-kit" -version = "1.0.13" +version = "1.0.14" description = "匠厂平台共享组件:Skill 实体 SDK + 桌面应用自动化 SDK" readme = "README.md" requires-python = ">=3.10" diff --git a/tests/test_release_workflow.py b/tests/test_release_workflow.py index fc6935a..48b8769 100644 --- a/tests/test_release_workflow.py +++ b/tests/test_release_workflow.py @@ -28,6 +28,32 @@ def publish_workflow_text() -> str: return f.read() +def test_workflow_packages_readme_at_root(workflow_text: str) -> None: + assert "readme_src = os.path.abspath('README.md')" in workflow_text + assert "readme_dst = os.path.join(PACKAGE, 'README.md')" in workflow_text + assert "Copied README.md" in workflow_text + assert ( + "raise RuntimeError('README.md exists in skill root but was not packaged')" + in workflow_text + ) + + +def test_workflow_metadata_reads_root_readme(workflow_text: str) -> None: + assert "readme_path = 'README.md'" in workflow_text + assert "frontmatter.load(readme_path)" in workflow_text + assert "metadata['readme_md'] = body" in workflow_text + + +def test_workflow_does_not_use_references_readme_for_marketplace( + workflow_text: str, +) -> None: + assert "os.path.join('references', 'README.md')" not in workflow_text + assert not re.search( + r"frontmatter\.load\([^)]*references[^)]*README", + workflow_text, + ) + + def test_workflow_packages_env_example_at_root(workflow_text: str) -> None: assert ".env.example" in workflow_text assert "Copied .env.example" in workflow_text diff --git a/tools/release.ps1 b/tools/release.ps1 index 1632aab..aee2592 100644 --- a/tools/release.ps1 +++ b/tools/release.ps1 @@ -28,6 +28,7 @@ 加密与 ZIP 内容由 CI 工作流 reusable-release-skill.yaml 的「Encrypt Source Code」步骤执行。CI 会: - 加密 scripts/(递归 PyArmor -r,输出到包内 scripts/,与源码目录树一致) - 复制 SKILL.md + - 若根目录存在 README.md,则复制到包根(明文,用于技能市场用户说明) - 复制 references/(排除 REQUIREMENTS.md) - 复制 assets/ - 复制 tests/