Skip to content

Commit 9ccc665

Browse files
authored
feat: release announcement on upgrade (#487)
2 parents 0249cb2 + ea6ae4e commit 9ccc665

File tree

5 files changed

+437
-0
lines changed

5 files changed

+437
-0
lines changed

l10n/bundle.l10n.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@
350350
"Document must be an object. Skipping…": "Document must be an object. Skipping…",
351351
"DocumentDB and MongoDB Accounts": "DocumentDB and MongoDB Accounts",
352352
"DocumentDB Documentation": "DocumentDB Documentation",
353+
"DocumentDB for VS Code has been updated. View the release notes?": "DocumentDB for VS Code has been updated. View the release notes?",
353354
"DocumentDB for VS Code is not signed in to Azure": "DocumentDB for VS Code is not signed in to Azure",
354355
"DocumentDB Local": "DocumentDB Local",
355356
"DocumentDB Performance Tips": "DocumentDB Performance Tips",
@@ -533,6 +534,7 @@
533534
"I want to connect to a local DocumentDB instance.": "I want to connect to a local DocumentDB instance.",
534535
"I want to connect to the Azure Cosmos DB Emulator for MongoDB (RU).": "I want to connect to the Azure Cosmos DB Emulator for MongoDB (RU).",
535536
"I want to connect using a connection string.": "I want to connect using a connection string.",
537+
"Ignore": "Ignore",
536538
"Ignoring the following files that do not match the \"*.json\" file name pattern:": "Ignoring the following files that do not match the \"*.json\" file name pattern:",
537539
"Import": "Import",
538540
"Import completed with errors.": "Import completed with errors.",
@@ -780,6 +782,7 @@
780782
"Refreshing Azure discovery tree…": "Refreshing Azure discovery tree…",
781783
"Registering Providers...": "Registering Providers...",
782784
"Regularly review index statistics to identify unused indexes. Each index adds overhead to write operations, so remove indexes that are not being utilized.": "Regularly review index statistics to identify unused indexes. Each index adds overhead to write operations, so remove indexes that are not being utilized.",
785+
"Release Notes": "Release Notes",
783786
"Reload": "Reload",
784787
"Reload document from the database": "Reload document from the database",
785788
"Reload Window": "Reload Window",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "vscode-documentdb",
33
"version": "0.7.0",
4+
"releaseNotesUrl": "https://github.com/microsoft/vscode-documentdb/blob/main/docs/release-notes/0.7.md",
45
"aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255",
56
"publisher": "ms-azuretools",
67
"displayName": "DocumentDB for VS Code",

src/documentdb/ClustersExtension.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import { AzureMongoRUDiscoveryProvider } from '../plugins/service-azure-mongo-ru
6363
import { AzureDiscoveryProvider } from '../plugins/service-azure-mongo-vcore/AzureDiscoveryProvider';
6464
import { AzureVMDiscoveryProvider } from '../plugins/service-azure-vm/AzureVMDiscoveryProvider';
6565
import { DiscoveryService } from '../services/discoveryServices';
66+
import { maybeShowReleaseNotesNotification } from '../services/releaseNotesNotification';
6667
import { DemoTask } from '../services/taskService/tasks/DemoTask';
6768
import { TaskService } from '../services/taskService/taskService';
6869
import { TaskProgressReportingService } from '../services/taskService/UI/taskProgressReportingService';
@@ -101,6 +102,15 @@ export class ClustersExtension implements vscode.Disposable {
101102
treeDataProvider: ext.connectionsBranchDataProvider,
102103
});
103104
ext.context.subscriptions.push(ext.connectionsTreeView);
105+
106+
// Show release notes notification when the Connections View becomes visible
107+
ext.context.subscriptions.push(
108+
ext.connectionsTreeView.onDidChangeVisibility((e) => {
109+
if (e.visible) {
110+
void maybeShowReleaseNotesNotification();
111+
}
112+
}),
113+
);
104114
}
105115

