diff --git a/packages/databricks-vscode/package.json b/packages/databricks-vscode/package.json
index 379a2950d..755cd6f96 100644
--- a/packages/databricks-vscode/package.json
+++ b/packages/databricks-vscode/package.json
@@ -698,7 +698,8 @@
"ansi-to-html": "^0.7.2",
"bcryptjs": "^2.4.3",
"triple-beam": "^1.4.1",
- "winston": "^3.10.0"
+ "winston": "^3.10.0",
+ "yaml": "^2.3.2"
},
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.2",
diff --git a/packages/databricks-vscode/resources/whats-new/1.2.md b/packages/databricks-vscode/resources/whats-new/1.2.md
new file mode 100644
index 000000000..a880ef09f
--- /dev/null
+++ b/packages/databricks-vscode/resources/whats-new/1.2.md
@@ -0,0 +1,46 @@
+
+
+# Databricks Extension v1.2.0
+
+## What's new?
+
+- [📗 Advanced notebook support with Databricks Connect](#dbconnect-notebook)
+
+## Advanced notebook support with Databricks Connect
+
+Before this update, you could already run notebooks locally with Databricks Connect. This update introduces advanced notebook support. This advanced support enables you to run notebooks locally with a similar experience as you have by running them on a Databricks cluster. The goal of this update is to bring much of the convenience of running notebooks on a Databricks cluster to your local development environment.
+
+This update includes:
+
+- [Magic commands such as `%run` and `%sql`](#magic-commands)
+- [Preconfigured globals such as `spark` and `dbutils`](#preconf-globals)
+- [Interactive widgets through `dbutils.widgets`](#widgets)
+- [Support for Databricks notebooks](#dbnb)
+
+### Magic commands
+
+You can now use Databricks magic commands locally from your notebooks.
+
+
+
+### Preconfigured globals
+
+Just like on a Databricks cluster, this update configures and provides you with some globals such as `spark` and `dbutils` when you run notebooks locally.
+
+
+
+### Interactive `dbutils.widgets`
+
+You can now use `dbutils.widgets` to create interactive widgets in your local notebooks.
+
+
+
+### Support for Databricks notebooks
+
+You can use Databricks notebooks locally with [VS Code Interactive Windows](https://code.visualstudio.com/docs/python/jupyter-support-py).
+
+
+
+### Further details
+
+For a detailed documentation of this feature, see [Use notebooks with Databricks Connect](https://docs.databricks.com/en/dev-tools/vscode-ext/dev-tasks/notebooks.html).
diff --git a/packages/databricks-vscode/resources/whats-new/1.2/dbnb.gif b/packages/databricks-vscode/resources/whats-new/1.2/dbnb.gif
new file mode 100644
index 000000000..36db6d13e
Binary files /dev/null and b/packages/databricks-vscode/resources/whats-new/1.2/dbnb.gif differ
diff --git a/packages/databricks-vscode/resources/whats-new/1.2/magic_sql.gif b/packages/databricks-vscode/resources/whats-new/1.2/magic_sql.gif
new file mode 100644
index 000000000..f585b824e
Binary files /dev/null and b/packages/databricks-vscode/resources/whats-new/1.2/magic_sql.gif differ
diff --git a/packages/databricks-vscode/resources/whats-new/1.2/preconf_globals.gif b/packages/databricks-vscode/resources/whats-new/1.2/preconf_globals.gif
new file mode 100644
index 000000000..a46a48a47
Binary files /dev/null and b/packages/databricks-vscode/resources/whats-new/1.2/preconf_globals.gif differ
diff --git a/packages/databricks-vscode/resources/whats-new/1.2/widgets.gif b/packages/databricks-vscode/resources/whats-new/1.2/widgets.gif
new file mode 100644
index 000000000..63b53e0e9
Binary files /dev/null and b/packages/databricks-vscode/resources/whats-new/1.2/widgets.gif differ
diff --git a/packages/databricks-vscode/src/extension.ts b/packages/databricks-vscode/src/extension.ts
index 6ebb63f71..dd6c631ec 100644
--- a/packages/databricks-vscode/src/extension.ts
+++ b/packages/databricks-vscode/src/extension.ts
@@ -50,6 +50,7 @@ import {DbConnectStatusBarButton} from "./language/DbConnectStatusBarButton";
import {NotebookAccessVerifier} from "./language/notebooks/NotebookAccessVerifier";
import {NotebookInitScriptManager} from "./language/notebooks/NotebookInitScriptManager";
import {showRestartNotebookDialogue} from "./language/notebooks/restartNotebookDialogue";
+import {showWhatsNewPopup} from "./whatsNewPopup";
export async function activate(
context: ExtensionContext
@@ -559,6 +560,14 @@ export async function activate(
);
});
+ showWhatsNewPopup(context, stateStorage).catch((e) => {
+ logging.NamedLogger.getOrCreate(Loggers.Extension).error(
+ "Error while showing popup for what's new",
+ e
+ );
+ });
+
+ stateStorage.lastInstalledExtensionVersion = packageMetadata.version;
CustomWhenContext.setActivated(true);
telemetry.recordEvent(Events.EXTENSION_ACTIVATED);
diff --git a/packages/databricks-vscode/src/language/DbConnectInstallPrompt.ts b/packages/databricks-vscode/src/language/DbConnectInstallPrompt.ts
index 16097e41a..5f4528186 100644
--- a/packages/databricks-vscode/src/language/DbConnectInstallPrompt.ts
+++ b/packages/databricks-vscode/src/language/DbConnectInstallPrompt.ts
@@ -47,11 +47,7 @@ export class DbConnectInstallPrompt implements Disposable {
const pkgUpdateMessagePart = hasPyspark
? "(pyspark will be uninstalled)"
: hasDbConnect
- ? `(databricks-connect will be updated to the latest version: ${
- dbConnectDetails.version
- } -> ${await this.pythonExtension.getLatestPackageVersion(
- "databricks-connect"
- )} )`
+ ? `(databricks-connect will be updated to the latest version: ${dbConnectDetails.version} -> ${DATABRICKS_CONNECT_VERSION} )`
: "";
const message = `${mainMessagePart} ${envMessagePart}. ${pkgUpdateMessagePart}`;
diff --git a/packages/databricks-vscode/src/vscode-objs/StateStorage.ts b/packages/databricks-vscode/src/vscode-objs/StateStorage.ts
index 6941ebbe3..e77684648 100644
--- a/packages/databricks-vscode/src/vscode-objs/StateStorage.ts
+++ b/packages/databricks-vscode/src/vscode-objs/StateStorage.ts
@@ -86,6 +86,20 @@ export class StateStorage {
);
}
+ get lastInstalledExtensionVersion() {
+ return this.context.workspaceState.get(
+ "databricks.lastInstalledExtensionVersion",
+ "0.0.0"
+ );
+ }
+
+ set lastInstalledExtensionVersion(value: string) {
+ this.context.workspaceState.update(
+ "databricks.lastInstalledExtensionVersion",
+ value
+ );
+ }
+
get fixedUUID() {
let uuid = this.context.workspaceState.get(
"databricks.fixedUUID"
diff --git a/packages/databricks-vscode/src/whatsNewPopup.test.ts b/packages/databricks-vscode/src/whatsNewPopup.test.ts
new file mode 100644
index 000000000..dda141165
--- /dev/null
+++ b/packages/databricks-vscode/src/whatsNewPopup.test.ts
@@ -0,0 +1,63 @@
+import {expect} from "chai";
+import {findFileFowWhatsNew} from "./whatsNewPopup";
+import {SemVer} from "semver";
+import * as tmp from "tmp";
+import path from "path";
+import {mkdir, writeFile} from "fs/promises";
+
+describe(__filename, () => {
+ let context: any;
+ let removeCallback: () => void;
+ let dirname: string;
+
+ before(async () => {
+ ({name: dirname, removeCallback} = tmp.dirSync({unsafeCleanup: true}));
+ context = {
+ asAbsolutePath: (ip: string) => path.join(dirname, ip),
+ } as any;
+
+ await mkdir(path.join(dirname, "resources", "whats-new"), {
+ recursive: true,
+ });
+ await writeFile(
+ path.join(dirname, "resources", "whats-new", "1.2.md"),
+ ""
+ );
+ });
+
+ after(() => {
+ removeCallback();
+ });
+
+ it("should use CHANGELOG.md for patch version upgrade", async () => {
+ const previousVersion = new SemVer("1.2.1");
+ const currentVersion = new SemVer("1.2.2");
+ expect(
+ await findFileFowWhatsNew(context, previousVersion, currentVersion)
+ ).to.equal(path.join(dirname, "CHANGELOG.md"));
+ });
+
+ it("should use custom markdown file for minor version upgrade", async () => {
+ const previousVersion = new SemVer("1.1.2");
+ const currentVersion = new SemVer("1.2.3");
+ expect(
+ await findFileFowWhatsNew(context, previousVersion, currentVersion)
+ ).to.equal(path.join(dirname, "resources", "whats-new", "1.2.md"));
+ });
+
+ it("should use custom markdown file for major version upgrade", async () => {
+ const previousVersion = new SemVer("0.1.2");
+ const currentVersion = new SemVer("1.2.3");
+ expect(
+ await findFileFowWhatsNew(context, previousVersion, currentVersion)
+ ).to.equal(path.join(dirname, "resources", "whats-new", "1.2.md"));
+ });
+
+ it("should use CHANGELOG.md if custom markdown file does not exist", async () => {
+ const previousVersion = new SemVer("1.1.2");
+ const currentVersion = new SemVer("1.3.3");
+ expect(
+ await findFileFowWhatsNew(context, previousVersion, currentVersion)
+ ).to.equal(path.join(dirname, "CHANGELOG.md"));
+ });
+});
diff --git a/packages/databricks-vscode/src/whatsNewPopup.ts b/packages/databricks-vscode/src/whatsNewPopup.ts
new file mode 100644
index 000000000..643bfd29e
--- /dev/null
+++ b/packages/databricks-vscode/src/whatsNewPopup.ts
@@ -0,0 +1,76 @@
+import {ExtensionContext, Uri, commands, window} from "vscode";
+import {PackageJsonUtils} from "./utils";
+import {StateStorage} from "./vscode-objs/StateStorage";
+import path from "path";
+import {exists} from "fs-extra";
+import * as semver from "semver";
+
+export async function findFileFowWhatsNew(
+ context: ExtensionContext,
+ previousVersion: semver.SemVer,
+ currentVersion: semver.SemVer
+) {
+ const markdownFile = context.asAbsolutePath(
+ path.join(
+ "resources",
+ "whats-new",
+ `${currentVersion.major}.${currentVersion.minor}.md`
+ )
+ );
+
+ // To maintain release discipline (prevent too big changes from being released in a patch version)
+ // we explicitly do not show the custom message popup for patch versions upgrades.
+ currentVersion.patch = 0;
+ previousVersion.patch = 0;
+
+ if (
+ semver.compare(currentVersion, previousVersion) > 0 &&
+ (await exists(markdownFile))
+ ) {
+ return markdownFile;
+ }
+
+ return context.asAbsolutePath("CHANGELOG.md");
+}
+
+export async function showWhatsNewPopup(
+ context: ExtensionContext,
+ storage: StateStorage
+) {
+ const packageJsonMetadata = await PackageJsonUtils.getMetadata(context);
+ const currentVersion = semver.parse(packageJsonMetadata.version);
+ if (currentVersion === null) {
+ return;
+ }
+
+ const previousVersion =
+ semver.parse(storage.lastInstalledExtensionVersion) ??
+ new semver.SemVer("0.0.0");
+
+ // if the extension is downgraded, we do not want to show the popup
+ if (semver.compare(currentVersion, previousVersion) <= 0) {
+ return;
+ }
+
+ // We try to find a custom markdown file for the current version,
+ // if not found, we use the changelog.md in its entirety.
+ const markdownFile = await findFileFowWhatsNew(
+ context,
+ previousVersion,
+ currentVersion
+ );
+
+ if (window.state.focused) {
+ commands.executeCommand("markdown.showPreview", Uri.file(markdownFile));
+ return;
+ }
+
+ const listener = window.onDidChangeWindowState((e) => {
+ if (!e.focused) {
+ return;
+ }
+ commands.executeCommand("markdown.showPreview", Uri.file(markdownFile));
+ listener.dispose();
+ });
+ context.subscriptions.push(listener);
+}
diff --git a/yarn.lock b/yarn.lock
index 227f851c1..24c7ab1aa 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -376,7 +376,7 @@ __metadata:
inversify: ^6.0.1
reflect-metadata: ^0.1.13
semver: ^7.5.4
- checksum: 2e28fb154da0743e5b26cd3bdb1dba6f286e1f34f41d64291fca872ae25678f44a7780bd965f8166632f5a2303a00ecc6def5a9570d09e8d37bcd6546d489cd3
+ checksum: b33948b1c9bb7ff37fe5d34eefedf78ac1df594b311aa2f3cbc7b5cf888c64512d06acb646635653c63fa7dc7634c09cfe7d0ff3cf0bda616c3f0b3494f50dde
languageName: node
linkType: hard
@@ -391,7 +391,7 @@ __metadata:
inversify: ^6.0.1
reflect-metadata: ^0.1.13
semver: ^7.5.4
- checksum: 2e28fb154da0743e5b26cd3bdb1dba6f286e1f34f41d64291fca872ae25678f44a7780bd965f8166632f5a2303a00ecc6def5a9570d09e8d37bcd6546d489cd3
+ checksum: b33948b1c9bb7ff37fe5d34eefedf78ac1df594b311aa2f3cbc7b5cf888c64512d06acb646635653c63fa7dc7634c09cfe7d0ff3cf0bda616c3f0b3494f50dde
languageName: node
linkType: hard
@@ -3717,6 +3717,7 @@ __metadata:
wdio-video-reporter: ^4.0.3
wdio-vscode-service: ^5.2.0
winston: ^3.10.0
+ yaml: ^2.3.2
yargs: ^17.7.2
languageName: unknown
linkType: soft
@@ -11184,6 +11185,13 @@ __metadata:
languageName: node
linkType: hard
+"yaml@npm:^2.3.2":
+ version: 2.3.2
+ resolution: "yaml@npm:2.3.2"
+ checksum: acd80cc24df12c808c6dec8a0176d404ef9e6f08ad8786f746ecc9d8974968c53c6e8a67fdfabcc5f99f3dc59b6bb0994b95646ff03d18e9b1dcd59eccc02146
+ languageName: node
+ linkType: hard
+
"yargs-parser@npm:20.2.4":
version: 20.2.4
resolution: "yargs-parser@npm:20.2.4"