Skip to content

Commit

Permalink
Merge pull request #1613 from nagilson/nagilson-2.0.1-release
Browse files Browse the repository at this point in the history
Fix SDK Linux Updates, & Add Cancellation Messages - 2.0.1 Release
  • Loading branch information
nagilson authored Jan 25, 2024
2 parents 946b20d + aac1f73 commit 2c4ca30
Show file tree
Hide file tree
Showing 22 changed files with 229 additions and 81 deletions.
4 changes: 2 additions & 2 deletions sample/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions sample/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1832,7 +1832,7 @@

"vscode-dotnet-runtime@file:../vscode-dotnet-runtime-extension":
"resolved" "file:../vscode-dotnet-runtime-extension"
"version" "2.0.0"
"version" "2.0.1"
dependencies:
"axios" "^1.3.4"
"axios-cache-interceptor" "^1.0.1"
Expand Down Expand Up @@ -1860,7 +1860,7 @@

"vscode-dotnet-sdk@file:../vscode-dotnet-sdk-extension":
"resolved" "file:../vscode-dotnet-sdk-extension"
"version" "2.0.0"
"version" "2.0.1"
dependencies:
"@types/chai" "4.2.22"
"@types/chai-as-promised" "^7.1.4"
Expand Down
22 changes: 21 additions & 1 deletion vscode-dotnet-runtime-extension/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,27 @@ The format is based on [Keep a Changelog],
and this project adheres to [Semantic Versioning].

## [Unreleased]
## [2.0.0] - 2023-09-18
## [2.0.1] - 2024-01-03

Fixes several key bugs with installing .NET:

- Ubuntu Global SDK Installs would fail for the first time on 18.04.
- The extension would print ... forever after installation failure for certain errors.
- The extension would fail to read Ubuntu directories properly for the first time if PMC was installed in certain scenarios.
- GitHub Forms is now added.
- Corrects behavior on our unknown Ubuntu Versions by estimating the correct behavior for known versions.
- Improve timeout error handling
- Catch bug in the caching library we use to prevent it from failing to cache
- Remove bug where status bar would stay red when cancelling install
- Fix bug where Linux would not update .NET SDKs properly when it could update instead of install
- Detect when a user cancels the installation in the password prompt or windows installer so we can remove the error failure message
- Adds more logging to the extension to improve diagnostics and speed to resolve github issues
- Improve installation management, so that the extension is aware that installs it manages can be deleted by external sources, to prevent it from thinking something is installed when it is no longer installed.
- Fix an issue where the uninstall command would think it could uninstall a global SDK. This is not the case.
- Improve detection logic for existing Ubuntu and RHEL installations of linux to prevent installing when it is not needed
- Several other key issues.

## [2.0.0] - 2023-11-23

The '.NET Runtime Install Tool' has been renamed to the '.NET Install Tool.'

