Add plugin: Behavior Tree Editor Plugin for ECS Framework v1.0.2 #19
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Validate Plugin Submission | |
| on: | |
| pull_request: | |
| paths: | |
| - 'plugins/**' | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Get changed files | |
| id: changed-files | |
| uses: tj-actions/changed-files@v41 | |
| with: | |
| files: 'plugins/**/manifest.json' | |
| - name: Validate manifests | |
| if: steps.changed-files.outputs.any_changed == 'true' | |
| run: | | |
| for file in ${{ steps.changed-files.outputs.all_changed_files }}; do | |
| echo "========================================" | |
| echo "Validating: $file" | |
| echo "========================================" | |
| # 验证 JSON 格式 | |
| echo "📝 Checking JSON format..." | |
| node scripts/validate-manifest.js "$file" | |
| # 安全检查 | |
| echo "🔒 Running security check..." | |
| node scripts/check-repo-security.js "$file" | |
| echo "✅ $file passed validation" | |
| echo "" | |
| done | |
| - name: Check version immutability | |
| if: steps.changed-files.outputs.any_changed == 'true' | |
| run: | | |
| # 检查是否有版本对应的 ZIP 已存在(版本不可变) | |
| for file in ${{ steps.changed-files.outputs.all_changed_files }}; do | |
| PLUGIN_DIR=$(dirname "$file") | |
| # 读取 manifest 中的所有版本(支持新旧结构) | |
| VERSIONS=$(node -e " | |
| const fs = require('fs'); | |
| const manifest = JSON.parse(fs.readFileSync('$file')); | |
| // 新结构:使用 versions 数组 | |
| if (Array.isArray(manifest.versions)) { | |
| manifest.versions.forEach(v => console.log(v.version)); | |
| } | |
| // 旧结构:使用 version 字段 | |
| else if (manifest.version) { | |
| console.log(manifest.version); | |
| } | |
| // 兜底:使用 latestVersion | |
| else if (manifest.latestVersion) { | |
| console.log(manifest.latestVersion); | |
| } | |
| ") | |
| # 检查主分支是否已有这些版本的 ZIP | |
| git fetch origin main:main 2>/dev/null || true | |
| for VERSION in $VERSIONS; do | |
| ZIP_FILE="$PLUGIN_DIR/versions/$VERSION.zip" | |
| if git show main:"$ZIP_FILE" >/dev/null 2>&1; then | |
| echo "❌ Error: Version $VERSION already exists for $(basename $PLUGIN_DIR)" | |
| echo " Versions are immutable. Please increment the version number." | |
| exit 1 | |
| fi | |
| done | |
| done | |
| echo "✅ All versions are new and valid" | |
| - name: Check for duplicate plugin IDs | |
| run: | | |
| echo "Checking for duplicate plugin IDs..." | |
| node -e " | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const ids = new Map(); | |
| for (const category of ['official', 'community']) { | |
| const categoryDir = path.join('plugins', category); | |
| if (!fs.existsSync(categoryDir)) continue; | |
| const pluginDirs = fs.readdirSync(categoryDir).filter(item => { | |
| const itemPath = path.join(categoryDir, item); | |
| return fs.statSync(itemPath).isDirectory(); | |
| }); | |
| for (const pluginId of pluginDirs) { | |
| const manifestPath = path.join(categoryDir, pluginId, 'manifest.json'); | |
| if (!fs.existsSync(manifestPath)) continue; | |
| const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')); | |
| if (ids.has(manifest.id)) { | |
| console.error(\`❌ Duplicate plugin ID found: \${manifest.id}\`); | |
| console.error(\` First seen in: \${ids.get(manifest.id)}\`); | |
| console.error(\` Duplicate in: \${category}/\${pluginId}\`); | |
| process.exit(1); | |
| } | |
| ids.set(manifest.id, \`\${category}/\${pluginId}\`); | |
| } | |
| } | |
| console.log('✅ No duplicate IDs found'); | |
| " | |
| - name: Test registry generation | |
| run: npm run generate-registry | |
| - name: Comment PR with success | |
| if: success() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const body = [ | |
| '✅ **Automated validation passed!**', | |
| '', | |
| 'Your plugin submission has passed all automated checks:', | |
| '- ✅ JSON format is valid', | |
| '- ✅ All required fields are present', | |
| '- ✅ Repository is accessible', | |
| '- ✅ Security scan passed', | |
| '- ✅ No duplicate plugin IDs', | |
| '- ✅ Version numbers are unique', | |
| '', | |
| '**Next steps:**', | |
| '1. A maintainer will review your plugin code', | |
| '2. Address any feedback from maintainers', | |
| '3. Once approved and merged, GitHub Actions will automatically build and package your plugin', | |
| '4. Your plugin will appear in the marketplace!', | |
| '', | |
| 'Thank you for your contribution! 🎉' | |
| ].join('\n'); | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: body | |
| }) | |
| - name: Comment PR with failure | |
| if: failure() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const body = [ | |
| '❌ **Automated validation failed**', | |
| '', | |
| 'Please review the error logs above and fix the issues.', | |
| '', | |
| '**Common problems:**', | |
| '- Invalid JSON format in manifest.json', | |
| '- Missing required fields (id, name, version, repository, etc.)', | |
| '- Invalid repository URL or repository not accessible', | |
| '- Trying to overwrite an existing version (versions are immutable)', | |
| '- Duplicate plugin ID', | |
| '- Security concerns detected', | |
| '', | |
| '**Resources:**', | |
| '- [Contributing Guide](https://github.com/esengine/ecs-editor-plugins/blob/main/CONTRIBUTING.md)', | |
| '- [Plugin Template](https://github.com/esengine/ecs-editor-plugins/tree/main/PLUGIN_TEMPLATE)', | |
| '', | |
| 'Feel free to ask for help in the comments if you need assistance!' | |
| ].join('\n'); | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: body | |
| }) |