Skip to content

Commit

Permalink
Add ANDROID_HOME flow.
Browse files Browse the repository at this point in the history
  • Loading branch information
garg3133 committed Oct 11, 2022
1 parent 4df56d2 commit 254bfc5
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 23 deletions.
28 changes: 28 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
"dependencies": {
"ansi-colors": "^4.1.3",
"cli-progress": "^3.11.2",
"dotenv": "^16.0.3",
"download": "^8.0.0",
"inquirer": "^8.2.4",
"minimist": "^1.2.6",
"untildify": "^4.0.0",
"which": "^2.0.2"
}
}
118 changes: 95 additions & 23 deletions src/commands/android/index.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,137 @@
import colors from 'ansi-colors';
import * as dotenv from 'dotenv';
import fs from 'fs';
import path from 'path';
import untildify from 'untildify';
import which from 'which';
import {execSync} from 'child_process';
import {prompt} from 'inquirer';

import {getPlatformName, symbols} from '../../utils';
import {BINARY_TO_PACKAGE_NAME, NIGHTWATCH_AVD, SDK_BINARY_LOCATIONS, SETUP_CONFIG_QUES} from './constants';
import {Options, Platform, SdkBinary, SetupConfigs} from './interfaces';
import {downloadAndSetupAndroidSdk, getAbiForOS, getBinaryNameForOS, installPackagesUsingSdkManager} from './utils';
import {Options, OtherInfo, Platform, SdkBinary, SetupConfigs} from './interfaces';
import {
downloadAndSetupAndroidSdk, getAbiForOS, getBinaryNameForOS,
getDefaultAndroidSdkRoot, installPackagesUsingSdkManager
} from './utils';


