Compare commits

..

No commits in common. "main" and "v2" have entirely different histories.
main ... v2

11 changed files with 7596 additions and 29860 deletions

View file

@ -44,7 +44,7 @@
"semi": "off",
"@typescript-eslint/semi": ["error", "never"],
"@typescript-eslint/type-annotation-spacing": "error",
"i18n-text/no-en": "off",
"i18n-text/no-en": "warn",
"@typescript-eslint/unbound-method": "error"
},
"env": {

View file

@ -1,7 +1,13 @@
name: Build & Test
on:
pull_request:
paths-ignore:
- '**.md'
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
@ -9,12 +15,12 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Setup node 20
uses: actions/setup-node@v4
- name: Setup node 16
uses: actions/setup-node@v3
with:
node-version: 20
node-version: '16'
- run: npm ci
@ -26,12 +32,12 @@ jobs:
format-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Setup node 20
uses: actions/setup-node@v4
- name: Setup node 16
uses: actions/setup-node@v3
with:
node-version: 20
node-version: '16'
- run: npm ci
@ -40,12 +46,12 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Setup node 20
uses: actions/setup-node@v4
- name: Setup node 16
uses: actions/setup-node@v3
with:
node-version: 20
node-version: '16'
- run: npm ci
@ -53,64 +59,35 @@ jobs:
runSdkManager:
runs-on: ${{ matrix.os }}
name: ${{ matrix.os }} - ${{ matrix.cmdline-tools-version }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-24.04
- ubuntu-22.04
- ubuntu-20.04
- macos-14
- macos-13
- macos-12
- windows-2022
- windows-2019
cmdline-tools-version:
- 12266719
- 11479570
- 11076708
- 10406996
- 9862592
- 9477386
- 9123335
- 8512546
os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-22.04, macos-11, macos-12, windows-2019, windows-2022 ]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Setup node 20
uses: actions/setup-node@v4
- name: Setup node 16
uses: actions/setup-node@v3
with:
node-version: 20
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'temurin'
node-version: '16'
- run: npm ci
- run: npm run build
- name: Run setup-android
uses: ./
with:
cmdline-tools-version: ${{ matrix.cmdline-tools-version }}
log-accepted-android-sdk-licenses: 'false'
- run: sdkmanager --list_installed
- run: node dist/index.js
- run: sdkmanager --list
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Setup node 20
uses: actions/setup-node@v4
- name: Setup node 16
uses: actions/setup-node@v3
with:
node-version: 20
node-version: '16'
- run: npm ci

View file

@ -31,13 +31,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v1
with:
languages: 'javascript'
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v1

View file

@ -1,10 +1,17 @@
name: Run Android build
on:
workflow_dispatch:
push:
pull_request:
paths:
- 'dist/**.js'
- '.github/*.json'
push:
branches:
- main
- releases/*
paths:
- 'dist/**.js'
- '.github/*.json'
jobs:
build:
@ -20,19 +27,19 @@ jobs:
if: ${{ false }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
repository: daveol/SampleApplication
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
path: ./build/
- name: Set up JDK 17
uses: actions/setup-java@v4
- name: Set up JDK 1.8
uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'temurin'
java-version: 1.8
distribution: 'adopt'
- name: Setup Android SDK
id: 'setup-android'

6
.idea/vcs.xml generated
View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View file

@ -3,10 +3,10 @@
![Build & Test](https://github.com/android-actions/setup-android/workflows/Build%20&%20Test/badge.svg)
This action sets up the Android SDK tools by:
- Downloading the SDK commandline tools, if the current version (16.0) is not found in either `$ANDROID_SDK_ROOT` or `$HOME/.android/sdk`.
- Downloading the SDK commandline tools, if the current version (7.0) is not found in either `$ANDROID_SDK_ROOT` or `$HOME/.android/sdk`.
- Accepting the SDK licenses.
- Installing `tools` and `platform-tools`.
- Adding `platform-tools` (contains adb) and `cmdline-tools/16.0/bin` (contains sdkmanager) to `$PATH`.
- Adding `platform-tools` (contains adb) and `cmdline-tools/7.0/bin` (contains sdkmanager) to `$PATH`.
- Setting up problem [matchers](/matchers.json).
On Windows 2016 runners, this action also checks if `$ANDROID_SDK_ROOT` path contains spaces.
@ -23,78 +23,20 @@ See [action.yml](action.yml)
## Basic
```yaml
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Set up JDK 17
- name: Set up JDK 1.8
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
java-version: 1.8
- name: Setup Android SDK
uses: android-actions/setup-android@v3
uses: android-actions/setup-android@v2
- name: Build SampleApplication
run: ./gradlew --no-daemon build
```
## Additional packages
Input parameter `packages` controls which packages this action will install from Android SDK.
Default value is `tools platform-tools`, supply an empty string to skip installing additional packages.
Additional packages can be installed at a later time by calling sdkmanager manually.
```yaml
- name: Setup Android SDK
uses: android-actions/setup-android@v3
with:
packages: ''
# ...
- run: sdkmanager tools platform-tools
```
## SDK Version selection
Command line tools are versioned using two variables - short and long.
Long one is the build number, used in the zip URL, short one is the human friendly version name.
By default, setup-android installs version 12266719 (short version 16.0).
To install a different version, call setup-android with desired long version as the input parameter `cmdline-tools-version`:
```yaml
- name: Setup Android SDK
uses: android-actions/setup-android@v3
with:
cmdline-tools-version: 8512546
```
#### Version table
| Short version | Long version |
|---------------| --- |
| 16.0 | 12266719 |
| 13.0 | 11479570 |
| 12.0 | 11076708 |
| 11.0 | 10406996 |
| 10.0 | 9862592 |
| 9.0 | 9477386 |
| 8.0 | 9123335 |
| 7.0 | 8512546 |
Current cmdline tools version can be found at https://developer.android.com/studio#command-line-tools-only
# Android SDK Licenses
Android SDK is not public domain software, it comes with a license.
Input parameter `accept-android-sdk-licenses` decides if Android SDK licenses should be agreed to on behalf of the user of this action.
Default option is 'yes', because otherwise SDK is unusable until said licenses are agreed to.
licenses are quite long, to prevent a wall of text in the action output, licenses can be agreed to silently.
Input parameter `log-accepted-android-sdk-licenses` controls whether license texts should be printed or omitted from the text output. Defaults to 'true'.
# Thanks
Based on the project [android-problem-matchers-action](https://github.com/jonasb/android-problem-matchers-action) from [@jonasb](https://github.com/jonasb)

View file

@ -2,29 +2,8 @@ name: 'Setup Android SDK Tools'
author: 'Android-Actions'
description: 'Setup the Android SDK Tools and add them to the path'
inputs:
cmdline-tools-version:
description: 'cmdline-tools-version. See https://developer.android.com/studio#command-line-tools-only'
required: false
default: '12266719'
accept-android-sdk-licenses:
description: 'Android SDK is usable only after the license agreement. Should setup-android agree to the licences, provided by "sdkmanager --licenses"'
required: false
default: 'true'
log-accepted-android-sdk-licenses:
description: 'Should accepted licenses be logged. If not, accepted licences will be accepted silently'
required: false
default: 'true'
packages:
description: 'Additional packages to install'
required: false
default: 'tools platform-tools'
runs:
using: node20
using: 'node16'
main: 'dist/index.js'
branding:

28496
dist/index.js vendored

File diff suppressed because one or more lines are too long

8465
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -25,24 +25,26 @@
"author": "daveol",
"license": "ISC",
"dependencies": {
"@actions/cache": "^3.2.4",
"@actions/core": "^1.10.1",
"@actions/tool-cache": "^2.0.1"
"@actions/cache": "^3.0.5",
"@actions/core": "^1.10.0",
"@actions/tool-cache": "^2.0.1",
"fs-extra": "^10.1.0"
},
"devDependencies": {
"@types/jest": "^29.5.5",
"@types/node": "^20.6.5",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vercel/ncc": "^0.38.0",
"eslint": "^8.57.0",
"eslint-plugin-github": "^5.0.1",
"eslint-plugin-jest": "^28.6.0",
"jest": "^29.7.0",
"jest-circus": "^29.7.0",
"@types/fs-extra": "^9.0.13",
"@types/jest": "^29.2.0",
"@types/node": "^16.11.66",
"@typescript-eslint/eslint-plugin": "^5.40.1",
"@typescript-eslint/parser": "^5.40.1",
"@vercel/ncc": "^0.34.0",
"eslint": "^8.25.0",
"eslint-plugin-github": "^4.4.0",
"eslint-plugin-jest": "^27.1.3",
"jest": "^29.2.1",
"jest-circus": "^29.2.1",
"js-yaml": "^4.1.0",
"prettier": "^3.3.2",
"ts-jest": "^29.1.5",
"typescript": "^5.5.4"
"prettier": "^2.7.1",
"ts-jest": "^29.0.3",
"typescript": "^4.8.4"
}
}

View file

@ -3,102 +3,109 @@ import * as tc from '@actions/tool-cache'
import * as exec from '@actions/exec'
import * as path from 'path'
import * as fs from 'fs'
import * as fse from 'fs-extra'
import * as os from 'os'
function getVersionShort(versionLong: string): string {
switch (versionLong) {
case '12266719':
return '16.0'
case '11479570':
return '13.0'
case '11076708':
return '12.0'
case '10406996':
return '11.0'
case '9862592':
return '10.0'
case '9477386':
return '9.0'
case '9123335':
return '8.0'
case '8512546':
return '7.0'
default:
return versionLong
}
}
const CMDLINE_TOOLS_VERSION = '7.0'
const COMMANDLINE_TOOLS_VERSION = '8512546'
const VERSION_LONG = core.getInput('cmdline-tools-version', {
trimWhitespace: true
})
if (VERSION_LONG.includes('/') || VERSION_LONG.includes('\\')) {
core.setFailed('Malformed cmdline-tools-version!')
throw new Error('Malformed cmdline-tools-version!')
}
const VERSION_SHORT = getVersionShort(VERSION_LONG)
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 COMMANDLINE_TOOLS_WIN_URL = `https://dl.google.com/android/repository/commandlinetools-win-${VERSION_LONG}_latest.zip`
const COMMANDLINE_TOOLS_MAC_URL = `https://dl.google.com/android/repository/commandlinetools-mac-${VERSION_LONG}_latest.zip`
const COMMANDLINE_TOOLS_LIN_URL = `https://dl.google.com/android/repository/commandlinetools-linux-${VERSION_LONG}_latest.zip`
const ANDROID_HOME_SDK_DIR = path.join(os.homedir(), '.android', 'sdk')
const HOME = os.homedir()
const ANDROID_HOME_DIR = path.join(HOME, '.android')
const ANDROID_HOME_SDK_DIR = path.join(ANDROID_HOME_DIR, 'sdk')
let ANDROID_SDK_ROOT = process.env['ANDROID_SDK_ROOT'] || ANDROID_HOME_SDK_DIR
async function callSdkManager(
sdkManager: string,
arg: string,
printOutput: Boolean = true
): Promise<void> {
function getSdkManagerPath(cmdToolsVersion: string): string {
return path.join(
ANDROID_SDK_ROOT,
'cmdline-tools',
cmdToolsVersion,
'bin',
'sdkmanager'
)
}
function findPreinstalledSdkManager(): {
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) {
const propertiesFile = path.join(
ANDROID_SDK_ROOT,
'cmdline-tools',
'latest',
'source.properties'
)
if (fs.existsSync(propertiesFile)) {
result.isCorrectVersion = fs
.readFileSync(propertiesFile, 'utf8')
.includes(`Pkg.Revision=${CMDLINE_TOOLS_VERSION}`)
}
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,
silent: !printOutput
input: acceptBuffer
})
}
async function installSdkManager(): Promise<string> {
const cmdlineTools = path.join(
ANDROID_SDK_ROOT,
'cmdline-tools',
VERSION_SHORT
fs.mkdirSync(ANDROID_SDK_ROOT, {recursive: true})
// touch $ANDROID_SDK_ROOT/repositories.cfg
fs.closeSync(
fs.openSync(path.join(ANDROID_SDK_ROOT, 'repositories.cfg'), 'w')
)
let sdkManagerExe = path.join(cmdlineTools, 'bin', 'sdkmanager')
if (!fs.existsSync(sdkManagerExe)) {
const latestCmdlineTools = path.join(
ANDROID_SDK_ROOT,
'cmdline-tools',
'latest'
)
const sourcePropertiesFile = path.join(
latestCmdlineTools,
'source.properties'
)
const latestSdkManagerExe = path.join(
latestCmdlineTools,
'bin',
'sdkmanager'
)
if (
fs.existsSync(latestCmdlineTools) &&
fs.existsSync(sourcePropertiesFile) &&
fs.existsSync(latestSdkManagerExe)
) {
const sourceProperties = fs.readFileSync(sourcePropertiesFile)
core.info(
`Found preinstalled sdkmanager in ${latestCmdlineTools} with following source.properties:`
)
core.info(sourceProperties.toString())
if (sourceProperties.includes(`Pkg.Revision=${VERSION_SHORT}`)) {
core.info(`Preinstalled sdkmanager has the correct version`)
sdkManagerExe = latestSdkManagerExe
} else {
core.info(`Wrong version in preinstalled sdkmanager`)
}
}
}
if (!fs.existsSync(sdkManagerExe)) {
const sdkManager = findPreinstalledSdkManager()
if (!sdkManager.isFound) {
let cmdlineToolsURL
if (process.platform === 'linux') {
cmdlineToolsURL = COMMANDLINE_TOOLS_LIN_URL
@ -110,27 +117,43 @@ async function installSdkManager(): Promise<string> {
core.error(`Unsupported platform: ${process.platform}`)
return ''
}
core.info(`Downloading commandline tools from ${cmdlineToolsURL}`)
const cmdlineToolsZip = await tc.downloadTool(cmdlineToolsURL)
const cmdlineToolsExtractedLocation = await tc.extractZip(cmdlineToolsZip)
const extractTo = path.join(ANDROID_SDK_ROOT, 'cmdline-tools')
await tc.extractZip(cmdlineToolsZip, extractTo)
// 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
)
// Create parent directory
fs.mkdirSync(path.dirname(desiredLocation), {recursive: true})
// Make sure we don't have leftover target directory (happens sometimes...)
if (fs.existsSync(cmdlineTools)) {
core.info(`Removing leftovers from ${cmdlineTools}`)
fs.rmSync(cmdlineTools, {recursive: true})
}
fs.renameSync(path.join(extractTo, 'cmdline-tools'), cmdlineTools)
if (fs.existsSync(desiredLocation)) fse.removeSync(desiredLocation)
// @TODO: use io.mv instead of fs-extra.moveSync once following issue is resolved:
// https://github.com/actions/toolkit/issues/706
fse.moveSync(
path.join(cmdlineToolsExtractedLocation, 'cmdline-tools'),
desiredLocation
)
fse.removeSync(cmdlineToolsExtractedLocation)
sdkManager.exePath = getSdkManagerPath(CMDLINE_TOOLS_VERSION)
sdkManager.isCorrectVersion = true
}
// touch $ANDROID_SDK_ROOT/repositories.cfg
fs.closeSync(
fs.openSync(path.join(ANDROID_SDK_ROOT, 'repositories.cfg'), 'w')
)
core.debug(`sdkmanager available at: ${sdkManagerExe}`)
return sdkManagerExe
if (!sdkManager.isCorrectVersion) {
await callSdkManager(
sdkManager.exePath,
`cmdline-tools;${CMDLINE_TOOLS_VERSION}`
)
sdkManager.exePath = getSdkManagerPath(CMDLINE_TOOLS_VERSION)
}
return sdkManager.exePath
}
async function run(): Promise<void> {
@ -152,36 +175,17 @@ async function run(): Promise<void> {
}
}
const sdkManagerExe = await installSdkManager()
const sdkManager = await installSdkManager()
core.debug(`sdkmanager installed to: ${sdkManager}`)
await callSdkManager(sdkManager, '--licenses')
await callSdkManager(sdkManager, 'tools')
await callSdkManager(sdkManager, 'platform-tools')
if (core.getBooleanInput('accept-android-sdk-licenses')) {
core.info('Accepting Android SDK licenses')
await callSdkManager(
sdkManagerExe,
'--licenses',
core.getBooleanInput('log-accepted-android-sdk-licenses')
)
}
const packages = core
.getInput('packages', {required: false})
.split(' ')
.map(function (str) {
return str.trim()
})
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
.filter(function (element, index, array) {
return element
})
for (const pkg of packages) {
await callSdkManager(sdkManagerExe, pkg)
}
core.setOutput('ANDROID_COMMANDLINE_TOOLS_VERSION', VERSION_LONG)
core.setOutput('ANDROID_COMMANDLINE_TOOLS_VERSION', COMMANDLINE_TOOLS_VERSION)
core.exportVariable('ANDROID_HOME', ANDROID_SDK_ROOT)
core.exportVariable('ANDROID_SDK_ROOT', ANDROID_SDK_ROOT)
core.addPath(path.dirname(sdkManagerExe))
core.addPath(path.dirname(sdkManager))
core.addPath(path.join(ANDROID_SDK_ROOT, 'platform-tools'))
core.debug('add matchers')