Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 201 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -419,11 +419,198 @@ jobs:
- name: 运行 test.sh
run: bash test.sh

# ==================== 发布模拟验证 ====================
publish-sim:
name: 发布模拟验证
runs-on: ubuntu-latest
timeout-minutes: 5

steps:
- name: 检出代码
uses: actions/checkout@v4

- name: 安装 Node.js
uses: actions/setup-node@v4
with:
node-version: "22"

- name: npm pack
working-directory: packages/cli-box-skill
run: |
npm pack
ls -la cli-box-skill-*.tgz

- name: 验证 tarball 文件清单
working-directory: packages/cli-box-skill
run: |
TARBALL=$(ls cli-box-skill-*.tgz)
echo "=== 验证 $TARBALL ==="
tar tzf "$TARBALL" | sort

REQUIRED=("package/postinstall.mjs" "package/installer/cli.mjs" "package/installer/shared.mjs" "package/bin/cli-box-wrapper.js" "package/skill/SKILL.md")
for f in "${REQUIRED[@]}"; do
if tar tzf "$TARBALL" | grep -q "$f"; then
echo "✓ $f"
else
echo "✗ $f MISSING"
exit 1
fi
done
echo ""
echo "✅ tarball 文件清单验证通过"

- name: 验证包结构
working-directory: packages/cli-box-skill
run: |
echo "=== package.json 字段检查 ==="
node -e "
const pkg = require('./package.json');
const checks = [
['name', pkg.name === 'cli-box-skill'],
['bin.cli-box', !!pkg.bin?.['cli-box']],
['bin.cli-box-skill', !!pkg.bin?.['cli-box-skill']],
['files includes postinstall.mjs', pkg.files?.includes('postinstall.mjs')],
['files includes installer/', pkg.files?.some(f => f.startsWith('installer/'))],
['optionalDependencies.cli-box-darwin-arm64', !!pkg.optionalDependencies?.['cli-box-darwin-arm64']],
];
let ok = true;
for (const [name, pass] of checks) {
console.log(pass ? '✓ ' + name : '✗ ' + name);
if (!pass) ok = false;
}
if (!ok) process.exit(1);
console.log('\n✅ 包结构验证通过');
"

# ==================== 升级流程测试 (macOS) ====================
skill-upgrade-flow:
name: 升级流程测试
runs-on: macos-latest
timeout-minutes: 10

steps:
- name: 检出代码
uses: actions/checkout@v4

- name: 安装 Node.js
uses: actions/setup-node@v4
with:
node-version: "22"

- name: 安装当前 latest 版本
run: npm install -g cli-box-skill@latest

- name: 验证 latest 安装
run: |
echo "=== 验证 cli-box-skill 命令 ==="
cli-box-skill --help
echo ""
echo "=== 验证二进制链接 ==="
ls -la ~/.cli-box/bin/cli-box || echo "⚠ cli-box binary not found"
ls -la ~/.cli-box/bin/cli-box-daemon || echo "⚠ cli-box-daemon binary not found"

- name: 模拟用户自定义 SKILL.md
run: |
mkdir -p ~/.claude/skills/cli-box
echo "# Custom SKILL.md (user modified)" > ~/.claude/skills/cli-box/SKILL.md
echo "Custom content that should be preserved" >> ~/.claude/skills/cli-box/SKILL.md
echo ""
echo "=== 自定义 SKILL.md 内容 ==="
cat ~/.claude/skills/cli-box/SKILL.md

- name: 从 PR 分支打包
working-directory: packages/cli-box-skill
run: |
npm pack
ls -la cli-box-skill-*.tgz

- name: 运行 upgrade 命令
working-directory: packages/cli-box-skill
run: |
echo "=== 运行 upgrade(无 daemon)==="
node installer/cli.mjs upgrade --yes 2>&1 | tee /tmp/upgrade-output.log

- name: 验证升级结果
run: |
echo "============================================"
echo " 升级结果验证"
echo "============================================"
echo ""

echo "=== 二进制链接检查 ==="
if [ -L ~/.cli-box/bin/cli-box ]; then
echo "✓ cli-box is a symlink"
ls -la ~/.cli-box/bin/cli-box
else
echo "⚠ cli-box is NOT a symlink"
fi

