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

only allow the exact version of the backing tool #2644

Merged
merged 2 commits into from
Jan 25, 2023
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
2 changes: 1 addition & 1 deletion eng/package/PackVSCodeExtension.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function Build-VsCodeExtension([string] $packageDirectory, [string] $outputSubDi
# set tool version
if ($kernelVersionNumber -Ne "") {
Write-Host "Setting tool version to $kernelVersionNumber"
$packageJsonContents.contributes.configuration.properties."dotnet-interactive.minimumInteractiveToolVersion"."default" = $kernelVersionNumber
$packageJsonContents.contributes.configuration.properties."dotnet-interactive.requiredInteractiveToolVersion"."default" = $kernelVersionNumber
}

SaveJson -packageJsonPath $packagejsonPath -packageJsonContents $packageJsonContents
Expand Down
7 changes: 4 additions & 3 deletions eng/publish/VerifyVSCodeExtension.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[CmdletBinding(PositionalBinding=$false)]
[CmdletBinding(PositionalBinding = $false)]
param (
[string]$extensionPath
)
Expand Down Expand Up @@ -28,15 +28,16 @@ try {
$availableVersions = ($packageQueryResults."data" | Select-Object -First 1)."versions" | ForEach-Object { $_."version" }

# ensure package exists
$expectedVersion = $packageJsonContents."contributes"."configuration"."properties"."dotnet-interactive.minimumInteractiveToolVersion"."default"
$expectedVersion = $packageJsonContents."contributes"."configuration"."properties"."dotnet-interactive.requiredInteractiveToolVersion"."default"
$exists = $availableVersions -contains $expectedVersion

# cleanup unpacked extension
Remove-Item -Path $tempDir -Recurse

if ($exists) {
Write-Host "Package version $expectedVersion exists on feed $toolFeed"
} else {
}
else {
Write-Host "Package version $expectedVersion not found on feed $toolFeed"
exit 1
}
Expand Down
10 changes: 5 additions & 5 deletions src/dotnet-interactive-vscode-common/src/acquisition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import * as fs from 'fs';
import * as path from 'path';
import { InstallInteractiveTool, InstallInteractiveArgs, CreateToolManifest, GetCurrentInteractiveVersion, InteractiveLaunchOptions, ReportInstallationStarted, ReportInstallationFinished } from './interfaces';

import { isVersionSufficient } from './utilities';
import { isVersionExactlyEqual } from './utilities';

// The acquisition function. Uses predefined callbacks for external command invocations to make testing easier.
export async function acquireDotnetInteractive(
args: InstallInteractiveArgs,
minDotNetInteractiveVersion: string,
requiredDotNetInteractiveVersion: string,
globalStoragePath: string,
getInteractiveVersion: GetCurrentInteractiveVersion,
createToolManifest: CreateToolManifest,
Expand All @@ -34,14 +34,14 @@ export async function acquireDotnetInteractive(
};

// determine if acquisition is necessary
const requiredVersion = args.toolVersion ?? minDotNetInteractiveVersion;
const requiredVersion = args.toolVersion ?? requiredDotNetInteractiveVersion;
const currentVersion = await getInteractiveVersion(args.dotnetPath, globalStoragePath);
if (currentVersion && isVersionSufficient(currentVersion, requiredVersion)) {
if (currentVersion && isVersionExactlyEqual(currentVersion, requiredVersion)) {
// current is acceptable
return launchOptions;
}

// no current version installed or it's out of date
// no current version installed or it's incorrect
reportInstallationStarted(requiredVersion);
await installInteractive({
dotnetPath: args.dotnetPath,
Expand Down
13 changes: 10 additions & 3 deletions src/dotnet-interactive-vscode-common/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,18 @@ import { PromiseCompletionSource } from './dotnet-interactive/promiseCompletionS

import * as constants from './constants';

export function registerAcquisitionCommands(context: vscode.ExtensionContext, diagnosticChannel: ReportChannel) {
export async function registerAcquisitionCommands(context: vscode.ExtensionContext, diagnosticChannel: ReportChannel): Promise<void> {
const dotnetConfig = vscode.workspace.getConfiguration(constants.DotnetConfigurationSectionName);
const minDotNetInteractiveVersion = dotnetConfig.get<string>('minimumInteractiveToolVersion');
const requiredDotNetInteractiveVersion = dotnetConfig.get<string>('requiredInteractiveToolVersion');
const interactiveToolSource = dotnetConfig.get<string>('interactiveToolSource');

if (!requiredDotNetInteractiveVersion) {
const errorTitle = 'Polyglot Notebooks extension will not work.';
const errorDetails = `Incorrect value for option "${constants.DotnetConfigurationSectionName}.requiredInteractiveToolVersion" in settings.json. Please remove this value and restart VS Code.`;
await vscode.window.showErrorMessage(errorTitle, { modal: true, detail: errorDetails });
throw new Error(errorDetails);
}

let cachedInstallArgs: InstallInteractiveArgs | undefined = undefined;
let acquirePromise: Promise<InteractiveLaunchOptions> | undefined = undefined;

Expand All @@ -44,7 +51,7 @@ export function registerAcquisitionCommands(context: vscode.ExtensionContext, di
const installationPromiseCompletionSource = new PromiseCompletionSource<void>();
acquirePromise = acquireDotnetInteractive(
installArgs,
minDotNetInteractiveVersion!,
requiredDotNetInteractiveVersion,
context.globalStorageUri.fsPath,
getInteractiveVersion,
createToolManifest,
Expand Down
6 changes: 3 additions & 3 deletions src/dotnet-interactive-vscode-common/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { registerAcquisitionCommands, registerKernelCommands, registerFileComman
import { languageToCellKind } from './interactiveNotebook';
import { InteractiveLaunchOptions, InstallInteractiveArgs } from './interfaces';

import { createOutput, debounce, getDotNetVersionOrThrow, getWorkingDirectoryForNotebook, isVersionSufficient, processArguments } from './utilities';
import { createOutput, debounce, getDotNetVersionOrThrow, getWorkingDirectoryForNotebook, isVersionGreaterOrEqual, processArguments } from './utilities';
import { OutputChannelAdapter } from './OutputChannelAdapter';

import * as notebookControllers from '../notebookControllers';
Expand Down Expand Up @@ -88,13 +88,13 @@ export async function activate(context: vscode.ExtensionContext) {
await waitForSdkPackExtension();

// this must happen early, because some following functions use the acquisition command
registerAcquisitionCommands(context, diagnosticsChannel);
await registerAcquisitionCommands(context, diagnosticsChannel);

// check sdk version
let showHelpPage = false;
try {
const dotnetVersion = await getDotNetVersionOrThrow(DotNetPathManager.getDotNetPath(), diagnosticsChannel);
if (!isVersionSufficient(dotnetVersion, minDotNetSdkVersion)) {
if (!isVersionGreaterOrEqual(dotnetVersion, minDotNetSdkVersion)) {
showHelpPage = true;
const message = `The .NET SDK version ${dotnetVersion} is not sufficient. The minimum required version is ${minDotNetSdkVersion}.`;
diagnosticsChannel.appendLine(message);
Expand Down
10 changes: 9 additions & 1 deletion src/dotnet-interactive-vscode-common/src/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,15 @@ export function getVersionNumber(output: string): string {
return lines[lines.length - 1];
}

export function isVersionSufficient(firstVersion: string, secondVersion: string): boolean {
export function isVersionExactlyEqual(firstVersion: string, secondVersion: string): boolean {
try {
return compareVersions.compare(firstVersion, secondVersion, '=');
} catch (_) {
return false;
}
}

export function isVersionGreaterOrEqual(firstVersion: string, secondVersion: string): boolean {
try {
return compareVersions.compare(firstVersion, secondVersion, '>=');
} catch (_) {
Expand Down
56 changes: 48 additions & 8 deletions src/dotnet-interactive-vscode-common/tests/acquisition.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ describe('Acquisition tests', () => {
});
});

it("simulate local tool exists, is out of date, and is updated to the auto min version", async () => {
it("simulate local tool exists, is out of date, and is updated to the auto version", async () => {
await withFakeGlobalStorageLocation(true, async globalStoragePath => {
const args = {
dotnetPath: 'dotnet',
Expand All @@ -206,7 +206,7 @@ describe('Acquisition tests', () => {

const launchOptions = await acquireDotnetInteractive(
args,
'42.42.42', // min version
'42.42.42', // required version
globalStoragePath,
getInteractiveVersionThatReturnsSpecificValue('0.0.0'), // report existing version 0.0.0 is installed
createToolManifestThatThrows, // throw if acquisition tries to create another manifest
Expand All @@ -233,7 +233,7 @@ describe('Acquisition tests', () => {
});
});

it("simulate local tool exists, is out of date, and is updated to the specified min version", async () => {
it("simulate local tool exists, is out of date, and is updated to the specified version", async () => {
await withFakeGlobalStorageLocation(true, async globalStoragePath => {
const args = {
dotnetPath: 'dotnet',
Expand All @@ -244,7 +244,7 @@ describe('Acquisition tests', () => {

const launchOptions = await acquireDotnetInteractive(
args,
'42.42.42', // min version
'42.42.42', // required version
globalStoragePath,
getInteractiveVersionThatReturnsSpecificValue('0.0.0'), // report existing version 0.0.0 is installed
createToolManifestThatThrows, // throw if acquisition tries to create another manifest
Expand Down Expand Up @@ -275,7 +275,47 @@ describe('Acquisition tests', () => {
await withFakeGlobalStorageLocation(true, async globalStoragePath => {
const args = {
dotnetPath: 'dotnet',
toolVersion: '42.42.42' // request at least this version
toolVersion: '42.42.42' // install exactly this
};
// prepopulate tool manifest...
await createEmptyToolManifest(args.dotnetPath, globalStoragePath);
// ...with existing version
await installInteractiveTool({ dotnetPath: 'dotnet', toolVersion: '42.42.42' }, globalStoragePath);

const launchOptions = await acquireDotnetInteractive(
args,
'42.42.42', // required version
globalStoragePath,
getInteractiveVersionThatReturnsSpecificValue('42.42.42'), // report existing version 42.42.42 is installed
createToolManifestThatThrows, // throw if acquisition tries to create another manifest
report,
installInteractiveToolThatAlwaysThrows, // throw if acquisition tries to install
report);

expect(globalStoragePath).to.be.a.directory();
const manifestPath = path.join(globalStoragePath, '.config', 'dotnet-tools.json');
expect(manifestPath).to.be.file().with.json;
const jsonContent = JSON.parse(fs.readFileSync(manifestPath).toString());
expect(jsonContent).to.deep.equal({
version: 1,
isRoot: true,
tools: {
'microsoft.dotnet-interactive': {
version: '42.42.42',
commands: [
'dotnet-interactive'
]
}
}
});
});
});

it("simulate local tool exists and is newer than required; version is downgraded", async () => {
await withFakeGlobalStorageLocation(true, async globalStoragePath => {
const args = {
dotnetPath: 'dotnet',
toolVersion: '42.42.42', // install exactly this
};
// prepopulate tool manifest...
await createEmptyToolManifest(args.dotnetPath, globalStoragePath);
Expand All @@ -284,12 +324,12 @@ describe('Acquisition tests', () => {

const launchOptions = await acquireDotnetInteractive(
args,
'42.42.42', // min version
'42.42.42', // required version
globalStoragePath,
getInteractiveVersionThatReturnsSpecificValue('43.43.43'), // report existing version 43.43.43 is installed
createToolManifestThatThrows, // throw if acquisition tries to create another manifest
report,
installInteractiveToolThatAlwaysThrows, // throw if acquisition tries to install
installInteractiveToolWithSpecificVersion('42.42.42'), // 'install' this version when asked
report);

expect(globalStoragePath).to.be.a.directory();
Expand All @@ -301,7 +341,7 @@ describe('Acquisition tests', () => {
isRoot: true,
tools: {
'microsoft.dotnet-interactive': {
version: '43.43.43',
version: '42.42.42', // 43.43.43 was downgraded to 42.42.42
commands: [
'dotnet-interactive'
]
Expand Down
6 changes: 3 additions & 3 deletions src/dotnet-interactive-vscode-insiders/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@
"default": "7.0",
"description": "The minimum required version of the .NET SDK."
},
"dotnet-interactive.minimumInteractiveToolVersion": {
"dotnet-interactive.requiredInteractiveToolVersion": {
"type": "string",
"default": "1.0.406101",
"description": "The minimum required version of the .NET Interactive tool."
"description": "The required version of the .NET Interactive tool."
}
}
},
Expand Down Expand Up @@ -804,4 +804,4 @@
"vscode-textmate": "6.0.0",
"vscode-uri": "3.0.6"
}
}
}
6 changes: 3 additions & 3 deletions src/dotnet-interactive-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,10 @@
"default": "7.0",
"description": "The minimum required version of the .NET SDK."
},
"dotnet-interactive.minimumInteractiveToolVersion": {
"dotnet-interactive.requiredInteractiveToolVersion": {
"type": "string",
"default": "1.0.406101",
"description": "The minimum required version of the .NET Interactive tool."
"description": "The required version of the .NET Interactive tool."
}
}
},
Expand Down Expand Up @@ -803,4 +803,4 @@
"vscode-textmate": "6.0.0",
"vscode-uri": "3.0.6"
}
}
}
4 changes: 2 additions & 2 deletions src/dotnet-interactive-vscode/update-versions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ try {
$newToolVersion = ($packageQueryResults."data" | Select-Object -First 1)."version"

# ...compare to existing...
$existingToolVersion = $packageJsonContents."contributes"."configuration"."properties"."dotnet-interactive.minimumInteractiveToolVersion"."default"
$existingToolVersion = $packageJsonContents."contributes"."configuration"."properties"."dotnet-interactive.requiredInteractiveToolVersion"."default"
if ($existingToolVersion -eq $newToolVersion) {
Write-Host "Existing tool version $existingToolVersion is up to date."
}
else {
Write-Host "Updating tool version from $existingToolVersion to $newToolVersion"
$packageJsonContents."contributes"."configuration"."properties"."dotnet-interactive.minimumInteractiveToolVersion"."default" = $newToolVersion
$packageJsonContents."contributes"."configuration"."properties"."dotnet-interactive.requiredInteractiveToolVersion"."default" = $newToolVersion
}
}

Expand Down