Check if sdkManager is actually available

GitHub Actions have Android-SDK preinstalled, but there's no sdkmanager.
Missing sdkmanager means no additional packages can be easily installed by dowsntream users.
This commit is contained in:
Vilius Sutkus '89 2021-01-26 01:16:38 +02:00 committed by Dave Olsthoorn
parent e3e9dc9b68
commit 87280a34d4

View file

@ -5,6 +5,7 @@ import * as path from 'path'
import * as fs from 'fs' import * as fs from 'fs'
import * as os from 'os' import * as os from 'os'
const CMDLINE_TOOLS_VERSION = '3.0'
const COMMANDLINE_TOOLS_VERSION = '6858069' const COMMANDLINE_TOOLS_VERSION = '6858069'
const COMMANDLINE_TOOLS_WIN_URL = `https://dl.google.com/android/repository/commandlinetools-win-${COMMANDLINE_TOOLS_VERSION}_latest.zip` const COMMANDLINE_TOOLS_WIN_URL = `https://dl.google.com/android/repository/commandlinetools-win-${COMMANDLINE_TOOLS_VERSION}_latest.zip`
@ -14,69 +15,140 @@ const COMMANDLINE_TOOLS_LIN_URL = `https://dl.google.com/android/repository/comm
const HOME = os.homedir() const HOME = os.homedir()
const ANDROID_HOME_DIR = path.join(HOME, '.android') const ANDROID_HOME_DIR = path.join(HOME, '.android')
const ANDROID_HOME_SDK_DIR = path.join(ANDROID_HOME_DIR, 'sdk') const ANDROID_HOME_SDK_DIR = path.join(ANDROID_HOME_DIR, 'sdk')
const ANDROID_REPOSITORIES_CFG = path.join(ANDROID_HOME_DIR, 'repositories.cfg') const ANDROID_SDK_ROOT = process.env['ANDROID_SDK_ROOT'] || ANDROID_HOME_SDK_DIR
const ANDROID_REPOSITORIES_CFG = path.join(ANDROID_SDK_ROOT, 'repositories.cfg')
async function install(): Promise<string> { function getSdkManagerPath(cmdToolsVersion: string): string {
const ANDROID_SDK_ROOT = const toolsBinDir = path.join(
process.env['ANDROID_SDK_ROOT'] || ANDROID_HOME_SDK_DIR ANDROID_SDK_ROOT,
const licenseDir = path.join(ANDROID_SDK_ROOT, 'licenses') 'cmdline-tools',
cmdToolsVersion,
// If the licences exist, the rest does too 'bin'
if (fs.existsSync(licenseDir)) { )
core.debug(`Skipping install, licenseDir found: ${licenseDir}`) if ('win32' === process.platform) {
return ANDROID_SDK_ROOT return path.join(toolsBinDir, 'sdkmanager.bat')
}
return path.join(toolsBinDir, 'sdkmanager')
} }
// create ~/.android/repositories.cfg function findPreinstalledSdkManager(): {
fs.mkdirSync(ANDROID_HOME_SDK_DIR, {recursive: true}) isFound: boolean
isCorrectVersion: boolean
exePath: string
} {
const result = {isFound: false, isCorrectVersion: false, exePath: ''}
// First try to find the version defined in CMDLINE_TOOLS_VERSION
result.exePath = getSdkManagerPath(CMDLINE_TOOLS_VERSION)
result.isFound = fs.existsSync(result.exePath)
if (result.isFound) {
result.isCorrectVersion = true
return result
}
// cmdline-tools could have a 'latest' version, but if it was installed 2 years ago
// it may not be 'latest' as of today
result.exePath = getSdkManagerPath('latest')
result.isFound = fs.existsSync(result.exePath)
if (result.isFound) {
return result
}
result.exePath = ''
// Find whatever version is available in ANDROID_SDK_ROOT
const cmdlineToolsDir = path.join(ANDROID_SDK_ROOT, 'cmdline-tools')
const foundVersions: string[] = fs.existsSync(cmdlineToolsDir)
? fs.readdirSync(cmdlineToolsDir)
: []
const foundVersionsFiltered: string[] = foundVersions.filter(
obj => '.' !== obj && '..' !== obj
)
// Sort by desc, to get 2.0 first, before 1.0
const foundVersionsSorted: string[] = foundVersionsFiltered.sort(
(a: string, b: string) => (a > b ? -1 : 1)
)
for (const version of foundVersionsSorted) {
result.exePath = getSdkManagerPath(version)
result.isFound = fs.existsSync(result.exePath)
if (result.isFound) {
return result
}
}
result.exePath = ''
return result
}
async function callSdkManager(sdkManager: string, arg: string): Promise<void> {
const acceptBuffer = Buffer.from(Array(10).fill('y').join('\n'), 'utf8')
await exec.exec(sdkManager, [arg], {
input: acceptBuffer
})
}
async function installSdkManager(): Promise<string> {
fs.mkdirSync(ANDROID_SDK_ROOT, {recursive: true})
// touch ~/.android/repositories.cfg
fs.closeSync(fs.openSync(ANDROID_REPOSITORIES_CFG, 'w')) fs.closeSync(fs.openSync(ANDROID_REPOSITORIES_CFG, 'w'))
const acceptBuffer = Buffer.from(Array(10).fill('y').join('\n'), 'utf8') const sdkManager = findPreinstalledSdkManager()
let sdkManager = '' if (!sdkManager.isFound) {
let cmdlineToolsURL
if (process.platform === 'linux') { if (process.platform === 'linux') {
const cmdlineToolsZip = await tc.downloadTool(COMMANDLINE_TOOLS_LIN_URL) cmdlineToolsURL = COMMANDLINE_TOOLS_LIN_URL
const cmdlineTools = await tc.extractZip(cmdlineToolsZip)
sdkManager = path.join(cmdlineTools, 'cmdline-tools', 'bin', 'sdkmanager')
} else if (process.platform === 'darwin') { } else if (process.platform === 'darwin') {
const cmdlineToolsZip = await tc.downloadTool(COMMANDLINE_TOOLS_MAC_URL) cmdlineToolsURL = COMMANDLINE_TOOLS_MAC_URL
const cmdlineTools = await tc.extractZip(cmdlineToolsZip)
sdkManager = path.join(cmdlineTools, 'cmdline-tools', 'bin', 'sdkmanager')
} else if (process.platform === 'win32') { } else if (process.platform === 'win32') {
const cmdlineToolsZip = await tc.downloadTool(COMMANDLINE_TOOLS_WIN_URL) cmdlineToolsURL = COMMANDLINE_TOOLS_WIN_URL
const cmdlineTools = await tc.extractZip(cmdlineToolsZip)
sdkManager = path.join(
cmdlineTools,
'cmdline-tools',
'bin',
'sdkmanager.bat'
)
} else { } else {
core.error(`Unsupported platform: ${process.platform}`) core.error(`Unsupported platform: ${process.platform}`)
return ''
}
const cmdlineToolsZip = await tc.downloadTool(cmdlineToolsURL)
const cmdlineToolsExtractedLocation = await tc.extractZip(cmdlineToolsZip)
// Move cmdline-tools to where it would be if it was installed through sdkmanager
// Will allow calling sdkmanager without --sdk_root='..' argument
const desiredLocation = path.join(
ANDROID_SDK_ROOT,
'cmdline-tools',
CMDLINE_TOOLS_VERSION
)
fs.mkdirSync(path.dirname(desiredLocation))
fs.renameSync(
path.join(cmdlineToolsExtractedLocation, 'cmdline-tools'),
desiredLocation
)
sdkManager.exePath = getSdkManagerPath(CMDLINE_TOOLS_VERSION)
sdkManager.isCorrectVersion = true
} }
await exec.exec( if (!sdkManager.isCorrectVersion) {
sdkManager, await callSdkManager(
['--licenses', `--sdk_root=${ANDROID_SDK_ROOT}`], sdkManager.exePath,
{input: acceptBuffer} `cmdline-tools;${CMDLINE_TOOLS_VERSION}`
) )
sdkManager.exePath = getSdkManagerPath(CMDLINE_TOOLS_VERSION)
await exec.exec( }
sdkManager, return sdkManager.exePath
['--include_obsolete', `--sdk_root=${ANDROID_SDK_ROOT}`, 'tools'],
{input: acceptBuffer}
)
return ANDROID_SDK_ROOT
} }
async function run(): Promise<void> { async function run(): Promise<void> {
const ANDROID_SDK_ROOT = await install() const sdkManager = await installSdkManager()
core.debug(`sdkmanager installed to: ${sdkManager}`)
await callSdkManager(sdkManager, '--licenses')
await callSdkManager(sdkManager, 'tools')
await callSdkManager(sdkManager, 'platform-tools')
core.setOutput('ANDROID_COMMANDLINE_TOOLS_VERSION', COMMANDLINE_TOOLS_VERSION) core.setOutput('ANDROID_COMMANDLINE_TOOLS_VERSION', COMMANDLINE_TOOLS_VERSION)
core.exportVariable('ANDROID_HOME', ANDROID_SDK_ROOT) core.exportVariable('ANDROID_HOME', ANDROID_SDK_ROOT)
core.exportVariable('ANDROID_SDK_ROOT', ANDROID_SDK_ROOT) core.exportVariable('ANDROID_SDK_ROOT', ANDROID_SDK_ROOT)
core.addPath(path.join(ANDROID_SDK_ROOT, 'cmdline-tools', 'bin')) core.addPath(path.dirname(sdkManager))
core.addPath(path.join(ANDROID_SDK_ROOT, 'platform-tools')) core.addPath(path.join(ANDROID_SDK_ROOT, 'platform-tools'))
core.debug('add matchers') core.debug('add matchers')