name: Plugin Library CI (Incremental) on: push: branches: [master, main] workflow_dispatch: inputs: force_publish: description: '强制全量发布 (忽略变更检测)' default: 'false' required: true type: choice options: - 'false' - 'true' env: SERVER_HOST: ${{ vars.SERVER_HOST }} AuthToken: ${{ vars.AUTH_TOKEN }} jobs: # 第一步:检测变更的模块 detect-changes: runs-on: dev container: node:18-alpine outputs: matrix: ${{ steps.detect.outputs.matrix }} has_changes: ${{ steps.detect.outputs.has_changes }} changed_count: ${{ steps.detect.outputs.changed_count }} steps: - name: Install Git & jq run: apk add --no-cache git jq - name: Checkout uses: http://106.52.62.106:3000/unity-registry/checkout@v4 with: fetch-depth: 2 # 关键:需要上次提交来对比差异 - name: Detect Changed Modules id: detect run: | # 如果是强制全量发布 if [ "${{ github.event.inputs.force_publish }}" = "true" ]; then echo "强制执行全量发布..." ALL_MODULES='["00.StaryEvo","00.StaryEvoTools","00.BuildOriginality","00.ARMazTools","01.HybridCLR","02.InformationSave","03.YooAsset","04.AudioCore","05.TableTextConversion","06.UIFarme","07.RKTools","08.UniTask","09.CodeChecker","10.StoryEditor","10.XNode","11.PointCloudTools"]' echo "matrix={\"module\":$ALL_MODULES}" >> $GITHUB_OUTPUT echo "has_changes=true" >> $GITHUB_OUTPUT echo "changed_count=15" >> $GITHUB_OUTPUT exit 0 fi # 获取变更文件列表(对比 HEAD~1 和 HEAD) # 处理首次提交的情况(没有 HEAD~1) if git rev-parse HEAD~1 >/dev/null 2>&1; then CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD) echo "变更文件列表:" echo "$CHANGED_FILES" else echo "首次提交,全量发布所有模块..." CHANGED_FILES=$(find Assets -type f 2>/dev/null) fi # 定义所有候选模块 ALL_MODULES=( "00.StaryEvo" "00.StaryEvoTools" "00.BuildOriginality" "00.ARMazTools" "01.HybridCLR" "02.InformationSave" "03.YooAsset" "04.AudioCore" "05.TableTextConversion" "06.UIFarme" "07.RKTools" "08.UniTask" "09.CodeChecker" "10.StoryEditor" "10.XNode" "11.PointCloudTools" ) # 检测哪些模块目录下有文件变更 CHANGED_MODULES=() for module in "${ALL_MODULES[@]}"; do MODULE_PATH="Assets/${module}" # 检查是否有文件属于这个模块 if echo "$CHANGED_FILES" | grep -q "^${MODULE_PATH}/"; then # 检查是否有 package.json(确保是有效的 npm 包) if [ -f "${MODULE_PATH}/package.json" ]; then CHANGED_MODULES+=("$module") echo "✅ 检测到变更: $module" else echo "⚠️ $module 有文件变更但缺少 package.json,跳过" fi fi done # 构建 JSON 矩阵输出 if [ ${#CHANGED_MODULES[@]} -gt 0 ]; then MATRIX_JSON=$(printf '%s\n' "${CHANGED_MODULES[@]}" | jq -R . | jq -s -c .) echo "matrix={\"module\":$MATRIX_JSON}" >> $GITHUB_OUTPUT echo "has_changes=true" >> $GITHUB_OUTPUT echo "changed_count=${#CHANGED_MODULES[@]}" >> $GITHUB_OUTPUT echo "总结: 本次将发布 ${#CHANGED_MODULES[@]} 个模块" else echo "没有检测到模块变更,跳过发布" echo "matrix={\"module\":[]}" >> $GITHUB_OUTPUT echo "has_changes=false" >> $GITHUB_OUTPUT echo "changed_count=0" >> $GITHUB_OUTPUT fi - name: Show Detection Result run: | echo "变更检测结果:" echo "Has Changes: ${{ steps.detect.outputs.has_changes }}" echo "Changed Count: ${{ steps.detect.outputs.changed_count }}" echo "Matrix: ${{ steps.detect.outputs.matrix }}" # 第二步:只对变更的模块执行发布 publish: needs: detect-changes if: needs.detect-changes.outputs.has_changes == 'true' runs-on: dev container: image: node:18-alpine # 可选:挂载 npm 缓存(需在 runner 宿主机创建 /cache/npm) volumes: - /cache/npm:/root/.npm:rw strategy: fail-fast: false # 根据变更数量动态调整并发(变更少时串行,多时并行) max-parallel: ${{ fromJSON(needs.detect-changes.outputs.changed_count) > 4 && 4 || 1 }} matrix: ${{ fromJSON(needs.detect-changes.outputs.matrix) }} steps: - name: Setup Node.js run: | # 如果使用了挂载缓存,先确保链接存在 ln -sf /srv/18-alpine/bin/node /usr/bin/node 2>/dev/null || true ln -sf /srv/18-alpine/bin/npm /usr/bin/npm 2>/dev/null || true node -v - name: Configure npm run: | npm config set registry "http://${SERVER_HOST}/npm" npm config set "//${SERVER_HOST}/:_authToken" "${AuthToken}" - name: Sparse Checkout (仅检出目标模块) uses: http://106.52.62.106:3000/unity-registry/checkout@v4 with: fetch-depth: 1 sparse-checkout: Assets/${{ matrix.module }} # 不检出历史,极大减少大仓库的 IO 时间 - name: Publish ${{ matrix.module }} working-directory: Assets/${{ matrix.module }} run: | echo "========================================" echo "开始发布: ${{ matrix.module }}" # 获取版本号 CURRENT_VERSION=$(node -p "require('./package.json').version" 2>/dev/null || echo "unknown") echo "当前版本: $CURRENT_VERSION" # 尝试发布 if npm publish --registry=http://${SERVER_HOST}/npm 2>&1; then echo "✅ ${{ matrix.module }}@$CURRENT_VERSION 发布成功" else PUBLISH_EXIT=$? # 检查是否因为版本已存在而失败(不算真失败) if npm view . --registry=http://${SERVER_HOST}/npm 2>/dev/null | grep -q "$CURRENT_VERSION"; then echo "⚠️ 版本 $CURRENT_VERSION 已存在,跳过" else echo "❌ 发布失败 (exit $PUBLISH_EXIT)" exit 1 # 真正的失败,终止 workflow fi fi - name: Complete if: always() run: echo "====== ${{ matrix.module }} 处理完成 ======" # 第三步:汇总通知(可选) summary: needs: [detect-changes, publish] if: always() && needs.detect-changes.outputs.has_changes == 'true' runs-on: dev steps: - name: Publish Summary run: | echo "## 发布汇总" >> $GITHUB_STEP_SUMMARY echo "- **变更模块数**: ${{ needs.detect-changes.outputs.changed_count }}" >> $GITHUB_STEP_SUMMARY echo "- **执行结果**: ${{ needs.publish.result }}" >> $GITHUB_STEP_SUMMARY