forked from react-native-community/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: install JDK automatically if missing (react-native-community#1065)
* feat: install JDK automatically if missing on Windows Install JDK@11 on Windows if missing. Later version break Gradle and prior versions do not provide a .zip for easy local installation. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Fix react-native-community#980 * chore: pr feedback * chore: replace node-unzipper with node-stream-zip * chore: pr feedback * chore: pr feedback
- Loading branch information
Showing
13 changed files
with
315 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// https://github.com/antelle/node-stream-zip/issues/36#issuecomment-596249657 | ||
declare module 'node-stream-zip' { | ||
import {Stream} from 'stream'; | ||
|
||
interface StreamZipOptions { | ||
/** | ||
* File to read | ||
*/ | ||
file: string; | ||
/** | ||
* You will be able to work with entries inside zip archive, otherwise the only way to access them is entry event | ||
* | ||
* default: true | ||
*/ | ||
storeEntries?: boolean; | ||
/** | ||
* By default, entry name is checked for malicious characters, like ../ or c:\123, pass this flag to disable validation errors | ||
* | ||
* default: false | ||
*/ | ||
skipEntryNameValidation?: boolean; | ||
/** | ||
* Undocumented adjustment of chunk size | ||
* | ||
* default: automatic | ||
*/ | ||
chunkSize?: number; | ||
} | ||
|
||
class ZipEntry { | ||
name: string; | ||
isDirectory: boolean; | ||
isFile: boolean; | ||
comment: string; | ||
size: number; | ||
} | ||
|
||
class StreamZip { | ||
constructor(config: StreamZipOptions); | ||
|
||
on(event: 'ready', handler: () => void): void; | ||
|
||
entry(entry: string): ZipEntry; | ||
entries(): ZipEntry[]; | ||
|
||
entriesCount: number; | ||
|
||
stream( | ||
entry: string, | ||
callback: (err: any | null, stream?: Stream) => void, | ||
): void; | ||
entryDataSync(entry: string): Buffer; | ||
openEntry( | ||
entry: string, | ||
callback: (err: any | null, entry?: ZipEntry) => void, | ||
sync: boolean, | ||
): void; | ||
extract( | ||
entry: string | null, | ||
outPath: string, | ||
callback: (err?: any) => void, | ||
): void; | ||
close(callback?: (err?: any) => void): void; | ||
} | ||
export = StreamZip; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
packages/cli/src/commands/doctor/healthchecks/__tests__/jdk.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import execa from 'execa'; | ||
import jdk from '../jdk'; | ||
import getEnvironmentInfo from '../../../../tools/envinfo'; | ||
import {EnvironmentInfo} from '../../types'; | ||
import {NoopLoader} from '../../../../tools/loader'; | ||
import * as common from '../common'; | ||
import * as unzip from '../../../../tools/unzip'; | ||
import * as deleteFile from '../../../../tools/deleteFile'; | ||
|
||
jest.mock('execa', () => jest.fn()); | ||
jest | ||
.spyOn(deleteFile, 'deleteFile') | ||
.mockImplementation(() => Promise.resolve()); | ||
|
||
const mockFetchToTemp = jest.fn(); | ||
jest.mock('@react-native-community/cli-tools', () => { | ||
return { | ||
fetchToTemp: mockFetchToTemp, | ||
}; | ||
}); | ||
|
||
const logSpy = jest.spyOn(common, 'logManualInstallation'); | ||
|
||
describe('jdk', () => { | ||
let environmentInfo: EnvironmentInfo; | ||
|
||
beforeAll(async () => { | ||
environmentInfo = await getEnvironmentInfo(); | ||
}, 15000); | ||
|
||
afterEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
it('returns a message if JDK is not installed', async () => { | ||
environmentInfo.Languages.Java = 'Not Found'; | ||
((execa as unknown) as jest.Mock).mockResolvedValue({stdout: ''}); | ||
const diagnostics = await jdk.getDiagnostics(environmentInfo); | ||
expect(diagnostics.needsToBeFixed).toBe(true); | ||
}); | ||
|
||
it('returns false if JDK version is in range', async () => { | ||
// @ts-ignore | ||
environmentInfo.Languages.Java = { | ||
version: '9', | ||
}; | ||
|
||
const diagnostics = await jdk.getDiagnostics(environmentInfo); | ||
expect(diagnostics.needsToBeFixed).toBe(false); | ||
}); | ||
|
||
it('returns true if JDK version is not in range', async () => { | ||
// @ts-ignore | ||
environmentInfo.Languages.Java = { | ||
version: '7', | ||
}; | ||
|
||
const diagnostics = await jdk.getDiagnostics(environmentInfo); | ||
expect(diagnostics.needsToBeFixed).toBe(true); | ||
}); | ||
|
||
it('logs manual installation steps to the screen for the default fix', async () => { | ||
const loader = new NoopLoader(); | ||
await jdk.runAutomaticFix({loader, environmentInfo}); | ||
expect(logSpy).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('downloads and unzips JDK on Windows when missing', async () => { | ||
const loader = new NoopLoader(); | ||
const loaderSucceedSpy = jest.spyOn(loader, 'succeed'); | ||
const loaderFailSpy = jest.spyOn(loader, 'fail'); | ||
const unzipSpy = jest | ||
.spyOn(unzip, 'unzip') | ||
.mockImplementation(() => Promise.resolve()); | ||
|
||
await jdk.win32AutomaticFix({loader, environmentInfo}); | ||
|
||
expect(loaderFailSpy).toHaveBeenCalledTimes(0); | ||
expect(logSpy).toHaveBeenCalledTimes(0); | ||
expect(unzipSpy).toBeCalledTimes(1); | ||
expect(loaderSucceedSpy).toBeCalledWith( | ||
'JDK installed successfully. Please restart your shell to see the changes', | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import {join} from 'path'; | ||
import versionRanges from '../versionRanges'; | ||
import {doesSoftwareNeedToBeFixed} from '../checkInstallation'; | ||
import {logManualInstallation} from './common'; | ||
import {HealthCheckInterface} from '../types'; | ||
|
||
import {downloadAndUnzip} from '../../../tools/downloadAndUnzip'; | ||
import { | ||
setEnvironment, | ||
updateEnvironment, | ||
} from '../../../tools/environmentVariables'; | ||
import {Ora} from 'ora'; | ||
|
||
export default { | ||
label: 'JDK', | ||
getDiagnostics: async ({Languages}) => ({ | ||
needsToBeFixed: doesSoftwareNeedToBeFixed({ | ||
version: | ||
typeof Languages.Java === 'string' | ||
? Languages.Java | ||
: Languages.Java.version, | ||
versionRange: versionRanges.JAVA, | ||
}), | ||
|
||
version: | ||
typeof Languages.Java === 'string' | ||
? Languages.Java | ||
: Languages.Java.version, | ||
versionRange: versionRanges.JAVA, | ||
}), | ||
win32AutomaticFix: async ({loader}: {loader: Ora}) => { | ||
try { | ||
// Installing JDK 11 because later versions seem to cause issues with gradle at the moment | ||
const installerUrl = | ||
'https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_windows-x64_bin.zip'; | ||
const installPath = process.env.LOCALAPPDATA || ''; // The zip is in a folder `jdk-11.02` so it can be unzipped directly there | ||
|
||
await downloadAndUnzip({ | ||
loader, | ||
downloadUrl: installerUrl, | ||
component: 'JDK', | ||
installPath, | ||
}); | ||
|
||
loader.text = 'Updating environment variables'; | ||
|
||
const jdkPath = join(installPath, 'jdk-11.0.2'); | ||
|
||
await setEnvironment('JAVA_HOME', jdkPath); | ||
await updateEnvironment('PATH', join(jdkPath, 'bin')); | ||
|
||
loader.succeed( | ||
'JDK installed successfully. Please restart your shell to see the changes', | ||
); | ||
} catch (e) { | ||
loader.fail(e); | ||
} | ||
}, | ||
runAutomaticFix: async () => { | ||
logManualInstallation({ | ||
healthcheck: 'JDK', | ||
url: 'https://openjdk.java.net/', | ||
}); | ||
}, | ||
} as HealthCheckInterface; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import {unlink} from 'fs'; | ||
import {promisify} from 'util'; | ||
|
||
export const deleteFile = promisify(unlink); |
Oops, something went wrong.