Changeup: consilidate code, drop cache, change download

This changes up way too much:
- Moving most (all) of the code to main.ts instead of the numerous
  files
- Dropping the caching functionality, since it should be optional
- now we will only download the android sdk tools if they are not
  already present, including if ANDROID_SDK_ROOT is already set
This commit is contained in:
Dave Olsthoorn 2020-08-26 17:51:32 +02:00
parent 57977119c1
commit 24b7e80ade
11 changed files with 71 additions and 370 deletions

View file

@ -4,9 +4,7 @@ description: 'Setup the Android SDK Tools and add them to the path'
runs: runs:
using: 'node12' using: 'node12'
main: 'dist/main/index.js' main: 'dist/index.js'
post: 'dist/post/index.js'
post-if: success()
branding: branding:
icon: 'list' icon: 'list'

1
dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/main/index.js vendored

File diff suppressed because one or more lines are too long

1
dist/post/index.js vendored

File diff suppressed because one or more lines are too long

39
package-lock.json generated
View file

@ -2170,14 +2170,6 @@
"integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==",
"dev": true "dev": true
}, },
"axios": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
"requires": {
"follow-redirects": "1.5.10"
}
},
"babel-jest": { "babel-jest": {
"version": "24.9.0", "version": "24.9.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz",
@ -3720,29 +3712,6 @@
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true "dev": true
}, },
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"requires": {
"debug": "=3.1.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"for-in": { "for-in": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@ -8544,14 +8513,6 @@
"async-limiter": "~1.0.0" "async-limiter": "~1.0.0"
} }
}, },
"xml-js": {
"version": "1.6.11",
"resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
"integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
"requires": {
"sax": "^1.2.4"
}
},
"xml-name-validator": { "xml-name-validator": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",

View file

@ -5,10 +5,10 @@
"description": "setup android action", "description": "setup android action",
"main": "lib/main.js", "main": "lib/main.js",
"scripts": { "scripts": {
"build": "ncc build src/main.ts --out dist/main --minify && ncc build src/post.ts --out dist/post --minify", "build": "ncc build src/main.ts --out dist/ --minify",
"format": "prettier --write **/*.ts", "format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts", "format-check": "prettier --check **/*.ts",
"lint": "eslint src/**/*.ts", "lint": "eslint src/*.ts",
"test": "jest", "test": "jest",
"all": "npm run format && npm run lint && npm run build && npm test" "all": "npm run format && npm run lint && npm run build && npm test"
}, },
@ -27,9 +27,7 @@
"dependencies": { "dependencies": {
"@actions/cache": "^1.0.2", "@actions/cache": "^1.0.2",
"@actions/core": "^1.2.0", "@actions/core": "^1.2.0",
"@actions/tool-cache": "^1.6.0", "@actions/tool-cache": "^1.6.0"
"axios": "^0.19.2",
"xml-js": "^1.6.11"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^26.0.10", "@types/jest": "^26.0.10",

View file

@ -1,189 +0,0 @@
import * as glob from '@actions/glob'
import * as cache from '@actions/cache'
import * as core from '@actions/core'
import * as crypto from 'crypto'
import * as fs from 'fs'
import {platform} from 'os'
import {
GRADLE_WRAPPER_GLOB,
GRADLE_CACHE_GLOB,
GRADLE_WRAPPER_DIR,
GRADLE_CACHE_DIR,
GRADLE_WRAPPER_KEY,
GRADLE_CACHE_KEY,
ANDROID_GLOB,
ANDROID_KEY,
COMMANDLINE_TOOLS_VERSION,
ANDROID_SDK_ROOT,
ANDROID_REPOSITORIES_CACHE,
ANDROID_REPOSITORIES_CFG,
VERSION
} from './constants'
async function hashFiles(globs: string[]): Promise<string | undefined> {
const globber = await glob.create(globs.join('\n'), {
followSymbolicLinks: false
})
const hashes: Buffer[] = []
for await (const file of globber.globGenerator()) {
// skip directories
if (fs.statSync(file).isDirectory()) continue
core.debug(`hashFiles: found ${file}`)
const hash = crypto.createHash('sha256')
fs.createReadStream(file).pipe(hash)
hashes.push(hash.digest())
}
// No files hashed
if (hashes.length === 0) {
core.debug('hashFiles: no hashes in array')
return
}
// Loop trough files
const completeHash = crypto.createHash('sha256')
for (const hash of hashes) {
completeHash.update(hash)
}
completeHash.end()
return completeHash.digest('hex')
}
export async function preGradleWrapper(): Promise<void> {
const wrapperHash = await hashFiles(GRADLE_WRAPPER_GLOB)
const wrapperKey = `gradle-wrapper-${platform}-${wrapperHash}`
const wrapperRestoreKeys = [`gradle-wrapper-${platform}-`, `gradle-wrapper-`]
// if no wrapper is present skip trying to retrieve it
if (!wrapperHash) {
core.info('A hash for the gradle wrapper could not be generated')
return
}
const wrapperCache = await cache.restoreCache(
[GRADLE_WRAPPER_DIR],
wrapperKey,
wrapperRestoreKeys
)
if (!wrapperCache) {
core.info(
'Gradle wrapper cache not found, expect a download from gradle wrapper.'
)
}
if (wrapperCache !== wrapperKey) {
core.saveState(GRADLE_WRAPPER_KEY, wrapperKey)
}
return
}
export async function postGradleWrapper(): Promise<void> {
const wrapperKey = core.getState(GRADLE_WRAPPER_KEY)
if (wrapperKey === '') {
core.info(
'A key for gradle wrapper was not defined, and thus there will not be a cache'
)
return
}
await cache.saveCache([GRADLE_WRAPPER_DIR], wrapperKey)
return
}
export async function preGradleCache(): Promise<void> {
const cacheHash = await hashFiles(GRADLE_CACHE_GLOB)
const cacheKey = `gradle-cache-${platform}-${cacheHash}`
const cacheRestoreKeys = [`gradle-cache-${platform}-`, `gradle-cache-`]
if (!cacheHash) {
core.info('A hash for the gradle dependencies could not be generated')
return
}
const cacheCache = await cache.restoreCache(
[GRADLE_CACHE_DIR],
cacheKey,
cacheRestoreKeys
)
if (!cacheCache) {
core.info('Gradle cache not found, expect dependency downloads from gradle')
}
if (cacheCache !== cacheKey) {
core.saveState(GRADLE_CACHE_KEY, cacheKey)
}
return
}
export async function postGradleCache(): Promise<void> {
const cacheKey = core.getState(GRADLE_CACHE_KEY)
if (cacheKey === '') {
core.info(
'A key for gradle cache was not defined, and thus there will not be a cache'
)
return
}
await cache.saveCache([GRADLE_CACHE_DIR], cacheKey)
return
}
export async function preAndroidCache(): Promise<void> {
const androidHash = await hashFiles(ANDROID_GLOB)
const androidKey = `android-${VERSION}-${platform}-${COMMANDLINE_TOOLS_VERSION}-${androidHash}`
const androidRestoreKeys = [
`android-${VERSION}-${platform}-${COMMANDLINE_TOOLS_VERSION}-`,
`android-${VERSION}-${platform}-`
]
if (!androidHash) {
core.info('A hash for the android sdk could not be generated')
return
}
const androidCache = await cache.restoreCache(
[ANDROID_SDK_ROOT, ANDROID_REPOSITORIES_CACHE, ANDROID_REPOSITORIES_CFG],
androidKey,
androidRestoreKeys
)
if (!androidCache) {
core.info(
'Android cache not found, expect dependency downloads from gradle'
)
}
if (androidCache !== androidKey) {
core.saveState(ANDROID_KEY, androidKey)
}
return
}
export async function postAndroidCache(): Promise<void> {
const androidKey = core.getState(ANDROID_KEY)
if (androidKey === '') {
core.info(
'A key for the android sdk was not defined, and thus there will not be a cache'
)
return
}
await cache.saveCache(
[ANDROID_SDK_ROOT, ANDROID_REPOSITORIES_CACHE, ANDROID_REPOSITORIES_CFG],
androidKey
)
return
}

View file

@ -1,49 +0,0 @@
import * as os from 'os'
import * as path from 'path'
export const ANNOTATION_MATCHERS = [
'android-lint-file-matcher.json',
'android-lint-line-matcher.json',
'gradle-matcher.json',
'kotlin-error-matcher.json',
'kotlin-warning-matcher.json'
]
export const HOME = os.homedir()
export const VERSION = 'v1'
// Gradle constants
// For caching the gradle cache in ~/.gradle/cache
export const GRADLE_CACHE_GLOB = [
'**/*.gradle',
'**.gradle',
'**/gradle.properties'
]
export const GRADLE_CACHE_DIR = path.join(HOME, '.gradle', 'cache')
export const GRADLE_CACHE_KEY = 'GRADLE_CACHE_KEY'
// For caching the gradle wrapper in ~/.gradle/wrapper
export const GRADLE_WRAPPER_GLOB = ['**/gradle/wrapper/**', '**/gradlew*']
export const GRADLE_WRAPPER_DIR = path.join(HOME, '.gradle', 'wrapper')
export const GRADLE_WRAPPER_KEY = 'GRADLE_WRAPPER_KEY'
// Android constants
export const ANDROID_SDK_ROOT = path.join(HOME, 'android')
export const ANDROID_GLOB = GRADLE_CACHE_GLOB
export const ANDROID_KEY = 'ANDROID_KEY'
export const ANDROID_REPOSITORIES_DIR = path.join(HOME, '.android')
export const ANDROID_REPOSITORIES_CFG = path.join(
ANDROID_REPOSITORIES_DIR,
'repositories.cfg'
)
export const ANDROID_REPOSITORIES_CACHE = path.join(
ANDROID_REPOSITORIES_DIR,
'cache'
)
export const COMMANDLINE_TOOLS_VERSION = '6609375'
export const COMMANDLINE_TOOLS_WIN_URL = `https://dl.google.com/android/repository/commandlinetools-win-${COMMANDLINE_TOOLS_VERSION}_latest.zip`
export const COMMANDLINE_TOOLS_MAC_URL = `https://dl.google.com/android/repository/commandlinetools-mac-${COMMANDLINE_TOOLS_VERSION}_latest.zip`
export const COMMANDLINE_TOOLS_LIN_URL = `https://dl.google.com/android/repository/commandlinetools-linux-${COMMANDLINE_TOOLS_VERSION}_latest.zip`

View file

@ -1,58 +0,0 @@
import * as fs from 'fs'
import * as path from 'path'
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as tc from '@actions/tool-cache'
import {
ANDROID_SDK_ROOT,
COMMANDLINE_TOOLS_LIN_URL,
COMMANDLINE_TOOLS_MAC_URL,
COMMANDLINE_TOOLS_WIN_URL,
ANDROID_REPOSITORIES_CFG,
ANDROID_REPOSITORIES_DIR
} from './constants'
export async function install(): Promise<void> {
const licenseDir = path.join(ANDROID_SDK_ROOT, 'licenses')
// If the licences exist, the rest does too
if (fs.existsSync(licenseDir) && fs.existsSync(ANDROID_REPOSITORIES_CFG)) {
core.debug(`Skipping install, licenseDir found: ${licenseDir}`)
return
}
// create ~/.android/repositories.cfg
fs.mkdirSync(ANDROID_REPOSITORIES_DIR, {recursive: true})
fs.closeSync(fs.openSync(ANDROID_REPOSITORIES_CFG, 'w'))
const acceptBuffer = Buffer.from(Array(10).fill('y').join('\n'), 'utf8')
let sdkManager = ''
if (process.platform === 'linux') {
const cmdlineToolsZip = await tc.downloadTool(COMMANDLINE_TOOLS_LIN_URL)
const cmdlineTools = await tc.extractZip(cmdlineToolsZip)
sdkManager = path.join(cmdlineTools, 'tools', 'bin', 'sdkmanager')
} else if (process.platform === 'darwin') {
const cmdlineToolsZip = await tc.downloadTool(COMMANDLINE_TOOLS_MAC_URL)
const cmdlineTools = await tc.extractZip(cmdlineToolsZip)
sdkManager = path.join(cmdlineTools, 'tools', 'bin', 'sdkmanager')
} else if (process.platform === 'win32') {
const cmdlineToolsZip = await tc.downloadTool(COMMANDLINE_TOOLS_WIN_URL)
const cmdlineTools = await tc.extractZip(cmdlineToolsZip)
sdkManager = path.join(cmdlineTools, 'tools', 'bin', 'sdkmanager.bat')
} else {
core.error(`Unsupported platform: ${process.platform}`)
}
await exec.exec(
sdkManager,
['--licenses', `--sdk_root=${ANDROID_SDK_ROOT}`],
{input: acceptBuffer}
)
exec.exec(
sdkManager,
['--include_obsolete', `--sdk_root=${ANDROID_SDK_ROOT}`, 'tools'],
{input: acceptBuffer}
)
}

View file

@ -1,14 +1,71 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as tc from '@actions/tool-cache'
import * as exec from '@actions/exec'
import * as path from 'path' import * as path from 'path'
import {ANDROID_SDK_ROOT, ANNOTATION_MATCHERS} from './constants' import * as fs from 'fs'
import {preGradleCache, preAndroidCache, preGradleWrapper} from './cache' import * as os from 'os'
import {install} from './install'
const COMMANDLINE_TOOLS_VERSION = '6609375'
const COMMANDLINE_TOOLS_WIN_URL = `https://dl.google.com/android/repository/commandlinetools-win-${COMMANDLINE_TOOLS_VERSION}_latest.zip`
const COMMANDLINE_TOOLS_MAC_URL = `https://dl.google.com/android/repository/commandlinetools-mac-${COMMANDLINE_TOOLS_VERSION}_latest.zip`
const COMMANDLINE_TOOLS_LIN_URL = `https://dl.google.com/android/repository/commandlinetools-linux-${COMMANDLINE_TOOLS_VERSION}_latest.zip`
const HOME = os.homedir()
const ANDROID_HOME_DIR = path.join(HOME, '.android')
const ANDROID_HOME_SDK_DIR = path.join(ANDROID_HOME_DIR, 'sdk')
const ANDROID_REPOSITORIES_CFG = path.join(ANDROID_HOME_DIR, 'repositories.cfg')
async function install(): Promise<string> {
const ANDROID_SDK_ROOT =
process.env['ANDROID_SDK_ROOT'] || ANDROID_HOME_SDK_DIR
const licenseDir = path.join(ANDROID_SDK_ROOT, 'licenses')
// If the licences exist, the rest does too
if (fs.existsSync(licenseDir) && fs.existsSync(ANDROID_REPOSITORIES_CFG)) {
core.debug(`Skipping install, licenseDir found: ${licenseDir}`)
return ANDROID_SDK_ROOT
}
// create ~/.android/repositories.cfg
fs.mkdirSync(ANDROID_HOME_SDK_DIR, {recursive: true})
fs.closeSync(fs.openSync(ANDROID_REPOSITORIES_CFG, 'w'))
const acceptBuffer = Buffer.from(Array(10).fill('y').join('\n'), 'utf8')
let sdkManager = ''
if (process.platform === 'linux') {
const cmdlineToolsZip = await tc.downloadTool(COMMANDLINE_TOOLS_LIN_URL)
const cmdlineTools = await tc.extractZip(cmdlineToolsZip)
sdkManager = path.join(cmdlineTools, 'tools', 'bin', 'sdkmanager')
} else if (process.platform === 'darwin') {
const cmdlineToolsZip = await tc.downloadTool(COMMANDLINE_TOOLS_MAC_URL)
const cmdlineTools = await tc.extractZip(cmdlineToolsZip)
sdkManager = path.join(cmdlineTools, 'tools', 'bin', 'sdkmanager')
} else if (process.platform === 'win32') {
const cmdlineToolsZip = await tc.downloadTool(COMMANDLINE_TOOLS_WIN_URL)
const cmdlineTools = await tc.extractZip(cmdlineToolsZip)
sdkManager = path.join(cmdlineTools, 'tools', 'bin', 'sdkmanager.bat')
} else {
core.error(`Unsupported platform: ${process.platform}`)
}
await exec.exec(
sdkManager,
['--licenses', `--sdk_root=${ANDROID_SDK_ROOT}`],
{input: acceptBuffer}
)
await exec.exec(
sdkManager,
['--include_obsolete', `--sdk_root=${ANDROID_SDK_ROOT}`, 'tools'],
{input: acceptBuffer}
)
return ANDROID_SDK_ROOT
}
async function run(): Promise<void> { async function run(): Promise<void> {
// process all caching but wait for them to all complete const ANDROID_SDK_ROOT = await install()
await Promise.all([preGradleWrapper(), preGradleCache(), preAndroidCache()])
await install()
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)
@ -17,11 +74,8 @@ async function run(): Promise<void> {
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')
const matchersPath = path.join(__dirname, '..', '..', '.github')
for (const matcher of ANNOTATION_MATCHERS) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(`##[add-matcher]${path.join(matchersPath, matcher)}`) console.log(`##[add-matcher]${path.join(__dirname, '..', 'matchers.json')}`)
}
} }
run() run()

View file

@ -1,13 +0,0 @@
import {postAndroidCache, postGradleCache, postGradleWrapper} from './cache'
async function run(): Promise<void> {
await Promise.all([
postGradleCache(),
postGradleWrapper(),
postAndroidCache()
])
return
}
run()