mirror of
				https://github.com/chickensoft-games/setup-godot.git
				synced 2025-10-31 19:43:58 +00:00 
			
		
		
		
	feat: initial commit
This commit is contained in:
		
						commit
						e128ba100d
					
				
							
								
								
									
										4
									
								
								.eslintignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.eslintignore
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | dist/ | ||||||
|  | lib/ | ||||||
|  | node_modules/ | ||||||
|  | jest.config.js | ||||||
							
								
								
									
										85
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,85 @@ | |||||||
|  | { | ||||||
|  |   "plugins": [ | ||||||
|  |     "jest", | ||||||
|  |     "@typescript-eslint" | ||||||
|  |   ], | ||||||
|  |   "extends": [ | ||||||
|  |     "plugin:github/recommended" | ||||||
|  |   ], | ||||||
|  |   "parser": "@typescript-eslint/parser", | ||||||
|  |   "parserOptions": { | ||||||
|  |     "ecmaVersion": 9, | ||||||
|  |     "sourceType": "module", | ||||||
|  |     "project": "./tsconfig.json" | ||||||
|  |   }, | ||||||
|  |   "rules": { | ||||||
|  |     "i18n-text/no-en": "off", | ||||||
|  |     "eslint-comments/no-use": "off", | ||||||
|  |     "import/no-namespace": "off", | ||||||
|  |     "no-unused-vars": "off", | ||||||
|  |     "@typescript-eslint/no-unused-vars": [ | ||||||
|  |       "warn", | ||||||
|  |       { | ||||||
|  |         "vars": "all", | ||||||
|  |         "args": "none" | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     "@typescript-eslint/explicit-member-accessibility": [ | ||||||
|  |       "error", | ||||||
|  |       { | ||||||
|  |         "accessibility": "no-public" | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     "@typescript-eslint/no-require-imports": "error", | ||||||
|  |     "@typescript-eslint/array-type": "error", | ||||||
|  |     "@typescript-eslint/await-thenable": "error", | ||||||
|  |     "@typescript-eslint/ban-ts-comment": "error", | ||||||
|  |     "camelcase": "off", | ||||||
|  |     "@typescript-eslint/consistent-type-assertions": "error", | ||||||
|  |     "@typescript-eslint/explicit-function-return-type": [ | ||||||
|  |       "error", | ||||||
|  |       { | ||||||
|  |         "allowExpressions": true | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     "@typescript-eslint/func-call-spacing": [ | ||||||
|  |       "error", | ||||||
|  |       "never" | ||||||
|  |     ], | ||||||
|  |     "@typescript-eslint/no-array-constructor": "error", | ||||||
|  |     "@typescript-eslint/no-empty-interface": "error", | ||||||
|  |     "@typescript-eslint/no-explicit-any": "error", | ||||||
|  |     "@typescript-eslint/no-extraneous-class": "error", | ||||||
|  |     "@typescript-eslint/no-for-in-array": "error", | ||||||
|  |     "@typescript-eslint/no-inferrable-types": "error", | ||||||
|  |     "@typescript-eslint/no-misused-new": "error", | ||||||
|  |     "@typescript-eslint/no-namespace": "error", | ||||||
|  |     "@typescript-eslint/no-non-null-assertion": "off", | ||||||
|  |     "@typescript-eslint/no-unnecessary-qualifier": "error", | ||||||
|  |     "@typescript-eslint/no-unnecessary-type-assertion": "error", | ||||||
|  |     "@typescript-eslint/no-useless-constructor": "error", | ||||||
|  |     "@typescript-eslint/no-var-requires": "error", | ||||||
|  |     "@typescript-eslint/prefer-for-of": "warn", | ||||||
|  |     "@typescript-eslint/prefer-function-type": "warn", | ||||||
|  |     "@typescript-eslint/prefer-includes": "error", | ||||||
|  |     "@typescript-eslint/prefer-string-starts-ends-with": "error", | ||||||
|  |     "@typescript-eslint/promise-function-async": "error", | ||||||
|  |     "@typescript-eslint/require-array-sort-compare": "error", | ||||||
|  |     "@typescript-eslint/restrict-plus-operands": "error", | ||||||
|  |     "semi": "off", | ||||||
|  |     "@typescript-eslint/semi": [ | ||||||
|  |       "error", | ||||||
|  |       "never" | ||||||
|  |     ], | ||||||
|  |     "@typescript-eslint/type-annotation-spacing": "error", | ||||||
|  |     "@typescript-eslint/unbound-method": "error" | ||||||
|  |   }, | ||||||
|  |   "env": { | ||||||
|  |     "node": true, | ||||||
|  |     "es6": true, | ||||||
|  |     "jest/globals": true | ||||||
|  |   }, | ||||||
|  |   "globals": { | ||||||
|  |     "NodeJS": true | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | dist/** -diff linguist-generated=true  | ||||||
							
								
								
									
										11
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | version: 2 | ||||||
|  | updates: | ||||||
|  |   - package-ecosystem: github-actions | ||||||
|  |     directory: / | ||||||
|  |     schedule: | ||||||
|  |       interval: monthly | ||||||
|  | 
 | ||||||
|  |   - package-ecosystem: npm | ||||||
|  |     directory: / | ||||||
|  |     schedule: | ||||||
|  |       interval: monthly | ||||||
							
								
								
									
										53
									
								
								.github/workflows/check-dist.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								.github/workflows/check-dist.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | # `dist/index.js` is a special file in Actions. | ||||||
|  | # When you reference an action with `uses:` in a workflow, | ||||||
|  | # `index.js` is the code that will run. | ||||||
|  | # For our project, we generate this file through a build process from other source files. | ||||||
|  | # We need to make sure the checked-in `index.js` actually matches what we expect it to be. | ||||||
|  | name: Check dist/ | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches: | ||||||
|  |       - main | ||||||
|  |     paths-ignore: | ||||||
|  |       - '**.md' | ||||||
|  |   pull_request: | ||||||
|  |     paths-ignore: | ||||||
|  |       - '**.md' | ||||||
|  |   workflow_dispatch: | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   check-dist: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  | 
 | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@v3 | ||||||
|  | 
 | ||||||
|  |       - name: Set Node.js 16.x | ||||||
|  |         uses: actions/setup-node@v3.5.1 | ||||||
|  |         with: | ||||||
|  |           node-version: 16.x | ||||||
|  | 
 | ||||||
|  |       - name: Install dependencies | ||||||
|  |         run: npm ci | ||||||
|  | 
 | ||||||
|  |       - name: Rebuild the dist/ directory | ||||||
|  |         run: | | ||||||
|  |           npm run build | ||||||
|  |           npm run package | ||||||
|  | 
 | ||||||
|  |       - name: Compare the expected and actual dist/ directories | ||||||
|  |         run: | | ||||||
|  |           if [ "$(git diff --ignore-all-space --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then | ||||||
|  |             echo "Detected uncommitted changes after build.  See status below:" | ||||||
|  |             git diff | ||||||
|  |             exit 1 | ||||||
|  |           fi | ||||||
|  |         id: diff | ||||||
|  | 
 | ||||||
|  |       # If index.js was different than expected, upload the expected version as an artifact | ||||||
|  |       - uses: actions/upload-artifact@v2 | ||||||
|  |         if: ${{ failure() && steps.diff.conclusion == 'failure' }} | ||||||
|  |         with: | ||||||
|  |           name: dist | ||||||
|  |           path: dist/ | ||||||
							
								
								
									
										45
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | name: 'build-test' | ||||||
|  | on: # rebuild any PRs and main branch changes | ||||||
|  |   pull_request: | ||||||
|  |   push: | ||||||
|  |     branches: | ||||||
|  |       - main | ||||||
|  |       - 'releases/*' | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   tests: | ||||||
|  |     name: 🧪 Test on ${{ matrix.os }} | ||||||
|  |     runs-on: ${{ matrix.os }} | ||||||
|  |     strategy: | ||||||
|  |       # Don't cancel other OS runners if one fails. | ||||||
|  |       fail-fast: false | ||||||
|  |       matrix: | ||||||
|  |         # Put the operating systems you want to run on here. | ||||||
|  |         os: [ubuntu-latest, macos-latest, windows-latest] | ||||||
|  |     env: | ||||||
|  |       DOTNET_CLI_TELEMETRY_OPTOUT: true | ||||||
|  |       DOTNET_NOLOGO: true | ||||||
|  |     defaults: | ||||||
|  |       run: | ||||||
|  |         # Use bash shells on all platforms. | ||||||
|  |         shell: bash | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@v3 | ||||||
|  |         name: 🧾 Checkout | ||||||
|  | 
 | ||||||
|  |       - uses: actions/setup-dotnet@v3 | ||||||
|  |         name: 💽 Setup .NET SDK | ||||||
|  |         with: | ||||||
|  |           dotnet-version: '6.0.x' | ||||||
|  | 
 | ||||||
|  |       - uses: ./ | ||||||
|  |         name: 🤖 Setup Godot | ||||||
|  |         with: | ||||||
|  |           # Version must include major, minor, and patch, and be >= 4.0.0 | ||||||
|  |           # Pre-release label is optional. | ||||||
|  |           version: 4.0.0-beta16 | ||||||
|  | 
 | ||||||
|  |       - name: 🔬 Verify Setup | ||||||
|  |         run: | | ||||||
|  |           dotnet --version | ||||||
|  |           godot --version | ||||||
							
								
								
									
										99
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | |||||||
|  | # Dependency directory | ||||||
|  | node_modules | ||||||
|  | 
 | ||||||
|  | # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore | ||||||
|  | # Logs | ||||||
|  | logs | ||||||
|  | *.log | ||||||
|  | npm-debug.log* | ||||||
|  | yarn-debug.log* | ||||||
|  | yarn-error.log* | ||||||
|  | lerna-debug.log* | ||||||
|  | 
 | ||||||
|  | # Diagnostic reports (https://nodejs.org/api/report.html) | ||||||
|  | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | ||||||
|  | 
 | ||||||
|  | # Runtime data | ||||||
|  | pids | ||||||
|  | *.pid | ||||||
|  | *.seed | ||||||
|  | *.pid.lock | ||||||
|  | 
 | ||||||
|  | # Directory for instrumented libs generated by jscoverage/JSCover | ||||||
|  | lib-cov | ||||||
|  | 
 | ||||||
|  | # Coverage directory used by tools like istanbul | ||||||
|  | coverage | ||||||
|  | *.lcov | ||||||
|  | 
 | ||||||
|  | # nyc test coverage | ||||||
|  | .nyc_output | ||||||
|  | 
 | ||||||
|  | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | ||||||
|  | .grunt | ||||||
|  | 
 | ||||||
|  | # Bower dependency directory (https://bower.io/) | ||||||
|  | bower_components | ||||||
|  | 
 | ||||||
|  | # node-waf configuration | ||||||
|  | .lock-wscript | ||||||
|  | 
 | ||||||
|  | # Compiled binary addons (https://nodejs.org/api/addons.html) | ||||||
|  | build/Release | ||||||
|  | 
 | ||||||
|  | # Dependency directories | ||||||
|  | jspm_packages/ | ||||||
|  | 
 | ||||||
|  | # TypeScript v1 declaration files | ||||||
|  | typings/ | ||||||
|  | 
 | ||||||
|  | # TypeScript cache | ||||||
|  | *.tsbuildinfo | ||||||
|  | 
 | ||||||
|  | # Optional npm cache directory | ||||||
|  | .npm | ||||||
|  | 
 | ||||||
|  | # Optional eslint cache | ||||||
|  | .eslintcache | ||||||
|  | 
 | ||||||
|  | # Optional REPL history | ||||||
|  | .node_repl_history | ||||||
|  | 
 | ||||||
|  | # Output of 'npm pack' | ||||||
|  | *.tgz | ||||||
|  | 
 | ||||||
|  | # Yarn Integrity file | ||||||
|  | .yarn-integrity | ||||||
|  | 
 | ||||||
|  | # dotenv environment variables file | ||||||
|  | .env | ||||||
|  | .env.test | ||||||
|  | 
 | ||||||
|  | # parcel-bundler cache (https://parceljs.org/) | ||||||
|  | .cache | ||||||
|  | 
 | ||||||
|  | # next.js build output | ||||||
|  | .next | ||||||
|  | 
 | ||||||
|  | # nuxt.js build output | ||||||
|  | .nuxt | ||||||
|  | 
 | ||||||
|  | # vuepress build output | ||||||
|  | .vuepress/dist | ||||||
|  | 
 | ||||||
|  | # Serverless directories | ||||||
|  | .serverless/ | ||||||
|  | 
 | ||||||
|  | # FuseBox cache | ||||||
|  | .fusebox/ | ||||||
|  | 
 | ||||||
|  | # DynamoDB Local files | ||||||
|  | .dynamodb/ | ||||||
|  | 
 | ||||||
|  | # OS metadata | ||||||
|  | .DS_Store | ||||||
|  | Thumbs.db | ||||||
|  | 
 | ||||||
|  | # Ignore built ts files | ||||||
|  | __tests__/runner/* | ||||||
|  | lib/**/* | ||||||
							
								
								
									
										3
									
								
								.prettierignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.prettierignore
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | dist/ | ||||||
|  | lib/ | ||||||
|  | node_modules/ | ||||||
							
								
								
									
										10
									
								
								.prettierrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.prettierrc.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | { | ||||||
|  |   "printWidth": 80, | ||||||
|  |   "tabWidth": 2, | ||||||
|  |   "useTabs": false, | ||||||
|  |   "semi": false, | ||||||
|  |   "singleQuote": true, | ||||||
|  |   "trailingComma": "none", | ||||||
|  |   "bracketSpacing": false, | ||||||
|  |   "arrowParens": "avoid" | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | 
 | ||||||
|  | The MIT License (MIT) | ||||||
|  | 
 | ||||||
|  | Copyright (c) 2023 Chickensoft Games and contributors | ||||||
|  | 
 | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||||
|  | furnished to do so, subject to the following conditions: | ||||||
|  | 
 | ||||||
|  | The above copyright notice and this permission notice shall be included in | ||||||
|  | all copies or substantial portions of the Software. | ||||||
|  | 
 | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  | THE SOFTWARE. | ||||||
							
								
								
									
										70
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | |||||||
|  | # Setup Godot | ||||||
|  | 
 | ||||||
|  | Setup Godot for headless use with macOS, Windows, and Linux CI/CD runners. | ||||||
|  | 
 | ||||||
|  | - ✅ Godot 4 Only. | ||||||
|  | - ✅ Setup and run Godot on the OS you are developing for. | ||||||
|  | - ✅ Caches Godot 4 installation for speedier workflows. | ||||||
|  | - ✅ Adds environment variables (`GODOT4`, `GODOT`) to the system path. | ||||||
|  | - ✅ Installs Godot on the runner — do whatever you want with it afterwards! | ||||||
|  | 
 | ||||||
|  | > **Godot 3.x and below are not supported.** | ||||||
|  | 
 | ||||||
|  | ## Usage | ||||||
|  | 
 | ||||||
|  | Example workflow: | ||||||
|  | 
 | ||||||
|  | ```yaml | ||||||
|  | name: 🚥 Status Checks | ||||||
|  | on: push | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   tests: | ||||||
|  |     name: 👀 Evaluate on ${{ matrix.os }} | ||||||
|  |     runs-on: ${{ matrix.os }} | ||||||
|  |     strategy: | ||||||
|  |       # Don't cancel other OS runners if one fails. | ||||||
|  |       fail-fast: false | ||||||
|  |       matrix: | ||||||
|  |         # Put the operating systems you want to run on here. | ||||||
|  |         os: [ubuntu-latest, macos-latest, windows-latest] | ||||||
|  |     env: | ||||||
|  |       DOTNET_CLI_TELEMETRY_OPTOUT: true | ||||||
|  |       DOTNET_NOLOGO: true | ||||||
|  |     defaults: | ||||||
|  |       run: | ||||||
|  |         # Use bash shells on all platforms. | ||||||
|  |         shell: bash | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@v3 | ||||||
|  |         name: 🧾 Checkout | ||||||
|  | 
 | ||||||
|  |       - uses: actions/setup-dotnet@v3 | ||||||
|  |         name: 💽 Setup .NET SDK | ||||||
|  |         with: | ||||||
|  |           # Use the .NET SDK from global.json in the root of the repository. | ||||||
|  |           global-json-file: global.json | ||||||
|  | 
 | ||||||
|  |       - name: 📦 Restore Dependencies | ||||||
|  |         run: dotnet restore | ||||||
|  | 
 | ||||||
|  |       - uses: chickensoft-games/setup-godot | ||||||
|  |         name: 🤖 Setup Godot | ||||||
|  |         with: | ||||||
|  |           # Version must include major, minor, and patch, and be >= 4.0.0 | ||||||
|  |           # Pre-release label is optional. | ||||||
|  |           version: 4.0.0-beta16 | ||||||
|  | 
 | ||||||
|  |       - name: 🔬 Verify Setup | ||||||
|  |         run: | | ||||||
|  |           dotnet --version | ||||||
|  |           godot --version | ||||||
|  | 
 | ||||||
|  |       - name: 🧑🔬 Generate .NET Bindings | ||||||
|  |         run: godot --headless --build-solutions --quit || exit 0 | ||||||
|  | 
 | ||||||
|  |       - name: 🦺 Build Projects | ||||||
|  |         run: dotnet build | ||||||
|  | 
 | ||||||
|  |       # Do whatever you want! | ||||||
|  | ``` | ||||||
							
								
								
									
										75
									
								
								__tests__/main.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								__tests__/main.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | import {describe, expect, test} from '@jest/globals' | ||||||
|  | 
 | ||||||
|  | import {getGodotUrl, getPlatform, parseVersion} from '../src/utils' | ||||||
|  | 
 | ||||||
|  | describe('parseVersion', () => { | ||||||
|  |   test('parses valid godot versions', () => { | ||||||
|  |     expect(parseVersion('3.5.2')).toEqual({ | ||||||
|  |       major: '3', | ||||||
|  |       minor: '5', | ||||||
|  |       patch: '2', | ||||||
|  |       label: '' | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|  |     expect(parseVersion('4.0.0-beta1')).toEqual({ | ||||||
|  |       major: '4', | ||||||
|  |       minor: '0', | ||||||
|  |       patch: '0', | ||||||
|  |       label: 'beta1' | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|  |     expect(parseVersion('4.0.0-beta.16')).toEqual({ | ||||||
|  |       major: '4', | ||||||
|  |       minor: '0', | ||||||
|  |       patch: '0', | ||||||
|  |       label: 'beta.16' | ||||||
|  |     }) | ||||||
|  |   }) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | describe('getGodotUrl', () => { | ||||||
|  |   test('4.0.0-beta1', () => { | ||||||
|  |     expect(getGodotUrl('4.0.0-beta1', getPlatform('linux'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/beta1/mono/Godot_v4.0-beta1_mono_linux_x86_64.zip' | ||||||
|  |     ) | ||||||
|  |     expect(getGodotUrl('4.0.0-beta1', getPlatform('win32'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/beta1/mono/Godot_v4.0-beta1_mono_win64.zip' | ||||||
|  |     ) | ||||||
|  |     expect(getGodotUrl('4.0.0-beta1', getPlatform('darwin'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/beta1/mono/Godot_v4.0-beta1_mono_macos.universal.zip' | ||||||
|  |     ) | ||||||
|  |   }) | ||||||
|  |   test('4.0.0-beta.16', () => { | ||||||
|  |     expect(getGodotUrl('4.0.0-beta.16', getPlatform('linux'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/beta16/mono/Godot_v4.0-beta16_mono_linux_x86_64.zip' | ||||||
|  |     ) | ||||||
|  |     expect(getGodotUrl('4.0.0-beta.16', getPlatform('win32'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/beta16/mono/Godot_v4.0-beta16_mono_win64.zip' | ||||||
|  |     ) | ||||||
|  |     expect(getGodotUrl('4.0.0-beta.16', getPlatform('darwin'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/beta16/mono/Godot_v4.0-beta16_mono_macos.universal.zip' | ||||||
|  |     ) | ||||||
|  |   }) | ||||||
|  |   test('4.0.0-beta8', () => { | ||||||
|  |     expect(getGodotUrl('4.0.0-beta8', getPlatform('linux'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/beta8/mono/Godot_v4.0-beta8_mono_linux_x86_64.zip' | ||||||
|  |     ) | ||||||
|  |     expect(getGodotUrl('4.0.0-beta8', getPlatform('win32'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/beta8/mono/Godot_v4.0-beta8_mono_win64.zip' | ||||||
|  |     ) | ||||||
|  |     expect(getGodotUrl('4.0.0-beta8', getPlatform('darwin'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/beta8/mono/Godot_v4.0-beta8_mono_macos.universal.zip' | ||||||
|  |     ) | ||||||
|  |   }) | ||||||
|  |   test('4.0.0', () => { | ||||||
|  |     expect(getGodotUrl('4.0.0', getPlatform('linux'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/mono/Godot_v4.0_mono_linux_x86_64.zip' | ||||||
|  |     ) | ||||||
|  |     expect(getGodotUrl('4.0.0', getPlatform('win32'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/mono/Godot_v4.0_mono_win64.zip' | ||||||
|  |     ) | ||||||
|  |     expect(getGodotUrl('4.0.0', getPlatform('darwin'))).toEqual( | ||||||
|  |       'https://downloads.tuxfamily.org/godotengine/4.0/mono/Godot_v4.0_mono_macos.universal.zip' | ||||||
|  |     ) | ||||||
|  |   }) | ||||||
|  | }) | ||||||
							
								
								
									
										38
									
								
								action.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								action.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | name: 'Setup Godot Action' | ||||||
|  | description: >- | ||||||
|  |   Setup Godot for headless use with macOS, Windows, and Linux CI/CD runners. | ||||||
|  | author: 'Chickensoft' | ||||||
|  | branding: | ||||||
|  |   icon: 'hard-drive' | ||||||
|  |   color: 'white' | ||||||
|  | inputs: | ||||||
|  |   version: | ||||||
|  |     description: >- | ||||||
|  |       Godot 4 version: e.g., 4.0.0-beta1, 4.0.0-beta.16, 4.0.0, etc. Must | ||||||
|  |       include major, minor, and patch (additional pre-release label is | ||||||
|  |       optional). | ||||||
|  |     required: true | ||||||
|  |   path: | ||||||
|  |     description: >- | ||||||
|  |       Path to install Godot to, relative to the current working directory of | ||||||
|  |       the action. | ||||||
|  |     default: 'godot' | ||||||
|  |   downloads-path: | ||||||
|  |     description: >- | ||||||
|  |       Path to download Godot to, relative to the current working directory of | ||||||
|  |       the action. | ||||||
|  |     default: 'downloads' | ||||||
|  |   bin-path: | ||||||
|  |     description: >- | ||||||
|  |       Path for binaries to be installed to, relative to the current working | ||||||
|  |       directory of the action. This is the path that will be added to the | ||||||
|  |       system path. | ||||||
|  |     default: 'bin' | ||||||
|  |   godot-sharp-release: | ||||||
|  |     description: >- | ||||||
|  |       Whether to use the release or debug version of GodotSharp.dll. The | ||||||
|  |       appropriate version will be symlinked in bin-path. | ||||||
|  |     default: 'false' | ||||||
|  | runs: | ||||||
|  |   using: 'node16' | ||||||
|  |   main: 'dist/index.js' | ||||||
							
								
								
									
										7
									
								
								cspell.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								cspell.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | { | ||||||
|  |   "words": [ | ||||||
|  |     "Chickensoft", | ||||||
|  |     "NOLOGO", | ||||||
|  |     "OPTOUT" | ||||||
|  |   ] | ||||||
|  | } | ||||||
							
								
								
									
										64321
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64321
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								dist/index.js.map
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dist/index.js.map
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1164
									
								
								dist/licenses.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1164
									
								
								dist/licenses.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								dist/sourcemap-register.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dist/sourcemap-register.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										9
									
								
								jest.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								jest.config.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | module.exports = { | ||||||
|  |   clearMocks: true, | ||||||
|  |   moduleFileExtensions: ['js', 'ts'], | ||||||
|  |   testMatch: ['**/*.test.ts'], | ||||||
|  |   transform: { | ||||||
|  |     '^.+\\.ts$': 'ts-jest' | ||||||
|  |   }, | ||||||
|  |   verbose: true | ||||||
|  | } | ||||||
							
								
								
									
										11835
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										11835
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										47
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | { | ||||||
|  |   "name": "setup-godot", | ||||||
|  |   "version": "0.0.0", | ||||||
|  |   "private": true, | ||||||
|  |   "description": "Setup Godot for headless use with macOS, Windows, and Linux runners.", | ||||||
|  |   "main": "lib/main.js", | ||||||
|  |   "scripts": { | ||||||
|  |     "build": "tsc", | ||||||
|  |     "format": "prettier --write '**/*.ts'", | ||||||
|  |     "format-check": "prettier --check '**/*.ts'", | ||||||
|  |     "lint": "eslint src/**/*.ts", | ||||||
|  |     "package": "ncc build --source-map --license licenses.txt", | ||||||
|  |     "package-local": "export NODE_OPTIONS=--openssl-legacy-provider; ncc build --source-map --license licenses.txt", | ||||||
|  |     "test": "jest", | ||||||
|  |     "all": "npm run build && npm run format && npm run lint && npm run package && npm test", | ||||||
|  |     "all-local": "npm run build && npm run format && npm run lint && npm run package-local && npm test" | ||||||
|  |   }, | ||||||
|  |   "repository": { | ||||||
|  |     "type": "git", | ||||||
|  |     "url": "git+https://github.com/chickensoft-games/setup-godot.git" | ||||||
|  |   }, | ||||||
|  |   "keywords": [ | ||||||
|  |     "actions", | ||||||
|  |     "node", | ||||||
|  |     "setup" | ||||||
|  |   ], | ||||||
|  |   "author": "", | ||||||
|  |   "license": "MIT", | ||||||
|  |   "dependencies": { | ||||||
|  |     "@actions/cache": "^3.1.2", | ||||||
|  |     "@actions/core": "^1.10.0", | ||||||
|  |     "@actions/tool-cache": "^2.0.1" | ||||||
|  |   }, | ||||||
|  |   "devDependencies": { | ||||||
|  |     "@types/node": "^18.11.18", | ||||||
|  |     "@typescript-eslint/parser": "^5.49.0", | ||||||
|  |     "@vercel/ncc": "^0.36.1", | ||||||
|  |     "eslint": "^8.33.0", | ||||||
|  |     "eslint-plugin-github": "^4.6.0", | ||||||
|  |     "eslint-plugin-jest": "^27.2.1", | ||||||
|  |     "jest": "^29.4.1", | ||||||
|  |     "js-yaml": "^4.1.0", | ||||||
|  |     "prettier": "^2.8.3", | ||||||
|  |     "ts-jest": "^29.0.5", | ||||||
|  |     "typescript": "^4.9.4" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										187
									
								
								src/main.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/main.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,187 @@ | |||||||
|  | import * as cache from '@actions/cache' | ||||||
|  | import * as core from '@actions/core' | ||||||
|  | import * as toolsCache from '@actions/tool-cache' | ||||||
|  | import * as fs from 'fs' | ||||||
|  | import * as os from 'os' | ||||||
|  | import path from 'path' | ||||||
|  | 
 | ||||||
|  | import { | ||||||
|  |   findExecutablesRecursively, | ||||||
|  |   getGodotFilenameFromVersionString, | ||||||
|  |   getGodotUrl, | ||||||
|  |   getPlatform, | ||||||
|  |   Platform | ||||||
|  | } from './utils' | ||||||
|  | 
 | ||||||
|  | async function run(platform: Platform | undefined = undefined): Promise<void> { | ||||||
|  |   platform = platform ?? getPlatform(process.platform) | ||||||
|  | 
 | ||||||
|  |   // Get action inputs
 | ||||||
|  |   const pathRelative = core.getInput('path').replace(/\s/g, '') | ||||||
|  |   const downloadsRelativePath = core | ||||||
|  |     .getInput('downloads-path') | ||||||
|  |     .replace(/\s/g, '') | ||||||
|  |   const version = core.getInput('version').replace(/\s/g, '') | ||||||
|  |   const binRelativePath = core.getInput('bin-path').replace(/\s/g, '') | ||||||
|  |   const godotSharpRelease = core.getBooleanInput('godot-sharp-release') | ||||||
|  | 
 | ||||||
|  |   // Compute derived information
 | ||||||
|  |   const userDir = os.homedir() | ||||||
|  |   const downloadsDir = path.join(userDir, downloadsRelativePath) | ||||||
|  |   const installationDir = path.join(userDir, pathRelative) | ||||||
|  |   const versionName = getGodotFilenameFromVersionString(version, platform) | ||||||
|  |   const godotUrl = getGodotUrl(version, platform) | ||||||
|  |   const godotDownloadPath = path.join(downloadsDir, `${versionName}.zip`) | ||||||
|  |   const godotInstallationPath = platform.getUnzippedPath( | ||||||
|  |     installationDir, | ||||||
|  |     versionName | ||||||
|  |   ) | ||||||
|  |   const binDir = path.join(userDir, binRelativePath) | ||||||
|  | 
 | ||||||
|  |   // Log values
 | ||||||
|  |   core.startGroup('🤖 Godot Action Inputs') | ||||||
|  |   core.info(`🤖 Godot version: ${version}`) | ||||||
|  |   core.info(`🤖 Godot version name: ${versionName}`) | ||||||
|  |   core.info(`🤖 Godot download url: ${godotUrl}`) | ||||||
|  |   core.info(`🧑💼 User directory: ${userDir}`) | ||||||
|  |   core.info(`🌏 Downloads directory: ${downloadsDir}`) | ||||||
|  |   core.info(`📥 Godot download path: ${godotDownloadPath}`) | ||||||
|  |   core.info(`📦 Godot installation directory: ${installationDir}`) | ||||||
|  |   core.info(`🤖 Godot installation path: ${godotInstallationPath}`) | ||||||
|  |   core.info(`📂 Bin directory: ${binDir}`) | ||||||
|  |   core.info(`🤖 GodotSharp release: ${godotSharpRelease}`) | ||||||
|  |   core.endGroup() | ||||||
|  | 
 | ||||||
|  |   try { | ||||||
|  |     // Ensure paths we are using exist.
 | ||||||
|  |     core.startGroup(`📂 Ensuring working directories exist...`) | ||||||
|  |     fs.mkdirSync(downloadsDir, {recursive: true}) | ||||||
|  |     fs.mkdirSync(installationDir, {recursive: true}) | ||||||
|  |     fs.mkdirSync(binDir, {recursive: true}) | ||||||
|  |     core.info(`✅ Working directories exist`) | ||||||
|  |     core.endGroup() | ||||||
|  | 
 | ||||||
|  |     // See if Godot is already installed.
 | ||||||
|  |     core.startGroup(`🤔 Checking if Godot is already in cache...`) | ||||||
|  |     const cached = await cache.restoreCache([godotInstallationPath], godotUrl) | ||||||
|  | 
 | ||||||
|  |     let executables: string[] | ||||||
|  |     if (!cached) { | ||||||
|  |       // Download Godot
 | ||||||
|  |       core.info(`🙃 Previous Godot download not found in cache`) | ||||||
|  |       core.endGroup() | ||||||
|  | 
 | ||||||
|  |       core.startGroup(`📥 Downloading Godot to ${godotDownloadPath}...`) | ||||||
|  |       const godotDownloadedPath = await toolsCache.downloadTool( | ||||||
|  |         godotUrl, | ||||||
|  |         godotDownloadPath | ||||||
|  |       ) | ||||||
|  |       core.info(`✅ Godot downloaded to ${godotDownloadedPath}`) | ||||||
|  |       core.endGroup() | ||||||
|  | 
 | ||||||
|  |       // Extract Godot
 | ||||||
|  |       core.startGroup(`📦 Extracting Godot to ${installationDir}...`) | ||||||
|  |       const godotExtractedPath = await toolsCache.extractZip( | ||||||
|  |         godotDownloadedPath, | ||||||
|  |         installationDir | ||||||
|  |       ) | ||||||
|  |       core.info(`✅ Godot extracted to ${godotExtractedPath}`) | ||||||
|  |       core.endGroup() | ||||||
|  | 
 | ||||||
|  |       // Show extracted files recursively and list executables.
 | ||||||
|  |       core.startGroup(`📄 Showing extracted files recursively...`) | ||||||
|  |       executables = await findExecutablesRecursively( | ||||||
|  |         platform, | ||||||
|  |         installationDir, | ||||||
|  |         '' | ||||||
|  |       ) | ||||||
|  |       core.info(`✅ Files shown`) | ||||||
|  |       core.endGroup() | ||||||
|  | 
 | ||||||
|  |       // Save extracted Godot contents to cache
 | ||||||
|  |       core.startGroup(`💾 Saving extracted Godot download to cache...`) | ||||||
|  |       await cache.saveCache([godotInstallationPath], godotUrl) | ||||||
|  |       core.info(`✅ Godot saved to cache`) | ||||||
|  |       core.endGroup() | ||||||
|  |     } else { | ||||||
|  |       core.info(`🎉 Previous Godot download found in cache!`) | ||||||
|  |       core.endGroup() | ||||||
|  | 
 | ||||||
|  |       core.startGroup(`📄 Showing cached files recursively...`) | ||||||
|  |       executables = await findExecutablesRecursively( | ||||||
|  |         platform, | ||||||
|  |         installationDir, | ||||||
|  |         '' | ||||||
|  |       ) | ||||||
|  |       core.info(`✅ Files shown`) | ||||||
|  |       core.endGroup() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     core.startGroup(`🚀 Executables:`) | ||||||
|  |     for (const executable of executables) { | ||||||
|  |       core.info(`  🚀 ${executable}`) | ||||||
|  |     } | ||||||
|  |     core.info(`✅ Executables shown`) | ||||||
|  |     core.endGroup() | ||||||
|  | 
 | ||||||
|  |     const godotExecutable = executables.find(exe => | ||||||
|  |       platform!.isGodotExecutable(path.basename(exe)) | ||||||
|  |     ) | ||||||
|  |     const godotSharp = executables.find(exe => { | ||||||
|  |       const file = exe.toLowerCase() | ||||||
|  |       return ( | ||||||
|  |         file.endsWith('godotsharp.dll') && | ||||||
|  |         (godotSharpRelease ? file.includes('release') : file.includes('debug')) | ||||||
|  |       ) | ||||||
|  |     })! | ||||||
|  | 
 | ||||||
|  |     if (!godotExecutable) { | ||||||
|  |       throw new Error('🚨 No Godot executable found!') | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!godotSharp) { | ||||||
|  |       throw new Error('🚨 No GodotSharp.dll found!') | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     core.startGroup(`🚀 Resolve Godot Executables:`) | ||||||
|  |     core.info(`🚀 Godot executable found at ${godotExecutable}`) | ||||||
|  |     core.info(`🚀 GodotSharp.dll found at ${godotSharp}`) | ||||||
|  |     core.endGroup() | ||||||
|  | 
 | ||||||
|  |     // Add bin directory to PATH
 | ||||||
|  |     core.startGroup(`🔦 Update PATH...`) | ||||||
|  |     core.addPath(binDir) | ||||||
|  |     core.info(`🔦 Added Bin Directory to PATH: ${binDir}`) | ||||||
|  |     // Add path containing GodotSharp.dll to PATH
 | ||||||
|  |     core.endGroup() | ||||||
|  | 
 | ||||||
|  |     // Create symlink to Godot executable
 | ||||||
|  |     const godotAlias = path.join(binDir, 'godot') | ||||||
|  |     const godotSharpDirAlias = path.join(binDir, 'GodotSharp') | ||||||
|  |     core.startGroup(`🔗 Creating symlinks to executables...`) | ||||||
|  |     fs.linkSync(godotExecutable, godotAlias) | ||||||
|  |     core.info(`✅ Symlink to Godot created`) | ||||||
|  |     // Create symlink to GodotSharp directory
 | ||||||
|  |     const godotSharpDir = path.join(path.dirname(godotSharp), '../..') | ||||||
|  |     // fs.mkdirSync(godotSharpDirAlias, {recursive: true})
 | ||||||
|  |     fs.symlinkSync(godotSharpDir, godotSharpDirAlias) | ||||||
|  |     core.info(`✅ Symlink to GodotSharp created at ${godotSharpDirAlias}`) | ||||||
|  |     core.endGroup() | ||||||
|  | 
 | ||||||
|  |     // Add environment variables
 | ||||||
|  |     core.startGroup(`🔧 Adding environment variables...`) | ||||||
|  |     core.exportVariable('GODOT', godotAlias) | ||||||
|  |     core.info(`  GODOT=${godotAlias}`) | ||||||
|  |     core.exportVariable('GODOT4', godotAlias) | ||||||
|  |     core.info(`  GODOT4=${godotAlias}`) | ||||||
|  |     core.info(`✅ Environment variables added`) | ||||||
|  |     core.endGroup() | ||||||
|  | 
 | ||||||
|  |     core.info(`✅ Finished!`) | ||||||
|  |   } catch (error) { | ||||||
|  |     const message = `${error}` | ||||||
|  |     core.setFailed(message) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | run() | ||||||
							
								
								
									
										211
									
								
								src/utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								src/utils.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,211 @@ | |||||||
|  | import * as core from '@actions/core' | ||||||
|  | import * as fs from 'fs' | ||||||
|  | import path from 'path' | ||||||
|  | 
 | ||||||
|  | export interface Platform { | ||||||
|  |   /** Godot installation filename suffix. */ | ||||||
|  |   godotFilenameSuffix: string | ||||||
|  |   /** | ||||||
|  |    * Returns true if the given path is most likely the Godot executable for | ||||||
|  |    * the platform. | ||||||
|  |    * @param basename File basename to check. | ||||||
|  |    */ | ||||||
|  |   isGodotExecutable(basename: string): boolean | ||||||
|  |   /** | ||||||
|  |    * Returns the path to the unzipped file for the platform. | ||||||
|  |    * @param installationDir Installation directory. | ||||||
|  |    * @param versionName Version name. | ||||||
|  |    */ | ||||||
|  |   getUnzippedPath(installationDir: string, versionName: string): string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class Linux implements Platform { | ||||||
|  |   godotFilenameSuffix = '_mono_linux_x86_64' | ||||||
|  |   isGodotExecutable(basename: string): boolean { | ||||||
|  |     return basename.toLowerCase().endsWith('x86_64') | ||||||
|  |   } | ||||||
|  |   getUnzippedPath(installationDir: string, versionName: string): string { | ||||||
|  |     return path.join(installationDir, versionName) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class Windows implements Platform { | ||||||
|  |   godotFilenameSuffix = '_mono_win64' | ||||||
|  |   isGodotExecutable(basename: string): boolean { | ||||||
|  |     return basename.toLowerCase().endsWith('_win64.exe') | ||||||
|  |   } | ||||||
|  |   getUnzippedPath(installationDir: string, versionName: string): string { | ||||||
|  |     return path.join(installationDir, versionName) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class MacOS implements Platform { | ||||||
|  |   godotFilenameSuffix = '_mono_macos.universal' | ||||||
|  |   isGodotExecutable(basename: string): boolean { | ||||||
|  |     return basename.toLowerCase() === 'godot' | ||||||
|  |   } | ||||||
|  |   getUnzippedPath(installationDir: string, versionName: string): string { | ||||||
|  |     return path.join(installationDir, 'Godot_mono.app') | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** Semantic version representation */ | ||||||
|  | interface SemanticVersion { | ||||||
|  |   /** Version major number */ | ||||||
|  |   major: string | ||||||
|  |   /** Version minor number */ | ||||||
|  |   minor: string | ||||||
|  |   /** Version patch number */ | ||||||
|  |   patch: string | ||||||
|  |   /** Pre-release label (e.g., `beta.16`) */ | ||||||
|  |   label: string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** Godot download url prefix. */ | ||||||
|  | const GODOT_URL_PREFIX = 'https://downloads.tuxfamily.org/godotengine/' | ||||||
|  | /** Godot filename prefix. */ | ||||||
|  | const GODOT_FILENAME_PREFIX = 'Godot_v' | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Official semantic version regex. | ||||||
|  |  * See https://semver.org
 | ||||||
|  |  */ | ||||||
|  | const SEMANTIC_VERSION_REGEX = | ||||||
|  |   /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/ | ||||||
|  | 
 | ||||||
|  | export function parseVersion(version: string): SemanticVersion { | ||||||
|  |   const match = version.match(SEMANTIC_VERSION_REGEX) | ||||||
|  |   if (match === null) { | ||||||
|  |     throw new Error(`⛔️ Invalid version: ${version}`) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const major = match[1] || '' | ||||||
|  |   const minor = match[2] || '' | ||||||
|  |   const patch = match[3] || '' | ||||||
|  |   const label = match[4] || '' | ||||||
|  |   return {major, minor, patch, label} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Returns the Godot download url for the given version and platform. | ||||||
|  |  * @param versionString Version string. | ||||||
|  |  * @param platform Current platform instance. | ||||||
|  |  * @returns Godot binary download url. | ||||||
|  |  */ | ||||||
|  | export function getGodotUrl(versionString: string, platform: Platform): string { | ||||||
|  |   const version = parseVersion(versionString) | ||||||
|  |   const major = version.major | ||||||
|  |   const minor = version.minor | ||||||
|  |   const patch = version.patch | ||||||
|  |   const label = version.label.replace('.', '') | ||||||
|  | 
 | ||||||
|  |   const filename = getGodotFilename(version, platform) | ||||||
|  | 
 | ||||||
|  |   let url = `${GODOT_URL_PREFIX + major}.${minor}` | ||||||
|  |   if (patch !== '' && patch !== '0') { | ||||||
|  |     url += `.${patch}` | ||||||
|  |   } | ||||||
|  |   url += '/' | ||||||
|  |   if (label !== '') { | ||||||
|  |     url += `${label}/` | ||||||
|  |   } | ||||||
|  |   url += `mono/${filename}.zip` | ||||||
|  | 
 | ||||||
|  |   return url | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function getGodotFilename( | ||||||
|  |   version: SemanticVersion, | ||||||
|  |   platform: Platform | ||||||
|  | ): string { | ||||||
|  |   const major = version.major | ||||||
|  |   const minor = version.minor | ||||||
|  |   const patch = version.patch | ||||||
|  |   const label = version.label.replace('.', '') | ||||||
|  | 
 | ||||||
|  |   let filename = GODOT_FILENAME_PREFIX + major | ||||||
|  | 
 | ||||||
|  |   if (minor !== '') { | ||||||
|  |     filename += `.${minor}` | ||||||
|  |   } | ||||||
|  |   if (patch !== '' && patch !== '0') { | ||||||
|  |     filename += `.${patch}` | ||||||
|  |   } | ||||||
|  |   if (label !== '') { | ||||||
|  |     filename += `-${label}` | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return filename + platform.godotFilenameSuffix | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function getGodotFilenameFromVersionString( | ||||||
|  |   versionString: string, | ||||||
|  |   platform: Platform | ||||||
|  | ): string { | ||||||
|  |   return getGodotFilename(parseVersion(versionString), platform) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function getPlatform(processPlatform: NodeJS.Platform): Platform { | ||||||
|  |   switch (processPlatform) { | ||||||
|  |     case 'linux': | ||||||
|  |       core.info('🐧 Running on Linux') | ||||||
|  |       return new Linux() | ||||||
|  |     case 'win32': | ||||||
|  |       core.info('⧉ Running on Windows') | ||||||
|  |       return new Windows() | ||||||
|  |     case 'darwin': | ||||||
|  |       core.info('🍏 Running on macOS') | ||||||
|  |       return new MacOS() | ||||||
|  |     default: | ||||||
|  |       throw new Error(`⛔️ Unrecognized platform: ${process.platform}`) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export async function findExecutablesRecursively( | ||||||
|  |   platform: Platform, | ||||||
|  |   dir: string, | ||||||
|  |   indent: string | ||||||
|  | ): Promise<string[]> { | ||||||
|  |   core.info(`${indent}📁 ${dir}`) | ||||||
|  |   let executables: string[] = [] | ||||||
|  |   const files = await fs.promises.readdir(dir, {withFileTypes: true}) | ||||||
|  |   for (const file of files) { | ||||||
|  |     const filePath = path.join(dir, file.name) | ||||||
|  |     if (file.isDirectory()) { | ||||||
|  |       const additionalExecutables = await findExecutablesRecursively( | ||||||
|  |         platform, | ||||||
|  |         filePath, | ||||||
|  |         `${indent}  ` | ||||||
|  |       ) | ||||||
|  |       executables = executables.concat(additionalExecutables) | ||||||
|  |     } else { | ||||||
|  |       // Test if file is executable. GodotSharp.dll is always considered an
 | ||||||
|  |       // executable.
 | ||||||
|  |       let isExecutable = file.name === 'GodotSharp.dll' ? true : false | ||||||
|  |       if (!isExecutable) { | ||||||
|  |         if (platform instanceof Windows) { | ||||||
|  |           // fs.constants.X_OK doesn't seem to work on Windows.
 | ||||||
|  |           // Resort to checking the file extension.
 | ||||||
|  |           if (file.name.toLowerCase().endsWith('.exe')) { | ||||||
|  |             isExecutable = true | ||||||
|  |           } | ||||||
|  |         } else { | ||||||
|  |           try { | ||||||
|  |             fs.accessSync(filePath, fs.constants.X_OK) | ||||||
|  |             isExecutable = true | ||||||
|  |           } catch (error) { | ||||||
|  |             // File is not executable.
 | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (isExecutable) { | ||||||
|  |         core.info(`${indent}  🚀 ${file.name}`) | ||||||
|  |         executables.push(filePath) | ||||||
|  |       } else { | ||||||
|  |         core.info(`${indent}  📄 ${file.name}`) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return executables | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | { | ||||||
|  |   "compilerOptions": { | ||||||
|  |     "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ | ||||||
|  |     "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ | ||||||
|  |     "outDir": "./lib", /* Redirect output structure to the directory. */ | ||||||
|  |     "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ | ||||||
|  |     "strict": true, /* Enable all strict type-checking options. */ | ||||||
|  |     "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ | ||||||
|  |     "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ | ||||||
|  |   }, | ||||||
|  |   "exclude": [ | ||||||
|  |     "node_modules", | ||||||
|  |     "**/*.test.ts" | ||||||
|  |   ] | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user