From 02b3b373a4d5987985b9bb4b919aaa039b81e207 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Thu, 31 Aug 2023 15:40:11 -0700 Subject: [PATCH 1/2] Consume per-runtime language servers To keep our package size more manageable, we now create a separate language server package per runtime. This changes our download tasks to adjust for this and updates to a new Roslyn version that has separate packages. --- package.json | 2 +- server/ServerDownload.csproj | 2 +- tasks/offlinePackagingTasks.ts | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index c510ffc91..d8c9f994d 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ } }, "defaults": { - "roslyn": "4.8.0-2.23428.2", + "roslyn": "4.8.0-3.23451.2", "omniSharp": "1.39.7", "razor": "7.0.0-preview.23423.3", "razorOmnisharp": "7.0.0-preview.23363.1" diff --git a/server/ServerDownload.csproj b/server/ServerDownload.csproj index 3d88b952a..bde703f88 100644 --- a/server/ServerDownload.csproj +++ b/server/ServerDownload.csproj @@ -20,7 +20,7 @@ - + \ No newline at end of file diff --git a/tasks/offlinePackagingTasks.ts b/tasks/offlinePackagingTasks.ts index 2da434ec2..73ff97dd4 100644 --- a/tasks/offlinePackagingTasks.ts +++ b/tasks/offlinePackagingTasks.ts @@ -76,7 +76,6 @@ gulp.task('installDependencies', async () => { // Install Tasks async function installRoslyn(packageJSON: any, platformInfo?: PlatformInformation) { const roslynVersion = packageJSON.defaults.roslyn; - const packagePath = await acquireNugetPackage('Microsoft.CodeAnalysis.LanguageServer', roslynVersion); // Find the matching server RID for the current platform. let serverPlatform: string; @@ -90,6 +89,11 @@ async function installRoslyn(packageJSON: any, platformInfo?: PlatformInformatio )!.rid; } + const packagePath = await acquireNugetPackage( + `Microsoft.CodeAnalysis.LanguageServer.${serverPlatform}`, + roslynVersion + ); + // Get the directory containing the server executable for the current platform. const serverExecutableDirectory = path.join(packagePath, 'content', 'LanguageServer', serverPlatform); if (!fs.existsSync(serverExecutableDirectory)) { @@ -150,7 +154,8 @@ async function acquireNugetPackage(packageName: string, packageVersion: string): const dotnetArgs = [ 'restore', path.join(rootPath, 'server'), - `/p:MicrosoftCodeAnalysisLanguageServerVersion=${packageVersion}`, + `/p:PackageName=${packageName}`, + `/p:PackageVersion=${packageVersion}`, ]; if (argv.interactive) { dotnetArgs.push('--interactive'); From 4ea6193aded5f187d45c3adeb11875bfc58e3d60 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Fri, 1 Sep 2023 14:53:42 -0700 Subject: [PATCH 2/2] Add another Gulp task to fetch all platform packages We fetch these from an upstream feed that has authenticated feeds as upstreams of it; this is an easy way to ensure everything is cached properly for all platforms. --- CONTRIBUTING.md | 6 ++-- tasks/offlinePackagingTasks.ts | 65 ++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 304d70dcc..a17f2a452 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,7 +49,7 @@ VSIXs can be created using the gulp command `gulp vsix:release:package`. This w To update the version of the roslyn server used by the extension do the following: 1. Find the the Roslyn signed build you want from [here](https://dnceng.visualstudio.com/internal/_build?definitionId=327&_a=summary). Typically the latest successful build of main is fine. -2. In the official build stage, look for the `Publish Assets` step. In there you will see it publishing the `Microsoft.CodeAnalysis.LanguageServer` package with some version, e.g. `4.6.0-3.23158.4`. Take note of that version number. +2. In the official build stage, look for the `Publish Assets` step. In there you will see it publishing the `Microsoft.CodeAnalysis.LanguageServer.neutral` package with some version, e.g. `4.6.0-3.23158.4`. Take note of that version number. 3. In the [package.json](package.json) inside the `defaults` section update the `roslyn` key to point to the version number you found above in step 2. -4. Build and test the change (make sure to run `gulp installDependencies` to get the new version!). If everything looks good, submit a PR. - * Adding new package versions might require authentication, run with the `--interactive` flag to login. You may need to install [azure artifacts nuget credential provider](https://github.com/microsoft/artifacts-credprovider#installation-on-windows) to run interactive authentication. +4. Ensure that version of the package is in the proper feeds by running `gulp updateRoslynVersion`. Note: you may need to install the [Azure Artifacts NuGet Credential Provider](https://github.com/microsoft/artifacts-credprovider#installation-on-windows) to run interactive authentication. +5. Build and test the change. If everything looks good, submit a PR. \ No newline at end of file diff --git a/tasks/offlinePackagingTasks.ts b/tasks/offlinePackagingTasks.ts index 73ff97dd4..ce9ead67f 100644 --- a/tasks/offlinePackagingTasks.ts +++ b/tasks/offlinePackagingTasks.ts @@ -73,8 +73,48 @@ gulp.task('installDependencies', async () => { } }); +gulp.task( + 'updateRoslynVersion', + // Run the fetch of all packages, and then also installDependencies after + gulp.series(async () => { + const packageJSON = getPackageJSON(); + + // Fetch the neutral package that we don't otherwise have in our platform list + await acquireRoslyn(packageJSON, undefined, true); + + // And now fetch each platform specific + for (const p of platformSpecificPackages) { + await acquireRoslyn(packageJSON, p.platformInfo, true); + } + }, 'installDependencies') +); + // Install Tasks async function installRoslyn(packageJSON: any, platformInfo?: PlatformInformation) { + const { packagePath, serverPlatform } = await acquireRoslyn(packageJSON, platformInfo, false); + + // Get the directory containing the server executable for the current platform. + const serverExecutableDirectory = path.join(packagePath, 'content', 'LanguageServer', serverPlatform); + if (!fs.existsSync(serverExecutableDirectory)) { + throw new Error(`Failed to find server executable directory at ${serverExecutableDirectory}`); + } + + console.log(`Extracting Roslyn executables from ${serverExecutableDirectory}`); + + // Copy the files to the language server directory. + fs.mkdirSync(languageServerDirectory); + fsextra.copySync(serverExecutableDirectory, languageServerDirectory); + const languageServerDll = path.join(languageServerDirectory, 'Microsoft.CodeAnalysis.LanguageServer.dll'); + if (!fs.existsSync(languageServerDll)) { + throw new Error(`Failed to copy server executable`); + } +} + +async function acquireRoslyn( + packageJSON: any, + platformInfo: PlatformInformation | undefined, + interactive: boolean +): Promise<{ packagePath: string; serverPlatform: string }> { const roslynVersion = packageJSON.defaults.roslyn; // Find the matching server RID for the current platform. @@ -91,24 +131,10 @@ async function installRoslyn(packageJSON: any, platformInfo?: PlatformInformatio const packagePath = await acquireNugetPackage( `Microsoft.CodeAnalysis.LanguageServer.${serverPlatform}`, - roslynVersion + roslynVersion, + interactive ); - - // Get the directory containing the server executable for the current platform. - const serverExecutableDirectory = path.join(packagePath, 'content', 'LanguageServer', serverPlatform); - if (!fs.existsSync(serverExecutableDirectory)) { - throw new Error(`Failed to find server executable directory at ${serverExecutableDirectory}`); - } - - console.log(`Extracting Roslyn executables from ${serverExecutableDirectory}`); - - // Copy the files to the language server directory. - fs.mkdirSync(languageServerDirectory); - fsextra.copySync(serverExecutableDirectory, languageServerDirectory); - const languageServerDll = path.join(languageServerDirectory, 'Microsoft.CodeAnalysis.LanguageServer.dll'); - if (!fs.existsSync(languageServerDll)) { - throw new Error(`Failed to copy server executable`); - } + return { packagePath, serverPlatform }; } async function installRazor(packageJSON: any, platformInfo: PlatformInformation) { @@ -142,7 +168,7 @@ async function installPackageJsonDependency( } } -async function acquireNugetPackage(packageName: string, packageVersion: string): Promise { +async function acquireNugetPackage(packageName: string, packageVersion: string, interactive: boolean): Promise { packageName = packageName.toLocaleLowerCase(); const packageOutputPath = path.join(nugetTempPath, packageName, packageVersion); if (fs.existsSync(packageOutputPath)) { @@ -157,7 +183,8 @@ async function acquireNugetPackage(packageName: string, packageVersion: string): `/p:PackageName=${packageName}`, `/p:PackageVersion=${packageVersion}`, ]; - if (argv.interactive) { + + if (interactive) { dotnetArgs.push('--interactive'); }