From 0adfd48460a0c5ba6d609cbfe5b8c693857cefc1 Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Thu, 18 Jun 2026 15:42:02 -0700 Subject: [PATCH 01/11] Clarify ensureDotnetDependencies arguments Document that the legacy dotnet.ensureDotnetDependencies command is intended to probe a specific dotnet DLL payload, matching the C# extension language server usage. Update IDotnetEnsureDependenciesContext to include string[] alongside the previously published SpawnSyncOptionsWithStringEncoding shape. This is not a breaking change because string[] is the runtime behavior existing callers already use today. Add focused functional coverage for the --info signal path and the DLL payload path. --- Documentation/commands.md | 6 ++ .../src/extension.ts | 4 +- .../DotnetCoreAcquisitionExtension.test.ts | 97 ++++++++++++++++++- .../install scripts/install-linux-prereqs.sh | 16 +-- .../src/IDotnetEnsureDependenciesContext.ts | 2 +- .../unit/LinuxPrereqsInstallerScript.test.ts | 63 ++++++++++++ 6 files changed, 177 insertions(+), 11 deletions(-) create mode 100644 vscode-dotnet-runtime-library/src/test/unit/LinuxPrereqsInstallerScript.test.ts diff --git a/Documentation/commands.md b/Documentation/commands.md index f3d0559b4b..da7f4a38a8 100644 --- a/Documentation/commands.md +++ b/Documentation/commands.md @@ -136,6 +136,12 @@ Note: Each VS Code window gets its own extension host log folder, so the returne This command is only applicable to Linux machines. It attempts to ensure that .NET dependencies are present and, if they are not, installs them or prompts the user to do so. It accepts a [IDotnetEnsureDependenciesContext](https://github.com/dotnet/vscode-dotnet-runtime/blob/main/vscode-dotnet-runtime-library/src/IDotnetEnsureDependenciesContext.ts) object and has a void return type. It is no longer supported but remains to support legacy behavior. +The intended probe shape is `command: ` with `arguments` set to a `string[]` containing the .NET DLL payload to load and run. For example, the C# extension calls this command with the acquired `dotnet` path and an argument array containing its language server DLL. This lets the command test whether the specific .NET payload needed by the caller can start, and if it fails with a Linux dependency signal, the user is prompted to install missing dependencies. + +Passing CLI-only arguments such as `['--info']` runs the .NET CLI information path instead of the caller's payload and can exercise different runtime dependencies. That can be useful for diagnosis, but it is not the intended contract for this legacy command. + +The TypeScript type for `arguments` includes both `string[]` and `child_process.SpawnSyncOptionsWithStringEncoding`. The `string[]` member reflects the runtime behavior that existing callers already use today, so adding it to the published type is not a breaking change. The older options-object shape remains accepted for compatibility with the previously published definition. + ### dotnet.reportIssue This is a **user-facing** command that opens a pre-populated GitHub issue in the browser and copies the issue body to the clipboard. It does not accept parameters and has a void return type. diff --git a/vscode-dotnet-runtime-extension/src/extension.ts b/vscode-dotnet-runtime-extension/src/extension.ts index b5d7a0e043..f1eb3b7e4e 100644 --- a/vscode-dotnet-runtime-extension/src/extension.ts +++ b/vscode-dotnet-runtime-extension/src/extension.ts @@ -911,7 +911,9 @@ ${JSON.stringify(commandContext)}`)); return; } - const result = cp.spawnSync(commandContext.command, commandContext.arguments); + const result = Array.isArray(commandContext.arguments) + ? cp.spawnSync(commandContext.command, commandContext.arguments) + : cp.spawnSync(commandContext.command, commandContext.arguments); const installer = new DotnetCoreDependencyInstaller(); if (installer.signalIndicatesMissingLinuxDependencies(result.signal!)) { diff --git a/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts b/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts index e09344f60b..6a8758fd84 100644 --- a/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts +++ b/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts @@ -3,6 +3,7 @@ * The .NET Foundation licenses this file to you under the MIT license. *--------------------------------------------------------------------------------------------*/ import * as chai from 'chai'; +import * as cp from 'child_process'; import { warn } from 'console'; import * as fs from 'fs'; import * as os from 'os'; @@ -13,6 +14,7 @@ import DotnetInstallMode, DotnetInstallType, DotnetVersionSpecRequirement, + DotnetCoreDependencyInstaller, EnvironmentVariableIsDefined, FileUtilities, getDistroInfo, @@ -58,6 +60,7 @@ suite('DotnetCoreAcquisitionExtension End to End', function () const requestingExtensionId = 'fake.extension'; const mockDisplayWorker = new MockWindowDisplayWorker(); let extensionContext: vscode.ExtensionContext; + let skipInstallCleanupAfterTest = false; const environmentVariableCollection = new MockEnvironmentVariableCollection(); const existingPathVersionToFake = '5.0.1~x64' @@ -116,7 +119,11 @@ suite('DotnetCoreAcquisitionExtension End to End', function () process.env.PATH = originalPATH; LocalMemoryCacheSingleton.getInstance().invalidate(); - await vscode.commands.executeCommand('dotnet.uninstallAll'); + if (!skipInstallCleanupAfterTest) + { + await vscode.commands.executeCommand('dotnet.uninstallAll'); + } + skipInstallCleanupAfterTest = false; mockState.clear(); MockTelemetryReporter.telemetryEvents = []; await new FileUtilities().wipeDirectory(storagePath); @@ -160,6 +167,94 @@ suite('DotnetCoreAcquisitionExtension End to End', function () assert.isTrue(logContents.length > 0, 'Log file is non-empty after activation'); }).timeout(standardTimeoutTime); + test('dotnet.ensureDotnetDependencies prompts when dotnet --info fails with a Linux dependency signal', async () => + { + const originalPlatform = os.platform; + const originalProcessPlatform = process.platform; + const originalSpawnSync = cp.spawnSync; + const originalPromptLinuxDependencyInstall = DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall; + let promptCount = 0; + + try + { + skipInstallCleanupAfterTest = true; + Object.defineProperty(os, 'platform', { value: () => 'linux', configurable: true, writable: true }); + Object.defineProperty(process, 'platform', { value: 'linux', configurable: true, writable: true }); + Object.defineProperty(cp, 'spawnSync', { + configurable: true, + writable: true, + value: (command: string, args?: string[]) => + { + assert.equal(command, 'dotnet'); + assert.deepEqual(args, ['--info']); + return { signal: 'SIGABRT', stderr: Buffer.from('Couldn\'t find a valid ICU package installed on the system.') }; + } + }); + DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall = async (message: string) => + { + assert.equal(message, 'Failed to run .NET runtime.'); + promptCount++; + return false; + }; + + await vscode.commands.executeCommand('dotnet.ensureDotnetDependencies', { command: 'dotnet', arguments: ['--info'] }); + + assert.equal(promptCount, 1, 'Missing Linux dependency prompt should be shown when dotnet --info aborts.'); + } + finally + { + Object.defineProperty(os, 'platform', { value: originalPlatform, configurable: true, writable: true }); + Object.defineProperty(process, 'platform', { value: originalProcessPlatform, configurable: true, writable: true }); + Object.defineProperty(cp, 'spawnSync', { value: originalSpawnSync, configurable: true, writable: true }); + DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall = originalPromptLinuxDependencyInstall; + } + }).timeout(standardTimeoutTime); + + test('dotnet.ensureDotnetDependencies does not prompt when a dotnet dll payload starts successfully', async () => + { + const originalPlatform = os.platform; + const originalProcessPlatform = process.platform; + const originalSpawnSync = cp.spawnSync; + const originalPromptLinuxDependencyInstall = DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall; + let promptCount = 0; + + try + { + skipInstallCleanupAfterTest = true; + Object.defineProperty(os, 'platform', { value: () => 'linux', configurable: true, writable: true }); + Object.defineProperty(process, 'platform', { value: 'linux', configurable: true, writable: true }); + Object.defineProperty(cp, 'spawnSync', { + configurable: true, + writable: true, + value: (command: string, args?: string[]) => + { + assert.equal(command, 'dotnet'); + assert.deepEqual(args, [path.join('server', 'Microsoft.CodeAnalysis.LanguageServer.dll')]); + return { signal: null }; + } + }); + DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall = async () => + { + promptCount++; + return false; + }; + + await vscode.commands.executeCommand('dotnet.ensureDotnetDependencies', { + command: 'dotnet', + arguments: [path.join('server', 'Microsoft.CodeAnalysis.LanguageServer.dll')] + }); + + assert.equal(promptCount, 0, 'Missing Linux dependency prompt should not be shown when the dotnet dll payload starts.'); + } + finally + { + Object.defineProperty(os, 'platform', { value: originalPlatform, configurable: true, writable: true }); + Object.defineProperty(process, 'platform', { value: originalProcessPlatform, configurable: true, writable: true }); + Object.defineProperty(cp, 'spawnSync', { value: originalSpawnSync, configurable: true, writable: true }); + DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall = originalPromptLinuxDependencyInstall; + } + }).timeout(standardTimeoutTime); + async function installRuntime(dotnetVersion: string, installMode: DotnetInstallMode, arch?: string) { let context: IDotnetAcquireContext = { version: dotnetVersion, requestingExtensionId, mode: installMode }; diff --git a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh index 38ef73405d..a9ef7a2dd7 100644 --- a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh +++ b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh @@ -69,7 +69,7 @@ checkNetCoreDeps(){ } checkAdditionalDeps(){ - if [ "$ADDITIONAL_DEPS" -ne "" ]; then + if [ "$ADDITIONAL_DEPS" != "" ]; then # Install additional dependencies if ! "$1" "$2 $ADDITIONAL_DEPS"; then echo "(!) Failed to install additional dependencies!" @@ -125,7 +125,7 @@ fi #openSUSE - Has to be first since apt-get is available but package names different if [ "$DISTRO" = "SUSE" ]; then echo "(*) Detected SUSE (unoffically/community supported)" - installAdditionalDeps sudoIf "zypper -n in" + checkAdditionalDeps sudoIf "zypper -n in" checkNetCoreDeps sudoIf "zypper -n in libopenssl1_0_0 libicu krb5 libz1" # Debian / Ubuntu @@ -139,8 +139,8 @@ elif [ "$DISTRO" = "Debian" ]; then exitScript 1 fi - installAdditionalDeps aptSudoIf "install -yq" - checkNetCoreDeps aptSudoIf "install -yq libicu[0-9][0-9] libkrb5-3 zlib1g $ADDITIONAL_DEPS" + checkAdditionalDeps aptSudoIf "install -yq" + checkNetCoreDeps aptSudoIf "install -yq ^libicu[0-9][0-9]*$ libkrb5-3 zlib1g $ADDITIONAL_DEPS" if [ $SKIPDOTNETCORE -eq 0 ]; then # Determine which version of libssl to install # dpkg-query can return "1" in some distros if the package is not found. "2" is an unexpected error @@ -180,7 +180,7 @@ elif [ "$DISTRO" = "RedHat" ]; then exitScript 1 fi - installAdditionalDeps sudoIf "yum -y install" + checkAdditionalDeps sudoIf "yum -y install" checkNetCoreDeps sudoIf "yum -y install openssl-libs krb5-libs libicu zlib" # Install openssl-compat10 for Fedora 29. Does not exist in # CentOS, so validate package exists first. @@ -198,13 +198,13 @@ elif [ "$DISTRO" = "RedHat" ]; then #ArchLinux elif [ "$DISTRO" = "ArchLinux" ]; then echo "(*) Detected Arch Linux (unoffically/community supported)" - installAdditionalDeps sudoIf "pacman -Sq --noconfirm --needed" + checkAdditionalDeps sudoIf "pacman -Sq --noconfirm --needed" checkNetCoreDeps sudoIf "pacman -Sq --noconfirm --needed gcr liburcu openssl-1.0 krb5 icu zlib" #Solus elif [ "$DISTRO" = "Solus" ]; then echo "(*) Detected Solus (unoffically/community supported)" - installAdditionalDeps sudoIf "eopkg -y it" + checkAdditionalDeps sudoIf "eopkg -y it" checkNetCoreDeps sudoIf "eopkg -y it libicu openssl zlib kerberos" #Alpine Linux @@ -223,7 +223,7 @@ elif [ "$DISTRO" = "Alpine" ]; then exitScript 1 fi - installAdditionalDeps sudoIf "apk add --no-cache" + checkAdditionalDeps sudoIf "apk add --no-cache" sudoIf "apk add --no-cache libssl1.0 icu krb5 zlib" # Unknown distro diff --git a/vscode-dotnet-runtime-library/src/IDotnetEnsureDependenciesContext.ts b/vscode-dotnet-runtime-library/src/IDotnetEnsureDependenciesContext.ts index 6444999f3e..66b94b8e39 100644 --- a/vscode-dotnet-runtime-library/src/IDotnetEnsureDependenciesContext.ts +++ b/vscode-dotnet-runtime-library/src/IDotnetEnsureDependenciesContext.ts @@ -7,6 +7,6 @@ import { EnsureDependenciesErrorConfiguration } from './Utils/ErrorHandler'; export interface IDotnetEnsureDependenciesContext { command: string; - arguments: cp.SpawnSyncOptionsWithStringEncoding; + arguments: string[] | cp.SpawnSyncOptionsWithStringEncoding; errorConfiguration?: EnsureDependenciesErrorConfiguration; } diff --git a/vscode-dotnet-runtime-library/src/test/unit/LinuxPrereqsInstallerScript.test.ts b/vscode-dotnet-runtime-library/src/test/unit/LinuxPrereqsInstallerScript.test.ts new file mode 100644 index 0000000000..e707d6dd63 --- /dev/null +++ b/vscode-dotnet-runtime-library/src/test/unit/LinuxPrereqsInstallerScript.test.ts @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------------------------- +* Licensed to the .NET Foundation under one or more agreements. +* The .NET Foundation licenses this file to you under the MIT license. +*--------------------------------------------------------------------------------------------*/ +import * as chai from 'chai'; +import * as cp from 'child_process'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; + +const assert = chai.assert; + +function writeExecutable(filePath: string, content: string): void +{ + fs.writeFileSync(filePath, content); + fs.chmodSync(filePath, 0o755); +} + +suite('Linux Prereqs Installer Script Unit Tests', function () +{ + test('Debian install uses a libicu package pattern that supports newer package versions', function () + { + if (os.platform() !== 'linux') + { + this.skip(); + } + + const scriptPath = path.resolve(__dirname, '../../../install scripts/install-linux-prereqs.sh'); + const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'dotnet-prereqs-script-')); + const fakeBin = path.join(testRoot, 'bin'); + const aptGetLog = path.join(testRoot, 'apt-get.log'); + fs.mkdirSync(fakeBin); + + try + { + writeExecutable(path.join(fakeBin, 'id'), '#!/usr/bin/env bash\nif [ "$1" = "-u" ]; then echo 0; exit 0; fi\nexit 0\n'); + writeExecutable(path.join(fakeBin, 'fuser'), '#!/usr/bin/env bash\nexit 1\n'); + writeExecutable(path.join(fakeBin, 'apt-get'), '#!/usr/bin/env bash\necho "$*" >> "$APT_GET_LOG"\nexit 0\n'); + writeExecutable(path.join(fakeBin, 'dpkg-query'), '#!/usr/bin/env bash\nprintf "ii\\tlibssl1.0.0:amd64\\n"\nexit 0\n'); + + const result = cp.spawnSync('bash', [scriptPath, 'Debian', '', 'false', ''], { + encoding: 'utf8', + env: { + ...process.env, + APT_GET_LOG: aptGetLog, + PATH: `${fakeBin}:${process.env.PATH ?? ''}` + } + }); + + assert.equal(result.status, 0, `stdout:\n${result.stdout}\nstderr:\n${result.stderr}`); + assert.notInclude(result.stderr, 'command not found'); + assert.notInclude(result.stderr, 'integer expected'); + + const aptGetCalls = fs.readFileSync(aptGetLog, 'utf8'); + assert.include(aptGetCalls, 'update'); + assert.include(aptGetCalls, 'install -yq ^libicu[0-9][0-9]*$ libkrb5-3 zlib1g'); + } + finally + { + fs.rmSync(testRoot, { recursive: true, force: true }); + } + }); +}); \ No newline at end of file From 60b205adb800ea1eeca2303fb32c0f14c5b81408 Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 19 Jun 2026 10:23:57 -0700 Subject: [PATCH 02/11] dont fail if libicu older dependency is not available + update sample to use net10 not net2.2 and allow custom dll --- .../HelloWorldConsoleApp.deps.json | 6 +- .../HelloWorldConsoleApp.dll | Bin 4608 -> 4608 bytes .../HelloWorldConsoleApp.runtimeconfig.json | 8 +- sample/package.json | 5 + sample/src/extension.ts | 86 +++++++++++++++++- .../install scripts/install-linux-prereqs.sh | 4 +- .../unit/LinuxPrereqsInstallerScript.test.ts | 6 +- vscode-dotnet-runtime-library/yarn.lock | 5 - 8 files changed, 105 insertions(+), 15 deletions(-) diff --git a/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.deps.json b/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.deps.json index 03e76bb60e..d62d848700 100644 --- a/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.deps.json +++ b/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.deps.json @@ -1,11 +1,11 @@ { "runtimeTarget": { - "name": ".NETCoreApp,Version=v2.2", - "signature": "da39a3ee5e6b4b0d3255bfef95601890afd80709" + "name": ".NETCoreApp,Version=v10.0", + "signature": "" }, "compilationOptions": {}, "targets": { - ".NETCoreApp,Version=v2.2": { + ".NETCoreApp,Version=v10.0": { "HelloWorldConsoleApp/1.0.0": { "runtime": { "HelloWorldConsoleApp.dll": {} diff --git a/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.dll b/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.dll index cc63cd6f20e1c23319d9df271d4924f1e65fd190..2c98800735416247fd04ca68b849ec02ba730d5e 100644 GIT binary patch delta 1121 zcmY*YQEXFH82-+sx9zHqPKRL#rcDQ(Wb0ZP>L%c3CzQw#*H(gF6Yq8p+ts^!>%Dg~ zjfNIc!-E0pc>#h?Y68AMz~BoZ(L{`i`eKYRA!?!z#*CPl5EB-S|2eH8+~)uO@Be$w zcfSAJw%On8KXEjYs6YRC>)rL*liAkCBkZNt&uMl;FqYMS+Xz%dS{oDxSXL{=#GC9; zDxHOTN`xA8SSg^X1B_~ls9;_B-keXgHgFG+*!-Y2&@Ho=*ZQ|#p?>BNFrWeB6q$19 z+wNQ-CFdgmi6K)h<0$c@E_Db~ z2PbivdZWY{_NC+(En*o8LsjprU8X~%J%$mj3(I7&hcHTN%PfJ12$Lu%991}>aJRx| z6&_Hy!KB1s6Gl--9&7Nb;#s_apTvz-8ycsP!xnr(_&7czEaF?jry=`g!XjqzBO=ZA zosp-`^8<~L_`jgM4rx{0*}M1lifvP-?e6HuwkgkAbodUG>p{rH>yb=f(Oan54)=F) zm-}YOt%;Cc^vq%?&P2|3PxFIi^B@oF)3hxRWBL`bqQ5cxKnWZUeLM^zh5eL$s;rKW z7gzoB_w}Ancb@;H_n9wGuOAT~Mk|f>D}REaFSqxpO40NAM6EXX9QOm;bGI)Q^0_=i zrMq{hZ!YlHJpYwRJE%EkeJ_<=a!X1s>0{_EamVrYd%j~8JvZzVU&wi9@+K~^Ts&@}dVv!-KI_(IKC3T8cv z4_RL5@^HvsbVGZA4-qfqhvwxdhBx!F(Xno*elBm^IplbI%3RHwLAf;X@YYArag>_w zIHEDCTmM~ZYR8Yf9sZGCyQcH^mxB&x#fA7fEu9r#$2W_c@oz45CvNH5$GaDQ{ox!iO9=gyt6;<4iC zNwGD1^>_Mak?^Y|J$r!Er&s*s5hWyOv-SdXQ@>D7`$$mOu+!^g#J5xee1wq#*x{w?@1B(Mh2#cc}SccEU4rPQf z1aHVrSj8nf^g|dUIpj9-6)+BRQqDEbX3lNGILU$>80RSwqnMcRhCMJ$W=J*nI()2P z8m349{WIK~C|JP6OcH@j;(`T~m4mc{7nue7kRGV!tmSOrY~k$W?Bk3>DeM9nZ97n> zSQMFtO4tvx$V2cF*$D5Et-#`4NO5fIJg|0V%%F4;#qc&TR)`|l5V?GAVvL>R)}VLA z5dAJbp$}~@#5Osu(GL5y3IJ~y6j1Te!3Vua1ML|2ao0ruWY_(_EA_Xo%71>!wa@5= zz5A?#7d%LyptAjVccX474asErX~i((x>h$Bstgh6cIP%5azeSR8yB16W>S@h+R+6s zf!wg7s(P<(sIf*}Gj)}1$L~$R)}%yI1N60{aCb&>q}e|Sq^*OU_&m-5v(tCpJei+9uxIQnk5gZx{*k!s-j6vdNh?#G|QAu z#I0~DA`O~RJ*HH|bW2mLC^k|dM=zz~X57L~DwHdhqOqPNQ%)pRMf#s`Nzad5khpLu zlSED?@eCyT)aeUlv>o}D(S{8<<>-{^p35V5mgbf}X8u0b?+<4C(*8VQsf6ac%IGoI YCwk6xYTli-ZWGpO=5su&BwgkB2aa>x$N&HU diff --git a/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.runtimeconfig.json b/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.runtimeconfig.json index 49dbda4c5c..f730443ccd 100644 --- a/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.runtimeconfig.json +++ b/sample/HelloWorldConsoleApp/HelloWorldConsoleApp.runtimeconfig.json @@ -1,9 +1,13 @@ { "runtimeOptions": { - "tfm": "netcoreapp2.2", + "tfm": "net10.0", "framework": { "name": "Microsoft.NETCore.App", - "version": "2.2.0" + "version": "10.0.0" + }, + "configProperties": { + "System.Reflection.Metadata.MetadataUpdater.IsSupported": false, + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false } } } \ No newline at end of file diff --git a/sample/package.json b/sample/package.json index a3c7443375..dcb87281ac 100644 --- a/sample/package.json +++ b/sample/package.json @@ -70,6 +70,11 @@ "title": "Get the .NET runtime acquisition log file path", "category": "Sample" }, + { + "command": "sample.dotnet.ensureDependencies", + "title": "Call ensureDotnetDependencies with custom dotnet arguments", + "category": "Sample" + }, { "command": "sample.dotnet.acquireGlobalSDK", "title": "Install .NET SDK Globally via .NET Install Tool (Former Runtime Extension)", diff --git a/sample/src/extension.ts b/sample/src/extension.ts index 2573b3e0d2..00ddb866e1 100644 --- a/sample/src/extension.ts +++ b/sample/src/extension.ts @@ -13,11 +13,28 @@ import DotnetVersionSpecRequirement, IDotnetAcquireContext, IDotnetAcquireResult, + IDotnetEnsureDependenciesContext, IDotnetFindPathContext, IDotnetListVersionsResult, IDotnetLogResult, } from 'vscode-dotnet-runtime-library'; +function parseEnsureDependenciesArguments(input: string): string[] +{ + const trimmed = input.trim(); + if (trimmed.startsWith('[')) + { + const parsed = JSON.parse(trimmed); + if (!Array.isArray(parsed) || parsed.some(arg => typeof arg !== 'string')) + { + throw new Error('Custom arguments JSON must be an array of strings.'); + } + return parsed; + } + + return trimmed.length === 0 ? [] : trimmed.split(/\s+/); +} + export function activate(context: vscode.ExtensionContext) { @@ -48,8 +65,8 @@ export function activate(context: vscode.ExtensionContext) { await vscode.commands.executeCommand('dotnet.showAcquisitionLog'); - // Console app requires .NET Core 2.2.0 - const commandRes = await vscode.commands.executeCommand('dotnet.acquire', { version: '2.2', requestingExtensionId }); + // Console app requires .NET 10. + const commandRes = await vscode.commands.executeCommand('dotnet.acquire', { version: '10.0', requestingExtensionId }); const dotnetPath = commandRes!.dotnetPath; if (!dotnetPath) { @@ -236,6 +253,70 @@ ${stderr}`); } }); + const sampleEnsureDependenciesRegistration = vscode.commands.registerCommand('sample.dotnet.ensureDependencies', async () => + { + const dotnetPath = await vscode.window.showInputBox({ + placeHolder: process.platform === 'win32' ? 'C:\\Program Files\\dotnet\\dotnet.exe' : '/usr/bin/dotnet', + value: 'dotnet', + prompt: 'The dotnet command or executable path to run.', + }); + + if (!dotnetPath) + { + return; + } + + const argumentMode = await vscode.window.showQuickPick(['DLL path', 'Custom arguments'], { + placeHolder: 'Choose the argument shape to pass to dotnet.ensureDotnetDependencies.' + }); + + if (!argumentMode) + { + return; + } + + let args: string[]; + if (argumentMode === 'DLL path') + { + const dllPath = await vscode.window.showInputBox({ + placeHolder: '/path/to/LanguageServer.dll', + prompt: 'The DLL path to pass as the single dotnet argument.', + }); + + if (!dllPath) + { + return; + } + args = [dllPath]; + } + else + { + const customArgs = await vscode.window.showInputBox({ + placeHolder: '--info or ["/path/to/app.dll", "--flag"]', + value: '--info', + prompt: 'Arguments to pass to dotnet. Use JSON array syntax if an argument contains spaces.', + }); + + if (customArgs === undefined) + { + return; + } + args = parseEnsureDependenciesArguments(customArgs); + } + + try + { + await vscode.commands.executeCommand('dotnet.showAcquisitionLog'); + const commandContext: IDotnetEnsureDependenciesContext = { command: dotnetPath, arguments: args }; + await vscode.commands.executeCommand('dotnet.ensureDotnetDependencies', commandContext); + vscode.window.showInformationMessage(`dotnet.ensureDotnetDependencies completed for: ${dotnetPath} ${args.join(' ')}`); + } + catch (error) + { + vscode.window.showErrorMessage((error as Error).toString()); + } + }); + const sampleGlobalSDKFromRuntimeRegistration = vscode.commands.registerCommand('sample.dotnet.acquireGlobalSDK', async (version: string | undefined) => { if (!version) @@ -354,6 +435,7 @@ ${JSON.stringify(result) ?? 'undefined'}`); sampleConcurrentASPNETTest, sampleShowAcquisitionLogRegistration, sampleGetAcquisitionLogRegistration, + sampleEnsureDependenciesRegistration, sampleFindPathRegistration, sampleAvailableInstallsRegistration ); diff --git a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh index a9ef7a2dd7..ce6b487542 100644 --- a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh +++ b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh @@ -156,11 +156,13 @@ elif [ "$DISTRO" = "Debian" ]; then echo "(!) libssl1.0.2 installation failed!" exitScript 1 fi - else + elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then if ! aptSudoIf "install -yq libssl1.0.0"; then echo "(!) libssl1.0.0 installation failed!" exitScript 1 fi + else + echo "(*) libssl1.0.x is not available. Skipping legacy dependency." fi else echo "(*) libssl1.0.x already installed." diff --git a/vscode-dotnet-runtime-library/src/test/unit/LinuxPrereqsInstallerScript.test.ts b/vscode-dotnet-runtime-library/src/test/unit/LinuxPrereqsInstallerScript.test.ts index e707d6dd63..20e851a6f4 100644 --- a/vscode-dotnet-runtime-library/src/test/unit/LinuxPrereqsInstallerScript.test.ts +++ b/vscode-dotnet-runtime-library/src/test/unit/LinuxPrereqsInstallerScript.test.ts @@ -35,8 +35,9 @@ suite('Linux Prereqs Installer Script Unit Tests', function () { writeExecutable(path.join(fakeBin, 'id'), '#!/usr/bin/env bash\nif [ "$1" = "-u" ]; then echo 0; exit 0; fi\nexit 0\n'); writeExecutable(path.join(fakeBin, 'fuser'), '#!/usr/bin/env bash\nexit 1\n'); - writeExecutable(path.join(fakeBin, 'apt-get'), '#!/usr/bin/env bash\necho "$*" >> "$APT_GET_LOG"\nexit 0\n'); - writeExecutable(path.join(fakeBin, 'dpkg-query'), '#!/usr/bin/env bash\nprintf "ii\\tlibssl1.0.0:amd64\\n"\nexit 0\n'); + writeExecutable(path.join(fakeBin, 'apt-get'), '#!/usr/bin/env bash\necho "$*" >> "$APT_GET_LOG"\nif [[ "$*" == *libssl1.0* ]]; then exit 1; fi\nexit 0\n'); + writeExecutable(path.join(fakeBin, 'apt-cache'), '#!/usr/bin/env bash\nexit 0\n'); + writeExecutable(path.join(fakeBin, 'dpkg-query'), '#!/usr/bin/env bash\necho "dpkg-query: no packages found matching libssl1.0.?"\nexit 1\n'); const result = cp.spawnSync('bash', [scriptPath, 'Debian', '', 'false', ''], { encoding: 'utf8', @@ -54,6 +55,7 @@ suite('Linux Prereqs Installer Script Unit Tests', function () const aptGetCalls = fs.readFileSync(aptGetLog, 'utf8'); assert.include(aptGetCalls, 'update'); assert.include(aptGetCalls, 'install -yq ^libicu[0-9][0-9]*$ libkrb5-3 zlib1g'); + assert.notInclude(aptGetCalls, 'libssl1.0'); } finally { diff --git a/vscode-dotnet-runtime-library/yarn.lock b/vscode-dotnet-runtime-library/yarn.lock index ac4cdca206..c171e4bae6 100644 --- a/vscode-dotnet-runtime-library/yarn.lock +++ b/vscode-dotnet-runtime-library/yarn.lock @@ -621,11 +621,6 @@ fs.realpath@^1.0.0: resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^2.3.3: - version "2.3.3" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fsevents/-/fsevents-2.3.3.tgz" - integrity sha1-ysZAd4XQNnWipeGlMFxpezR9kNY= - function-bind@^1.1.2: version "1.1.2" resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/function-bind/-/function-bind-1.1.2.tgz" From 16eb4048917bde73ced08c8928789b27f8c2ebeb Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 19 Jun 2026 10:44:33 -0700 Subject: [PATCH 03/11] capture more meaningful output error --- sample/yarn.lock | 40 ------------------- .../DotnetCoreAcquisitionExtension.test.ts | 2 +- vscode-dotnet-runtime-extension/yarn.lock | 40 ------------------- .../install scripts/install-linux-prereqs.sh | 16 ++++---- .../DotnetCoreDependencyInstaller.ts | 35 ++++++++++++++-- .../src/IDotnetEnsureDependenciesContext.ts | 3 +- 6 files changed, 43 insertions(+), 93 deletions(-) diff --git a/sample/yarn.lock b/sample/yarn.lock index 5fc1677023..a9c40b6ab3 100644 --- a/sample/yarn.lock +++ b/sample/yarn.lock @@ -229,46 +229,6 @@ https-proxy-agent "^7.0.0" tslib "^2.6.2" -"@vscode/vsce-sign-alpine-arm64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz" - integrity sha1-LNJEyvXo7FQ/QvuR1N87kzZByPo= - -"@vscode/vsce-sign-alpine-x64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz" - integrity sha1-sOgKR5IAHGbif+7iwR6CGtH6FoA= - -"@vscode/vsce-sign-darwin-arm64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz" - integrity sha1-S4+hq1XygKmZhb48BvtzDleBDM4= - -"@vscode/vsce-sign-darwin-x64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz" - integrity sha1-0skYbZUFSYJyy93YODuwOOvPWCA= - -"@vscode/vsce-sign-linux-arm@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz" - integrity sha1-CifEKkrbN+lu7HjNe/o4jNTp++8= - -"@vscode/vsce-sign-linux-arm64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz" - integrity sha1-s9hWAUQEC5INjG7dQ3QxS1glVIE= - -"@vscode/vsce-sign-linux-x64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz" - integrity sha1-reEcru7VJPwWvWxDykmuoAKV3ow= - -"@vscode/vsce-sign-win32-arm64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz" - integrity sha1-BoiWgUjgPrOSR5yEkcclBnIb7/w= - "@vscode/vsce-sign-win32-x64@2.0.6": version "2.0.6" resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz" diff --git a/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts b/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts index 6a8758fd84..7a217a7ec9 100644 --- a/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts +++ b/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts @@ -11,10 +11,10 @@ import * as path from 'path'; import * as vscode from 'vscode'; import { + DotnetCoreDependencyInstaller, DotnetInstallMode, DotnetInstallType, DotnetVersionSpecRequirement, - DotnetCoreDependencyInstaller, EnvironmentVariableIsDefined, FileUtilities, getDistroInfo, diff --git a/vscode-dotnet-runtime-extension/yarn.lock b/vscode-dotnet-runtime-extension/yarn.lock index 836359d3a7..0248c9c34e 100644 --- a/vscode-dotnet-runtime-extension/yarn.lock +++ b/vscode-dotnet-runtime-extension/yarn.lock @@ -472,46 +472,6 @@ ora "^8.1.0" semver "^7.6.2" -"@vscode/vsce-sign-alpine-arm64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz" - integrity sha1-LNJEyvXo7FQ/QvuR1N87kzZByPo= - -"@vscode/vsce-sign-alpine-x64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz" - integrity sha1-sOgKR5IAHGbif+7iwR6CGtH6FoA= - -"@vscode/vsce-sign-darwin-arm64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz" - integrity sha1-S4+hq1XygKmZhb48BvtzDleBDM4= - -"@vscode/vsce-sign-darwin-x64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz" - integrity sha1-0skYbZUFSYJyy93YODuwOOvPWCA= - -"@vscode/vsce-sign-linux-arm@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz" - integrity sha1-CifEKkrbN+lu7HjNe/o4jNTp++8= - -"@vscode/vsce-sign-linux-arm64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz" - integrity sha1-s9hWAUQEC5INjG7dQ3QxS1glVIE= - -"@vscode/vsce-sign-linux-x64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz" - integrity sha1-reEcru7VJPwWvWxDykmuoAKV3ow= - -"@vscode/vsce-sign-win32-arm64@2.0.6": - version "2.0.6" - resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz" - integrity sha1-BoiWgUjgPrOSR5yEkcclBnIb7/w= - "@vscode/vsce-sign-win32-x64@2.0.6": version "2.0.6" resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz" diff --git a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh index ce6b487542..dc2600d0c9 100644 --- a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh +++ b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh @@ -44,7 +44,7 @@ sudoIf() # Utility function that waits for any existing installation operations to complete # on Debian/Ubuntu based distributions and then calls apt-get -aptSudoIf() +aptSudoIf() { while sudoIf fuser /var/lib/dpkg/lock >/dev/null 2>&1; do echo -ne "(*) Waiting for other package operations to complete.\r" @@ -131,7 +131,7 @@ if [ "$DISTRO" = "SUSE" ]; then # Debian / Ubuntu elif [ "$DISTRO" = "Debian" ]; then echo "(*) Detected Debian / Ubuntu" - + # Get latest package data echo -e "\n(*) Updating package lists..." if ! aptSudoIf "update"; then @@ -141,7 +141,7 @@ elif [ "$DISTRO" = "Debian" ]; then checkAdditionalDeps aptSudoIf "install -yq" checkNetCoreDeps aptSudoIf "install -yq ^libicu[0-9][0-9]*$ libkrb5-3 zlib1g $ADDITIONAL_DEPS" - if [ $SKIPDOTNETCORE -eq 0 ]; then + if [ $SKIPDOTNETCORE -eq 0 ]; then # Determine which version of libssl to install # dpkg-query can return "1" in some distros if the package is not found. "2" is an unexpected error LIBSSL=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1) @@ -164,7 +164,7 @@ elif [ "$DISTRO" = "Debian" ]; then else echo "(*) libssl1.0.x is not available. Skipping legacy dependency." fi - else + else echo "(*) libssl1.0.x already installed." fi fi @@ -183,8 +183,8 @@ elif [ "$DISTRO" = "RedHat" ]; then fi checkAdditionalDeps sudoIf "yum -y install" - checkNetCoreDeps sudoIf "yum -y install openssl-libs krb5-libs libicu zlib" - # Install openssl-compat10 for Fedora 29. Does not exist in + checkNetCoreDeps sudoIf "yum -y install openssl-libs krb5-libs libicu zlib" + # Install openssl-compat10 for Fedora 29. Does not exist in # CentOS, so validate package exists first. if [ $SKIPDOTNETCORE -eq 0 ]; then if ! sudoIf "yum -q list compat-openssl10" >/dev/null 2>&1; then @@ -212,8 +212,8 @@ elif [ "$DISTRO" = "Solus" ]; then #Alpine Linux elif [ "$DISTRO" = "Alpine" ]; then echo "(*) Detected Alpine Linux" - - # Update package repo indexes + + # Update package repo indexes echo -e "\n(*) Updating and upgrading..." if ! sudoIf "apk update --wait 30"; then echo "(!) Failed to update package lists." diff --git a/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts b/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts index bdffbb7aa0..99c6ad5a40 100644 --- a/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts +++ b/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts @@ -21,6 +21,8 @@ export interface IAdditionalLibs export class DotnetCoreDependencyInstaller { private readonly platform = process.platform; + private lastTerminalCommandOutput = ''; + private lastTerminalCommandOutputFile = ''; public signalIndicatesMissingLinuxDependencies(signal: string): boolean { @@ -94,10 +96,11 @@ export class DotnetCoreDependencyInstaller { const msg = (exitCode === 4 ? 'Your Linux distribution is not supported by the automated installer' : - 'The dependency installer failed.'); + `The dependency installer failed with exit code ${exitCode}.`); + const outputDetails = this.getLastTerminalCommandOutputDetails(); // Terminal will pause for input on error so this is just an info message with a more info button const failResponse = await vscode.window.showErrorMessage( - `${msg} Try installing dependencies manually.`, + `${msg} Try installing dependencies manually.${outputDetails}`, 'More Info'); if (failResponse === 'More Info') { @@ -130,6 +133,7 @@ export class DotnetCoreDependencyInstaller { const fullCommand = `"${command}" ${((args?.length ?? 0) > 0 ? ` "${args.join('" "')}"` : '')}`; const exitCodeFile = path.join(__dirname, '..', `terminal-exit-code-${Math.floor(Math.random() * 1000000)}`); + const outputFile = path.join(__dirname, '..', `terminal-output-${Math.floor(Math.random() * 1000000)}`); const commandList = new Array(); if (this.platform === 'win32') { @@ -152,7 +156,7 @@ export class DotnetCoreDependencyInstaller commandList.push( 'clear', `echo 0 > "${exitCodeFile}"`, - `${fullCommand} || echo $? > "${exitCodeFile}"`, + `(${fullCommand}; echo $? > "${exitCodeFile}") 2>&1 | tee "${outputFile}"`, ); if (promptAfterRun) { @@ -177,6 +181,14 @@ export class DotnetCoreDependencyInstaller // Hack to get exit code - VS Code terminal does not return it try { + this.lastTerminalCommandOutput = ''; + this.lastTerminalCommandOutputFile = outputFile; + if (fs.existsSync(outputFile)) + { + this.lastTerminalCommandOutput = fs.readFileSync(outputFile).toString().trim(); + fs.unlinkSync(outputFile); + } + if (fs.existsSync(exitCodeFile)) { const exitFile = fs.readFileSync(exitCodeFile).toString().trim(); @@ -227,4 +239,21 @@ export class DotnetCoreDependencyInstaller // shellCommand will be null if bash is not found return shellCommand ? shellCommand.toString() : which('sh')?.toString() ?? 'sh'; } + + private getLastTerminalCommandOutputDetails(): string + { + if (!this.lastTerminalCommandOutput) + { + return this.lastTerminalCommandOutputFile + ? ` No installer output was captured. Check the Linux dependency installer terminal for details.` + : ''; + } + + const maxOutputLength = 1200; + const output = this.lastTerminalCommandOutput.length > maxOutputLength + ? `...${this.lastTerminalCommandOutput.slice(-maxOutputLength)}` + : this.lastTerminalCommandOutput; + + return `\n\nInstaller output:\n${output}`; + } } diff --git a/vscode-dotnet-runtime-library/src/IDotnetEnsureDependenciesContext.ts b/vscode-dotnet-runtime-library/src/IDotnetEnsureDependenciesContext.ts index 66b94b8e39..63686ad5e1 100644 --- a/vscode-dotnet-runtime-library/src/IDotnetEnsureDependenciesContext.ts +++ b/vscode-dotnet-runtime-library/src/IDotnetEnsureDependenciesContext.ts @@ -5,7 +5,8 @@ import * as cp from 'child_process'; import { EnsureDependenciesErrorConfiguration } from './Utils/ErrorHandler'; -export interface IDotnetEnsureDependenciesContext { +export interface IDotnetEnsureDependenciesContext +{ command: string; arguments: string[] | cp.SpawnSyncOptionsWithStringEncoding; errorConfiguration?: EnsureDependenciesErrorConfiguration; From 8cf2988ee0f7c6f3e45f601b01002bf9614ded67 Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 19 Jun 2026 11:18:04 -0700 Subject: [PATCH 04/11] allow the unbundled vsix and bundled vsix to be testable and find the folder for the scripts --- .../DotnetCoreDependencyInstaller.ts | 79 +++++++++++++++++-- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts b/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts index 99c6ad5a40..feadefd5d5 100644 --- a/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts +++ b/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts @@ -48,15 +48,21 @@ export class DotnetCoreDependencyInstaller public async installLinuxDependencies(additionalLibs: IAdditionalLibs = {}, skipDotNetCore = false): Promise { - const scriptRoot = path.join(__dirname, '..', 'install scripts'); + const scriptRoot = this.getInstallScriptsRoot(); const shellCommand = this.getShellCommand(); + const distroScript = path.join(scriptRoot, 'determine-linux-distro.sh'); // Determine the distro - const result = cp.spawnSync(shellCommand, [path.join(scriptRoot, 'determine-linux-distro.sh')]); - if (result.status !== 0) + const result = cp.spawnSync(shellCommand, [distroScript]); + if (result.status !== 0 || result.error) { - console.log(`Failed to determine distro. Exit code: ${result.status}`); - return result.status!; + // This early-return path never reaches the terminal capture below, so build the diagnostics here + // and stash them so the failure popup can surface a concrete reason instead of a bare exit code. + this.lastTerminalCommandOutput = this.describeDistroDetectionFailure(shellCommand, scriptRoot, distroScript, result); + this.lastTerminalCommandOutputFile = distroScript; + console.log(this.lastTerminalCommandOutput); + // Normalize a missing-binary spawn error (status === null) to 127 so callers report "command not found" consistently. + return result.status ?? 127; } const distro = result.stdout.toString().trim(); console.log(`Found distro ${distro}`); @@ -73,6 +79,44 @@ export class DotnetCoreDependencyInstaller moreInfoUrl]); } + /** + * Builds a human-readable diagnostic for a failed distro-detection spawn so the failure popup can explain + * exactly what went wrong (e.g. the shell or script could not be found, which surfaces as exit code 127). + */ + private describeDistroDetectionFailure(shellCommand: string, scriptRoot: string, scriptPath: string, result: cp.SpawnSyncReturns): string + { + const lines: string[] = []; + lines.push('Failed to detect the Linux distribution before installing dependencies.'); + lines.push(`Shell: ${shellCommand} (exists: ${fs.existsSync(shellCommand)})`); + lines.push(`Script root: ${scriptRoot}`); + lines.push(`Script: ${scriptPath} (exists: ${fs.existsSync(scriptPath)})`); + lines.push(`Exit code: ${result.status ?? 'null'}`); + if (result.signal) + { + lines.push(`Signal: ${result.signal}`); + } + if (result.error) + { + const errno = (result.error as NodeJS.ErrnoException).code; + lines.push(`Spawn error: ${result.error.message}${errno ? ` (${errno})` : ''}`); + } + const stderr = result.stderr?.toString().trim(); + if (stderr) + { + lines.push(`stderr: ${stderr}`); + } + const stdout = result.stdout?.toString().trim(); + if (stdout) + { + lines.push(`stdout: ${stdout}`); + } + if (result.status === 127) + { + lines.push('Exit code 127 means a command was not found — usually the shell or the install script path does not exist at runtime.'); + } + return lines.join('\n'); + } + public async promptLinuxDependencyInstall(message: string, additionalLibs: IAdditionalLibs = {}, skipDotNetCore = false): Promise { while (true) @@ -240,6 +284,29 @@ export class DotnetCoreDependencyInstaller return shellCommand ? shellCommand.toString() : which('sh')?.toString() ?? 'sh'; } + private getInstallScriptsRoot(): string + { + // The 'install scripts' folder ships next to the compiled code, but its exact location depends on how this + // module is loaded: + // - Unbundled library (e.g. unit tests): this file is in dist/Acquisition, so the scripts are one level up in dist/install scripts. + // - Webpacked extension: this file is bundled into dist/extension.js (__dirname === dist, since node.__dirname is false), + // so the scripts are in dist/install scripts (no parent traversal). + // Resolving the wrong one made spawnSync run a non-existent script and return exit code 127. + const candidates = [ + path.join(__dirname, 'install scripts'), + path.join(__dirname, '..', 'install scripts'), + ]; + for (const candidate of candidates) + { + if (fs.existsSync(candidate)) + { + return candidate; + } + } + // Preserve prior behavior when neither candidate exists (unusual packaging); callers will surface the resulting error. + return path.join(__dirname, '..', 'install scripts'); + } + private getLastTerminalCommandOutputDetails(): string { if (!this.lastTerminalCommandOutput) @@ -254,6 +321,6 @@ export class DotnetCoreDependencyInstaller ? `...${this.lastTerminalCommandOutput.slice(-maxOutputLength)}` : this.lastTerminalCommandOutput; - return `\n\nInstaller output:\n${output}`; + return `\n\nDetails:\n${output}`; } } From 37affcc5db6e54522d9bad8d98c1d10fa35573ad Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 19 Jun 2026 11:24:18 -0700 Subject: [PATCH 05/11] remove bloated ai text --- Documentation/commands.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/commands.md b/Documentation/commands.md index da7f4a38a8..ddcf47969a 100644 --- a/Documentation/commands.md +++ b/Documentation/commands.md @@ -140,7 +140,6 @@ The intended probe shape is `command: ` with `arguments` set Passing CLI-only arguments such as `['--info']` runs the .NET CLI information path instead of the caller's payload and can exercise different runtime dependencies. That can be useful for diagnosis, but it is not the intended contract for this legacy command. -The TypeScript type for `arguments` includes both `string[]` and `child_process.SpawnSyncOptionsWithStringEncoding`. The `string[]` member reflects the runtime behavior that existing callers already use today, so adding it to the published type is not a breaking change. The older options-object shape remains accepted for compatibility with the previously published definition. ### dotnet.reportIssue From f64138d40913ad6a72dee4615f5191af64c6608e Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 19 Jun 2026 11:24:52 -0700 Subject: [PATCH 06/11] tests use proper nodejs prototyping --- vscode-dotnet-runtime-extension/src/extension.ts | 4 +++- .../DotnetCoreAcquisitionExtension.test.ts | 14 ++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/vscode-dotnet-runtime-extension/src/extension.ts b/vscode-dotnet-runtime-extension/src/extension.ts index f1eb3b7e4e..f81c180cc7 100644 --- a/vscode-dotnet-runtime-extension/src/extension.ts +++ b/vscode-dotnet-runtime-extension/src/extension.ts @@ -911,9 +911,11 @@ ${JSON.stringify(commandContext)}`)); return; } + // commandContext.arguments is either the dotnet process args (string[]) or a SpawnSync options object. + // Use the 3-arg overload (empty args + options) for the options case so the two paths are distinct. const result = Array.isArray(commandContext.arguments) ? cp.spawnSync(commandContext.command, commandContext.arguments) - : cp.spawnSync(commandContext.command, commandContext.arguments); + : cp.spawnSync(commandContext.command, [], commandContext.arguments); const installer = new DotnetCoreDependencyInstaller(); if (installer.signalIndicatesMissingLinuxDependencies(result.signal!)) { diff --git a/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts b/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts index 7a217a7ec9..74ad7798cd 100644 --- a/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts +++ b/vscode-dotnet-runtime-extension/src/test/functional/DotnetCoreAcquisitionExtension.test.ts @@ -170,8 +170,8 @@ suite('DotnetCoreAcquisitionExtension End to End', function () test('dotnet.ensureDotnetDependencies prompts when dotnet --info fails with a Linux dependency signal', async () => { const originalPlatform = os.platform; - const originalProcessPlatform = process.platform; const originalSpawnSync = cp.spawnSync; + const originalSignalCheck = DotnetCoreDependencyInstaller.prototype.signalIndicatesMissingLinuxDependencies; const originalPromptLinuxDependencyInstall = DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall; let promptCount = 0; @@ -179,7 +179,8 @@ suite('DotnetCoreAcquisitionExtension End to End', function () { skipInstallCleanupAfterTest = true; Object.defineProperty(os, 'platform', { value: () => 'linux', configurable: true, writable: true }); - Object.defineProperty(process, 'platform', { value: 'linux', configurable: true, writable: true }); + // Stub the platform-gated signal check rather than mutating the read-only process.platform, so this runs on any OS. + DotnetCoreDependencyInstaller.prototype.signalIndicatesMissingLinuxDependencies = (signal: string) => signal === 'SIGABRT'; Object.defineProperty(cp, 'spawnSync', { configurable: true, writable: true, @@ -204,8 +205,8 @@ suite('DotnetCoreAcquisitionExtension End to End', function () finally { Object.defineProperty(os, 'platform', { value: originalPlatform, configurable: true, writable: true }); - Object.defineProperty(process, 'platform', { value: originalProcessPlatform, configurable: true, writable: true }); Object.defineProperty(cp, 'spawnSync', { value: originalSpawnSync, configurable: true, writable: true }); + DotnetCoreDependencyInstaller.prototype.signalIndicatesMissingLinuxDependencies = originalSignalCheck; DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall = originalPromptLinuxDependencyInstall; } }).timeout(standardTimeoutTime); @@ -213,8 +214,8 @@ suite('DotnetCoreAcquisitionExtension End to End', function () test('dotnet.ensureDotnetDependencies does not prompt when a dotnet dll payload starts successfully', async () => { const originalPlatform = os.platform; - const originalProcessPlatform = process.platform; const originalSpawnSync = cp.spawnSync; + const originalSignalCheck = DotnetCoreDependencyInstaller.prototype.signalIndicatesMissingLinuxDependencies; const originalPromptLinuxDependencyInstall = DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall; let promptCount = 0; @@ -222,7 +223,8 @@ suite('DotnetCoreAcquisitionExtension End to End', function () { skipInstallCleanupAfterTest = true; Object.defineProperty(os, 'platform', { value: () => 'linux', configurable: true, writable: true }); - Object.defineProperty(process, 'platform', { value: 'linux', configurable: true, writable: true }); + // Stub the platform-gated signal check rather than mutating the read-only process.platform, so this runs on any OS. + DotnetCoreDependencyInstaller.prototype.signalIndicatesMissingLinuxDependencies = (signal: string) => signal === 'SIGABRT'; Object.defineProperty(cp, 'spawnSync', { configurable: true, writable: true, @@ -249,8 +251,8 @@ suite('DotnetCoreAcquisitionExtension End to End', function () finally { Object.defineProperty(os, 'platform', { value: originalPlatform, configurable: true, writable: true }); - Object.defineProperty(process, 'platform', { value: originalProcessPlatform, configurable: true, writable: true }); Object.defineProperty(cp, 'spawnSync', { value: originalSpawnSync, configurable: true, writable: true }); + DotnetCoreDependencyInstaller.prototype.signalIndicatesMissingLinuxDependencies = originalSignalCheck; DotnetCoreDependencyInstaller.prototype.promptLinuxDependencyInstall = originalPromptLinuxDependencyInstall; } }).timeout(standardTimeoutTime); From 34ace96e9ebf541318a773404f0bc7bfa0425d30 Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 19 Jun 2026 11:25:24 -0700 Subject: [PATCH 07/11] remove nl --- Documentation/commands.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/commands.md b/Documentation/commands.md index ddcf47969a..016c09299a 100644 --- a/Documentation/commands.md +++ b/Documentation/commands.md @@ -140,7 +140,6 @@ The intended probe shape is `command: ` with `arguments` set Passing CLI-only arguments such as `['--info']` runs the .NET CLI information path instead of the caller's payload and can exercise different runtime dependencies. That can be useful for diagnosis, but it is not the intended contract for this legacy command. - ### dotnet.reportIssue This is a **user-facing** command that opens a pre-populated GitHub issue in the browser and copies the issue body to the clipboard. It does not accept parameters and has a void return type. From fe5b26b40f940baafd9d5c12a473ed961d8ab39b Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 19 Jun 2026 11:31:59 -0700 Subject: [PATCH 08/11] remove redundant exit code conditional with interpretation of exit code --- .../src/Acquisition/DotnetCoreDependencyInstaller.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts b/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts index feadefd5d5..c12ff8385f 100644 --- a/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts +++ b/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts @@ -110,10 +110,6 @@ export class DotnetCoreDependencyInstaller { lines.push(`stdout: ${stdout}`); } - if (result.status === 127) - { - lines.push('Exit code 127 means a command was not found — usually the shell or the install script path does not exist at runtime.'); - } return lines.join('\n'); } From b6a4cde1b58d4380e5786d3760a9270cc666bfc1 Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 19 Jun 2026 11:32:41 -0700 Subject: [PATCH 09/11] Move ensure dependencies arg helper function beside the function in sample that uses it --- sample/src/extension.ts | 44 ++++++++++++------- .../install scripts/install-linux-prereqs.sh | 2 +- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/sample/src/extension.ts b/sample/src/extension.ts index 00ddb866e1..686bbee6a8 100644 --- a/sample/src/extension.ts +++ b/sample/src/extension.ts @@ -19,22 +19,6 @@ import IDotnetLogResult, } from 'vscode-dotnet-runtime-library'; -function parseEnsureDependenciesArguments(input: string): string[] -{ - const trimmed = input.trim(); - if (trimmed.startsWith('[')) - { - const parsed = JSON.parse(trimmed); - if (!Array.isArray(parsed) || parsed.some(arg => typeof arg !== 'string')) - { - throw new Error('Custom arguments JSON must be an array of strings.'); - } - return parsed; - } - - return trimmed.length === 0 ? [] : trimmed.split(/\s+/); -} - export function activate(context: vscode.ExtensionContext) { @@ -253,6 +237,23 @@ ${stderr}`); } }); + // Accept either whitespace-separated args (e.g. "--info") or a JSON string array for values that contain spaces. + function parseEnsureDependenciesArguments(input: string): string[] + { + const trimmed = input.trim(); + if (trimmed.startsWith('[')) + { + const parsed = JSON.parse(trimmed); + if (!Array.isArray(parsed) || parsed.some((arg: unknown) => typeof arg !== 'string')) + { + throw new Error('Custom arguments JSON must be an array of strings.'); + } + return parsed; + } + + return trimmed.length === 0 ? [] : trimmed.split(/\s+/); + } + const sampleEnsureDependenciesRegistration = vscode.commands.registerCommand('sample.dotnet.ensureDependencies', async () => { const dotnetPath = await vscode.window.showInputBox({ @@ -301,7 +302,16 @@ ${stderr}`); { return; } - args = parseEnsureDependenciesArguments(customArgs); + + try + { + args = parseEnsureDependenciesArguments(customArgs); + } + catch (error) + { + vscode.window.showErrorMessage(`Invalid custom arguments: ${(error as Error).message}`); + return; + } } try diff --git a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh index dc2600d0c9..ab9d92a58a 100644 --- a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh +++ b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh @@ -140,7 +140,7 @@ elif [ "$DISTRO" = "Debian" ]; then fi checkAdditionalDeps aptSudoIf "install -yq" - checkNetCoreDeps aptSudoIf "install -yq ^libicu[0-9][0-9]*$ libkrb5-3 zlib1g $ADDITIONAL_DEPS" + checkNetCoreDeps aptSudoIf "install -yq ^libicu[0-9][0-9]*$ libkrb5-3 zlib1g" if [ $SKIPDOTNETCORE -eq 0 ]; then # Determine which version of libssl to install # dpkg-query can return "1" in some distros if the package is not found. "2" is an unexpected error From 0c0e8e1e2582f0fea624a9b7f23c728cda6f08aa Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 19 Jun 2026 11:41:20 -0700 Subject: [PATCH 10/11] do not allow false positives for libicu lookup --- .../install scripts/install-linux-prereqs.sh | 4 ++-- .../src/Acquisition/DotnetCoreDependencyInstaller.ts | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh index ab9d92a58a..e19107287f 100644 --- a/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh +++ b/vscode-dotnet-runtime-library/install scripts/install-linux-prereqs.sh @@ -151,12 +151,12 @@ elif [ "$DISTRO" = "Debian" ]; then fi if [ "$(echo "$LIBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then # No libssl install 1.0.2 for Debian, 1.0.0 for Ubuntu - if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then + if [[ ! -z $(apt-cache --names-only search '^libssl1\.0\.2$') ]]; then if ! aptSudoIf "install -yq libssl1.0.2"; then echo "(!) libssl1.0.2 installation failed!" exitScript 1 fi - elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then + elif [[ ! -z $(apt-cache --names-only search '^libssl1\.0\.0$') ]]; then if ! aptSudoIf "install -yq libssl1.0.0"; then echo "(!) libssl1.0.0 installation failed!" exitScript 1 diff --git a/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts b/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts index c12ff8385f..dc6afadfbc 100644 --- a/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts +++ b/vscode-dotnet-runtime-library/src/Acquisition/DotnetCoreDependencyInstaller.ts @@ -193,10 +193,13 @@ export class DotnetCoreDependencyInstaller { // Note that "|| echo $? >" in this command sequence is a hack to get the exit code from the // executed command given VS Code terminal does not return it. + // The exit code is captured inside the subshell before the pipe, so appending "|| true" to the + // tee step keeps a missing/failing tee from breaking the "&&" chain before the final "exit 0" + // (which lets the terminal auto-close). If tee is unavailable, output capture is simply skipped. commandList.push( 'clear', `echo 0 > "${exitCodeFile}"`, - `(${fullCommand}; echo $? > "${exitCodeFile}") 2>&1 | tee "${outputFile}"`, + `(${fullCommand}; echo $? > "${exitCodeFile}") 2>&1 | tee "${outputFile}" || true`, ); if (promptAfterRun) { From c5c491eb847f833a43e929687eae9a708c0bf115 Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Tue, 21 Jul 2026 13:30:34 -0700 Subject: [PATCH 11/11] Restore yarn.lock files to upstream/main Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- sample/yarn.lock | 40 +++++++++++++++++++++++ vscode-dotnet-runtime-extension/yarn.lock | 40 +++++++++++++++++++++++ vscode-dotnet-runtime-library/yarn.lock | 5 +++ 3 files changed, 85 insertions(+) diff --git a/sample/yarn.lock b/sample/yarn.lock index a9c40b6ab3..5fc1677023 100644 --- a/sample/yarn.lock +++ b/sample/yarn.lock @@ -229,6 +229,46 @@ https-proxy-agent "^7.0.0" tslib "^2.6.2" +"@vscode/vsce-sign-alpine-arm64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz" + integrity sha1-LNJEyvXo7FQ/QvuR1N87kzZByPo= + +"@vscode/vsce-sign-alpine-x64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz" + integrity sha1-sOgKR5IAHGbif+7iwR6CGtH6FoA= + +"@vscode/vsce-sign-darwin-arm64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz" + integrity sha1-S4+hq1XygKmZhb48BvtzDleBDM4= + +"@vscode/vsce-sign-darwin-x64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz" + integrity sha1-0skYbZUFSYJyy93YODuwOOvPWCA= + +"@vscode/vsce-sign-linux-arm@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz" + integrity sha1-CifEKkrbN+lu7HjNe/o4jNTp++8= + +"@vscode/vsce-sign-linux-arm64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz" + integrity sha1-s9hWAUQEC5INjG7dQ3QxS1glVIE= + +"@vscode/vsce-sign-linux-x64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz" + integrity sha1-reEcru7VJPwWvWxDykmuoAKV3ow= + +"@vscode/vsce-sign-win32-arm64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz" + integrity sha1-BoiWgUjgPrOSR5yEkcclBnIb7/w= + "@vscode/vsce-sign-win32-x64@2.0.6": version "2.0.6" resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz" diff --git a/vscode-dotnet-runtime-extension/yarn.lock b/vscode-dotnet-runtime-extension/yarn.lock index 0248c9c34e..836359d3a7 100644 --- a/vscode-dotnet-runtime-extension/yarn.lock +++ b/vscode-dotnet-runtime-extension/yarn.lock @@ -472,6 +472,46 @@ ora "^8.1.0" semver "^7.6.2" +"@vscode/vsce-sign-alpine-arm64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz" + integrity sha1-LNJEyvXo7FQ/QvuR1N87kzZByPo= + +"@vscode/vsce-sign-alpine-x64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz" + integrity sha1-sOgKR5IAHGbif+7iwR6CGtH6FoA= + +"@vscode/vsce-sign-darwin-arm64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz" + integrity sha1-S4+hq1XygKmZhb48BvtzDleBDM4= + +"@vscode/vsce-sign-darwin-x64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz" + integrity sha1-0skYbZUFSYJyy93YODuwOOvPWCA= + +"@vscode/vsce-sign-linux-arm@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz" + integrity sha1-CifEKkrbN+lu7HjNe/o4jNTp++8= + +"@vscode/vsce-sign-linux-arm64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz" + integrity sha1-s9hWAUQEC5INjG7dQ3QxS1glVIE= + +"@vscode/vsce-sign-linux-x64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz" + integrity sha1-reEcru7VJPwWvWxDykmuoAKV3ow= + +"@vscode/vsce-sign-win32-arm64@2.0.6": + version "2.0.6" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz" + integrity sha1-BoiWgUjgPrOSR5yEkcclBnIb7/w= + "@vscode/vsce-sign-win32-x64@2.0.6": version "2.0.6" resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz" diff --git a/vscode-dotnet-runtime-library/yarn.lock b/vscode-dotnet-runtime-library/yarn.lock index c171e4bae6..ac4cdca206 100644 --- a/vscode-dotnet-runtime-library/yarn.lock +++ b/vscode-dotnet-runtime-library/yarn.lock @@ -621,6 +621,11 @@ fs.realpath@^1.0.0: resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= +fsevents@^2.3.3: + version "2.3.3" + resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fsevents/-/fsevents-2.3.3.tgz" + integrity sha1-ysZAd4XQNnWipeGlMFxpezR9kNY= + function-bind@^1.1.2: version "1.1.2" resolved "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/function-bind/-/function-bind-1.1.2.tgz"