export class AndroidSetup {
sdkRoot: string;
options: Options;
cwd: string;
rootDir: string;
platform: Platform;
binaryLocation: {[key: string]: string};
otherInfo: OtherInfo;

constructor(options: Options, cwd = process.cwd()) {
constructor(options: Options, rootDir = process.cwd()) {
this.sdkRoot = '';
this.options = options;
this.cwd = cwd;
this.rootDir = rootDir;
this.platform = getPlatformName();
this.binaryLocation = {};
this.otherInfo = {
androidHomeInGlobalEnv: false
};
}

async run() {
let result = true;

if (this.options.help) {
this.showHelp();

return true;
return result;
}

this.sdkRoot = this.getSdkRoot();
if (this.sdkRoot === '') {
return false;
}
const sdkRootEnv = this.getSdkRootFromEnv();
this.sdkRoot = sdkRootEnv || await this.getSdkRootFromUser();

const setupConfigs: SetupConfigs = await this.getSetupConfigs(this.options);
console.log();

const missingRequirements = this.verifySetup(setupConfigs);

if (this.options.setup) {
return await this.setupAndroid(setupConfigs, missingRequirements);
result = await this.setupAndroid(setupConfigs, missingRequirements);
} else if (missingRequirements.length) {
return false;
result = false;
}

return true;
if (!sdkRootEnv) {
this.sdkRootEnvSetInstructions();
}

return result;
}

showHelp() {
console.log('Help menu for android');
}

getSdkRoot(): string {
getSdkRootFromEnv(): string {
console.log('Checking the value of ANDROID_HOME environment variable...');

this.otherInfo.androidHomeInGlobalEnv = 'ANDROID_HOME' in process.env;

dotenv.config({path: path.join(this.rootDir, '.env')});

const androidHome = process.env.ANDROID_HOME;
const fromDotEnv = this.otherInfo.androidHomeInGlobalEnv ? '' : ' (taken from .env)';

if (androidHome) {
console.log(
` ${colors.green(symbols().ok)} ANDROID_HOME is set to '${androidHome}'\n`
);
const androidHomeFinal = untildify(androidHome);

const androidHomeAbsolute = path.resolve(this.rootDir, androidHomeFinal);
if (androidHomeFinal !== androidHomeAbsolute) {
console.log(` ${colors.yellow('!')} ANDROID_HOME is set to '${androidHomeFinal}'${fromDotEnv} which is NOT an absolute path.`);
console.log(` ${colors.green(symbols().ok)} Considering ANDROID_HOME to be '${androidHomeAbsolute}'\n`);

return androidHomeAbsolute;
}

console.log(` ${colors.green(symbols().ok)} ANDROID_HOME is set to '${androidHomeFinal}'${fromDotEnv}\n`);

return androidHome;
return androidHomeFinal;
}

if (typeof androidHome === 'undefined') {
if (androidHome === undefined) {
console.log(
` ${colors.red(symbols().fail)} ANDROID_HOME environment variable is NOT set!'\n`
` ${colors.red(symbols().fail)} ANDROID_HOME environment variable is NOT set!\n`
);
} else {
console.log(
` ${colors.red(symbols().fail)} ANDROID_HOME is set to '${androidHome} which is NOT a valid path!'\n`
` ${colors.red(symbols().fail)} ANDROID_HOME is set to '${androidHome}'${fromDotEnv} which is NOT a valid path!\n`
);
}

// if real device, verifying if all the requirements are present in known locations or added to PATH beforehand (only applicable for adb).

return '';
}

async getSdkRootFromUser() {
const answers: {sdkRoot: string} = await prompt([
{
type: 'input',
name: 'sdkRoot',
message: 'Where do you wish to verify/download Android SDKs?',
default: getDefaultAndroidSdkRoot(this.platform),
filter: (input: string) => path.resolve(this.rootDir, untildify(input))
}
]);

const {sdkRoot} = answers;

if (!this.otherInfo.androidHomeInGlobalEnv) {
// if ANDROID_HOME is already set in global env, saving it to .env is of no use.
// this is important if global ANDROID_HOME env is set to '', in which case we
// should not save the user supplied value to .env.
const envPath = path.join(this.rootDir, '.env');
fs.appendFileSync(envPath, `\nANDROID_HOME=${sdkRoot}\n`);
}

return sdkRoot;
}

getConfigFromOptions(options: {[key: string]: string | string[] | boolean}) {
const configs: SetupConfigs = {};

Expand Down Expand Up @@ -479,4 +528,27 @@ export class AndroidSetup {

return result;
}

sdkRootEnvSetInstructions() {
console.log();
console.log(colors.red('IMPORTANT'));
console.log(colors.red('---------'));

if (this.otherInfo.androidHomeInGlobalEnv && process.env.ANDROID_HOME === '') {
console.log(`${colors.cyan('ANDROID_HOME')} env is set to '' which is NOT a valid path!\n`);
console.log(`Please set ${colors.cyan('ANDROID_HOME')} to '${this.sdkRoot}' in your environment variables.`);
console.log('(As ANDROID_HOME env is already set, temporarily saving it to .env won\'t work.)\n');
} else {
console.log(
`${colors.cyan('ANDROID_HOME')} env was temporarily saved in ${colors.cyan(
'.env'
)} file (set to '${this.sdkRoot}').\n`
);
console.log(`Please set ${colors.cyan(
'ANDROID_HOME'
)} env to '${this.sdkRoot}' globally and then delete it from ${colors.cyan('.env')} file.`);
}

console.log('Doing this now might save you from future troubles.\n');
}
}
4 changes: 4 additions & 0 deletions src/commands/android/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ export interface Options {

export type Platform = 'windows' | 'linux' | 'mac';

export interface OtherInfo {
androidHomeInGlobalEnv: boolean;
}

export interface SetupConfigs {
mode?: 'real' | 'emulator' | 'both';
browsers?: 'chrome' | 'firefox' | 'both' | 'none';
Expand Down
18 changes: 18 additions & 0 deletions src/commands/android/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import cliProgress from 'cli-progress';
import download from 'download';
import fs from 'fs';
import path from 'path';
import {homedir} from 'os';
import {execSync} from 'child_process';

import {copySync, rmDirSync, symbols} from '../../utils';
Expand Down Expand Up @@ -39,6 +40,23 @@ export const getAbiForOS = () => {
return 'x86_64';
};

export const getDefaultAndroidSdkRoot = (platform: Platform) => {
if (platform === 'windows') {
let basePath = process.env.LOCALAPPDATA;
if (!basePath) {
basePath = homedir();
}

return path.join(basePath, 'Android', 'sdk');
}

if (platform === 'linux') {
return path.join(homedir(), 'Android', 'Sdk');
}

return path.join(homedir(), 'Library', 'Android', 'sdk');
};

export const downloadAndSetupAndroidSdk = async (sdkRoot: string, platform: Platform) => {
// make sure `cmdline-tools` folder is not present already
const cmdline_tools = path.join(sdkRoot, 'cmdline-tools');
Expand Down

0 comments on commit 254bfc5

Please sign in to comment.