Skip to content

Commit

Permalink
Add deprecation notice for Java<11. (#4347)
Browse files Browse the repository at this point in the history
* Add deprecation notice for Java<11.

* Add CHANGELOG and fix lint.
  • Loading branch information
yuchenshi committed Mar 23, 2022
1 parent 0e5b515 commit 588eba3
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Marks Java 10 and below as deprecated. Support will be dropped in Firebase CLI v11. Please upgrade to Java version 11 or above to continue using the emulators. (#4347)
8 changes: 7 additions & 1 deletion src/commands/emulators-start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { EmulatorRegistry } from "../emulator/registry";
import { Emulators, EMULATORS_SUPPORTED_BY_UI } from "../emulator/types";
import * as clc from "cli-color";
import { Constants } from "../emulator/constants";
import { logLabeledWarning } from "../utils";

// eslint-disable-next-line @typescript-eslint/no-var-requires
const Table = require("cli-table");
Expand All @@ -26,8 +27,9 @@ module.exports = new Command("emulators:start")
.action(async (options: any) => {
const killSignalPromise = commandUtils.shutdownWhenKilled(options);

let deprecationNotices;
try {
await controller.startAll(options);
({ deprecationNotices } = await controller.startAll(options));
} catch (e: any) {
await controller.cleanShutdown();
throw e;
Expand Down Expand Up @@ -111,6 +113,10 @@ Issues? Report them at ${stylizeLink(
// Add this line above once connect page is implemented
// It is now safe to connect your app. Instructions: http://${uiInfo?.host}:${uiInfo?.port}/connect

for (const notice of deprecationNotices) {
logLabeledWarning("emulators", notice, "warn");
}

// Hang until explicitly killed
await killSignalPromise;
});
7 changes: 6 additions & 1 deletion src/commands/ext-dev-emulators-start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ module.exports = new Command("ext:dev:emulators:start")
.action(async (options: any) => {
const killSignalPromise = commandUtils.shutdownWhenKilled(options);
const emulatorOptions = await optionsHelper.buildOptions(options);

let deprecationNotices;
try {
commandUtils.beforeEmulatorCommand(emulatorOptions);
await controller.startAll(emulatorOptions);
({ deprecationNotices } = await controller.startAll(emulatorOptions));
} catch (e: any) {
await controller.cleanShutdown();
if (!(e instanceof FirebaseError)) {
Expand All @@ -30,6 +32,9 @@ module.exports = new Command("ext:dev:emulators:start")
}

utils.logSuccess("All emulators ready, it is now safe to connect.");
for (const notice of deprecationNotices) {
utils.logLabeledWarning("emulators", notice, "warn");
}

// Hang until explicitly killed
await killSignalPromise;
Expand Down
103 changes: 102 additions & 1 deletion src/emulator/commandUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,18 +416,119 @@ export async function emulatorExec(script: string, options: any) {
extraEnv.GCLOUD_PROJECT = projectId;
}
let exitCode = 0;
let deprecationNotices;
try {
const showUI = !!options.ui;
await controller.startAll(options, showUI);
({ deprecationNotices } = await controller.startAll(options, showUI));
exitCode = await runScript(script, extraEnv);
await onExit(options);
} finally {
await controller.cleanShutdown();
}

for (const notice of deprecationNotices) {
utils.logLabeledWarning("emulators", notice, "warn");
}

if (exitCode !== 0) {
throw new FirebaseError(`Script "${clc.bold(script)}" exited with code ${exitCode}`, {
exit: exitCode,
});
}
}

// Regex to extract Java major version. Only works with Java >= 9.
// See: http://openjdk.java.net/jeps/223
const JAVA_VERSION_REGEX = /version "([1-9][0-9]*)/;
const MIN_SUPPORTED_JAVA_MAJOR_VERSION = 11;
const JAVA_HINT = "Please make sure Java is installed and on your system PATH.";

/**
* Return whether Java major verion is supported. Throws if Java not available.
*
* @returns true if Java >= 11, false otherwise
*/
export async function checkJavaSupported(): Promise<boolean> {
return new Promise<string>((resolve, reject) => {
let child;
try {
child = childProcess.spawn(
"java",
["-Duser.language=en", "-Dfile.encoding=UTF-8", "-version"],
{
stdio: ["inherit", "pipe", "pipe"],
}
);
} catch (err: any) {
return reject(
new FirebaseError(`Could not spawn \`java -version\`. ${JAVA_HINT}`, { original: err })
);
}

let output = "";
let error = "";
child.stdout?.on("data", (data) => {
const str = data.toString("utf8");
logger.debug(str);
output += str;
});
child.stderr?.on("data", (data) => {
const str = data.toString("utf8");
logger.debug(str);
error += str;
});

child.once("error", (err) => {
reject(
new FirebaseError(`Could not spawn \`java -version\`. ${JAVA_HINT}`, { original: err })
);
});

child.once("exit", (code, signal) => {
if (signal) {
// This is an unlikely situation where the short-lived Java process to
// check version was killed by a signal.
reject(new FirebaseError(`Process \`java -version\` was killed by signal ${signal}.`));
} else if (code && code !== 0) {
// `java -version` failed. For example, this may happen on some OS X
// where `java` is by default a stub that prints out more information on
// how to install Java. It is critical for us to relay stderr/stdout.
reject(
new FirebaseError(
`Process \`java -version\` has exited with code ${code}. ${JAVA_HINT}\n` +
`-----Original stdout-----\n${output}` +
`-----Original stderr-----\n${error}`
)
);
} else {
// Join child process stdout and stderr for further parsing. Order does
// not matter here because we'll parse only a small part later.
resolve(`${output}\n${error}`);
}
});
}).then((output) => {
const match = output.match(JAVA_VERSION_REGEX);
if (match) {
const version = match[1];
const versionInt = parseInt(version, 10);
if (!versionInt) {
utils.logLabeledWarning(
"emulators",
`Failed to parse Java version. Got "${match[0]}".`,
"warn"
);
} else {
logger.debug(`Parsed Java major version: ${versionInt}`);
return versionInt >= MIN_SUPPORTED_JAVA_MAJOR_VERSION;
}
} else {
logger.debug("java -version outputs:", output);
logger.warn(`Failed to parse Java version.`);
}
return false;
});
}

export const JAVA_DEPRECATION_WARNING =
"Support for Java version <= 10 will be dropped soon in firebase-tools@11. " +
"Please upgrade to Java version 11 or above to continue using the emulators.";
17 changes: 15 additions & 2 deletions src/emulator/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { EmulatorLogger } from "./emulatorLogger";
import * as portUtils from "./portUtils";
import { EmulatorHubClient } from "./hubClient";
import { promptOnce } from "../prompt";
import { FLAG_EXPORT_ON_EXIT_NAME } from "./commandUtils";
import { FLAG_EXPORT_ON_EXIT_NAME, JAVA_DEPRECATION_WARNING } from "./commandUtils";
import { fileExistsSync } from "../fsutils";
import { StorageEmulator } from "./storage";
import { getStorageRulesConfig } from "./storage/rules/config";
Expand All @@ -46,6 +46,7 @@ import { ParsedTriggerDefinition } from "./functionsEmulatorShared";
import { ExtensionsEmulator } from "./extensionsEmulator";
import { previews } from "../previews";
import { normalizeAndValidate } from "../functions/projectConfig";
import { requiresJava } from "./downloadableEmulators";

const START_LOGGING_EMULATOR = utils.envOverride(
"START_LOGGING_EMULATOR",
Expand Down Expand Up @@ -332,7 +333,10 @@ interface EmulatorOptions extends Options {
extDevEnv?: Record<string, string>;
}

export async function startAll(options: EmulatorOptions, showUI = true): Promise<void> {
export async function startAll(
options: EmulatorOptions,
showUI = true
): Promise<{ deprecationNotices: string[] }> {
// Emulators config is specified in firebase.json as:
// "emulators": {
// "firestore": {
Expand All @@ -353,6 +357,13 @@ export async function startAll(options: EmulatorOptions, showUI = true): Promise
`No emulators to start, run ${clc.bold("firebase init emulators")} to get started.`
);
}
const deprecationNotices = [];
if (targets.some(requiresJava)) {
if (!(await commandUtils.checkJavaSupported())) {
utils.logLabeledWarning("emulators", JAVA_DEPRECATION_WARNING, "warn");
deprecationNotices.push(JAVA_DEPRECATION_WARNING);
}
}
const hubLogger = EmulatorLogger.forEmulator(Emulators.HUB);
hubLogger.logLabeled("BULLET", "emulators", `Starting emulators: ${targets.join(", ")}`);

Expand Down Expand Up @@ -761,6 +772,8 @@ export async function startAll(options: EmulatorOptions, showUI = true): Promise
await instance.connect();
}
}

return { deprecationNotices };
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/emulator/downloadableEmulators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ export async function handleEmulatorProcessError(emulator: Emulators, err: any):
}
}

export function requiresJava(emulator: Emulators): boolean {
if (emulator in Commands) {
return Commands[emulator as keyof typeof Commands].binary === "java";
}
return false;
}

async function _runBinary(
emulator: DownloadableEmulatorDetails,
command: DownloadableEmulatorCommand,
Expand Down

0 comments on commit 588eba3

Please sign in to comment.