From 23ee2393c6643f17db117ec5b70e01e0d72c151e Mon Sep 17 00:00:00 2001 From: yhh <359807859@qq.com> Date: Mon, 15 Dec 2025 09:33:51 +0800 Subject: [PATCH] =?UTF-8?q?chore(release):=20=E5=87=86=E5=A4=87=E5=8F=91?= =?UTF-8?q?=E5=B8=83=20v2.4.0=EF=BC=8C=E6=94=B9=E8=BF=9B=20CI=20=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 @esengine/ecs-framework 版本号到 2.4.0 - 更新中英文 changelog - CI: 支持标签触发自动发布(v* 或 package-v* 格式) - CI: 保留手动触发选项 - CI: 标签模式下自动创建 GitHub Release --- .github/workflows/release.yml | 190 +++++++++++++++++++++++++--------- docs/changelog.md | 48 +++++++++ docs/en/changelog.md | 48 +++++++++ packages/core/package.json | 2 +- 4 files changed, 240 insertions(+), 48 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 99f3e633..093059ec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,10 +1,26 @@ name: Release NPM Packages on: + # 标签触发:支持 v* 和 {package}-v* 格式 + # Tag trigger: supports v* and {package}-v* formats + push: + tags: + - 'v*' + - 'core-v*' + - 'behavior-tree-v*' + - 'editor-core-v*' + - 'node-editor-v*' + - 'blueprint-v*' + - 'tilemap-v*' + - 'physics-rapier2d-v*' + - 'worker-generator-v*' + + # 保留手动触发选项 + # Keep manual trigger option workflow_dispatch: inputs: package: - description: '选择要发布的包' + description: '选择要发布的包 | Select package to publish' required: true type: choice options: @@ -15,19 +31,15 @@ on: - blueprint - tilemap - physics-rapier2d + - worker-generator version_type: - description: '版本更新类型' + description: '版本更新类型 | Version bump type' required: true type: choice options: - patch - minor - major - - custom - custom_version: - description: '自定义版本号 (仅当选择 custom 时使用,例如: 2.2.9)' - required: false - type: string permissions: contents: write @@ -36,7 +48,7 @@ permissions: jobs: release-package: - name: Release ${{ github.event.inputs.package }} Package + name: Release Package runs-on: ubuntu-latest steps: - name: Checkout @@ -45,6 +57,42 @@ jobs: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} + - name: Parse tag or input + id: parse + run: | + if [ "${{ github.event_name }}" = "push" ]; then + # 从标签解析包名和版本 | Parse package and version from tag + TAG="${GITHUB_REF#refs/tags/}" + echo "tag=$TAG" >> $GITHUB_OUTPUT + + # 解析格式:v1.0.0 或 package-v1.0.0 + # Parse format: v1.0.0 or package-v1.0.0 + if [[ "$TAG" =~ ^v([0-9]+\.[0-9]+\.[0-9]+.*)$ ]]; then + PACKAGE="core" + VERSION="${BASH_REMATCH[1]}" + elif [[ "$TAG" =~ ^([a-z-]+)-v([0-9]+\.[0-9]+\.[0-9]+.*)$ ]]; then + PACKAGE="${BASH_REMATCH[1]}" + VERSION="${BASH_REMATCH[2]}" + else + echo "::error::Invalid tag format: $TAG" + echo "Expected: v1.0.0 or package-v1.0.0" + exit 1 + fi + + echo "package=$PACKAGE" >> $GITHUB_OUTPUT + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "mode=tag" >> $GITHUB_OUTPUT + echo "📦 Package: $PACKAGE" + echo "📌 Version: $VERSION" + else + # 手动触发:从 package.json 读取并 bump 版本 + # Manual trigger: read from package.json and bump version + PACKAGE="${{ github.event.inputs.package }}" + echo "package=$PACKAGE" >> $GITHUB_OUTPUT + echo "mode=manual" >> $GITHUB_OUTPUT + echo "version_type=${{ github.event.inputs.version_type }}" >> $GITHUB_OUTPUT + fi + - name: Install pnpm uses: pnpm/action-setup@v4 @@ -58,76 +106,124 @@ jobs: - name: Install dependencies run: pnpm install + - name: Verify version (tag mode) + if: steps.parse.outputs.mode == 'tag' + run: | + PACKAGE="${{ steps.parse.outputs.package }}" + EXPECTED_VERSION="${{ steps.parse.outputs.version }}" + + # 获取 package.json 中的版本 + # Get version from package.json + ACTUAL_VERSION=$(node -p "require('./packages/$PACKAGE/package.json').version") + + if [ "$EXPECTED_VERSION" != "$ACTUAL_VERSION" ]; then + echo "::error::Version mismatch!" + echo "Tag version: $EXPECTED_VERSION" + echo "package.json version: $ACTUAL_VERSION" + echo "" + echo "Please update packages/$PACKAGE/package.json to version $EXPECTED_VERSION before tagging." + exit 1 + fi + + echo "✅ Version verified: $EXPECTED_VERSION" + + - name: Bump version (manual mode) + if: steps.parse.outputs.mode == 'manual' + id: bump + run: | + PACKAGE="${{ steps.parse.outputs.package }}" + cd packages/$PACKAGE + + CURRENT=$(node -p "require('./package.json').version") + IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" + + case "${{ steps.parse.outputs.version_type }}" in + major) NEW_VERSION="$((MAJOR+1)).0.0" ;; + minor) NEW_VERSION="$MAJOR.$((MINOR+1)).0" ;; + patch) NEW_VERSION="$MAJOR.$MINOR.$((PATCH+1))" ;; + esac + + # Update package.json + node -e "const fs=require('fs'); const pkg=JSON.parse(fs.readFileSync('package.json')); pkg.version='$NEW_VERSION'; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2)+'\n')" + + echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT + echo "📌 Bumped version: $CURRENT → $NEW_VERSION" + + - name: Set final version + id: version + run: | + if [ "${{ steps.parse.outputs.mode }}" = "tag" ]; then + echo "value=${{ steps.parse.outputs.version }}" >> $GITHUB_OUTPUT + else + echo "value=${{ steps.bump.outputs.version }}" >> $GITHUB_OUTPUT + fi + - name: Build core package (if needed) - if: ${{ github.event.inputs.package != 'core' && github.event.inputs.package != 'node-editor' }} + if: ${{ steps.parse.outputs.package != 'core' && steps.parse.outputs.package != 'node-editor' && steps.parse.outputs.package != 'worker-generator' }} run: | cd packages/core pnpm run build - name: Build node-editor package (if needed for blueprint) - if: ${{ github.event.inputs.package == 'blueprint' }} + if: ${{ steps.parse.outputs.package == 'blueprint' }} run: | cd packages/node-editor pnpm run build - # - name: Run tests - # run: | - # cd packages/${{ github.event.inputs.package }} - # npm run test:ci - - - name: Update version - id: version - run: | - cd packages/${{ github.event.inputs.package }} - if [ "${{ github.event.inputs.version_type }}" = "custom" ]; then - NEW_VERSION=${{ github.event.inputs.custom_version }} - else - # Get current version and bump it - CURRENT=$(node -p "require('./package.json').version") - IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" - case "${{ github.event.inputs.version_type }}" in - major) NEW_VERSION="$((MAJOR+1)).0.0" ;; - minor) NEW_VERSION="$MAJOR.$((MINOR+1)).0" ;; - patch) NEW_VERSION="$MAJOR.$MINOR.$((PATCH+1))" ;; - esac - fi - # Update package.json using node - node -e "const fs=require('fs'); const pkg=JSON.parse(fs.readFileSync('package.json')); pkg.version='$NEW_VERSION'; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2)+'\n')" - echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT - echo "发布版本: $NEW_VERSION" - - name: Build package run: | - cd packages/${{ github.event.inputs.package }} + cd packages/${{ steps.parse.outputs.package }} pnpm run build:npm - name: Publish to npm env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - cd packages/${{ github.event.inputs.package }}/dist + cd packages/${{ steps.parse.outputs.package }}/dist pnpm publish --access public --no-git-checks - - name: Create Pull Request + - name: Create GitHub Release (tag mode) + if: steps.parse.outputs.mode == 'tag' + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ steps.parse.outputs.tag }} + name: "${{ steps.parse.outputs.package }} v${{ steps.version.outputs.value }}" + body: | + ## 🚀 @esengine/${{ steps.parse.outputs.package }} v${{ steps.version.outputs.value }} + + 📦 **NPM**: [@esengine/${{ steps.parse.outputs.package }}@${{ steps.version.outputs.value }}](https://www.npmjs.com/package/@esengine/${{ steps.parse.outputs.package }}/v/${{ steps.version.outputs.value }}) + + ```bash + npm install @esengine/${{ steps.parse.outputs.package }}@${{ steps.version.outputs.value }} + ``` + + --- + *自动发布 | Auto-released by GitHub Actions* + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Pull Request (manual mode) + if: steps.parse.outputs.mode == 'manual' uses: peter-evans/create-pull-request@v6 with: token: ${{ secrets.GITHUB_TOKEN }} - commit-message: "chore(${{ github.event.inputs.package }}): release v${{ steps.version.outputs.new_version }}" - branch: release/${{ github.event.inputs.package }}-v${{ steps.version.outputs.new_version }} + commit-message: "chore(${{ steps.parse.outputs.package }}): release v${{ steps.version.outputs.value }}" + branch: release/${{ steps.parse.outputs.package }}-v${{ steps.version.outputs.value }} delete-branch: true - title: "chore(${{ github.event.inputs.package }}): Release v${{ steps.version.outputs.new_version }}" + title: "chore(${{ steps.parse.outputs.package }}): Release v${{ steps.version.outputs.value }}" body: | - ## 🚀 Release v${{ steps.version.outputs.new_version }} + ## 🚀 Release v${{ steps.version.outputs.value }} - 此 PR 更新 `@esengine/${{ github.event.inputs.package }}` 包的版本号 + 此 PR 更新 `@esengine/${{ steps.parse.outputs.package }}` 包的版本号 ### 变更 - - ✅ 已发布到 npm: [@esengine/${{ github.event.inputs.package }}@${{ steps.version.outputs.new_version }}](https://www.npmjs.com/package/@esengine/${{ github.event.inputs.package }}/v/${{ steps.version.outputs.new_version }}) - - ✅ 更新 `packages/${{ github.event.inputs.package }}/package.json` → `${{ steps.version.outputs.new_version }}` + - ✅ 已发布到 npm: [@esengine/${{ steps.parse.outputs.package }}@${{ steps.version.outputs.value }}](https://www.npmjs.com/package/@esengine/${{ steps.parse.outputs.package }}/v/${{ steps.version.outputs.value }}) + - ✅ 更新 `packages/${{ steps.parse.outputs.package }}/package.json` → `${{ steps.version.outputs.value }}` --- *此 PR 由发布工作流自动创建* labels: | release - ${{ github.event.inputs.package }} + ${{ steps.parse.outputs.package }} automated pr diff --git a/docs/changelog.md b/docs/changelog.md index 90e7906b..5fc2c842 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -4,6 +4,54 @@ --- +## v2.4.0 (2025-12-15) + +### Features + +- **EntityHandle 实体句柄**: 轻量级实体引用抽象 (#304) + - 28位索引 + 20位代数(generation)设计,高效复用已销毁实体槽位 + - `EntityHandleManager` 管理句柄生命周期和有效性验证 + - 支持句柄转换为实体引用,检测悬空引用 + +- **SystemScheduler 系统调度器**: 声明式系统调度 (#304) + - 新增 `@Stage(name)` 装饰器指定系统执行阶段 + - 新增 `@Before(SystemClass)` / `@After(SystemClass)` 装饰器声明系统依赖 + - 新增 `@InSet(setName)` 装饰器将系统归入逻辑分组 + - 基于拓扑排序自动解析执行顺序,检测循环依赖 + +- **EpochManager 变更检测**: 帧级变更追踪机制 (#304) + - 跟踪组件添加/修改时间戳(epoch) + - 支持查询"自上次检查以来变化的组件" + - 适用于脏检测、增量更新等优化场景 + +- **CompiledQuery 编译查询**: 预编译类型安全查询 (#304) + - 编译时生成优化的查询逻辑,减少运行时开销 + - 完整的 TypeScript 类型推断支持 + - 支持 `With`、`Without`、`Changed` 等查询条件组合 + +- **PluginServiceRegistry**: 类型安全的插件服务注册表 (#300) + - 通过 `Core.pluginServices` 访问 + - 支持 `ServiceToken` 模式获取服务 + +- **组件自动注册**: `@ECSComponent` 装饰器增强 (#302) + - 装饰器现在自动注册到 `ComponentRegistry` + - 解决 `Decorators ↔ ComponentRegistry` 循环依赖 + - 新建 `ComponentTypeUtils.ts` 作为底层无依赖模块 + +### API Changes + +- `EntitySystem` 添加 `getBefore()` / `getAfter()` / `getSets()` getter 方法 +- `Entity` 添加 `markDirty()` 辅助方法用于手动触发变更检测 +- `IScene` 添加 `epochManager` 属性 +- `CommandBuffer.pendingCount` 修正为返回实际操作数(而非实体数) + +### Documentation + +- 更新系统调度文档,添加声明式依赖配置章节 +- 更新实体查询文档,添加编译查询使用说明 + +--- + ## v2.3.2 (2025-12-08) ### Features diff --git a/docs/en/changelog.md b/docs/en/changelog.md index 26df68af..09ac78d1 100644 --- a/docs/en/changelog.md +++ b/docs/en/changelog.md @@ -4,6 +4,54 @@ This document records the version update history of the `@esengine/ecs-framework --- +## v2.4.0 (2025-12-15) + +### Features + +- **EntityHandle**: Lightweight entity reference abstraction (#304) + - 28-bit index + 20-bit generation design for efficient reuse of destroyed entity slots + - `EntityHandleManager` manages handle lifecycle and validity verification + - Support handle-to-entity conversion with dangling reference detection + +- **SystemScheduler**: Declarative system scheduling (#304) + - New `@Stage(name)` decorator to specify system execution stage + - New `@Before(SystemClass)` / `@After(SystemClass)` decorators to declare dependencies + - New `@InSet(setName)` decorator to group systems logically + - Automatic execution order resolution via topological sort with cycle detection + +- **EpochManager**: Frame-level change detection mechanism (#304) + - Track component add/modify timestamps (epochs) + - Support querying "components changed since last check" + - Suitable for dirty checking, incremental updates, and other optimization scenarios + +- **CompiledQuery**: Pre-compiled type-safe queries (#304) + - Compile-time generated optimized query logic, reducing runtime overhead + - Full TypeScript type inference support + - Support `With`, `Without`, `Changed` and other query condition combinations + +- **PluginServiceRegistry**: Type-safe plugin service registry (#300) + - Accessible via `Core.pluginServices` + - Support `ServiceToken` pattern for service retrieval + +- **Component Auto-Registration**: `@ECSComponent` decorator enhancement (#302) + - Decorator now automatically registers to `ComponentRegistry` + - Resolved `Decorators ↔ ComponentRegistry` circular dependency + - New `ComponentTypeUtils.ts` as low-level dependency-free module + +### API Changes + +- `EntitySystem` adds `getBefore()` / `getAfter()` / `getSets()` getter methods +- `Entity` adds `markDirty()` helper method for manual change detection triggering +- `IScene` adds `epochManager` property +- `CommandBuffer.pendingCount` corrected to return actual operation count (not entity count) + +### Documentation + +- Updated system scheduling documentation with declarative dependency configuration +- Updated entity query documentation with compiled query usage + +--- + ## v2.3.2 (2025-12-08) ### Features diff --git a/packages/core/package.json b/packages/core/package.json index 6a586c91..010f960b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@esengine/ecs-framework", - "version": "2.3.2", + "version": "2.4.0", "description": "用于Laya、Cocos Creator等JavaScript游戏引擎的高性能ECS框架", "main": "dist/index.cjs", "module": "dist/index.mjs",