Expand Down
4 changes: 2 additions & 2 deletions vscode-dotnet-runtime-extension/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vscode-dotnet-runtime-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"description": "This extension installs and manages different versions of the .NET SDK and Runtime.",
"appInsightsKey": "02dc18e0-7494-43b2-b2a3-18ada5fcb522",
"icon": "images/dotnetIcon.png",
"version": "2.0.0",
"version": "2.0.1",
"publisher": "ms-dotnettools",
"engines": {
"vscode": "^1.74.0"
Expand Down
24 changes: 12 additions & 12 deletions vscode-dotnet-runtime-extension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export function activate(context: vscode.ExtensionContext, extensionContext?: IE
showLogCommand: `${commandPrefix}.${commandKeys.showAcquisitionLog}`,
packageJson
} as IEventStreamContext;
const [eventStream, outputChannel, loggingObserver, eventStreamObservers, telemetryObserver] = registerEventStream(eventStreamContext, vsCodeExtensionContext, utilContext);
const [globalEventStream, outputChannel, loggingObserver, eventStreamObservers, telemetryObserver] = registerEventStream(eventStreamContext, vsCodeExtensionContext, utilContext);


// Setting up command-shared classes for Runtime & SDK Acquisition
Expand All @@ -125,8 +125,8 @@ export function activate(context: vscode.ExtensionContext, extensionContext?: IE
const dotnetAcquireRegistration = vscode.commands.registerCommand(`${commandPrefix}.${commandKeys.acquire}`, async (commandContext: IDotnetAcquireContext) => {
let fullyResolvedVersion = '';
const dotnetPath = await callWithErrorHandling<Promise<IDotnetAcquireResult>>(async () => {
eventStream.post(new DotnetRuntimeAcquisitionStarted(commandContext.requestingExtensionId));
eventStream.post(new DotnetAcquisitionRequested(commandContext.version, commandContext.requestingExtensionId));
globalEventStream.post(new DotnetRuntimeAcquisitionStarted(commandContext.requestingExtensionId));
globalEventStream.post(new DotnetAcquisitionRequested(commandContext.version, commandContext.requestingExtensionId));

runtimeAcquisitionWorker.setAcquisitionContext(commandContext);
telemetryObserver?.setAcquisitionContext(runtimeContext, commandContext);
Expand Down Expand Up @@ -154,7 +154,7 @@ export function activate(context: vscode.ExtensionContext, extensionContext?: IE
}, runtimeIssueContextFunctor(commandContext.errorConfiguration, 'acquire', commandContext.version), commandContext.requestingExtensionId, runtimeContext);

const installKey = runtimeAcquisitionWorker.getInstallKey(fullyResolvedVersion);
eventStream.post(new DotnetRuntimeAcquisitionTotalSuccessEvent(commandContext.version, installKey, commandContext.requestingExtensionId ?? '', dotnetPath?.dotnetPath ?? ''));
globalEventStream.post(new DotnetRuntimeAcquisitionTotalSuccessEvent(commandContext.version, installKey, commandContext.requestingExtensionId ?? '', dotnetPath?.dotnetPath ?? ''));
return dotnetPath;
});

Expand All @@ -167,8 +167,8 @@ export function activate(context: vscode.ExtensionContext, extensionContext?: IE

const pathResult = callWithErrorHandling(async () =>
{
eventStream.post(new DotnetSDKAcquisitionStarted(commandContext.requestingExtensionId));
eventStream.post(new DotnetAcquisitionRequested(commandContext.version, commandContext.requestingExtensionId));
globalEventStream.post(new DotnetSDKAcquisitionStarted(commandContext.requestingExtensionId));
globalEventStream.post(new DotnetAcquisitionRequested(commandContext.version, commandContext.requestingExtensionId));

const existingPath = await resolveExistingPathIfExists(existingPathConfigWorker, commandContext);
if(existingPath)
Expand Down Expand Up @@ -196,7 +196,7 @@ export function activate(context: vscode.ExtensionContext, extensionContext?: IE

const dotnetAcquireStatusRegistration = vscode.commands.registerCommand(`${commandPrefix}.${commandKeys.acquireStatus}`, async (commandContext: IDotnetAcquireContext) => {
const pathResult = callWithErrorHandling(async () => {
eventStream.post(new DotnetAcquisitionStatusRequested(commandContext.version, commandContext.requestingExtensionId));
globalEventStream.post(new DotnetAcquisitionStatusRequested(commandContext.version, commandContext.requestingExtensionId));
const resolvedVersion = await runtimeVersionResolver.getFullRuntimeVersion(commandContext.version);
const dotnetPath = await runtimeAcquisitionWorker.acquireStatus(resolvedVersion, true);
return dotnetPath;
Expand All @@ -220,7 +220,7 @@ export function activate(context: vscode.ExtensionContext, extensionContext?: IE
const result = cp.spawnSync(commandContext.command, commandContext.arguments);
const installer = new DotnetCoreDependencyInstaller();
if (installer.signalIndicatesMissingLinuxDependencies(result.signal!)) {
eventStream.post(new DotnetAcquisitionMissingLinuxDependencies());
globalEventStream.post(new DotnetAcquisitionMissingLinuxDependencies());
await installer.promptLinuxDependencyInstall('Failed to run .NET runtime.');
}
}, runtimeIssueContextFunctor(commandContext.errorConfiguration, 'ensureDependencies'));
Expand All @@ -239,7 +239,7 @@ export function activate(context: vscode.ExtensionContext, extensionContext?: IE

const existingPath = existingPathResolver.resolveExistingPath(configResolver.getPathConfigurationValue(), commandContext.requestingExtensionId, displayWorker);
if (existingPath) {
eventStream.post(new DotnetExistingPathResolutionCompleted(existingPath.dotnetPath));
globalEventStream.post(new DotnetExistingPathResolutionCompleted(existingPath.dotnetPath));
return new Promise((resolve) => {
resolve(existingPath);
});
Expand All @@ -254,8 +254,8 @@ export function activate(context: vscode.ExtensionContext, extensionContext?: IE
return {
storagePath: context.globalStoragePath,
extensionState: context.globalState,
eventStream,
installationValidator: new InstallationValidator(eventStream),
eventStream: globalEventStream,
installationValidator: new InstallationValidator(globalEventStream),
timeoutSeconds: resolvedTimeoutSeconds,
installDirectoryProvider: isRuntimeInstall ? new RuntimeInstallationDirectoryProvider(context.globalStoragePath): new SdkInstallationDirectoryProvider(context.globalStoragePath),
proxyUrl: proxyLink,
Expand All @@ -276,7 +276,7 @@ export function activate(context: vscode.ExtensionContext, extensionContext?: IE
errorConfiguration: errorConfiguration || AcquireErrorConfiguration.DisplayAllErrorPopups,
displayWorker,
extensionConfigWorker: configResolver,
eventStream,
eventStream: globalEventStream,
commandName,
version,
moreInfoUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@
"commandParts": ["-f", "{path}"]
}
],
"expectedDistroFeedInstallDirectory": "/usr/lib64/dotnet/dotnet",
"expectedDistroFeedInstallDirectory": "/usr/lib64/dotnet",
"expectedMicrosoftFeedInstallDirectory": "",
"installedSDKVersionsCommand": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ export class DotnetCoreAcquisitionWorker implements IDotnetCoreAcquisitionWorker

this.context.eventStream.post(new DotnetBeginGlobalInstallerExecution(`Beginning to run installer for ${installKey} in ${os.platform()}.`))
const installerResult = await installer.installSDK();
this.context.eventStream.post(new DotnetCompletedGlobalInstallerExecution(`Beginning to run installer for ${installKey} in ${os.platform()}.`))
this.context.eventStream.post(new DotnetCompletedGlobalInstallerExecution(`Completed installer for ${installKey} in ${os.platform()}.`))

if(installerResult !== '0')
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,23 @@ export class GenericDistroSDKProvider extends IDistroDotnetSDKProvider
public async getInstalledGlobalDotnetPathIfExists(installType : LinuxInstallType) : Promise<string | null>
{
const commandResult = await this.commandRunner.executeMultipleCommands(this.myDistroCommands(this.currentInstallPathCommandKey));

const oldReturnStatusSetting = this.commandRunner.returnStatus;
this.commandRunner.returnStatus = true;
const commandSignal = await this.commandRunner.executeMultipleCommands(this.myDistroCommands(this.currentInstallPathCommandKey));
this.commandRunner.returnStatus = oldReturnStatusSetting;

if(commandSignal[0] !== '0') // no dotnet error can be returned, dont want to try to parse this as a path
{
return null;
}

if(commandResult[0])
{
commandResult[0] = commandResult[0].trim();
}

if(commandResult && this.resolvePathAsSymlink)
if(commandResult[0] && this.resolvePathAsSymlink)
{
let symLinkReadCommand = this.myDistroCommands(this.readSymbolicLinkCommandKey);
symLinkReadCommand = CommandExecutor.replaceSubstringsInCommands(symLinkReadCommand, this.missingPathKey, commandResult[0]);
Expand All @@ -51,7 +62,7 @@ export class GenericDistroSDKProvider extends IDistroDotnetSDKProvider
}
}

return commandResult[0];
return commandResult[0] ?? null;
}

public async dotnetPackageExistsOnSystem(fullySpecifiedDotnetVersion : string, installType : LinuxInstallType) : Promise<boolean>
Expand All @@ -77,11 +88,15 @@ export class GenericDistroSDKProvider extends IDistroDotnetSDKProvider

public async upgradeDotnet(versionToUpgrade : string, installType : LinuxInstallType): Promise<string>
{
const oldReturnStatusSetting = this.commandRunner.returnStatus;
this.commandRunner.returnStatus = true;

let command = this.myDistroCommands(this.updateCommandKey);
const sdkPackage = await this.myDotnetVersionPackageName(versionToUpgrade, installType);
command = CommandExecutor.replaceSubstringsInCommands(command, this.missingPackageNameKey, sdkPackage);
const commandResult = (await this.commandRunner.executeMultipleCommands(command))[0];

this.commandRunner.returnStatus = oldReturnStatusSetting;
return commandResult[0];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import
{
DotnetAcquisitionDistroUnknownError,
DotnetConflictingLinuxInstallTypesError,
DotnetCustomLinuxInstallExistsError
DotnetCustomLinuxInstallExistsError,
DotnetInstallLinuxChecks,
DotnetUpgradedEvent
} from '../EventStream/EventStreamEvents';
import { GenericDistroSDKProvider } from './GenericDistroSDKProvider'
import { VersionResolver } from './VersionResolver';
Expand Down Expand Up @@ -67,6 +69,8 @@ export class LinuxVersionResolver
protected distroSDKProvider : IDistroDotnetSDKProvider | null = null;
protected commandRunner : ICommandExecutor;
protected versionResolver : VersionResolver;
public okUpdateExitCode = 11188; // Arbitrary number that is not shared or used by other things we rely on as an exit code
public okAlreadyExistsExitCode = 11166;

public conflictingInstallErrorMessage = `A dotnet installation was found which indicates dotnet that was installed via Microsoft package feeds. But for this distro and version, we only acquire .NET via the distro feeds.
You should not mix distro feed and microsoft feed installations. To continue, please completely remove this version of dotnet to continue by following https://learn.microsoft.com/dotnet/core/install/remove-runtime-sdk-versions?pivots=os-linux.
Expand Down Expand Up @@ -181,9 +185,9 @@ export class LinuxVersionResolver
case 'Red Hat Enterprise Linux':
if(this.isRedHatVersion7(distroAndVersion.version))
{
const error = new DotnetAcquisitionDistroUnknownError(new Error(this.redhatUnsupportedDistroErrorMessage), getInstallKeyFromContext(this.acquireContext));
this.acquisitionContext.eventStream.post(error);
throw error.error;
const unsupportedRhelErr = new DotnetAcquisitionDistroUnknownError(new Error(this.redhatUnsupportedDistroErrorMessage), getInstallKeyFromContext(this.acquireContext));
this.acquisitionContext.eventStream.post(unsupportedRhelErr);
throw unsupportedRhelErr.error;
}
return new RedHatDistroSDKProvider(distroAndVersion, this.acquisitionContext, this.utilityContext);
default:
Expand Down Expand Up @@ -250,34 +254,43 @@ export class LinuxVersionResolver
* @returns 0 if we can proceed. Will throw if a conflicting install exists. If we can update, it will do the update and return 1.
* A string is returned in case we want to make this return more info about the update.
*/
private async UpdateOrRejectIfVersionRequestDoesNotRequireInstall(fullySpecifiedDotnetVersion : string, existingInstall : string | null)
private async UpdateOrRejectIfVersionRequestDoesNotRequireInstall(fullySpecifiedDotnetVersion : string, existingInstall : string | null) : Promise<string>
{
await this.Initialize();

this.acquisitionContext.eventStream.post(new DotnetInstallLinuxChecks(`Checking to see if we should install, update, or cancel...`));
if(existingInstall)
{
const existingGlobalInstallSDKVersion = await this.distroSDKProvider!.getInstalledGlobalDotnetVersionIfExists();
if(existingGlobalInstallSDKVersion && Number(this.versionResolver.getMajorMinor(existingGlobalInstallSDKVersion)) ===
Number(this.versionResolver.getMajorMinor(fullySpecifiedDotnetVersion)))
{
if(Number(this.versionResolver.getMajorMinor(existingGlobalInstallSDKVersion)) > Number(this.versionResolver.getMajorMinor(fullySpecifiedDotnetVersion)))
const isPatchUpgrade = Number(this.versionResolver.getFeatureBandPatchVersion(existingGlobalInstallSDKVersion)) <
Number(this.versionResolver.getFeatureBandPatchVersion(fullySpecifiedDotnetVersion));

if(Number(this.versionResolver.getMajorMinor(existingGlobalInstallSDKVersion)) > Number(this.versionResolver.getMajorMinor(fullySpecifiedDotnetVersion))
|| Number(this.versionResolver.getFeatureBandFromVersion(existingGlobalInstallSDKVersion)) > Number(this.versionResolver.getFeatureBandFromVersion(fullySpecifiedDotnetVersion)))
{
// We shouldn't downgrade to a lower patch
const err = new DotnetCustomLinuxInstallExistsError(new Error(`An installation of ${fullySpecifiedDotnetVersion} was requested but ${existingGlobalInstallSDKVersion} is already available.`),
getInstallKeyFromContext(this.acquireContext));
this.acquisitionContext.eventStream.post(err);
throw err.error;
}
else if(await this.distroSDKProvider!.dotnetPackageExistsOnSystem(fullySpecifiedDotnetVersion, 'sdk') ||
Number(this.versionResolver.getFeatureBandPatchVersion(existingGlobalInstallSDKVersion)) < Number(this.versionResolver.getFeatureBandPatchVersion(fullySpecifiedDotnetVersion)))
else if(await this.distroSDKProvider!.dotnetPackageExistsOnSystem(fullySpecifiedDotnetVersion, 'sdk') || isPatchUpgrade)
{
// We can update instead of doing an install
return (await this.distroSDKProvider!.upgradeDotnet(existingGlobalInstallSDKVersion, 'sdk')) ? '1' : '1';
this.acquisitionContext.eventStream.post(new DotnetUpgradedEvent(
isPatchUpgrade ?
`Updating .NET: Current Version: ${existingGlobalInstallSDKVersion} to ${fullySpecifiedDotnetVersion}.`
:
`Repairing .NET Packages for ${existingGlobalInstallSDKVersion}.`));
return (await this.distroSDKProvider!.upgradeDotnet(existingGlobalInstallSDKVersion, 'sdk')) === '0' ? String(this.okUpdateExitCode) : '1';
}
else
{
// An existing install exists.
return '1';
return String(this.okAlreadyExistsExitCode);
}
}
// Additional logic to check the major.minor could be added here if we wanted to prevent installing lower major.minors if an existing install existed.
Expand Down Expand Up @@ -310,7 +323,11 @@ export class LinuxVersionResolver
{
return await this.distroSDKProvider!.installDotnet(fullySpecifiedDotnetVersion, 'sdk') ? '0' : '1';
}
return updateOrRejectState;
else if(updateOrRejectState === String(this.okUpdateExitCode) || updateOrRejectState === String(this.okAlreadyExistsExitCode))
{
return '0';
}
return String(updateOrRejectState);
}

/**
Expand Down
Loading

0 comments on commit 2c4ca30

Please sign in to comment.