Skip to content

Commit db58e00

Browse files
FrankLiu4138claude
andcommitted
fix(upgrade): check extension version before calling gotoAgentMode
- Add MIN_APPMOD_VERSION (1.15.0) constant and check installed extension version before proceeding, fixing failures when extension is outdated - Show reload prompt when extension is updated (not freshly installed) - Distinguish three extension states (up-to-date/outdated/not-installed) in notification button text and message body - Rename display name to "GitHub Copilot modernization" Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
1 parent e9ae840 commit db58e00

4 files changed

Lines changed: 89 additions & 16 deletions

File tree

src/constants.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ export namespace ExtensionName {
3636
export const APP_MODERNIZATION_FOR_JAVA = "vscjava.migrate-java-to-azure";
3737
// Java upgrade extension is merged into app modernization extension
3838
export const APP_MODERNIZATION_UPGRADE_FOR_JAVA = APP_MODERNIZATION_FOR_JAVA;
39-
export const APP_MODERNIZATION_EXTENSION_NAME = "GitHub Copilot app modernization";
39+
export const APP_MODERNIZATION_EXTENSION_NAME = "GitHub Copilot modernization";
4040
}
4141

4242
export namespace Upgrade {
4343
export const PACKAGE_ID_FOR_JAVA_RUNTIME = "java:*";
44+
/** Minimum version of the appmod extension that supports gotoAgentMode command */
45+
export const MIN_APPMOD_VERSION = "1.15.0";
4446
}
4547

