Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ${{ matrix.os }}
env:
JAVA_TOOL_OPTIONS: -Xmx4g
timeout-minutes: 15
timeout-minutes: ${{ matrix.timeout-minutes || 15 }}
strategy:
matrix:
include:
Expand All @@ -31,6 +31,7 @@ jobs:
api-level: 31
target: default
arch: x86_64
timeout-minutes: 20
- os: ubuntu-24.04
api-level: 34
target: aosp_atd
Expand Down
26 changes: 26 additions & 0 deletions __tests__/sdk-installer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { parseCmdlineToolsMajorRevision } from '../src/sdk-installer';

describe('cmdline-tools revision parser tests', () => {
it('Parses the major revision of the cmdline-tools preinstalled on ubuntu-24.04', () => {
const sourceProperties = ['Pkg.UserSrc=false', 'Pkg.Revision=12.0', 'Pkg.Path=cmdline-tools;12.0', 'Pkg.Desc=Android SDK Command-line Tools', ''].join('\n');
expect(parseCmdlineToolsMajorRevision(sourceProperties)).toBe(12);
});

it('Parses the major revision of the cmdline-tools bundled with the action', () => {
const sourceProperties = ['Pkg.UserSrc=false', 'Pkg.Revision=23.0', 'Pkg.Path=cmdline-tools;23.0', 'Pkg.Desc=Android SDK Command-line Tools', ''].join('\n');
expect(parseCmdlineToolsMajorRevision(sourceProperties)).toBe(23);
});

it('Returns null if the revision is missing', () => {
const sourceProperties = ['Pkg.UserSrc=false', 'Pkg.Desc=Android SDK Command-line Tools', ''].join('\n');
expect(parseCmdlineToolsMajorRevision(sourceProperties)).toBeNull();
});

it('Returns null if the revision is malformed', () => {
expect(parseCmdlineToolsMajorRevision('Pkg.Revision=unknown')).toBeNull();
});

it('Returns null for empty source properties', () => {
expect(parseCmdlineToolsMajorRevision('')).toBeNull();
});
});
23 changes: 21 additions & 2 deletions lib/sdk-installer.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseCmdlineToolsMajorRevision = parseCmdlineToolsMajorRevision;
exports.installAndroidSdk = installAndroidSdk;
const core = __importStar(require("@actions/core"));
const exec = __importStar(require("@actions/exec"));
Expand All @@ -44,6 +45,15 @@ const BUILD_TOOLS_VERSION = '37.0.0';
const CMDLINE_TOOLS_VERSION = '16111833';
const CMDLINE_TOOLS_URL_MAC = `https://dl.google.com/android/repository/commandlinetools-mac_x86_64-${CMDLINE_TOOLS_VERSION}_latest.zip`;
const CMDLINE_TOOLS_URL_LINUX = `https://dl.google.com/android/repository/commandlinetools-linux-${CMDLINE_TOOLS_VERSION}_latest.zip`;
// keep in sync with CMDLINE_TOOLS_VERSION
const CMDLINE_TOOLS_MIN_MAJOR_REVISION = 23;
/**
* Returns the major revision of an installed cmdline-tools package from the content of its `source.properties`, or `null` if the revision cannot be determined.
*/
function parseCmdlineToolsMajorRevision(sourceProperties) {
const match = /^Pkg\.Revision=(\d+)/m.exec(sourceProperties);
return match ? Number(match[1]) : null;
}
/**
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
* and the system image for the chosen API level, CPU arch, and target.
Expand All @@ -54,10 +64,19 @@ async function installAndroidSdk(apiLevel, systemImageApiLevel, target, arch, ch
const isOnMac = process.platform === 'darwin';
const isArm = process.arch === 'arm64';
const cmdlineToolsPath = `${process.env.ANDROID_HOME}/cmdline-tools`;
if (!fs.existsSync(cmdlineToolsPath)) {
console.log('Installing new cmdline-tools.');
const sourcePropertiesPath = `${cmdlineToolsPath}/latest/source.properties`;
// a preinstalled cmdline-tools too old to parse minor API levels such as android-37.1 must be replaced, not kept
const installedRevision = fs.existsSync(sourcePropertiesPath) ? parseCmdlineToolsMajorRevision(fs.readFileSync(sourcePropertiesPath, 'utf8')) : null;
if (installedRevision === null || installedRevision < CMDLINE_TOOLS_MIN_MAJOR_REVISION) {
if (installedRevision === null) {
console.log('Installing new cmdline-tools.');
}
else {
console.log(`Replacing cmdline-tools revision ${installedRevision} with revision ${CMDLINE_TOOLS_MIN_MAJOR_REVISION}.`);
}
const sdkUrl = isOnMac ? CMDLINE_TOOLS_URL_MAC : CMDLINE_TOOLS_URL_LINUX;
const downloadPath = await tc.downloadTool(sdkUrl);
await io.rmRF(`${cmdlineToolsPath}/latest`);
await tc.extractZip(downloadPath, cmdlineToolsPath);
await io.mv(`${cmdlineToolsPath}/cmdline-tools`, `${cmdlineToolsPath}/latest`);
}
Expand Down
22 changes: 20 additions & 2 deletions src/sdk-installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ const BUILD_TOOLS_VERSION = '37.0.0';
const CMDLINE_TOOLS_VERSION = '16111833';
const CMDLINE_TOOLS_URL_MAC = `https://dl.google.com/android/repository/commandlinetools-mac_x86_64-${CMDLINE_TOOLS_VERSION}_latest.zip`;
const CMDLINE_TOOLS_URL_LINUX = `https://dl.google.com/android/repository/commandlinetools-linux-${CMDLINE_TOOLS_VERSION}_latest.zip`;
// keep in sync with CMDLINE_TOOLS_VERSION
const CMDLINE_TOOLS_MIN_MAJOR_REVISION = 23;

/**
* Returns the major revision of an installed cmdline-tools package from the content of its `source.properties`, or `null` if the revision cannot be determined.
*/
export function parseCmdlineToolsMajorRevision(sourceProperties: string): number | null {
const match = /^Pkg\.Revision=(\d+)/m.exec(sourceProperties);
return match ? Number(match[1]) : null;
}

