feat(cli): add CLI tool for adding ECS framework to existing projects (#339)
* feat(cli): add CLI tool for adding ECS framework to existing projects - Support Cocos Creator 2.x/3.x, LayaAir 3.x, and Node.js platforms - Auto-detect project type based on directory structure - Generate ECSManager with full configuration (debug, remote debug, WebSocket URL) - Auto-install dependencies with npm/yarn/pnpm detection - Platform-specific decorators and lifecycle methods * chore: add changeset for @esengine/cli * fix(ci): fix YAML syntax error in ai-issue-helper workflow * fix(cli): resolve file system race conditions (CodeQL) * chore(ci): remove unused and broken workflows * fix(ci): fix YAML encoding in release.yml
This commit is contained in:
73
.github/workflows/ai-batch-analyze-issues.yml
vendored
73
.github/workflows/ai-batch-analyze-issues.yml
vendored
@@ -1,73 +0,0 @@
|
||||
name: AI Batch Analyze Issues
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
mode:
|
||||
description: '分析模式'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- 'recent' # 最近 10 个 issue
|
||||
- 'open' # 所有打开的 issue
|
||||
- 'all' # 所有 issue(慎用)
|
||||
default: 'recent'
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
- name: Install GitHub CLI
|
||||
run: |
|
||||
gh --version || (curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
|
||||
sudo apt update
|
||||
sudo apt install gh)
|
||||
|
||||
- name: Batch Analyze Issues
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
MODE="${{ github.event.inputs.mode }}"
|
||||
|
||||
# 获取 issue 列表
|
||||
if [ "$MODE" = "recent" ]; then
|
||||
echo "📊 分析最近 10 个 issue..."
|
||||
ISSUES=$(gh issue list --limit 10 --json number --jq '.[].number')
|
||||
elif [ "$MODE" = "open" ]; then
|
||||
echo "📊 分析所有打开的 issue..."
|
||||
ISSUES=$(gh issue list --state open --json number --jq '.[].number')
|
||||
else
|
||||
echo "📊 分析所有 issue(这可能需要很长时间)..."
|
||||
ISSUES=$(gh issue list --state all --limit 100 --json number --jq '.[].number')
|
||||
fi
|
||||
|
||||
# 为每个 issue 添加 AI 分析评论
|
||||
for issue_num in $ISSUES; do
|
||||
echo "🤖 分析 Issue #$issue_num..."
|
||||
|
||||
# 获取 issue 内容
|
||||
ISSUE_BODY=$(gh issue view $issue_num --json body --jq '.body')
|
||||
ISSUE_TITLE=$(gh issue view $issue_num --json title --jq '.title')
|
||||
|
||||
# 添加触发评论
|
||||
gh issue comment $issue_num --body "@ai-helper 请帮我分析这个 issue" || true
|
||||
|
||||
# 避免 API 限制
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "✅ 批量分析完成!"
|
||||
echo "查看结果:https://github.com/${{ github.repository }}/issues"
|
||||
61
.github/workflows/ai-helper-tip.yml
vendored
61
.github/workflows/ai-helper-tip.yml
vendored
@@ -1,61 +0,0 @@
|
||||
name: AI Helper Tip
|
||||
|
||||
# 对所有新创建的 issue 自动回复 AI 助手使用说明(新老用户都适用)
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
tip:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Post AI Helper Usage Tip
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const message = [
|
||||
"## 🤖 AI 助手可用 | AI Helper Available",
|
||||
"",
|
||||
"**中文说明:**",
|
||||
"",
|
||||
"本项目配备了 AI 智能助手,可以帮助你快速获得解答!",
|
||||
"",
|
||||
"**使用方法:** 在评论中提及 `@ai-helper`,AI 会自动搜索项目代码并提供解决方案。",
|
||||
"",
|
||||
"**示例:**",
|
||||
"```",
|
||||
"@ai-helper 如何创建一个新的 System?",
|
||||
"@ai-helper 这个报错是什么原因?",
|
||||
"```",
|
||||
"",
|
||||
"---",
|
||||
"",
|
||||
"**English:**",
|
||||
"",
|
||||
"This project has an AI assistant to help you get answers quickly!",
|
||||
"",
|
||||
"**How to use:** Mention `@ai-helper` in a comment, and AI will automatically search the codebase and provide solutions.",
|
||||
"",
|
||||
"**Examples:**",
|
||||
"```",
|
||||
"@ai-helper How do I create a new System?",
|
||||
"@ai-helper What causes this error?",
|
||||
"```",
|
||||
"",
|
||||
"---",
|
||||
"",
|
||||
"💡 *AI 助手基于代码库提供建议,复杂问题建议等待维护者回复*",
|
||||
"💡 *AI suggestions are based on the codebase. For complex issues, please wait for maintainer responses*"
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: message
|
||||
});
|
||||
|
||||
console.log('✅ AI helper tip posted successfully');
|
||||
80
.github/workflows/ai-issue-helper.yml
vendored
80
.github/workflows/ai-issue-helper.yml
vendored
@@ -1,80 +0,0 @@
|
||||
name: AI Issue Helper
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
models: read
|
||||
|
||||
jobs:
|
||||
ai-helper:
|
||||
runs-on: ubuntu-latest
|
||||
# å<>ªåœ¨çœŸå®žç”¨æˆ·æ<C2B7><C3A6>到 @ai-helper 时触å<C2A6>‘,忽略机器人评è®? if: |
|
||||
contains(github.event.comment.body, '@ai-helper') &&
|
||||
github.event.comment.user.type != 'Bot'
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get Issue Details
|
||||
id: issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number
|
||||
});
|
||||
|
||||
// é™<C3A9>制长度,é<C592>¿å…<C3A5>è¶…è¿?token é™<C3A9>制
|
||||
const maxLength = 1000;
|
||||
const truncate = (str, max) => {
|
||||
if (!str) return '';
|
||||
return str.length > max ? str.substring(0, max) + '...[内容过长已截æ–]' : str;
|
||||
};
|
||||
|
||||
core.exportVariable('ISSUE_TITLE', truncate(issue.data.title || '', 200));
|
||||
core.exportVariable('ISSUE_BODY', truncate(issue.data.body || '', maxLength));
|
||||
core.exportVariable('COMMENT_BODY', truncate(context.payload.comment.body || '', 500));
|
||||
core.exportVariable('ISSUE_NUMBER', context.issue.number);
|
||||
|
||||
- name: Create Prompt
|
||||
id: prompt
|
||||
run: |
|
||||
cat > prompt.txt << 'PROMPT_EOF'
|
||||
Issue #${{ env.ISSUE_NUMBER }}
|
||||
|
||||
æ ‡é¢˜: ${{ env.ISSUE_TITLE }}
|
||||
|
||||
内容: ${{ env.ISSUE_BODY }}
|
||||
|
||||
评论: ${{ env.COMMENT_BODY }}
|
||||
|
||||
请æ<C2B7>œç´¢é¡¹ç›®ä»£ç <C3A7>å¹¶æ<C2B6><C3A6>供解决方案ã€? PROMPT_EOF
|
||||
|
||||
- name: AI Analysis
|
||||
uses: actions/ai-inference@v1
|
||||
id: ai
|
||||
with:
|
||||
model: 'gpt-4o'
|
||||
enable-github-mcp: true
|
||||
max-tokens: 1500
|
||||
system-prompt: |
|
||||
ä½ æ˜¯ ECS Framework (TypeScript ECS 框架) çš?AI 助手ã€? 主è¦<C3A8>代ç <C3A7>åœ?packages/framework/core/srcã€? æ<>œç´¢ç›¸å…³ä»£ç <C3A7>å<EFBFBD>Žï¼Œç”¨ä¸æ–‡ç®€æ´<C3A6>回ç”问题,包å<E280A6>«é—®é¢˜åˆ†æž<C3A6>ã€<C3A3>解决方案和代ç <C3A7>引用ã€? prompt-file: prompt.txt
|
||||
|
||||
- name: Post AI Response
|
||||
env:
|
||||
AI_RESPONSE: ${{ steps.ai.outputs.response }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: process.env.AI_RESPONSE
|
||||
});
|
||||
56
.github/workflows/ai-issue-moderator.yml
vendored
56
.github/workflows/ai-issue-moderator.yml
vendored
@@ -1,56 +0,0 @@
|
||||
name: AI Issue Moderator
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
models: read
|
||||
|
||||
jobs:
|
||||
moderate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Content
|
||||
uses: actions/ai-inference@v1
|
||||
id: check
|
||||
with:
|
||||
model: 'gpt-4o-mini'
|
||||
system-prompt: |
|
||||
你是一个内容审查助手。
|
||||
检查内容是否包含:
|
||||
1. 垃圾信息或广告
|
||||
2. 恶意或攻击性内容
|
||||
3. 与项目完全无关的内容
|
||||
|
||||
只返回 "SPAM" 或 "OK",不要其他内容。
|
||||
prompt: |
|
||||
标题:${{ github.event.issue.title || github.event.comment.body }}
|
||||
|
||||
内容:
|
||||
${{ github.event.issue.body || github.event.comment.body }}
|
||||
|
||||
- name: Mark as Spam
|
||||
if: contains(steps.check.outputs.response, 'SPAM')
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// 添加 spam 标签
|
||||
github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: ['spam']
|
||||
});
|
||||
|
||||
// 添加评论
|
||||
github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: '🤖 这个内容被 AI 检测为可能的垃圾内容。如果这是误判,请联系维护者。\n\n🤖 This content was detected as potential spam by AI. If this is a false positive, please contact the maintainers.'
|
||||
});
|
||||
160
.github/workflows/batch-label-issues.yml
vendored
160
.github/workflows/batch-label-issues.yml
vendored
@@ -1,160 +0,0 @@
|
||||
name: Batch Label Issues
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
mode:
|
||||
description: 'æ ‡ç¾æ¨¡å¼<C3A5>'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- 'recent' # 最�20 �issue
|
||||
- 'open' # 所有打开�issue
|
||||
- 'unlabeled' # å<>ªå¤„ç<E2809E>†æ²¡æœ‰æ ‡ç¾çš„ issue
|
||||
- 'all' # 所�issue(慎用)
|
||||
default: 'recent'
|
||||
|
||||
skip_labeled:
|
||||
description: 'è·³è¿‡å·²æœ‰æ ‡ç¾çš?issue'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
batch-label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
- name: Batch Label Issues
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
MODE="${{ github.event.inputs.mode }}"
|
||||
SKIP_LABELED="${{ github.event.inputs.skip_labeled }}"
|
||||
|
||||
echo "📊 开始批é‡<C3A9>æ‰“æ ‡ç¾..."
|
||||
echo "模å¼<C3A5>: $MODE"
|
||||
echo "è·³è¿‡å·²æ ‡ç? $SKIP_LABELED"
|
||||
|
||||
# 获å<C2B7>– issue 列表
|
||||
if [ "$MODE" = "recent" ]; then
|
||||
echo "📋 获å<C2B7>–最è¿?20 ä¸?issue..."
|
||||
ISSUES=$(gh issue list --limit 20 --json number,labels,title,body --jq '.[] | {number, labels: [.labels[].name], title, body}')
|
||||
elif [ "$MODE" = "open" ]; then
|
||||
echo "📋 获å<C2B7>–所有打开çš?issue..."
|
||||
ISSUES=$(gh issue list --state open --json number,labels,title,body --jq '.[] | {number, labels: [.labels[].name], title, body}')
|
||||
elif [ "$MODE" = "unlabeled" ]; then
|
||||
echo "📋 获å<C2B7>–æ²¡æœ‰æ ‡ç¾çš?issue..."
|
||||
ISSUES=$(gh issue list --state all --json number,labels,title,body --jq '.[] | select(.labels | length == 0) | {number, labels: [.labels[].name], title, body}')
|
||||
else
|
||||
echo "📋 获å<C2B7>–所æœ?issue(é™<C3A9>åˆ?100 个)..."
|
||||
ISSUES=$(gh issue list --state all --limit 100 --json number,labels,title,body --jq '.[] | {number, labels: [.labels[].name], title, body}')
|
||||
fi
|
||||
|
||||
# 临时文件
|
||||
echo "$ISSUES" > /tmp/issues.json
|
||||
|
||||
# 处ç<E2809E>†æ¯<C3A6>个 issue
|
||||
cat /tmp/issues.json | jq -c '.' | while read -r issue; do
|
||||
ISSUE_NUM=$(echo "$issue" | jq -r '.number')
|
||||
EXISTING_LABELS=$(echo "$issue" | jq -r '.labels | join(",")')
|
||||
TITLE=$(echo "$issue" | jq -r '.title')
|
||||
BODY=$(echo "$issue" | jq -r '.body')
|
||||
|
||||
echo ""
|
||||
echo "ðŸ”<C5B8> 处ç<E2809E>† Issue #$ISSUE_NUM: $TITLE"
|
||||
echo " çŽ°æœ‰æ ‡ç¾: $EXISTING_LABELS"
|
||||
|
||||
# è·³è¿‡å·²æœ‰æ ‡ç¾çš?issue
|
||||
if [ "$SKIP_LABELED" = "true" ] && [ ! -z "$EXISTING_LABELS" ]; then
|
||||
echo " â<>ï¸<C3AF> è·³è¿‡ï¼ˆå·²æœ‰æ ‡ç¾ï¼‰"
|
||||
continue
|
||||
fi
|
||||
|
||||
# 分æž<C3A6>å†…å®¹å¹¶æ‰“æ ‡ç¾
|
||||
LABELS_TO_ADD=""
|
||||
|
||||
# 检�bug
|
||||
if echo "$TITLE $BODY" | grep -iE "(bug|错误|崩溃|crash|error|exception|问题|fix)" > /dev/null; then
|
||||
LABELS_TO_ADD="$LABELS_TO_ADD bug"
|
||||
echo " ðŸ<C3B0>› 检测到: bug"
|
||||
fi
|
||||
|
||||
# 检�feature request
|
||||
if echo "$TITLE $BODY" | grep -iE "(feature|功能|enhancement|improve|优化|建议|新增|æ·»åŠ |add)" > /dev/null; then
|
||||
LABELS_TO_ADD="$LABELS_TO_ADD enhancement"
|
||||
echo " �检测到: enhancement"
|
||||
fi
|
||||
|
||||
# 检�question
|
||||
if echo "$TITLE $BODY" | grep -iE "(question|疑问|how to|如何|怎么|为什么|why|咨询|\?|�" > /dev/null; then
|
||||
LABELS_TO_ADD="$LABELS_TO_ADD question"
|
||||
echo " â<>?检测到: question"
|
||||
fi
|
||||
|
||||
# 检�documentation
|
||||
if echo "$TITLE $BODY" | grep -iE "(doc|文档|readme|guide|tutorial|教程|说明)" > /dev/null; then
|
||||
LABELS_TO_ADD="$LABELS_TO_ADD documentation"
|
||||
echo " 📖 检测到: documentation"
|
||||
fi
|
||||
|
||||
# 检�performance
|
||||
if echo "$TITLE $BODY" | grep -iE "(performance|性能|slow|æ…¢|lag|å<>¡é¡¿|optimize|优化)" > /dev/null; then
|
||||
LABELS_TO_ADD="$LABELS_TO_ADD performance"
|
||||
echo " �检测到: performance"
|
||||
fi
|
||||
|
||||
# 检�core
|
||||
if echo "$TITLE $BODY" | grep -iE "(@esengine/ecs-framework|packages/framework/core|core package|æ ¸å¿ƒåŒ?" > /dev/null; then
|
||||
LABELS_TO_ADD="$LABELS_TO_ADD core"
|
||||
echo " 🎯 检测到: core"
|
||||
fi
|
||||
|
||||
# 检�editor
|
||||
if echo "$TITLE $BODY" | grep -iE "(editor|编辑器|tauri)" > /dev/null; then
|
||||
LABELS_TO_ADD="$LABELS_TO_ADD editor"
|
||||
echo " 🎨 检测到: editor"
|
||||
fi
|
||||
|
||||
# 检�network
|
||||
if echo "$TITLE $BODY" | grep -iE "(network|网络|multiplayer|多人|å<>Œæ¥)" > /dev/null; then
|
||||
LABELS_TO_ADD="$LABELS_TO_ADD network"
|
||||
echo " ðŸŒ<C5B8> 检测到: network"
|
||||
fi
|
||||
|
||||
# 检�help wanted
|
||||
if echo "$TITLE $BODY" | grep -iE "(help wanted|需è¦<C3A8>帮助|求助)" > /dev/null; then
|
||||
LABELS_TO_ADD="$LABELS_TO_ADD help wanted"
|
||||
echo " 🆘 检测到: help wanted"
|
||||
fi
|
||||
|
||||
# æ·»åŠ æ ‡ç¾
|
||||
if [ ! -z "$LABELS_TO_ADD" ]; then
|
||||
echo " âœ?æ·»åŠ æ ‡ç¾: $LABELS_TO_ADD"
|
||||
for label in $LABELS_TO_ADD; do
|
||||
gh issue edit $ISSUE_NUM --add-label "$label" 2>&1 | grep -v "already exists" || true
|
||||
done
|
||||
echo " 💬 æ·»åŠ è¯´æ˜Žè¯„è®º..."
|
||||
gh issue comment $ISSUE_NUM --body $'🤖 è‡ªåŠ¨æ ‡ç¾ç³»ç»Ÿæ£€æµ‹åˆ°æ?issue å¹¶æ·»åŠ äº†ç›¸å…³æ ‡ç¾ã€‚如有误判,请告知维护者。\n\n🤖 Auto-labeling system detected and labeled this issue. Please let maintainers know if this is incorrect.' || true
|
||||
else
|
||||
echo " ℹï¸<C3AF> 未检测到明确类型"
|
||||
fi
|
||||
|
||||
# é<>¿å…<C3A5> API é™<C3A9>制
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "âœ?批é‡<C3A9>æ ‡ç¾å®Œæˆ<C3A6>ï¼?
|
||||
echo "查看结果: https://github.com/${{ github.repository }}/issues"
|
||||
146
.github/workflows/cleanup-dependabot.yml
vendored
146
.github/workflows/cleanup-dependabot.yml
vendored
@@ -1,146 +0,0 @@
|
||||
name: Cleanup Old Dependabot PRs
|
||||
|
||||
# 手动触发的 workflow,用于清理堆积的 Dependabot PR
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
days_old:
|
||||
description: '关闭多少天前创建的 PR(默认 7 天)'
|
||||
required: false
|
||||
default: '7'
|
||||
dry_run:
|
||||
description: '试运行模式(true=仅显示,不关闭)'
|
||||
required: false
|
||||
default: 'true'
|
||||
type: choice
|
||||
options:
|
||||
- 'true'
|
||||
- 'false'
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: List and Close Old Dependabot PRs
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const daysOld = parseInt('${{ github.event.inputs.days_old }}') || 7;
|
||||
const dryRun = '${{ github.event.inputs.dry_run }}' === 'true';
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setDate(cutoffDate.getDate() - daysOld);
|
||||
|
||||
console.log(`🔍 查找超过 ${daysOld} 天的 Dependabot PR...`);
|
||||
console.log(`📅 截止日期: ${cutoffDate.toISOString()}`);
|
||||
console.log(`🏃 模式: ${dryRun ? '试运行(不会实际关闭)' : '实际执行'}`);
|
||||
console.log('---');
|
||||
|
||||
// 获取所有 Dependabot PR
|
||||
const { data: pulls } = await github.rest.pulls.list({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
const dependabotPRs = pulls.filter(pr =>
|
||||
pr.user.login === 'dependabot[bot]' &&
|
||||
new Date(pr.created_at) < cutoffDate
|
||||
);
|
||||
|
||||
console.log(`📊 找到 ${dependabotPRs.length} 个符合条件的 Dependabot PR`);
|
||||
console.log('');
|
||||
|
||||
if (dependabotPRs.length === 0) {
|
||||
console.log('✅ 没有需要清理的 PR');
|
||||
return;
|
||||
}
|
||||
|
||||
// 按类型分组
|
||||
const byType = {
|
||||
dev: [],
|
||||
prod: [],
|
||||
actions: [],
|
||||
other: []
|
||||
};
|
||||
|
||||
for (const pr of dependabotPRs) {
|
||||
const title = pr.title.toLowerCase();
|
||||
const labels = pr.labels.map(l => l.name);
|
||||
|
||||
let type = 'other';
|
||||
if (title.includes('dev-dependencies') || title.includes('development')) {
|
||||
type = 'dev';
|
||||
} else if (title.includes('production-dependencies')) {
|
||||
type = 'prod';
|
||||
} else if (labels.includes('github-actions')) {
|
||||
type = 'actions';
|
||||
}
|
||||
|
||||
byType[type].push(pr);
|
||||
}
|
||||
|
||||
console.log('📋 PR 分类统计:');
|
||||
console.log(` 🔧 开发依赖: ${byType.dev.length} 个`);
|
||||
console.log(` 📦 生产依赖: ${byType.prod.length} 个`);
|
||||
console.log(` ⚙️ GitHub Actions: ${byType.actions.length} 个`);
|
||||
console.log(` ❓ 其他: ${byType.other.length} 个`);
|
||||
console.log('');
|
||||
|
||||
// 处理每个 PR
|
||||
for (const pr of dependabotPRs) {
|
||||
const age = Math.floor((Date.now() - new Date(pr.created_at)) / (1000 * 60 * 60 * 24));
|
||||
|
||||
console.log(`${dryRun ? '🔍' : '🗑️ '} #${pr.number}: ${pr.title}`);
|
||||
console.log(` 创建时间: ${pr.created_at} (${age} 天前)`);
|
||||
console.log(` 链接: ${pr.html_url}`);
|
||||
|
||||
if (!dryRun) {
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
state: 'closed'
|
||||
});
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: `🤖 **自动关闭旧的 Dependabot PR**
|
||||
|
||||
此 PR 已超过 ${daysOld} 天未合并,已被自动关闭以清理积压。
|
||||
|
||||
📌 **下一步:**
|
||||
- Dependabot 已配置为月度运行,届时会创建新的分组更新
|
||||
- 新的 Mergify 规则会智能处理不同类型的依赖更新
|
||||
- 开发依赖和 GitHub Actions 会自动合并(即使 CI 失败)
|
||||
- 生产依赖需要 CI 通过才会自动合并
|
||||
|
||||
如果需要立即应用此更新,请手动更新依赖。
|
||||
|
||||
---
|
||||
*此操作由仓库维护者手动触发的清理工作流执行*`
|
||||
});
|
||||
|
||||
console.log(' ✅ 已关闭并添加说明');
|
||||
} else {
|
||||
console.log(' ℹ️ 试运行模式 - 未执行操作');
|
||||
}
|
||||
console.log('');
|
||||
}
|
||||
|
||||
console.log('---');
|
||||
if (dryRun) {
|
||||
console.log(`✨ 试运行完成!共发现 ${dependabotPRs.length} 个待清理的 PR`);
|
||||
console.log('💡 要实际执行清理,请将 dry_run 参数设为 false 重新运行');
|
||||
} else {
|
||||
console.log(`✅ 清理完成!已关闭 ${dependabotPRs.length} 个 Dependabot PR`);
|
||||
}
|
||||
23
.github/workflows/issue-labeler.yml
vendored
23
.github/workflows/issue-labeler.yml
vendored
@@ -1,23 +0,0 @@
|
||||
name: Issue Labeler
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Label Issues
|
||||
uses: github/issue-labeler@v3.4
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
configuration-path: .github/labeler.yml
|
||||
enable-versioned-regex: 1
|
||||
28
.github/workflows/issue-translator.yml
vendored
28
.github/workflows/issue-translator.yml
vendored
@@ -1,28 +0,0 @@
|
||||
name: Issue Translator
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
translate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Translate Issues
|
||||
uses: tomsun28/issues-translate-action@v2.7
|
||||
with:
|
||||
IS_MODIFY_TITLE: false
|
||||
# 设置为 true 会修改标题,false 只在评论中添加翻译
|
||||
CUSTOM_BOT_NOTE: |
|
||||
<details>
|
||||
<summary>🌏 Translation / 翻译</summary>
|
||||
|
||||
Bot detected the issue body's language is not English, translate it automatically.
|
||||
机器人检测到 issue 内容非英文,自动翻译。
|
||||
|
||||
</details>
|
||||
41
.github/workflows/release.yml
vendored
41
.github/workflows/release.yml
vendored
@@ -1,7 +1,6 @@
|
||||
name: Release NPM Packages
|
||||
|
||||
on:
|
||||
# æ ‡ç¾è§¦å<C2A6>‘:支æŒ?v* å’?{package}-v* æ ¼å¼<C3A5>
|
||||
# Tag trigger: supports v* and {package}-v* formats
|
||||
push:
|
||||
tags:
|
||||
@@ -15,12 +14,11 @@ on:
|
||||
- 'physics-rapier2d-v*'
|
||||
- 'worker-generator-v*'
|
||||
|
||||
# ä¿<EFBFBD>留手动触å<EFBFBD>‘选项
|
||||
# Keep manual trigger option
|
||||
# Manual trigger option
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
package:
|
||||
description: '选择è¦<EFBFBD>å<EFBFBD>‘布的åŒ?| Select package to publish'
|
||||
description: 'Select package to publish'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
@@ -33,7 +31,7 @@ on:
|
||||
- physics-rapier2d
|
||||
- worker-generator
|
||||
version_type:
|
||||
description: '版本更新类型 | Version bump type'
|
||||
description: 'Version bump type'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
@@ -61,11 +59,10 @@ jobs:
|
||||
id: parse
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "push" ]; then
|
||||
# ä»Žæ ‡ç¾è§£æž<C3A6>包å<E280A6><C3A5>和版本 | Parse package and version from tag
|
||||
# Parse package and version from tag
|
||||
TAG="${GITHUB_REF#refs/tags/}"
|
||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||
|
||||
# è§£æž<C3A6>æ ¼å¼<C3A5>: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"
|
||||
@@ -82,10 +79,9 @@ jobs:
|
||||
echo "package=$PACKAGE" >> $GITHUB_OUTPUT
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "mode=tag" >> $GITHUB_OUTPUT
|
||||
echo "📦 Package: $PACKAGE"
|
||||
echo "📌 Version: $VERSION"
|
||||
echo "Package: $PACKAGE"
|
||||
echo "Version: $VERSION"
|
||||
else
|
||||
# 手动触å<C2A6>‘:从 package.json 读å<C2BB>–å¹?bump 版本
|
||||
# Manual trigger: read from package.json and bump version
|
||||
PACKAGE="${{ github.event.inputs.package }}"
|
||||
echo "package=$PACKAGE" >> $GITHUB_OUTPUT
|
||||
@@ -112,7 +108,6 @@ jobs:
|
||||
PACKAGE="${{ steps.parse.outputs.package }}"
|
||||
EXPECTED_VERSION="${{ steps.parse.outputs.version }}"
|
||||
|
||||
# 获å<C2B7>– package.json ä¸çš„版本
|
||||
# Get version from package.json
|
||||
ACTUAL_VERSION=$(node -p "require('./packages/$PACKAGE/package.json').version")
|
||||
|
||||
@@ -125,7 +120,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "�Version verified: $EXPECTED_VERSION"
|
||||
echo "Version verified: $EXPECTED_VERSION"
|
||||
|
||||
- name: Bump version (manual mode)
|
||||
if: steps.parse.outputs.mode == 'manual'
|
||||
@@ -147,7 +142,7 @@ jobs:
|
||||
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"
|
||||
echo "Bumped version: $CURRENT -> $NEW_VERSION"
|
||||
|
||||
- name: Set final version
|
||||
id: version
|
||||
@@ -188,19 +183,18 @@ jobs:
|
||||
with:
|
||||
tag_name: ${{ steps.parse.outputs.tag }}
|
||||
name: "${{ steps.parse.outputs.package }} v${{ steps.version.outputs.value }}"
|
||||
# ä¸<C3A4>设置为 latest,latest ä¿<C3A4>ç•™ç»™ç¼–è¾‘å™¨çƒæ›´æ–°ä½¿ç”? # Don't mark as latest, reserve latest for editor auto-update
|
||||
make_latest: false
|
||||
body: |
|
||||
## 🚀 @esengine/${{ steps.parse.outputs.package }} v${{ steps.version.outputs.value }}
|
||||
## @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 }})
|
||||
**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 }}
|
||||
```
|
||||
|
||||
---
|
||||
*自动å<EFBFBD>‘布 | Auto-released by GitHub Actions*
|
||||
*Auto-released by GitHub Actions*
|
||||
generate_release_notes: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -215,15 +209,16 @@ jobs:
|
||||
delete-branch: true
|
||||
title: "chore(${{ steps.parse.outputs.package }}): Release v${{ steps.version.outputs.value }}"
|
||||
body: |
|
||||
## 🚀 Release v${{ steps.version.outputs.value }}
|
||||
## Release v${{ steps.version.outputs.value }}
|
||||
|
||||
æ?PR æ›´æ–° `@esengine/${{ steps.parse.outputs.package }}` 包的版本å<EFBFBD>?
|
||||
### å<>˜æ›´
|
||||
- âœ?å·²å<C2B2>‘布到 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 }}`
|
||||
This PR updates `@esengine/${{ steps.parse.outputs.package }}` package version.
|
||||
|
||||
### Changes
|
||||
- Published to 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 }})
|
||||
- Updated `packages/${{ steps.parse.outputs.package }}/package.json` to `${{ steps.version.outputs.value }}`
|
||||
|
||||
---
|
||||
*æ?PR ç”±å<C2B1>‘布工作æµ<C3A6>自动创建*
|
||||
*This PR was automatically created by the release workflow*
|
||||
labels: |
|
||||
release
|
||||
${{ steps.parse.outputs.package }}
|
||||
|
||||
46
.github/workflows/size-limit.yml
vendored
46
.github/workflows/size-limit.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: Size Limit
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
paths:
|
||||
- 'packages/framework/core/src/**'
|
||||
- 'packages/framework/core/package.json'
|
||||
- '.size-limit.json'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
size:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build core package
|
||||
run: |
|
||||
cd packages/framework/core
|
||||
pnpm run build:npm
|
||||
|
||||
- name: Check bundle size
|
||||
uses: andresz1/size-limit-action@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
skip_step: install
|
||||
58
.github/workflows/welcome.yml
vendored
58
.github/workflows/welcome.yml
vendored
@@ -1,58 +0,0 @@
|
||||
name: Welcome
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
welcome:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Welcome new contributors
|
||||
uses: actions/first-interaction@v1.3.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-message: |
|
||||
👋 你好!感谢你提交第一个 issue!
|
||||
|
||||
我们会尽快查看并回复。同时,建议你:
|
||||
- 📚 查看[文档](https://esengine.github.io/ecs-framework/)
|
||||
- 🤖 使用 [AI 文档助手](https://deepwiki.com/esengine/esengine)
|
||||
- 💬 加入 [QQ 交流群](https://jq.qq.com/?_wv=1027&k=29w1Nud6)
|
||||
|
||||
---
|
||||
|
||||
👋 Hello! Thanks for opening your first issue!
|
||||
|
||||
We'll review it as soon as possible. Meanwhile, you might want to:
|
||||
- 📚 Check the [documentation](https://esengine.github.io/ecs-framework/)
|
||||
- 🤖 Use [AI documentation assistant](https://deepwiki.com/esengine/esengine)
|
||||
|
||||
pr-message: |
|
||||
👋 你好!感谢你提交第一个 Pull Request!
|
||||
|
||||
在我们 Review 之前,请确保:
|
||||
- ✅ 代码遵循项目规范
|
||||
- ✅ 通过所有测试
|
||||
- ✅ 更新了相关文档
|
||||
- ✅ Commit 遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范
|
||||
|
||||
查看完整的[贡献指南](https://github.com/esengine/esengine/blob/master/CONTRIBUTING.md)。
|
||||
|
||||
---
|
||||
|
||||
👋 Hello! Thanks for your first Pull Request!
|
||||
|
||||
Before we review, please ensure:
|
||||
- ✅ Code follows project conventions
|
||||
- ✅ All tests pass
|
||||
- ✅ Documentation is updated
|
||||
- ✅ Commits follow [Conventional Commits](https://www.conventionalcommits.org/)
|
||||
|
||||
See the full [Contributing Guide](https://github.com/esengine/esengine/blob/master/CONTRIBUTING.md).
|
||||
Reference in New Issue
Block a user