4648
/**

src/upgrade/display/notificationManager.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
// Licensed under the MIT license.
33

44
import { commands, ExtensionContext, extensions, window } from "vscode";
5+
import * as semver from "semver";
56
import { UpgradeReason, type IUpgradeIssuesRenderer, type UpgradeIssue } from "../type";
6-
import { buildCVENotificationMessage, buildFixPrompt, buildNotificationMessage } from "../utility";
7+
import { buildCVENotificationMessage, buildFixPrompt, buildNotificationMessage, type ExtensionState } from "../utility";
78
import { Commands } from "../../commands";
89
import { Settings } from "../../settings";
910
import { instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper";
10-
import { ExtensionName } from "../../constants";
11+
import { ExtensionName, Upgrade } from "../../constants";
1112
import { CveUpgradeIssue } from "../cve";
1213

1314
const KEY_PREFIX = 'javaupgrade.notificationManager';
@@ -17,6 +18,8 @@ const BUTTON_TEXT_UPGRADE = "Upgrade Now";
1718
const BUTTON_TEXT_FIX_CVE = "Fix Now";
1819
const BUTTON_TEXT_INSTALL_AND_UPGRADE = "Install Extension and Upgrade";
1920
const BUTTON_TEXT_INSTALL_AND_FIX_CVE = "Install Extension and Fix";
21+
const BUTTON_TEXT_UPDATE_AND_UPGRADE = "Update Extension and Upgrade";
22+
const BUTTON_TEXT_UPDATE_AND_FIX_CVE = "Update Extension and Fix";
2023
const BUTTON_TEXT_NOT_NOW = "Not Now";
2124

2225
const SECONDS_IN_A_DAY = 24 * 60 * 60;
@@ -26,6 +29,19 @@ function getNowTs() {
2629
return Number(new Date()) / 1000;
2730
}
2831

32+
function getExtensionState(): ExtensionState {
33+
const ext = extensions.getExtension(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
34+
if (!ext) {
35+
return "not-installed";
36+
}
37+
const version = ext.packageJSON?.version;
38+
if (version && semver.gte(version, Upgrade.MIN_APPMOD_VERSION)) {
39+
return "up-to-date";
40+
}
41+
// Treat missing version as outdated (conservative)
42+
return "outdated";
43+
}
44+
2945
class NotificationManager implements IUpgradeIssuesRenderer {
3046
private hasShown = false;
3147
private context?: ExtensionContext;
@@ -61,18 +77,33 @@ class NotificationManager implements IUpgradeIssuesRenderer {
6177
}
6278
this.hasShown = true;
6379

64-
const hasExtension = !!extensions.getExtension(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
80+
const extensionState = getExtensionState();
6581
const prompt = buildFixPrompt(issue);
6682

6783
let notificationMessage = "";
6884

6985
if (hasCVEIssue) {
70-
notificationMessage = buildCVENotificationMessage(cveIssues, hasExtension);
86+
notificationMessage = buildCVENotificationMessage(cveIssues, extensionState);
7187
} else {
72-
notificationMessage = buildNotificationMessage(issue, hasExtension);
88+
notificationMessage = buildNotificationMessage(issue, extensionState);
89+
}
90+
91+
let upgradeButtonText: string;
92+
let fixCVEButtonText: string;
93+
switch (extensionState) {
94+
case "up-to-date":
95+
upgradeButtonText = BUTTON_TEXT_UPGRADE;
96+
fixCVEButtonText = BUTTON_TEXT_FIX_CVE;
97+
break;
98+
case "outdated":
99+
upgradeButtonText = BUTTON_TEXT_UPDATE_AND_UPGRADE;
100+
fixCVEButtonText = BUTTON_TEXT_UPDATE_AND_FIX_CVE;
101+
break;
102+
case "not-installed":
103+
upgradeButtonText = BUTTON_TEXT_INSTALL_AND_UPGRADE;
104+
fixCVEButtonText = BUTTON_TEXT_INSTALL_AND_FIX_CVE;
105+
break;
73106
}
74-
const upgradeButtonText = hasExtension ? BUTTON_TEXT_UPGRADE : BUTTON_TEXT_INSTALL_AND_UPGRADE;
75-
const fixCVEButtonText = hasExtension ? BUTTON_TEXT_FIX_CVE : BUTTON_TEXT_INSTALL_AND_FIX_CVE;
76107
sendInfo(operationId, {
77108
operationName: "java.dependency.upgradeNotification.show",
78109
});

src/upgrade/upgradeManager.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ class UpgradeManager {
2626

2727
// Upgrade project
2828
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.JAVA_UPGRADE_WITH_COPILOT, async (promptText?: string) => {
29-
await checkOrInstallAppModExtensionForUpgrade(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
29+
const canProceed = await checkOrInstallAppModExtensionForUpgrade(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
30+
if (!canProceed) {
31+
return;
32+
}
3033
const promptToUse = promptText ?? DEFAULT_UPGRADE_PROMPT;
3134
await commands.executeCommand(Commands.GOTO_AGENT_MODE, { prompt: promptToUse, useCustomAgent: true });
3235
}));

src/upgrade/utility.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,20 @@ function findEolDate(currentVersion: string, eolDate: Record<string, string>): s
2222
return null;
2323
}
2424

25-
export function buildNotificationMessage(issue: UpgradeIssue, hasExtension: boolean): string {
25+
export type ExtensionState = "up-to-date" | "outdated" | "not-installed";
26+
27+
function getActionWord(extensionState: ExtensionState, verb: string): string {
28+
switch (extensionState) {
29+
case "up-to-date":
30+
return verb;
31+
case "outdated":
32+
return `update ${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension and ${verb}`;
33+
case "not-installed":
34+
return `install ${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension and ${verb}`;
35+
}
36+
}
37+
38+
export function buildNotificationMessage(issue: UpgradeIssue, extensionState: ExtensionState): string {
2639
const {
2740
packageId,
2841
currentVersion,
@@ -31,7 +44,7 @@ export function buildNotificationMessage(issue: UpgradeIssue, hasExtension: bool
3144
packageDisplayName
3245
} = issue;
3346

34-
const upgradeWord = hasExtension ? "upgrade" : `install ${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension and upgrade`;
47+
const upgradeWord = getActionWord(extensionState, "upgrade");
3548

3649
if (packageId === Upgrade.PACKAGE_ID_FOR_JAVA_RUNTIME) {
3750
return `This project is using an older Java runtime (${currentVersion}). Would you like to ${upgradeWord} it to the latest LTS version?`;
@@ -51,7 +64,7 @@ export function buildNotificationMessage(issue: UpgradeIssue, hasExtension: bool
5164
}
5265
}
5366

54-
export function buildCVENotificationMessage(issues: CveUpgradeIssue[], hasExtension: boolean): string {
67+
export function buildCVENotificationMessage(issues: CveUpgradeIssue[], extensionState: ExtensionState): string {
5568

5669
if (issues.length === 0) {
5770
return "No CVE issues found.";
@@ -81,7 +94,7 @@ export function buildCVENotificationMessage(issues: CveUpgradeIssue[], hasExtens
8194
CVESeverityDistribution: severityText,
8295
});
8396

84-
const fixWord = hasExtension ? "fix" : `install ${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension and fix`;
97+
const fixWord = getActionWord(extensionState, "fix");
8598

8699
if (issues.length === 1) {
87100
return `${severityText} CVE vulnerability is detected in this project. Would you like to ${fixWord} it now?`;
@@ -154,11 +167,35 @@ export async function checkOrPopupToInstallAppModExtensionForModernization(
154167
}
155168

156169
export async function checkOrInstallAppModExtensionForUpgrade(
157-
extensionIdToCheck: string): Promise<void> {
158-
if (extensions.getExtension(extensionIdToCheck)) {
159-
return;
170+
extensionIdToCheck: string): Promise<boolean> {
171+
const ext = extensions.getExtension(extensionIdToCheck);
172+
173+
if (ext) {
174+
const installedVersion = ext.packageJSON?.version;
175+
if (installedVersion && semver.gte(installedVersion, Upgrade.MIN_APPMOD_VERSION)) {
176+
return true;
177+
}
160178
}
161179

162180
await commands.executeCommand("workbench.extensions.installExtension", ExtensionName.APP_MODERNIZATION_FOR_JAVA);
181+
182+
if (ext) {
183+
// Extension was updated (not freshly installed) — reload required
184+
const reload = await window.showInformationMessage(
185+
`${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension has been updated. Reload VS Code to start the upgrade experience.`,
186+
"Reload Now"
187+
);
188+
if (reload === "Reload Now") {
189+
await commands.executeCommand("workbench.action.reloadWindow");
190+
return true;
191+
} else {
192+
await window.showInformationMessage(
193+
`${ExtensionName.APP_MODERNIZATION_EXTENSION_NAME} extension has been updated. Please reload VS Code manually to start the upgrade experience.`
194+
);
195+
return false;
196+
}
197+
}
198+
163199
await checkOrPromptToEnableAppModExtension("upgrade");
200+
return true;
164201
}

0 commit comments

Comments
 (0)