if [ -L ~/.cli-box/bin/cli-box-daemon ]; then
echo "✓ cli-box-daemon is a symlink"
ls -la ~/.cli-box/bin/cli-box-daemon
else
echo "⚠ cli-box-daemon is NOT a symlink"
fi

echo ""

echo "=== SKILL.md 保留检查 ==="
if [ -f ~/.claude/skills/cli-box/SKILL.md ]; then
CONTENT=$(cat ~/.claude/skills/cli-box/SKILL.md)
if echo "$CONTENT" | grep -q "Custom content that should be preserved"; then
echo "✓ SKILL.md preserved (custom content intact)"
else
echo "✗ SKILL.md was overwritten!"
echo "Expected: 'Custom content that should be preserved'"
echo "Got:"
cat ~/.claude/skills/cli-box/SKILL.md
exit 1
fi
else
echo "⚠ SKILL.md not found at ~/.claude/skills/cli-box/SKILL.md"
fi

echo ""

echo "=== cli-box-skill 命令检查 ==="
cli-box-skill --help 2>&1 | head -5

- name: 上传升级日志
if: always()
uses: actions/upload-artifact@v4
with:
name: upgrade-output
path: /tmp/upgrade-output.log
retention-days: 7

# ==================== cli-box-skill 单元测试 ====================
skill-unit-test:
name: cli-box-skill 单元测试
runs-on: ubuntu-latest
timeout-minutes: 5

steps:
- name: 检出代码
uses: actions/checkout@v4

- name: 安装 Node.js
uses: actions/setup-node@v4
with:
node-version: "22"

- name: 安装依赖
working-directory: packages/cli-box-skill
run: npm install

- name: 运行单元测试
working-directory: packages/cli-box-skill
run: node --test

# ==================== 门禁结果汇总 ====================
gate-result:
name: 门禁结果
runs-on: ubuntu-latest
needs: [rust-fmt, rust-clippy, rust-test, frontend-test, e2e-test, unified-test, security]
needs: [rust-fmt, rust-clippy, rust-test, frontend-test, e2e-test, unified-test, security, publish-sim, skill-upgrade-flow, skill-unit-test]
if: always()

steps:
Expand Down Expand Up @@ -457,6 +644,9 @@ jobs:
E2E_TEST="${{ needs.e2e-test.result }}"
UNIFIED_TEST="${{ needs.unified-test.result }}"
SECURITY_RESULT="${{ needs.security.result }}"
PUBLISH_SIM="${{ needs.publish-sim.result }}"
UPGRADE_FLOW="${{ needs.skill-upgrade-flow.result }}"
SKILL_UNIT="${{ needs.skill-unit-test.result }}"

echo "| 检查项 | 状态 |"
echo "|-------|------|"
Expand All @@ -467,6 +657,9 @@ jobs:
echo "| Playwright E2E | $E2E_TEST |"
echo "| 统一测试 (test.sh) | $UNIFIED_TEST |"
echo "| 安全检查 | $SECURITY_RESULT |"
echo "| 发布模拟验证 | $PUBLISH_SIM |"
echo "| 升级流程测试 | $UPGRADE_FLOW |"
echo "| cli-box-skill 单元测试 | $SKILL_UNIT |"
echo ""

if [ -f coverage-artifacts/rust-coverage-summary.md ]; then
Expand All @@ -487,7 +680,10 @@ jobs:
"$FRONTEND_TEST" == "success" && \
"$E2E_TEST" == "success" && \
"$UNIFIED_TEST" == "success" && \
"$SECURITY_RESULT" == "success" ]]; then
"$SECURITY_RESULT" == "success" && \
"$PUBLISH_SIM" == "success" && \
"$UPGRADE_FLOW" == "success" && \
"$SKILL_UNIT" == "success" ]]; then
echo "✅ 所有门禁检查通过!"
exit 0
else
Expand All @@ -510,6 +706,9 @@ jobs:
'Playwright E2E': '${{ needs.e2e-test.result }}',
'统一测试 (test.sh)': '${{ needs.unified-test.result }}',
'安全检查': '${{ needs.security.result }}',
'发布模拟验证': '${{ needs.publish-sim.result }}',
'升级流程测试': '${{ needs.skill-upgrade-flow.result }}',
'cli-box-skill 单元测试': '${{ needs.skill-unit-test.result }}',
};

const statusEmoji = (status) => status === 'success' ? '✅' : (status === 'skipped' ? '⏭️' : '❌');
Expand Down
Loading
Loading