mirror of
				https://github.com/chickensoft-games/setup-godot.git
				synced 2025-10-31 09:03:56 +00:00 
			
		
		
		
	feat: infer godot version from global.json (if specified) (#24)
* feat: infer godot version from global.json (if specified) * fix: restore run settings
This commit is contained in:
		
							parent
							
								
									fe0bfb4b4b
								
							
						
					
					
						commit
						ca46d7ba46
					
				| @ -10,7 +10,10 @@ | ||||
|   "parserOptions": { | ||||
|     "ecmaVersion": 9, | ||||
|     "sourceType": "module", | ||||
|     "project": "./tsconfig.json" | ||||
|     "project": [ | ||||
|       "./tsconfig.json", | ||||
|       "./tsconfig.test.json" | ||||
|     ] | ||||
|   }, | ||||
|   "rules": { | ||||
|     "i18n-text/no-en": "off", | ||||
|  | ||||
							
								
								
									
										22
									
								
								.github/workflows/test_global_json.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								.github/workflows/test_global_json.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| name: 'build-test-global-json' | ||||
| on: # rebuild any PRs and main branch changes | ||||
|   pull_request: | ||||
|   push: | ||||
| 
 | ||||
| jobs: | ||||
|   tests: | ||||
|     name: 🌐 Test with version from global.json | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|         name: 🧾 Checkout | ||||
| 
 | ||||
|       - uses: ./ | ||||
|         name: 🤖 Setup Godot | ||||
|         with: | ||||
|           version: global.json # Use the version specified in global.json | ||||
|           use-dotnet: false | ||||
|        | ||||
|       - name: 🔬 Verify Godot | ||||
|         run: | | ||||
|           godot --version | ||||
							
								
								
									
										37
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								README.md
									
									
									
									
									
								
							| @ -80,7 +80,41 @@ jobs: | ||||
| 
 | ||||
| ## Inputs | ||||
| 
 | ||||
| See [action.yml][action] for information about the action's inputs. | ||||
| See [action.yml][action] for the complete guide to all of the action's inputs. | ||||
| 
 | ||||
| ### Specifying the Godot Version | ||||
| 
 | ||||
| The Godot version should be specified the same as any [GodotSharp] version string: e.g., `4.0.0-beta1`, `4.0.0-beta.16`, `4.0.0`, etc. | ||||
| 
 | ||||
| In place of a version, you can specify `global` or `global.json` to use the version of Godot specified by the project's global.json file. | ||||
| 
 | ||||
| ```yaml | ||||
|   - uses: chickensoft-games/setup-godot@v1 | ||||
|     name: 🤖 Setup Godot | ||||
|     with: | ||||
|       version: global.json # use Godot version specified by global.json | ||||
| ``` | ||||
| 
 | ||||
| For that to work, your project must have a `global.json` file in the root directory with contents similar to the following. | ||||
| 
 | ||||
| ```json | ||||
| { | ||||
|   "sdk": { | ||||
|     "version": "6.0.406", | ||||
|     "rollForward": "latestMinor" | ||||
|   }, | ||||
|   "msbuild-sdks": { | ||||
|     "Godot.NET.Sdk": "4.0.0" | ||||
|   } | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| **Important:** If using a global.json file in your project, do *not* specify the version of the Godot.NET.Sdk in your project's `.csproj` file. Note that Godot tends to add this back to your `.csproj` file every time you save the Godot project, so discard those changes before committing to source control. | ||||
| 
 | ||||
| ```xml | ||||
| <Project Sdk="Godot.NET.Sdk"> <!-- GOOD --> | ||||
| <Project Sdk="Godot.NET.Sdk/4.0.0"> <!-- BAD --> | ||||
| ``` | ||||
| 
 | ||||
| [chickensoft-badge]: https://raw.githubusercontent.com/chickensoft-games/chickensoft_site/main/static/img/badges/chickensoft_badge.svg | ||||
| [chickensoft-website]: https://chickensoft.games | ||||
| @ -89,3 +123,4 @@ See [action.yml][action] for information about the action's inputs. | ||||
| [read-the-docs-badge]: https://raw.githubusercontent.com/chickensoft-games/chickensoft_site/main/static/img/badges/read_the_docs_badge.svg | ||||
| [docs]: https://chickensoft.games/docs | ||||
| [action]: ./action.yml | ||||
| [GodotSharp]: https://www.nuget.org/packages/GodotSharp#versions-body-tab | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import {describe, expect, test} from '@jest/globals' | ||||
| import os from 'os' | ||||
| import path from 'path' | ||||
| import * as os from 'os' | ||||
| import * as path from 'path' | ||||
| 
 | ||||
| import { | ||||
|   getExportTemplatePath, | ||||
|  | ||||
							
								
								
									
										31
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								action.yml
									
									
									
									
									
								
							| @ -8,9 +8,34 @@ branding: | ||||
| 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). | ||||
|       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). Specify `global` or `global.json` to use the version from the project's global.json file. | ||||
| 
 | ||||
|       ```yaml | ||||
|       - uses: chickensoft/setup-godot-action@v1 | ||||
|         with: | ||||
|           version: global | ||||
|       ``` | ||||
| 
 | ||||
|       In the root of your project, include a global.json file: | ||||
| 
 | ||||
|       ```json | ||||
|       { | ||||
|         "sdk": { | ||||
|           "version": "6.0.406", | ||||
|           "rollForward": "latestMinor" | ||||
|         }, | ||||
|         "msbuild-sdks": { | ||||
|           "Godot.NET.Sdk": "4.0.0" | ||||
|         } | ||||
|       } | ||||
|       ``` | ||||
| 
 | ||||
|       **Important:** If using a global.json file in your project, do *not* specify the version of the Godot.NET.Sdk in your project's `*.csproj` file. | ||||
| 
 | ||||
|       ```xml | ||||
|       <Project Sdk="Godot.NET.Sdk"> <!-- GOOD --> | ||||
|       <Project Sdk="Godot.NET.Sdk/4.0.0"> <!-- BAD --> | ||||
|       ``` | ||||
|     required: true | ||||
|   path: | ||||
|     description: >- | ||||
|  | ||||
| @ -2,6 +2,7 @@ | ||||
|   "words": [ | ||||
|     "Chickensoft", | ||||
|     "godotsharp", | ||||
|     "msbuild", | ||||
|     "NOLOGO", | ||||
|     "norelease", | ||||
|     "OPTOUT", | ||||
|  | ||||
							
								
								
									
										50
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										50
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -49,22 +49,40 @@ const fs = __importStar(__nccwpck_require__(7147)); | ||||
| const os = __importStar(__nccwpck_require__(2037)); | ||||
| const path_1 = __importDefault(__nccwpck_require__(1017)); | ||||
| const utils_1 = __nccwpck_require__(918); | ||||
| function run(platform = undefined) { | ||||
| function run(platform) { | ||||
|     var _a, _b, _c; | ||||
|     return __awaiter(this, void 0, void 0, function* () { | ||||
|         platform = platform !== null && platform !== void 0 ? platform : (0, utils_1.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, ''); | ||||
|         let version = core.getInput('version').replace(/\s/g, ''); | ||||
|         const useDotnet = core.getBooleanInput('use-dotnet'); | ||||
|         const binRelativePath = core.getInput('bin-path').replace(/\s/g, ''); | ||||
|         const godotSharpRelease = core.getBooleanInput('godot-sharp-release'); | ||||
|         // Compute derived information
 | ||||
|         const checkoutDirectory = (_a = process.env['GITHUB_WORKSPACE']) !== null && _a !== void 0 ? _a : ''; | ||||
|         const userDir = os.homedir(); | ||||
|         const downloadsDir = path_1.default.join(userDir, downloadsRelativePath); | ||||
|         const installationDir = path_1.default.join(userDir, pathRelative); | ||||
|         // Log values
 | ||||
|         core.startGroup('🏝 Environment Information'); | ||||
|         core.info(`📁 Checkout directory: ${checkoutDirectory}`); | ||||
|         // See if Godot version needs to be inferred from a global.json file.
 | ||||
|         if (version.toLowerCase().includes('global')) { | ||||
|             const globalJsonPath = path_1.default.join(checkoutDirectory, 'global.json'); | ||||
|             const hasGlobalJsonFile = fs.existsSync(globalJsonPath); | ||||
|             core.info(`📢 Inferring Godot version from global.json file.`); | ||||
|             core.info(`🌐 global.json file path: ${globalJsonPath}`); | ||||
|             core.info(`🌐 global.json file exists: ${hasGlobalJsonFile}`); | ||||
|             if (!hasGlobalJsonFile) { | ||||
|                 throw new Error(`🚨 Cannot find global.json file to infer the Godot version from.`); | ||||
|             } | ||||
|             const globalJsonFileContents = fs.readFileSync('global.json', 'utf8'); | ||||
|             const globalJson = (_b = JSON.parse(globalJsonFileContents)) !== null && _b !== void 0 ? _b : {}; | ||||
|             version = (_c = globalJson['msbuild-sdks']['Godot.NET.Sdk']) !== null && _c !== void 0 ? _c : ''; | ||||
|         } | ||||
|         // Compute derived information from Godot version.
 | ||||
|         const versionName = (0, utils_1.getGodotFilenameFromVersionString)(version, platform, useDotnet); | ||||
|         const godotUrl = (0, utils_1.getGodotUrl)(version, platform, useDotnet, false); | ||||
|         const godotDownloadPath = path_1.default.join(downloadsDir, `${versionName}.zip`); | ||||
| @ -73,8 +91,6 @@ function run(platform = undefined) { | ||||
|         const exportTemplateUrl = (0, utils_1.getGodotUrl)(version, platform, useDotnet, true); | ||||
|         const exportTemplatePath = (0, utils_1.getExportTemplatePath)(version, platform, useDotnet); | ||||
|         const exportTemplateDownloadPath = path_1.default.join(downloadsDir, 'export_templates.zip'); | ||||
|         // Log values
 | ||||
|         core.startGroup('🤖 Godot Action Inputs'); | ||||
|         core.info(`🤖 Godot version: ${version}`); | ||||
|         core.info(`🤖 Godot version name: ${versionName}`); | ||||
|         core.info(`🟣 Use .NET: ${useDotnet}`); | ||||
| @ -209,7 +225,7 @@ function run(platform = undefined) { | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| run(); | ||||
| run((0, utils_1.getPlatform)(process.platform)); | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
| @ -259,11 +275,11 @@ exports.findExecutablesRecursively = exports.getPlatform = exports.getGodotFilen | ||||
| const core = __importStar(__nccwpck_require__(2186)); | ||||
| const fs = __importStar(__nccwpck_require__(7147)); | ||||
| const normalize_path_1 = __importDefault(__nccwpck_require__(5388)); | ||||
| const os_1 = __importDefault(__nccwpck_require__(2037)); | ||||
| const path_1 = __importDefault(__nccwpck_require__(1017)); | ||||
| const os = __importStar(__nccwpck_require__(2037)); | ||||
| const path = __importStar(__nccwpck_require__(1017)); | ||||
| class Linux { | ||||
|     constructor() { | ||||
|         this.GODOT_EXPORT_TEMPLATE_BASE_PATH = path_1.default.join(os_1.default.homedir(), '.local/share/godot'); | ||||
|         this.GODOT_EXPORT_TEMPLATE_BASE_PATH = path.join(os.homedir(), '.local/share/godot'); | ||||
|     } | ||||
|     godotFilenameSuffix(useDotnet) { | ||||
|         if (useDotnet) { | ||||
| @ -275,13 +291,13 @@ class Linux { | ||||
|         return basename.toLowerCase().endsWith('x86_64'); | ||||
|     } | ||||
|     getUnzippedPath(installationDir, versionName, useDotnet) { | ||||
|         return path_1.default.join(installationDir, versionName); | ||||
|         return path.join(installationDir, versionName); | ||||
|     } | ||||
| } | ||||
| exports.Linux = Linux; | ||||
| class Windows { | ||||
|     constructor() { | ||||
|         this.GODOT_EXPORT_TEMPLATE_BASE_PATH = path_1.default.normalize(path_1.default.join(os_1.default.homedir(), '\\AppData\\Roaming\\Godot')); | ||||
|         this.GODOT_EXPORT_TEMPLATE_BASE_PATH = path.normalize(path.join(os.homedir(), '\\AppData\\Roaming\\Godot')); | ||||
|     } | ||||
|     godotFilenameSuffix(useDotnet) { | ||||
|         if (useDotnet) { | ||||
| @ -293,13 +309,13 @@ class Windows { | ||||
|         return basename.toLowerCase().endsWith('_win64.exe'); | ||||
|     } | ||||
|     getUnzippedPath(installationDir, versionName, useDotnet) { | ||||
|         return path_1.default.join(installationDir, versionName); | ||||
|         return path.join(installationDir, versionName); | ||||
|     } | ||||
| } | ||||
| exports.Windows = Windows; | ||||
| class MacOS { | ||||
|     constructor() { | ||||
|         this.GODOT_EXPORT_TEMPLATE_BASE_PATH = path_1.default.join(os_1.default.homedir(), '/Library/Application Support/Godot/'); | ||||
|         this.GODOT_EXPORT_TEMPLATE_BASE_PATH = path.join(os.homedir(), '/Library/Application Support/Godot/'); | ||||
|     } | ||||
|     godotFilenameSuffix(useDotnet) { | ||||
|         return `${useDotnet ? '_mono' : ''}_macos.universal`; | ||||
| @ -308,7 +324,7 @@ class MacOS { | ||||
|         return basename.toLowerCase() === 'godot'; | ||||
|     } | ||||
|     getUnzippedPath(installationDir, versionName, useDotnet) { | ||||
|         return path_1.default.join(installationDir, `Godot${useDotnet ? '_mono' : ''}.app`); | ||||
|         return path.join(installationDir, `Godot${useDotnet ? '_mono' : ''}.app`); | ||||
|     } | ||||
| } | ||||
| exports.MacOS = MacOS; | ||||
| @ -387,7 +403,7 @@ function getExportTemplatePath(versionString, platform, useDotnet) { | ||||
|     } | ||||
|     if (useDotnet) | ||||
|         folderName += '.mono'; | ||||
|     return (0, normalize_path_1.default)(path_1.default.join(platform.GODOT_EXPORT_TEMPLATE_BASE_PATH, version.major === '4' ? 'export_templates' : 'templates', folderName)); | ||||
|     return (0, normalize_path_1.default)(path.join(platform.GODOT_EXPORT_TEMPLATE_BASE_PATH, version.major === '4' ? 'export_templates' : 'templates', folderName)); | ||||
| } | ||||
| exports.getExportTemplatePath = getExportTemplatePath; | ||||
| function getGodotFilename(version, platform, useDotnet) { | ||||
| @ -441,7 +457,7 @@ function findExecutablesRecursively(platform, dir, indent) { | ||||
|         let executables = []; | ||||
|         const files = yield fs.promises.readdir(dir, { withFileTypes: true }); | ||||
|         for (const file of files) { | ||||
|             const filePath = path_1.default.join(dir, file.name); | ||||
|             const filePath = path.join(dir, file.name); | ||||
|             if (file.isDirectory()) { | ||||
|                 const additionalExecutables = yield findExecutablesRecursively(platform, filePath, `${indent}  `); | ||||
|                 executables = executables.concat(additionalExecutables); | ||||
|  | ||||
							
								
								
									
										2
									
								
								dist/index.js.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/index.js.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										9
									
								
								global.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								global.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| { | ||||
|   "sdk": { | ||||
|     "version": "6.0.406", | ||||
|     "rollForward": "latestMinor" | ||||
|   }, | ||||
|   "msbuild-sdks": { | ||||
|     "Godot.NET.Sdk": "4.0.1" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										37
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								src/main.ts
									
									
									
									
									
								
							| @ -14,23 +14,44 @@ import { | ||||
|   Platform | ||||
| } from './utils' | ||||
| 
 | ||||
| async function run(platform: Platform | undefined = undefined): Promise<void> { | ||||
|   platform = platform ?? getPlatform(process.platform) | ||||
| 
 | ||||
| async function run(platform: Platform): Promise<void> { | ||||
|   // 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, '') | ||||
|   let version = core.getInput('version').replace(/\s/g, '') | ||||
|   const useDotnet = core.getBooleanInput('use-dotnet') | ||||
|   const binRelativePath = core.getInput('bin-path').replace(/\s/g, '') | ||||
|   const godotSharpRelease = core.getBooleanInput('godot-sharp-release') | ||||
|   const checkoutDirectory = process.env['GITHUB_WORKSPACE'] ?? '' | ||||
| 
 | ||||
|   // Compute derived information
 | ||||
|   const userDir = os.homedir() | ||||
|   const downloadsDir = path.join(userDir, downloadsRelativePath) | ||||
|   const installationDir = path.join(userDir, pathRelative) | ||||
| 
 | ||||
|   // Log values
 | ||||
|   core.startGroup('🏝 Environment Information') | ||||
|   core.info(`📁 Checkout directory: ${checkoutDirectory}`) | ||||
| 
 | ||||
|   // See if Godot version needs to be inferred from a global.json file.
 | ||||
|   if (version.toLowerCase().includes('global')) { | ||||
|     const globalJsonPath = path.join(checkoutDirectory, 'global.json') | ||||
|     const hasGlobalJsonFile = fs.existsSync(globalJsonPath) | ||||
|     core.info(`📢 Inferring Godot version from global.json file.`) | ||||
|     core.info(`🌐 global.json file path: ${globalJsonPath}`) | ||||
|     core.info(`🌐 global.json file exists: ${hasGlobalJsonFile}`) | ||||
|     if (!hasGlobalJsonFile) { | ||||
|       throw new Error( | ||||
|         `🚨 Cannot find global.json file to infer the Godot version from.` | ||||
|       ) | ||||
|     } | ||||
|     const globalJsonFileContents = fs.readFileSync('global.json', 'utf8') | ||||
|     const globalJson = JSON.parse(globalJsonFileContents) ?? {} | ||||
|     version = globalJson['msbuild-sdks']['Godot.NET.Sdk'] ?? '' | ||||
|   } | ||||
| 
 | ||||
|   // Compute derived information from Godot version.
 | ||||
|   const versionName = getGodotFilenameFromVersionString( | ||||
|     version, | ||||
|     platform, | ||||
| @ -52,8 +73,6 @@ async function run(platform: Platform | undefined = undefined): Promise<void> { | ||||
|     'export_templates.zip' | ||||
|   ) | ||||
| 
 | ||||
|   // Log values
 | ||||
|   core.startGroup('🤖 Godot Action Inputs') | ||||
|   core.info(`🤖 Godot version: ${version}`) | ||||
|   core.info(`🤖 Godot version name: ${versionName}`) | ||||
|   core.info(`🟣 Use .NET: ${useDotnet}`) | ||||
| @ -188,7 +207,7 @@ async function run(platform: Platform | undefined = undefined): Promise<void> { | ||||
|     core.endGroup() | ||||
| 
 | ||||
|     const godotExecutable = executables.find(exe => | ||||
|       platform!.isGodotExecutable(path.basename(exe)) | ||||
|       platform.isGodotExecutable(path.basename(exe)) | ||||
|     ) | ||||
|     const godotSharp = executables.find(exe => { | ||||
|       const file = exe.toLowerCase() | ||||
| @ -250,4 +269,4 @@ async function run(platform: Platform | undefined = undefined): Promise<void> { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| run() | ||||
| run(getPlatform(process.platform)) | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| import * as core from '@actions/core' | ||||
| import * as fs from 'fs' | ||||
| import normalize from 'normalize-path' | ||||
| import os from 'os' | ||||
| import path from 'path' | ||||
| import * as os from 'os' | ||||
| import * as path from 'path' | ||||
| 
 | ||||
| export interface Platform { | ||||
|   /** Godot installation filename suffix. */ | ||||
|  | ||||
| @ -1,13 +1,16 @@ | ||||
| { | ||||
|   "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'. */ | ||||
|     "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'. */ | ||||
|   }, | ||||
|   "include": [ | ||||
|     "src/**/*" | ||||
|   ], | ||||
|   "exclude": [ | ||||
|     "node_modules", | ||||
|     "**/*.test.ts" | ||||
|  | ||||
							
								
								
									
										9
									
								
								tsconfig.test.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tsconfig.test.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| { | ||||
|   "extends": "./tsconfig.json", | ||||
|   "include": [ | ||||
|     "__tests__/**/*" | ||||
|   ], | ||||
|   "exclude": [ | ||||
|     "node_modules", | ||||
|   ] | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user