Skip to content
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
3 changes: 2 additions & 1 deletion patched-vscode/build/gulpfile.extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ const compilations = [
'extensions/simple-browser/tsconfig.json',
'extensions/sagemaker-extension/tsconfig.json',
'extensions/sagemaker-idle-extension/tsconfig.json',
'extensions/sagemaker-extensions-sync/tsconfig.json',
'extensions/sagemaker-terminal-crash-mitigation/tsconfig.json',
'extensions/sagemaker-open-notebook-extension/tsconfig.json',
'extensions/sagemaker-ui-dark-theme/tsconfig.json',
'extensions/post-startup-notifications/tsconfig.json',
'extensions/post-startup-notifications/tsconfig.json',
'extensions/tunnel-forwarding/tsconfig.json',
'extensions/typescript-language-features/test-workspace/tsconfig.json',
'extensions/typescript-language-features/web/tsconfig.json',
Expand Down
3 changes: 2 additions & 1 deletion patched-vscode/build/npm/dirs.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ const dirs = [
'extensions/php-language-features',
'extensions/references-view',
'extensions/sagemaker-extension',
'extensions/sagemaker-extensions-sync',
'extensions/sagemaker-idle-extension',
'extensions/sagemaker-terminal-crash-mitigation',
'extensions/sagemaker-open-notebook-extension',
'extensions/sagemaker-ui-dark-theme',
'extensions/post-startup-notifications',
'extensions/post-startup-notifications',
'extensions/search-result',
'extensions/simple-browser',
'extensions/tunnel-forwarding',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"dbaeumer.vscode-eslint",
"amodio.tsl-problem-matcher",
"ms-vscode.extension-test-runner"
]
}
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": ["dbaeumer.vscode-eslint", "amodio.tsl-problem-matcher", "ms-vscode.extension-test-runner"]
}
12 changes: 12 additions & 0 deletions patched-vscode/extensions/sagemaker-extensions-sync/.vscodeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.vscode/**
.vscode-test/**
out/test/**
out/**
test/**
src/**
tsconfig.json
out/test/**
out/**
cgmanifest.json
yarn.lock
preview-src/**
3 changes: 3 additions & 0 deletions patched-vscode/extensions/sagemaker-extensions-sync/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SageMaker Code Editor Extensions Sync

Notifies users if the extensions directory is missing pre-packaged extensions from SageMaker Distribution and give them the option to sync them.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*---------------------------------------------------------------------------------------------
* Copyright Amazon.com Inc. or its affiliates. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

//@ts-check

'use strict';

const withBrowserDefaults = require('../shared.webpack.config').browser;

module.exports = withBrowserDefaults({
context: __dirname,
entry: {
extension: './src/extension.ts'
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright Amazon.com Inc. or its affiliates. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

//@ts-check

'use strict';

const withDefaults = require('../shared.webpack.config');

module.exports = withDefaults({
context: __dirname,
resolve: {
mainFields: ['module', 'main']
},
entry: {
extension: './src/extension.ts',
}
});
44 changes: 44 additions & 0 deletions patched-vscode/extensions/sagemaker-extensions-sync/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "sagemaker-extensions-sync",
"displayName": "SageMaker Extensions Sync",
"description": "Sync pre-packaged extensions from SageMaker Distribution",
"extensionKind": [
"workspace"
],
"version": "1.0.0",
"publisher": "sagemaker",
"license": "MIT",
"engines": {
"vscode": "^1.70.0"
},
"main": "./out/extension",
"categories": [
"Other"
],
"activationEvents": [
"*"
],
"capabilities": {
"virtualWorkspaces": true,
"untrustedWorkspaces": {
"supported": true
}
},
"contributes": {
"commands": [
{
"command": "extensions-sync.syncExtensions",
"title": "Sync Extensions from SageMaker Distribution",
"category": "Extensions Sync"
}
]
},
"scripts": {
"compile": "gulp compile-extension:sagemaker-extensions-sync",
"watch": "npm run build-preview && gulp watch-extension:sagemaker-extensions-sync",
"vscode:prepublish": "npm run build-ext",
"build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:sagemaker-idle-extension ./tsconfig.json"
},
"dependencies": {},
"repository": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// constants
export const PERSISTENT_VOLUME_EXTENSIONS_DIR = "/home/sagemaker-user/sagemaker-code-editor-server-data/extensions";
export const IMAGE_EXTENSIONS_DIR = "/opt/amazon/sagemaker/sagemaker-code-editor-server-data/extensions";
export const LOG_PREFIX = "[sagemaker-extensions-sync]";

export class ExtensionInfo {
constructor(
public name: string,
public publisher: string,
public version: string,
public path: string | null
) {}

get identifier(): string {
return `${this.publisher}.${this.name}@${this.version}`;
}

toString(): string {
return `ExtensionInfo: ${this.identifier} (${this.path})`;
}
}
100 changes: 100 additions & 0 deletions patched-vscode/extensions/sagemaker-extensions-sync/src/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import * as process from "process";
import * as vscode from 'vscode';

import {
ExtensionInfo,
IMAGE_EXTENSIONS_DIR,
LOG_PREFIX,
PERSISTENT_VOLUME_EXTENSIONS_DIR,
} from "./constants"

import {
getExtensionsFromDirectory,
getInstalledExtensions,
installExtension,
refreshExtensionsMetadata } from "./utils"

export async function activate() {

// this extension will only activate within a sagemaker app
const isSageMakerApp = !!process.env?.SAGEMAKER_APP_TYPE_LOWERCASE;
if (!isSageMakerApp) {
return;
}

// get installed extensions. this could be different from pvExtensions b/c vscode sometimes doesn't delete the assets
// for an old extension when uninstalling or changing versions
const installedExtensions = new Set(await getInstalledExtensions());
console.log(`${LOG_PREFIX} Found installed extensions: `, Array.from(installedExtensions));

const prePackagedExtensions: ExtensionInfo[] = await getExtensionsFromDirectory(IMAGE_EXTENSIONS_DIR);
const prePackagedExtensionsById: Record<string, ExtensionInfo> = {};
prePackagedExtensions.forEach(extension => {
prePackagedExtensionsById[extension.identifier] = extension;
});

console.log(`${LOG_PREFIX} Found pre-packaged extensions: `, prePackagedExtensions);

const pvExtensions = await getExtensionsFromDirectory(PERSISTENT_VOLUME_EXTENSIONS_DIR);
const pvExtensionsByName: Record<string, ExtensionInfo> = {};
const pvExtensionsById: Record<string, ExtensionInfo> = {};
pvExtensions.forEach(extension => {
if (installedExtensions.has(extension.identifier)) { // only index extensions that are installed
pvExtensionsByName[extension.name] = extension;
pvExtensionsById[extension.identifier] = extension;
}
});
console.log(`${LOG_PREFIX} Found installed extensions in persistent volume: `, pvExtensionsById);

// check each pre-packaged extension, record if it is not in installed extensions or version mismatch
// store unsynced extensions as {identifier pre-packaged ext: currently installed version}
const unsyncedExtensions: Record<string, string | null> = {}
prePackagedExtensions.forEach(extension => {
const id = extension.identifier;
if (!(installedExtensions.has(id))){
unsyncedExtensions[id] = pvExtensionsByName[extension.name]?.version ?? null;
}
});
console.log(`${LOG_PREFIX} Unsynced extensions: `, unsyncedExtensions);

if (Object.keys(unsyncedExtensions).length !== 0) {
const selection = await vscode.window.showWarningMessage(
'Warning: You have unsynchronized extensions from SageMaker Distribution \
which could result in incompatibilities with Code Editor. Do you want to install them?',
"Synchronize Extensions", "Dismiss");

if (selection === "Synchronize Extensions") {
const quickPick = vscode.window.createQuickPick();
quickPick.items = Object.keys(unsyncedExtensions).map(extensionId => ({
label: extensionId,
description: unsyncedExtensions[extensionId] ? `Currently installed version: ${unsyncedExtensions[extensionId]}` : undefined,
}));
quickPick.placeholder = 'Select extensions to install';
quickPick.canSelectMany = true;
quickPick.ignoreFocusOut = true;

quickPick.onDidAccept(async () => {
const selectedExtensions = quickPick.selectedItems.map(item => item.label);

for (const extensionId of selectedExtensions) {
const extensionName = prePackagedExtensionsById[extensionId].name;
await installExtension(prePackagedExtensionsById[extensionId], pvExtensionsByName[extensionName]);
}
await refreshExtensionsMetadata();

quickPick.hide();
await vscode.window.showInformationMessage(
'Extensions have been installed. \nWould you like to reload the window?',
{ modal: true },
'Reload'
).then(selection => {
if (selection === 'Reload') {
vscode.commands.executeCommand('workbench.action.reloadWindow');
}
});
});

quickPick.show();
}
}
}
Loading