/**
* Installs & updates the Android SDK for the macOS platform, including SDK platform for the chosen API level, latest build tools, platform tools, Android Emulator,
Expand All @@ -30,10 +40,18 @@ export async function installAndroidSdk(
const isArm = process.arch === 'arm64';

const cmdlineToolsPath = `${process.env.ANDROID_HOME}/cmdline-tools`;
if (!fs.existsSync(cmdlineToolsPath)) {
console.log('Installing new cmdline-tools.');
const sourcePropertiesPath = `${cmdlineToolsPath}/latest/source.properties`;
// a preinstalled cmdline-tools too old to parse minor API levels such as android-37.1 must be replaced, not kept
const installedRevision = fs.existsSync(sourcePropertiesPath) ? parseCmdlineToolsMajorRevision(fs.readFileSync(sourcePropertiesPath, 'utf8')) : null;
if (installedRevision === null || installedRevision < CMDLINE_TOOLS_MIN_MAJOR_REVISION) {
if (installedRevision === null) {
console.log('Installing new cmdline-tools.');
} else {
console.log(`Replacing cmdline-tools revision ${installedRevision} with revision ${CMDLINE_TOOLS_MIN_MAJOR_REVISION}.`);
}
const sdkUrl = isOnMac ? CMDLINE_TOOLS_URL_MAC : CMDLINE_TOOLS_URL_LINUX;
const downloadPath = await tc.downloadTool(sdkUrl);
await io.rmRF(`${cmdlineToolsPath}/latest`);
await tc.extractZip(downloadPath, cmdlineToolsPath);
await io.mv(`${cmdlineToolsPath}/cmdline-tools`, `${cmdlineToolsPath}/latest`);
}
Expand Down
Loading