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 { 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 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 userDir = os.homedir() const downloadsDir = path.join(userDir, downloadsRelativePath) const installationDir = path.join(userDir, pathRelative) const versionName = getGodotFilenameFromVersionString( version, platform, useDotnet ) const godotUrl = getGodotUrl(version, platform, useDotnet) const godotDownloadPath = path.join(downloadsDir, `${versionName}.zip`) const godotInstallationPath = platform.getUnzippedPath( installationDir, versionName, useDotnet ) 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(`🟣 Use .NET: ${useDotnet}`) 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 && useDotnet) { throw new Error('🚨 No GodotSharp.dll found!') } core.startGroup(`🚀 Resolve Godot Executables:`) core.info(`🚀 Godot executable found at ${godotExecutable}`) if (useDotnet) { 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') core.startGroup(`🔗 Creating symlinks to executables...`) fs.linkSync(godotExecutable, godotAlias) core.info(`✅ Symlink to Godot created`) const godotSharpDirAlias = path.join(binDir, 'GodotSharp') if (useDotnet) { // Create symlink to GodotSharp directory const godotSharpDir = path.join(path.dirname(godotSharp), '../..') 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()