106116
registerDiscoveryTree(_activateContext: IActionContext): void {
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { checkVersionForNotification } from './releaseNotesNotification';
7+
8+
describe('releaseNotesNotification', () => {
9+
describe('checkVersionForNotification', () => {
10+
describe('version comparison logic', () => {
11+
it('should show notification when upgrading from 0.6.0 to 0.7.0', () => {
12+
const result = checkVersionForNotification('0.7.0', '0.6.0', false);
13+
14+
expect(result.shouldShowNotification).toBe(true);
15+
expect(result.currentMajorMinor).toBe('0.7.0');
16+
expect(result.storedMajorMinor).toBe('0.6.0');
17+
});
18+
19+
it('should show notification when upgrading from 0.7.0 to 0.8.0', () => {
20+
const result = checkVersionForNotification('0.8.0', '0.7.0', false);
21+
22+
expect(result.shouldShowNotification).toBe(true);
23+
});
24+
25+
it('should show notification when upgrading from 0.7.0 to 1.0.0 (major version change)', () => {
26+
const result = checkVersionForNotification('1.0.0', '0.7.0', false);
27+
28+
expect(result.shouldShowNotification).toBe(true);
29+
});
30+
31+
it('should NOT show notification for patch update (0.7.0 to 0.7.1)', () => {
32+
const result = checkVersionForNotification('0.7.1', '0.7.0', false);
33+
34+
expect(result.shouldShowNotification).toBe(false);
35+
});
36+
37+
it('should NOT show notification for same version', () => {
38+
const result = checkVersionForNotification('0.7.0', '0.7.0', false);
39+
40+
expect(result.shouldShowNotification).toBe(false);
41+
});
42+
43+
it('should NOT show notification when stored version is newer (downgrade scenario)', () => {
44+
const result = checkVersionForNotification('0.7.0', '0.8.0', false);
45+
46+
expect(result.shouldShowNotification).toBe(false);
47+
});
48+
});
49+
50+
describe('prerelease version handling', () => {
51+
it('should show notification when upgrading from 0.6.0 to 0.7.1-alpha', () => {
52+
const result = checkVersionForNotification('0.7.1-alpha', '0.6.0', false);
53+
54+
expect(result.shouldShowNotification).toBe(true);
55+
expect(result.currentMajorMinor).toBe('0.7.0');
56+
});
57+
58+
it('should NOT show notification for patch with prerelease (0.7.0 to 0.7.1-alpha)', () => {
59+
const result = checkVersionForNotification('0.7.1-alpha', '0.7.0', false);
60+
61+
expect(result.shouldShowNotification).toBe(false);
62+
});
63+
64+
it('should show notification when upgrading to minor with prerelease (0.7.0 to 0.8.0-beta)', () => {
65+
const result = checkVersionForNotification('0.8.0-beta', '0.7.0', false);
66+
67+
expect(result.shouldShowNotification).toBe(true);
68+
});
69+
70+
it('should NOT show notification between prerelease versions of same minor (0.7.1-alpha to 0.7.2-beta)', () => {
71+
const result = checkVersionForNotification('0.7.2-beta', '0.7.1-alpha', false);
72+
73+
expect(result.shouldShowNotification).toBe(false);
74+
});
75+
76+
it('should handle stored prerelease version correctly (0.7.0-rc.1 to 0.8.0)', () => {
77+
const result = checkVersionForNotification('0.8.0', '0.7.0-rc.1', false);
78+
79+
expect(result.shouldShowNotification).toBe(true);
80+
});
81+
82+
it('should NOT show notification for same minor with different prereleases (0.7.0-alpha to 0.7.0-beta)', () => {
83+
const result = checkVersionForNotification('0.7.0-beta', '0.7.0-alpha', false);
84+
85+
expect(result.shouldShowNotification).toBe(false);
86+
});
87+
88+
it('should show notification when upgrading from prerelease to release of next minor (0.7.1-alpha to 0.8.0)', () => {
89+
const result = checkVersionForNotification('0.8.0', '0.7.1-alpha', false);
90+
91+
expect(result.shouldShowNotification).toBe(true);
92+
});
93+
});
94+
95+
describe('first-time install handling', () => {
96+
it('should NOT show notification on first install (no stored version, no welcome flag)', () => {
97+
const result = checkVersionForNotification('0.7.0', undefined, false);
98+
99+
expect(result.shouldShowNotification).toBe(false);
100+
expect(result.isFirstInstall).toBe(true);
101+
expect(result.currentMajorMinor).toBe('0.7.0');
102+
});
103+
104+
it('should normalize version on first install with prerelease', () => {
105+
const result = checkVersionForNotification('0.7.1-alpha', undefined, false);
106+
107+
expect(result.shouldShowNotification).toBe(false);
108+
expect(result.isFirstInstall).toBe(true);
109+
expect(result.currentMajorMinor).toBe('0.7.0');
110+
expect(result.storedMajorMinor).toBe('0.7.0');
111+
});
112+
});
113+
114+
describe('transitional code for 0.7.0 upgrade', () => {
115+
it('should show notification when upgrading from pre-0.7.0 (welcome flag present, no release notes key)', () => {
116+
const result = checkVersionForNotification('0.7.0', undefined, true);
117+
118+
expect(result.shouldShowNotification).toBe(true);
119+
expect(result.isUpgradeFromPre070).toBe(true);
120+
expect(result.storedMajorMinor).toBe('0.0.0');
121+
});
122+
123+
it('should show notification for pre-0.7.0 upgrade even with prerelease version', () => {
124+
const result = checkVersionForNotification('0.7.1-alpha', undefined, true);
125+
126+
expect(result.shouldShowNotification).toBe(true);
127+
expect(result.isUpgradeFromPre070).toBe(true);
128+
});
129+
});
130+
131+
describe('version normalization', () => {
132+
it('should normalize current version to major.minor.0', () => {
133+
const result = checkVersionForNotification('0.7.5', '0.6.0', false);
134+
135+
expect(result.currentMajorMinor).toBe('0.7.0');
136+
});
137+
138+
it('should normalize stored version to major.minor.0', () => {
139+
const result = checkVersionForNotification('0.8.0', '0.7.5', false);
140+
141+
expect(result.storedMajorMinor).toBe('0.7.0');
142+
});
143+
});
144+
145+
describe('error handling', () => {
146+
it('should return parseError for invalid current version', () => {
147+
const result = checkVersionForNotification('invalid', '0.7.0', false);
148+
149+
expect(result.parseError).toBe(true);
150+
expect(result.shouldShowNotification).toBe(false);
151+
});
152+
153+
it('should handle invalid stored version gracefully (treats as first install)', () => {
154+
const result = checkVersionForNotification('0.7.0', 'invalid', false);
155+
156+
// Invalid stored version is treated as null (first install scenario)
157+
expect(result.shouldShowNotification).toBe(false);
158+
expect(result.isFirstInstall).toBe(true);
159+
});
160+
});
161+
});
162+
});

0 commit comments

Comments
 (0)