Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support java 17 runtime when create function project #3311

Merged
merged 7 commits into from
Sep 13, 2022
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import { AzExtFsExtra } from '@microsoft/vscode-azext-utils';
import * as path from 'path';
import { Progress } from 'vscode';
import { buildGradleFileName, JavaBuildTool, settingsGradleFileName } from '../../../constants';
import { localize } from '../../../localize';
import { confirmOverwriteFile } from '../../../utils/fs';
import { gradleUtils } from '../../../utils/gradleUtils';
import { javaUtils } from '../../../utils/javaUtils';
import { nonNullProp } from '../../../utils/nonNull';
import { IJavaProjectWizardContext } from '../javaSteps/IJavaProjectWizardContext';
import { java11, java8 } from '../javaSteps/JavaVersionStep';
import { java8 } from '../javaSteps/JavaVersionStep';
import { ScriptProjectCreateStep } from './ScriptProjectCreateStep';

const backupGradlePluginVersion = "1.8.2";
const backupGradlePluginVersion = "1.11.0";
const metaDataUrl = "https://plugins.gradle.org/m2/com/microsoft/azure/azure-functions-gradle-plugin/maven-metadata.xml";

export class GradleProjectCreateStep extends ScriptProjectCreateStep {
Expand Down Expand Up @@ -54,14 +54,9 @@ export class GradleProjectCreateStep extends ScriptProjectCreateStep {
return `rootProject.name = "${context.javaArtifactId}"`;
}

getCompatibilityVersion(javaVersion: string | undefined): string {
if (javaVersion === java8) {
return "1.8";
} else if (javaVersion === java11) {
return "11";
} else {
throw new Error(localize('invalidJavaVersion', 'Invalid Java version "{0}".', javaVersion));
}
getCompatibilityVersion(context: IJavaProjectWizardContext): string {
const javaVersion: string = nonNullProp(context, 'javaVersion');
return javaVersion === java8 ? "1.8" : javaVersion;
}

async getBuildGradleContent(context: IJavaProjectWizardContext): Promise<string> {
Expand All @@ -75,13 +70,13 @@ group '${context.javaGroupId}'
version '${context.javaProjectVersion}'

dependencies {
implementation 'com.microsoft.azure.functions:azure-functions-java-library:1.4.2'
implementation 'com.microsoft.azure.functions:azure-functions-java-library:2.0.1'
testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
testImplementation 'org.mockito:mockito-core:3.3.3'
}

sourceCompatibility = '${this.getCompatibilityVersion(context.javaVersion)}'
targetCompatibility = '${this.getCompatibilityVersion(context.javaVersion)}'
sourceCompatibility = '${this.getCompatibilityVersion(context)}'
targetCompatibility = '${this.getCompatibilityVersion(context)}'

compileJava.options.encoding = 'UTF-8'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class MavenProjectCreateStep extends ProjectCreateStepBase {
'archetype:generate',
mavenUtils.formatMavenArg('DarchetypeGroupId', 'com.microsoft.azure'),
mavenUtils.formatMavenArg('DarchetypeArtifactId', 'azure-functions-archetype'),
mavenUtils.formatMavenArg('DarchetypeVersion', 'LATEST'),
mavenUtils.formatMavenArg('DjavaVersion', javaVersion),
mavenUtils.formatMavenArg('DgroupId', nonNullProp(context, 'javaGroupId')),
mavenUtils.formatMavenArg('DartifactId', artifactId),
Expand Down
33 changes: 29 additions & 4 deletions src/commands/createNewProject/javaSteps/JavaVersionStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,54 @@
*--------------------------------------------------------------------------------------------*/

import { AzureWizardPromptStep, IAzureQuickPickItem } from "@microsoft/vscode-azext-utils";
import { previewDescription } from "../../../constants";
import { hasMinFuncCliVersion } from "../../../funcCoreTools/hasMinFuncCliVersion";
import { localize } from "../../../localize";
import { IJavaProjectWizardContext } from "./IJavaProjectWizardContext";
import { getJavaVersion } from "./JavaVersions";

export const java8: string = '8';
export const java11: string = '11';
export const java17: string = '17';

type javaVersionInfo = {
label: string,
data: string,
description?: string,
miniFunc: string
}

const versionInfo: javaVersionInfo[] = [
{ label: 'Java 8', data: java8, miniFunc: '1.0.0' },
{ label: 'Java 11', data: java11, miniFunc: '3.0.2630' },
{ label: 'Java 17', data: java17, miniFunc: '4.0.0', description: previewDescription }
];

export class JavaVersionStep extends AzureWizardPromptStep<IJavaProjectWizardContext> {

public static async setDefaultVersion(context: IJavaProjectWizardContext): Promise<void> {
if (!await hasMinFuncCliVersion(context, '3.0.2630', context.version)) {
context.javaVersion = java8;
}
}

public async prompt(context: IJavaProjectWizardContext): Promise<void> {
const picks: IAzureQuickPickItem<string>[] = [
{ label: 'Java 8', data: java8 },
{ label: 'Java 11', data: java11 },
];
const picks: IAzureQuickPickItem<string>[] = await this.getPicks(context);
const placeHolder: string = localize('selectJavaVersion', 'Select a version of Java');
context.javaVersion = (await context.ui.showQuickPick(picks, { placeHolder })).data;
}

async getPicks(context: IJavaProjectWizardContext): Promise<IAzureQuickPickItem<string>[]> {
const javaVersion: number = await getJavaVersion();
const result: IAzureQuickPickItem<string>[] = [];
for (const version of versionInfo) {
if (await hasMinFuncCliVersion(context, version.miniFunc, context.version) && javaVersion >= Number(version.data)) {
result.push(version);
}
}
return result;
}

public shouldPrompt(context: IJavaProjectWizardContext): boolean {
return !context.javaVersion;
}
Expand Down
69 changes: 69 additions & 0 deletions src/commands/createNewProject/javaSteps/JavaVersions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AzExtFsExtra } from '@microsoft/vscode-azext-utils';
import { localize } from '../../../localize';
import { cpUtils } from "../../../utils/cpUtils";

import * as path from 'path';

export async function getJavaVersion(): Promise<number> {
const javaHome: string | undefined = process.env['JAVA_HOME'];
let javaVersion = javaHome ? await checkVersionInReleaseFile(javaHome) : undefined;
if (!javaVersion) {
javaVersion = await checkVersionByCLI(javaHome ? path.join(javaHome, 'bin', 'java') : 'java');
}
if (!javaVersion) {
const message: string = localize('javaNotFound', 'Failed to get Java version. Please ensure that Java is installed and JAVA_HOME environment variable is set.');
throw new Error(message);
}
return javaVersion;
}

async function checkVersionInReleaseFile(javaHome: string): Promise<number | undefined> {
if (!javaHome) {
return undefined;
}
const releaseFile = path.join(javaHome, "release");
if (!await AzExtFsExtra.pathExists(releaseFile)) {
return undefined;
}

try {
const content = await AzExtFsExtra.readFile(releaseFile);
const regexp = /^JAVA_VERSION="(.*)"/gm;
const match = regexp.exec(content.toString());
return match ? flattenMajorVersion(match[1]) : undefined;
} catch (error) {
// ignore
return undefined;
}
}

async function checkVersionByCLI(javaExec: string): Promise<number | undefined> {
if (!javaExec) {
return undefined;
}
const result: cpUtils.ICommandResult = await cpUtils.tryExecuteCommand(undefined, undefined, javaExec, '-version');
const output: string = result.cmdOutputIncludingStderr;
const regexp = /version "(.*)"/g;
const match = regexp.exec(output);
return match ? flattenMajorVersion(match[1]) : undefined;
}

function flattenMajorVersion(version: string): number {
// Ignore '1.' prefix for legacy Java versions
if (version.startsWith("1.")) {
version = version.substring(2);
}

const regexp = /\d+/g;
const match = regexp.exec(version);
let javaVersion = 0;
if (match) {
javaVersion = parseInt(match[0], 10);
}

return javaVersion;
}
4 changes: 2 additions & 2 deletions src/commands/deploy/verifyAppSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function verifyAppSettings(context: IActionContext, node: SlotTreeI
await verifyVersionAndLanguage(context, projectPath, node.site.fullName, version, language, appSettings.properties);

// update the settings if the remote runtime was changed
let updateAppSettings: boolean = appSettings[workerRuntimeKey] !== remoteRuntime;
let updateAppSettings: boolean = appSettings.properties[workerRuntimeKey] !== remoteRuntime;
if (node.site.isLinux) {
const remoteBuildSettingsChanged = verifyLinuxRemoteBuildSettings(context, appSettings.properties, bools);
updateAppSettings ||= remoteBuildSettingsChanged;
Expand All @@ -38,7 +38,7 @@ export async function verifyAppSettings(context: IActionContext, node: SlotTreeI
if (updateAppSettings) {
await client.updateApplicationSettings(appSettings);
// if the user cancels the deployment, the app settings node doesn't reflect the updated settings
await node.appSettingsTreeItem.refresh(context);
await node.appSettingsTreeItem?.refresh(context);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/project/createNewProject.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ for (const version of [FuncVersion.v2, FuncVersion.v3, FuncVersion.v4]) {
const appName: string = 'javaApp';
const javaBaseInputs: (TestInput | string | RegExp)[] = [TestInput.UseDefaultValue, TestInput.UseDefaultValue, TestInput.UseDefaultValue, TestInput.UseDefaultValue, appName];
if (version !== FuncVersion.v2) { // v2 doesn't support picking a java version
javaBaseInputs.unshift(/11/);
javaBaseInputs.unshift(/8/);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this get changed to an earlier version of Java?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As some of the test environment uses java 8 as default java version, we add java version validation in this pr and will not provide java 11 as an option in this case

}

testCases.push({
Expand Down