-
-
Notifications
You must be signed in to change notification settings - Fork 308
LTS 2.0.0 -- Combined Release #815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5268630
d856336
f4bc5d2
786ee37
8194790
d17b099
cfac5f1
7e9d0bf
17a0ea3
f445106
a0c79bd
8a41533
e4c156e
7f89530
cf3478c
26903e9
8d81236
49b37f7
b3e1639
3033ee0
ccbe1bc
12f2871
7db70a7
4f07508
47670cf
ff56194
1bb31f3
aa2e05d
1186717
4870fb5
007852a
5e54bcd
fe63d7b
1f3affe
f06f99b
7615bbd
cff7597
40dd436
7c0c4c2
120c3c5
4d7e871
b3bd405
9789eb5
3976b7c
e9c247f
1e2bb88
79ae558
81ba9c3
5a42214
5bdcf12
79d12aa
280a10d
b4ffa3e
bcf32b4
4724eea
a16f663
011e341
d53cd98
ae296a7
e34af96
750c10b
c7422c0
415d9e2
a864249
c5043df
1f5f6b7
90d7b26
2eb5bd3
4979a39
f2e7568
d82481b
db42c76
7b8f109
488c259
cefebca
b19ced7
222665a
e2a778d
0cb3cb3
39f885d
25dbf37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| name: Release CLI | ||
|
|
||
| on: | ||
| release: | ||
| types: [published] | ||
| workflow_dispatch: | ||
| inputs: | ||
| tag: | ||
| description: 'Release tag to build (e.g., v2.0.0). Uses latest release if empty.' | ||
| required: false | ||
| type: string | ||
| publish-npm: | ||
| description: 'Publish to npm' | ||
| required: false | ||
| default: false | ||
| type: boolean | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.event.release.tag_name || inputs.tag || github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| build-binaries: | ||
| name: Build ${{ matrix.target }} | ||
| runs-on: ${{ matrix.os }} | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| - target: linux-x64 | ||
| os: ubuntu-latest | ||
| pkg-target: node20-linux-x64 | ||
| binary-name: game-ci-linux-x64 | ||
| - target: linux-arm64 | ||
| os: ubuntu-latest | ||
| pkg-target: node20-linux-arm64 | ||
| binary-name: game-ci-linux-arm64 | ||
| - target: macos-x64 | ||
| os: macos-latest | ||
| pkg-target: node20-macos-x64 | ||
| binary-name: game-ci-macos-x64 | ||
| - target: macos-arm64 | ||
| os: macos-latest | ||
| pkg-target: node20-macos-arm64 | ||
| binary-name: game-ci-macos-arm64 | ||
| - target: windows-x64 | ||
| os: windows-latest | ||
| pkg-target: node20-win-x64 | ||
| binary-name: game-ci-windows-x64.exe | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ github.event.release.tag_name || inputs.tag || github.ref }} | ||
|
|
||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
|
|
||
| - name: Install dependencies | ||
| run: yarn install --frozen-lockfile | ||
|
|
||
| - name: Build TypeScript | ||
| run: yarn build | ||
|
|
||
| - name: Verify CLI before packaging | ||
| run: node lib/cli.js version | ||
|
|
||
| - name: Build standalone binary | ||
| run: npx pkg lib/cli.js --target ${{ matrix.pkg-target }} --output ${{ matrix.binary-name }} --compress GZip | ||
|
|
||
| - name: Verify standalone binary (non-cross-compiled) | ||
| if: | | ||
| (matrix.target == 'linux-x64' && runner.os == 'Linux') || | ||
| (matrix.target == 'macos-arm64' && runner.os == 'macOS' && runner.arch == 'ARM64') || | ||
| (matrix.target == 'macos-x64' && runner.os == 'macOS' && runner.arch == 'X64') || | ||
| (matrix.target == 'windows-x64' && runner.os == 'Windows') | ||
| run: ./${{ matrix.binary-name }} version | ||
| shell: bash | ||
|
|
||
| - uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: binary-${{ matrix.target }} | ||
| path: ${{ matrix.binary-name }} | ||
| retention-days: 5 | ||
|
|
||
| create-checksums-and-upload: | ||
| name: Checksums and release upload | ||
| needs: build-binaries | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - uses: actions/download-artifact@v4 | ||
| with: | ||
| path: binaries | ||
| pattern: binary-* | ||
| merge-multiple: true | ||
|
|
||
| - name: List binaries | ||
| run: ls -la binaries/ | ||
|
|
||
| - name: Generate SHA256 checksums | ||
| run: | | ||
| cd binaries | ||
| sha256sum game-ci-* > checksums.txt | ||
| echo "=== checksums.txt ===" | ||
| cat checksums.txt | ||
|
|
||
| - name: Determine release tag | ||
| id: tag | ||
| run: | | ||
| if [ "${{ github.event_name }}" = "release" ]; then | ||
| echo "tag=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT" | ||
| elif [ -n "${{ inputs.tag }}" ]; then | ||
| echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "No release tag available. Skipping upload." | ||
| echo "tag=" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| - name: Upload binaries to release | ||
| if: steps.tag.outputs.tag != '' | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| cd binaries | ||
| for f in game-ci-* checksums.txt; do | ||
| echo "Uploading $f..." | ||
| gh release upload "${{ steps.tag.outputs.tag }}" "$f" \ | ||
| --repo "${{ github.repository }}" \ | ||
| --clobber | ||
| done | ||
|
|
||
| publish-npm: | ||
| name: Publish to npm | ||
| needs: build-binaries | ||
| runs-on: ubuntu-latest | ||
| if: >- | ||
| (github.event_name == 'release') || (github.event_name == 'workflow_dispatch' && inputs.publish-npm) | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ github.event.release.tag_name || inputs.tag || github.ref }} | ||
|
|
||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| registry-url: 'https://registry.npmjs.org' | ||
|
|
||
| - name: Install dependencies | ||
| run: yarn install --frozen-lockfile | ||
|
|
||
| - name: Build | ||
| run: yarn build | ||
|
|
||
| - name: Run tests | ||
| run: yarn test | ||
|
|
||
| - name: Verify CLI | ||
| run: | | ||
| node lib/cli.js version | ||
| node lib/cli.js --help | ||
|
|
||
| - name: Publish to npm | ||
| run: npm publish --provenance --access public | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,203 @@ | ||
| name: Validate Community Plugins | ||
|
|
||
| on: | ||
| schedule: | ||
| # Run weekly on Sunday at 02:00 UTC | ||
| - cron: '0 2 * * 0' | ||
| workflow_dispatch: | ||
| inputs: | ||
| plugin_filter: | ||
| description: 'Filter plugins by name (regex pattern, empty = all)' | ||
| required: false | ||
| default: '' | ||
| unity_version: | ||
| description: 'Override Unity version (empty = use plugin default)' | ||
| required: false | ||
| default: '' | ||
|
|
||
| permissions: | ||
| contents: read | ||
| issues: write | ||
|
|
||
| jobs: | ||
| load-plugins: | ||
| name: Load Plugin Registry | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| matrix: ${{ steps.parse.outputs.matrix }} | ||
| plugin_count: ${{ steps.parse.outputs.count }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Parse plugin registry | ||
| id: parse | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const fs = require('fs'); | ||
| const yaml = require('js-yaml'); | ||
|
|
||
| const registry = yaml.load(fs.readFileSync('community-plugins.yml', 'utf8')); | ||
| let plugins = registry.plugins || []; | ||
|
|
||
| // Apply name filter if provided | ||
| const filter = '${{ github.event.inputs.plugin_filter }}'; | ||
| if (filter) { | ||
| const regex = new RegExp(filter, 'i'); | ||
| plugins = plugins.filter(p => regex.test(p.name)); | ||
| } | ||
|
|
||
| // Expand platform matrix | ||
| const matrix = []; | ||
| for (const plugin of plugins) { | ||
| const platforms = plugin.platforms || ['StandaloneLinux64']; | ||
| for (const platform of platforms) { | ||
| matrix.push({ | ||
| name: plugin.name, | ||
| package: plugin.package, | ||
| source: plugin.source || 'git', | ||
| unity: '${{ github.event.inputs.unity_version }}' || plugin.unity || '2021.3', | ||
| platform: platform, | ||
| timeout: plugin.timeout || 30 | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| core.setOutput('matrix', JSON.stringify({ include: matrix })); | ||
| core.setOutput('count', matrix.length); | ||
| console.log(`Found ${matrix.length} plugin-platform combinations to validate`); | ||
|
|
||
| validate: | ||
| name: '${{ matrix.name }} (${{ matrix.platform }})' | ||
| needs: load-plugins | ||
| if: needs.load-plugins.outputs.plugin_count > 0 | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: ${{ fromJson(matrix.timeout) }} | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: ${{ fromJson(needs.load-plugins.outputs.matrix) }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Create test project | ||
| run: | | ||
| mkdir -p test-project/Assets | ||
| mkdir -p test-project/Packages | ||
| mkdir -p test-project/ProjectSettings | ||
|
|
||
| # Create minimal manifest.json | ||
| if [ "${{ matrix.source }}" = "git" ]; then | ||
| cat > test-project/Packages/manifest.json << 'MANIFEST' | ||
| { | ||
| "dependencies": { | ||
| "com.unity.modules.imgui": "1.0.0", | ||
| "com.unity.modules.jsonserialize": "1.0.0" | ||
| } | ||
| } | ||
| MANIFEST | ||
|
|
||
| # Add git package via manifest | ||
| cd test-project | ||
| cat Packages/manifest.json | python3 -c " | ||
| import sys, json | ||
| manifest = json.load(sys.stdin) | ||
| manifest['dependencies']['${{ matrix.name }}'] = '${{ matrix.package }}' | ||
| json.dump(manifest, sys.stdout, indent=2) | ||
| " > Packages/manifest.tmp && mv Packages/manifest.tmp Packages/manifest.json | ||
|
Comment on lines
+104
to
+106
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -name "validate-community-plugins.yml" -o -name "community-plugins.yml" | head -20Repository: game-ci/unity-builder Length of output: 139 🏁 Script executed: cat .github/workflows/validate-community-plugins.ymlRepository: game-ci/unity-builder Length of output: 7418 🏁 Script executed: cat .github/workflows/community-plugins.ymlRepository: game-ci/unity-builder Length of output: 136 🌐 Web query:
💡 Result: In Unity UPM:
Package name format rules (for
Dependency value formats (project manifest):
Example (correct): "dependencies": {
"com.unity.timeline": "1.8.7",
"com.mycompany.mypackage": "2.3.1"
}Sources: Unity Manual on project manifest dependencies [1], Unity Manual on package manifest ( [1] (docs.unity3d.com) Citations:
🏁 Script executed: cat community-plugins.yml | head -100Repository: game-ci/unity-builder Length of output: 1096 🏁 Script executed: wc -l community-plugins.ymlRepository: game-ci/unity-builder Length of output: 89 Use package identifiers for dependency keys, not plugin display names. Line 104 writes dependencies as To fix, add a 🔧 Suggested fixIn - name: UniTask
+ packageName: com.cysharp.unitask
package: https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTaskIn the matrix construction step, include Then update line 104: - manifest['dependencies']['${{ matrix.name }}'] = '${{ matrix.package }}'
+ manifest['dependencies']['${{ matrix.packageName }}'] = '${{ matrix.package }}'🤖 Prompt for AI Agents |
||
| cd .. | ||
| fi | ||
|
|
||
| # Create minimal ProjectSettings | ||
| cat > test-project/ProjectSettings/ProjectVersion.txt << EOF | ||
| m_EditorVersion: ${{ matrix.unity }} | ||
| EOF | ||
|
|
||
| - name: Build with unity-builder | ||
| uses: ./ | ||
| id: build | ||
| with: | ||
| projectPath: test-project | ||
| targetPlatform: ${{ matrix.platform }} | ||
| unityVersion: ${{ matrix.unity }} | ||
| continue-on-error: true | ||
|
|
||
| - name: Record result | ||
| if: always() | ||
| run: | | ||
| STATUS="${{ steps.build.outcome }}" | ||
| echo "## ${{ matrix.name }} — ${{ matrix.platform }}" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| if [ "$STATUS" = "success" ]; then | ||
| echo "✅ **PASSED** — Compiled and built successfully" >> $GITHUB_STEP_SUMMARY | ||
| else | ||
| echo "❌ **FAILED** — Build or compilation failed" >> $GITHUB_STEP_SUMMARY | ||
| fi | ||
|
Comment on lines
+122
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's check the workflow file exists and view the relevant section
find . -name "validate-community-plugins.yml" -type fRepository: game-ci/unity-builder Length of output: 115 🌐 Web query:
💡 Result:
How to fail the workflow/job based on a “continue-on-error” failure (common pattern):
Sources
🏁 Script executed: # Let's read the workflow file to verify the code and check for a report job
cat -n ./.github/workflows/validate-community-plugins.yml | sed -n '110,150p'Repository: game-ci/unity-builder Length of output: 1839 🏁 Script executed: # Also search for any report job or downstream jobs
grep -n "job\|report\|Report" ./.github/workflows/validate-community-plugins.ymlRepository: game-ci/unity-builder Length of output: 486 🏁 Script executed: # Check if there are more steps in the validate job after line 139
cat -n ./.github/workflows/validate-community-plugins.yml | sed -n '139,145p'Repository: game-ci/unity-builder Length of output: 310 🏁 Script executed: # Also get the full validate job structure to see all steps
sed -n '22,141p' ./.github/workflows/validate-community-plugins.yml | tail -50Repository: game-ci/unity-builder Length of output: 1959 🏁 Script executed: # Let's see the full report job implementation to understand how it reads job conclusions
sed -n '141,180p' ./.github/workflows/validate-community-plugins.ymlRepository: game-ci/unity-builder Length of output: 1812 Failed builds are masked in the validation report due to With Preserve summary + fail job when build fails - name: Build with unity-builder
uses: ./
id: build
with:
projectPath: test-project
targetPlatform: ${{ matrix.platform }}
unityVersion: ${{ matrix.unity }}
continue-on-error: true
- name: Record result
if: always()
run: |
STATUS="${{ steps.build.outcome }}"
echo "## ${{ matrix.name }} — ${{ matrix.platform }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$STATUS" = "success" ]; then
echo "✅ **PASSED** — Compiled and built successfully" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **FAILED** — Build or compilation failed" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "- Unity: ${{ matrix.unity }}" >> $GITHUB_STEP_SUMMARY
echo "- Platform: ${{ matrix.platform }}" >> $GITHUB_STEP_SUMMARY
echo "- Source: ${{ matrix.source }}" >> $GITHUB_STEP_SUMMARY
echo "- Package: \`${{ matrix.package }}\`" >> $GITHUB_STEP_SUMMARY
+
+ - name: Fail validation job when build failed
+ if: steps.build.outcome != 'success'
+ run: exit 1🧰 Tools🪛 actionlint (1.7.11)[error] 126-126: shellcheck reported issue in this script: SC2086:info:10:40: Double quote to prevent globbing and word splitting (shellcheck) [error] 126-126: shellcheck reported issue in this script: SC2086:info:11:46: Double quote to prevent globbing and word splitting (shellcheck) [error] 126-126: shellcheck reported issue in this script: SC2086:info:12:42: Double quote to prevent globbing and word splitting (shellcheck) [error] 126-126: shellcheck reported issue in this script: SC2086:info:13:48: Double quote to prevent globbing and word splitting (shellcheck) [error] 126-126: shellcheck reported issue in this script: SC2086:info:2:58: Double quote to prevent globbing and word splitting (shellcheck) [error] 126-126: shellcheck reported issue in this script: SC2086:info:3:12: Double quote to prevent globbing and word splitting (shellcheck) [error] 126-126: shellcheck reported issue in this script: SC2086:info:5:60: Double quote to prevent globbing and word splitting (shellcheck) [error] 126-126: shellcheck reported issue in this script: SC2086:info:7:56: Double quote to prevent globbing and word splitting (shellcheck) [error] 126-126: shellcheck reported issue in this script: SC2086:info:9:12: Double quote to prevent globbing and word splitting (shellcheck) [error] 126-126: shellcheck reported issue in this script: SC2129:style:9:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects (shellcheck) 🤖 Prompt for AI Agents |
||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "- Unity: ${{ matrix.unity }}" >> $GITHUB_STEP_SUMMARY | ||
| echo "- Platform: ${{ matrix.platform }}" >> $GITHUB_STEP_SUMMARY | ||
| echo "- Source: ${{ matrix.source }}" >> $GITHUB_STEP_SUMMARY | ||
| echo "- Package: \`${{ matrix.package }}\`" >> $GITHUB_STEP_SUMMARY | ||
|
|
||
| report: | ||
| name: Validation Report | ||
| needs: [load-plugins, validate] | ||
| if: always() | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Generate summary | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const { data: run } = await github.rest.actions.listJobsForWorkflowRun({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| run_id: context.runId | ||
| }); | ||
|
|
||
| const validateJobs = run.jobs.filter(j => j.name.startsWith('validate')); | ||
| const passed = validateJobs.filter(j => j.conclusion === 'success').length; | ||
| const failed = validateJobs.filter(j => j.conclusion === 'failure').length; | ||
| const total = validateJobs.length; | ||
|
|
||
| let summary = `# Community Plugin Validation Report\n\n`; | ||
| summary += `**${passed}/${total} passed** | ${failed} failed\n\n`; | ||
| summary += `| Plugin | Platform | Status |\n|--------|----------|--------|\n`; | ||
|
|
||
| for (const job of validateJobs) { | ||
| const icon = job.conclusion === 'success' ? '✅' : '❌'; | ||
| summary += `| ${job.name} | | ${icon} ${job.conclusion} |\n`; | ||
| } | ||
|
|
||
| await core.summary.addRaw(summary).write(); | ||
|
|
||
| // Create or update issue if there are failures | ||
| if (failed > 0) { | ||
| const title = `Community Plugin Validation: ${failed} failure(s) — ${new Date().toISOString().split('T')[0]}`; | ||
| const body = summary + `\n\n[Workflow Run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`; | ||
|
|
||
| const { data: issues } = await github.rest.issues.listForRepo({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| state: 'open', | ||
| labels: 'community-plugin-validation' | ||
| }); | ||
|
|
||
| if (issues.length > 0) { | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: issues[0].number, | ||
| body: body | ||
| }); | ||
| } else { | ||
| await github.rest.issues.create({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| title: title, | ||
| body: body, | ||
| labels: ['community-plugin-validation'] | ||
| }); | ||
| } | ||
| } | ||
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Copilot Autofix
AI about 1 month ago
In general, the fix is to explicitly declare a
permissionsblock restricting theGITHUB_TOKENto the least privileges needed. For this specific workflow, thebuild-binariesjob only needs to read the repository contents (foractions/checkout) and upload artifacts; upload-artifact uses workflow-scoped storage and does not require additional repository write permissions. Therefore, we can safely addpermissions: contents: readto that job. The other jobs (create-checksums-and-uploadandpublish-npm) already have explicit permissions and don’t need changes.Concretely, in
.github/workflows/release-cli.yml, underjobs: build-binaries:, add apermissions:section (aligned withruns-on) withcontents: read. No imports or additional methods are needed, as this is YAML configuration for GitHub Actions only. This change keeps existing behavior but ensures theGITHUB_TOKENforbuild-binariescannot be used to modify repository contents or other resources.