diff --git a/.github/workflows/reusable-release-skill.yaml b/.github/workflows/reusable-release-skill.yaml index 8098646..44844e5 100644 --- a/.github/workflows/reusable-release-skill.yaml +++ b/.github/workflows/reusable-release-skill.yaml @@ -70,7 +70,7 @@ jobs: python3.12 -c "import os,base64,pathlib,subprocess; os.environ['PATH']='/usr/local/bin:/usr/local/python3.12/bin:'+os.environ.get('PATH',''); p=pathlib.Path('/tmp/pyarmor-reg.zip'); p.write_bytes(base64.standard_b64decode(os.environ['PYARMOR_REG_B64'])); subprocess.run(['pyarmor','reg',str(p)],check=True); p.unlink(missing_ok=True)" fi - # 递归加密整个 scripts/(含 cli、service、db、util 等子包);产物保留与源码一致的 scripts/ 层级,入口为 scripts/main.py。 + # Obfuscate scripts recursively. Copy package support files as plain text. - name: Encrypt Source Code run: | export PATH="/usr/local/bin:/usr/local/python3.12/bin:${PATH:-}" @@ -78,9 +78,47 @@ jobs: set -euo pipefail test -d scripts ( cd scripts && pyarmor gen --platform "${PYARMOR_PLATFORM}" -r -O ../dist/package/scripts . ) - cp SKILL.md dist/package/ - if [ -d references ]; then cp -r references dist/package/; fi - if [ -d assets ]; then cp -r assets dist/package/; fi + + printf '%s\n' \ + 'import os' \ + 'import shutil' \ + '' \ + "PACKAGE = 'dist/package'" \ + '' \ + 'def common_ignore(dir_path, names):' \ + ' ignored = set()' \ + ' for name in names:' \ + ' lower = name.lower()' \ + " if name in ('__pycache__', '.pytest_cache', 'artifacts'):" \ + ' ignored.add(name)' \ + " elif lower.endswith('.pyc') or lower.endswith('.pyo') or lower.endswith('.db'):" \ + ' ignored.add(name)' \ + ' return list(ignored)' \ + '' \ + "ref_src = os.path.abspath('references')" \ + '' \ + 'def references_ignore(dir_path, names):' \ + ' ignored = set(common_ignore(dir_path, names))' \ + " if os.path.abspath(dir_path) == ref_src and 'REQUIREMENTS.md' in names:" \ + " ignored.add('REQUIREMENTS.md')" \ + ' return list(ignored)' \ + '' \ + 'def copy_dir(src, dst, ignore_fn):' \ + ' if os.path.isdir(src):' \ + ' shutil.copytree(src, dst, ignore=ignore_fn, dirs_exist_ok=True)' \ + '' \ + "shutil.copy2('SKILL.md', os.path.join(PACKAGE, 'SKILL.md'))" \ + "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)" \ + "copy_dir('evals', os.path.join(PACKAGE, 'evals'), common_ignore)" \ + '' \ + "print('Package top-level entries:')" \ + 'for name in sorted(os.listdir(PACKAGE)):' \ + " print(' -', name)" \ + > /tmp/package_skill_release_copy.py + + python3.12 /tmp/package_skill_release_copy.py - name: Parse Metadata and Pack id: build_task diff --git a/tools/release.ps1 b/tools/release.ps1 index eb3a481..05eb0ec 100644 --- a/tools/release.ps1 +++ b/tools/release.ps1 @@ -25,8 +25,13 @@ .NOTES Requires: git, PowerShell 5+ - 加密与 ZIP 内容由 CI 工作流 reusable-release-skill.yaml 的「Encrypt Source Code」步骤执行: - 对 scripts/ 递归 PyArmor(-r),输出到包内 scripts/(与源码目录树一致),并复制 SKILL.md、references/、assets/(若存在)。 + 加密与 ZIP 内容由 CI 工作流 reusable-release-skill.yaml 的「Encrypt Source Code」步骤执行。CI 会: + - 加密 scripts/(递归 PyArmor -r,输出到包内 scripts/,与源码目录树一致) + - 复制 SKILL.md + - 复制 references/(排除 REQUIREMENTS.md) + - 复制 assets/ + - 复制 tests/ + - 复制 evals/(除 scripts 外均为明文;若目录不存在则跳过;复制时排除常见缓存与运行产物) 本脚本在打 tag 前会做一次 scripts/ 结构自检,避免子目录未提交却仍发布。 #> @@ -218,7 +223,9 @@ try { Assert-SkillReleasePackagingSources -SkillRoot $skillRoot } - $upstream = (& git rev-parse --abbrev-ref --symbolic-full-name "@{u}" 2>$null) + # 用 cmd /c + 2>&1 将 stderr 合并进 stdout,避免 PowerShell 在 $ErrorActionPreference=Stop + # 下把首次发布时 "fatal: ambiguous argument '@{u}'" 之类的 stderr 误判为异常。 + $upstream = & cmd /c 'git rev-parse --abbrev-ref --symbolic-full-name "@{u}" 2>&1' $hasUpstream = ($LASTEXITCODE -eq 0) if ($DryRun) {