diff --git a/.github/workflows/unity-build.yml b/.github/workflows/unity-build.yml index e0ff576..23fc12a 100644 --- a/.github/workflows/unity-build.yml +++ b/.github/workflows/unity-build.yml @@ -38,6 +38,7 @@ jobs: unity-cli --version - name: Setup Unity shell: bash + timeout-minutes: 30 run: | unity-cli hub-install --auto-update unity-cli setup-unity --unity-version "${{ matrix.unity-version }}" --build-targets "${{ matrix.build-target }}" --json diff --git a/package-lock.json b/package-lock.json index 2517aa7..0f39c7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@rage-against-the-pixel/unity-cli", - "version": "1.3.2", + "version": "1.3.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@rage-against-the-pixel/unity-cli", - "version": "1.3.2", + "version": "1.3.3", "license": "MIT", "dependencies": { "@electron/asar": "^4.0.1", diff --git a/package.json b/package.json index 69509e1..a92d061 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rage-against-the-pixel/unity-cli", - "version": "1.3.2", + "version": "1.3.3", "description": "A command line utility for the Unity Game Engine.", "author": "RageAgainstThePixel", "license": "MIT", diff --git a/src/android-sdk.ts b/src/android-sdk.ts index 8c5c62b..4b9f48b 100644 --- a/src/android-sdk.ts +++ b/src/android-sdk.ts @@ -5,6 +5,7 @@ import { spawn } from 'child_process'; import { Logger } from './logging'; import { UnityEditor } from './unity-editor'; import { + isProcessElevated, ReadFileContents, ResolveGlobToPath } from './utilities'; @@ -124,10 +125,21 @@ async function execSdkManager(sdkManagerPath: string, javaPath: string, args: st try { exitCode = await new Promise((resolve, reject) => { - const child = spawn(sdkManagerPath, args, { + let cmd = sdkManagerPath; + let cmdArgs = args; + + if (process.platform === 'win32') { + if (!isProcessElevated()) { + throw new Error('Android SDK installation requires elevated (administrator) privileges. Please rerun as Administrator.'); + } + + cmd = 'cmd.exe'; + cmdArgs = ['/c', sdkManagerPath, ...args]; + } + + const child = spawn(cmd, cmdArgs, { stdio: ['pipe', 'pipe', 'pipe'], env: { - ...process.env, JAVA_HOME: process.platform === 'win32' ? `"${javaPath}"` : javaPath } }); @@ -147,7 +159,7 @@ async function execSdkManager(sdkManagerPath: string, javaPath: string, args: st function handleDataStream(data: Buffer) { const chunk = data.toString(); output += chunk; - process.stderr.write(chunk); + process.stdout.write(chunk); } const acceptBuffer = Buffer.from(Array(10).fill('y').join(os.EOL), 'utf8'); child.stdin.write(acceptBuffer); diff --git a/src/utilities.ts b/src/utilities.ts index f707be1..647837d 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -4,7 +4,7 @@ import * as path from 'path'; import * as https from 'https'; import * as readline from 'readline'; import { glob } from 'glob'; -import { spawn } from 'child_process'; +import { spawn, spawnSync } from 'child_process'; import { Logger, LogLevel } from './logging'; const logger = Logger.instance; @@ -572,4 +572,17 @@ export async function KillChildProcesses(procInfo: ProcInfo): Promise { } catch (error) { logger.error(`Failed to kill child processes of pid ${procInfo.pid}:\n${JSON.stringify(error)}`); } +} + +/** + * Checks if the current process is running with elevated (administrator) privileges. + * @returns True if the process is elevated, false otherwise. + */ +export function isProcessElevated(): boolean { + if (process.platform !== 'win32') { return true; } // We can sudo easily on non-windows platforms + const probe = spawnSync('powershell.exe', [ + '-NoLogo', '-NoProfile', '-Command', + "[Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent().IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)" + ], { encoding: 'utf8' }); + return probe.status === 0 && probe.stdout.trim().toLowerCase() === 'true'; } \ No newline at end of file