Skip to content

Commit 7e09588

Browse files
committed
Build VSIXs on multiple platforms to parallelize build
1 parent 64d29e2 commit 7e09588

File tree

7 files changed

+175
-97
lines changed

7 files changed

+175
-97
lines changed

.vscode/launch.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,17 @@
129129
],
130130
"preLaunchTask": "buildDev"
131131
},
132+
{
133+
"type": "node",
134+
"request": "launch",
135+
"name": "Debug gulp task",
136+
"preLaunchTask": "build",
137+
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
138+
"args": [
139+
"${input:gulpTaskName}"
140+
],
141+
"cwd": "${workspaceFolder}"
142+
},
132143
{
133144
"type": "node",
134145
"request": "launch",
@@ -212,7 +223,11 @@
212223
"slnFilterWithCsproj",
213224
"slnWithGenerator"
214225
]
215-
// type specific configuration attributes
226+
},
227+
{
228+
"id": "gulpTaskName",
229+
"description": "The name of the gulp task to debug",
230+
"type": "promptString",
216231
}
217232
]
218233
}

azure-pipelines-official.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ parameters:
1313
default: 'default'
1414

1515
stages:
16-
- template: azure-pipelines/build.yml
16+
- template: azure-pipelines/build-all.yml
1717
parameters:
1818
versionNumberOverride: ${{ parameters.versionNumberOverride }}
1919

azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pr:
1212
- main
1313

1414
stages:
15-
- template: azure-pipelines/build.yml
15+
- template: azure-pipelines/build-all.yml
1616

1717
- stage: Test
1818
displayName: Test

azure-pipelines/build-all.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
parameters:
2+
- name: versionNumberOverride
3+
type: string
4+
default: 'default'
5+
6+
stages:
7+
- stage: Build
8+
displayName: 'Build VSIXs'
9+
dependsOn: []
10+
jobs:
11+
- template: build.yml
12+
parameters:
13+
versionNumberOverride: ${{ parameters.versionNumberOverride }}
14+
vmImageName: ubuntu-latest
15+
platform: linux
16+
- template: build.yml
17+
parameters:
18+
versionNumberOverride: ${{ parameters.versionNumberOverride }}
19+
vmImageName: windows-latest
20+
platform: windows
21+
- template: build.yml
22+
parameters:
23+
versionNumberOverride: ${{ parameters.versionNumberOverride }}
24+
vmImageName: macOS-latest
25+
platform: darwin

azure-pipelines/build.yml

Lines changed: 65 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,70 @@ parameters:
22
- name: versionNumberOverride
33
type: string
44
default: 'default'
5+
- name: vmImageName
6+
type: string
7+
default: ''
8+
- name: platform
9+
type: string
10+
11+
jobs:
12+
- job:
13+
displayName: 'Build ${{ parameters.platform }} prerelease vsixs'
14+
pool:
15+
name: Azure Pipelines
16+
vmImage: ${{ parameters.vmImageName }}
17+
steps:
18+
- checkout: self
19+
clean: true
20+
submodules: true
21+
fetchTags: false
22+
fetchDepth: 0
23+
24+
- template: prereqs.yml
25+
parameters:
26+
versionNumberOverride: ${{ parameters.versionNumberOverride }}
27+
28+
- script: gulp vsix:release:package:${{ parameters.platform }} --prerelease
29+
displayName: 'Build VSIXs'
30+
31+
- task: PublishBuildArtifacts@1
32+
# Run the publish step so we have vsix's even if the tests fail.
33+
condition: succeededOrFailed()
34+
displayName: 'Publish VSIXs'
35+
inputs:
36+
PathtoPublish: '$(Build.SourcesDirectory)/vsix'
37+
ArtifactName: 'VSIX_Prerelease_$(System.JobAttempt)'
38+
39+
- script: npm run test:artifacts
40+
displayName: 'Run artifacts tests'
41+
42+
- job:
43+
displayName: 'Build ${{ parameters.platform }} release vsixs'
44+
pool:
45+
name: Azure Pipelines
46+
vmImage: ${{ parameters.vmImageName }}
47+
steps:
48+
- checkout: self
49+
clean: true
50+
submodules: true
51+
fetchTags: false
52+
fetchDepth: 0
53+
54+
- template: prereqs.yml
55+
parameters:
56+
versionNumberOverride: ${{ parameters.versionNumberOverride }}
57+
58+
- script: gulp vsix:release:package:${{ parameters.platform }}
59+
displayName: 'Build VSIXs'
60+
61+
- task: PublishBuildArtifacts@1
62+
# Run the publish step so we have vsix's even if the tests fail.
63+
condition: succeededOrFailed()
64+
displayName: 'Publish VSIXs'
65+
inputs:
66+
PathtoPublish: '$(Build.SourcesDirectory)/vsix'
67+
ArtifactName: 'VSIX_Release_$(System.JobAttempt)'
568

6-
stages:
7-
- stage: Build
8-
displayName: 'Build VSIXs'
9-
jobs:
10-
- job:
11-
displayName: 'Build Prerelease VSIXs'
12-
steps:
13-
- checkout: self
14-
clean: true
15-
submodules: true
16-
fetchTags: false
17-
fetchDepth: 0
18-
19-
- template: prereqs.yml
20-
parameters:
21-
versionNumberOverride: ${{ parameters.versionNumberOverride }}
22-
23-
- script: gulp 'vsix:release:package' --prerelease
24-
displayName: 'Build VSIXs'
25-
26-
- task: PublishPipelineArtifact@1
27-
# Run the publish step so we have vsix's even if the tests fail.
28-
condition: succeededOrFailed()
29-
displayName: 'Publish VSIXs'
30-
inputs:
31-
targetPath: '$(Build.SourcesDirectory)/vsix'
32-
artifactName: 'VSIX_Prerelease_$(System.JobAttempt)'
33-
34-
- script: npm run test:artifacts
35-
displayName: 'Run artifacts tests'
36-
37-
- job:
38-
displayName: 'Build Release VSIXs'
39-
steps:
40-
- checkout: self
41-
clean: true
42-
submodules: true
43-
fetchTags: false
44-
fetchDepth: 0
45-
46-
- template: prereqs.yml
47-
parameters:
48-
versionNumberOverride: ${{ parameters.versionNumberOverride }}
49-
50-
- script: gulp 'vsix:release:package'
51-
displayName: 'Build VSIXs'
52-
53-
- task: PublishPipelineArtifact@1
54-
# Run the publish step so we have vsix's even if the tests fail.
55-
condition: succeededOrFailed()
56-
displayName: 'Publish VSIXs'
57-
inputs:
58-
targetPath: '$(Build.SourcesDirectory)/vsix'
59-
artifactName: 'VSIX_Release_$(System.JobAttempt)'
60-
61-
- script: npm run test:artifacts
62-
displayName: 'Run artifacts tests'
69+
- script: npm run test:artifacts
70+
displayName: 'Run artifacts tests'
6371

tasks/commandLineArguments.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
import * as minimist from 'minimist';
77
import * as path from 'path';
88

9-
const argv = minimist(process.argv.slice(2), {
10-
boolean: ['retainVsix'],
11-
});
9+
const argv = minimist(process.argv.slice(2));
1210

1311
export const commandLineOptions = {
14-
retainVsix: !!argv['retainVsix'],
1512
outputFolder: makePathAbsolute(argv['o']),
1613
codeExtensionPath: makePathAbsolute(argv['codeExtensionPath']),
1714
};

tasks/offlinePackagingTasks.ts

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import NetworkSettings from '../src/networkSettings';
1717
import { downloadAndInstallPackages } from '../src/packageManager/downloadAndInstallPackages';
1818
import { getRuntimeDependenciesPackages } from '../src/tools/runtimeDependencyPackageUtils';
1919
import { getAbsolutePathPackagesToInstall } from '../src/packageManager/getAbsolutePathPackagesToInstall';
20-
import { commandLineOptions } from '../tasks/commandLineArguments';
2120
import {
2221
codeExtensionPath,
2322
packedVsixOutputRoot,
@@ -33,8 +32,14 @@ import path = require('path');
3332
// eslint-disable-next-line @typescript-eslint/no-var-requires
3433
const argv = require('yargs').argv;
3534

35+
interface VSIXPlatformInfo {
36+
vsceTarget: string;
37+
rid: string;
38+
platformInfo: PlatformInformation;
39+
}
40+
3641
// Mapping of vsce vsix packaging target to the RID used to build the server executable
37-
export const platformSpecificPackages = [
42+
export const platformSpecificPackages: VSIXPlatformInfo[] = [
3843
{ vsceTarget: 'win32-x64', rid: 'win-x64', platformInfo: new PlatformInformation('win32', 'x86_64') },
3944
{ vsceTarget: 'win32-ia32', rid: 'win-x86', platformInfo: new PlatformInformation('win32', 'x86') },
4045
{ vsceTarget: 'win32-arm64', rid: 'win-arm64', platformInfo: new PlatformInformation('win32', 'arm64') },
@@ -46,16 +51,46 @@ export const platformSpecificPackages = [
4651
{ vsceTarget: 'darwin-arm64', rid: 'osx-arm64', platformInfo: new PlatformInformation('darwin', 'arm64') },
4752
];
4853

49-
gulp.task('vsix:release:package', async () => {
50-
//if user does not want to clean up the existing vsix packages
51-
await cleanAsync(/* deleteVsix: */ !commandLineOptions.retainVsix);
54+
const vsixTasks: string[] = [];
55+
for (const p of platformSpecificPackages) {
56+
let platformName: string;
57+
if (p.platformInfo.isWindows()) {
58+
platformName = 'windows';
59+
} else if (p.platformInfo.isLinux()) {
60+
platformName = 'linux';
61+
} else if (p.platformInfo.isMacOS()) {
62+
platformName = 'darwin';
63+
} else {
64+
throw new Error(`Unexpected platform ${p.platformInfo.platform}`);
65+
}
66+
67+
const taskName = `vsix:release:package:${platformName}:${p.vsceTarget}`;
68+
vsixTasks.push(taskName);
69+
gulp.task(taskName, async () => {
70+
await doPackageOffline(p);
71+
});
72+
}
5273

53-
await doPackageOffline();
74+
gulp.task('vsix:release:package:windows', gulp.series(...vsixTasks.filter((t) => t.includes('windows'))));
75+
gulp.task('vsix:release:package:linux', gulp.series(...vsixTasks.filter((t) => t.includes('linux'))));
76+
gulp.task('vsix:release:package:darwin', gulp.series(...vsixTasks.filter((t) => t.includes('darwin'))));
77+
gulp.task('vsix:release:package:neutral', async () => {
78+
await doPackageOffline(undefined);
5479
});
5580

81+
gulp.task(
82+
'vsix:release:package',
83+
gulp.series(
84+
'vsix:release:package:windows',
85+
'vsix:release:package:linux',
86+
'vsix:release:package:darwin',
87+
'vsix:release:package:neutral'
88+
)
89+
);
90+
5691
// Downloads dependencies for local development.
5792
gulp.task('installDependencies', async () => {
58-
await cleanAsync(/* deleteVsix: */ false);
93+
await cleanAsync();
5994

6095
const packageJSON = getPackageJSON();
6196

@@ -210,7 +245,8 @@ async function acquireNugetPackage(packageName: string, packageVersion: string,
210245
return packageOutputPath;
211246
}
212247

213-
async function doPackageOffline() {
248+
async function doPackageOffline(vsixPlatform: VSIXPlatformInfo | undefined) {
249+
await cleanAsync();
214250
// Set the package.json version based on the value in version.json.
215251
const versionInfo = await nbgv.getVersion();
216252
console.log(versionInfo.npmPackageVersion);
@@ -229,38 +265,37 @@ async function doPackageOffline() {
229265
// Now that we've updated the version, get the package.json.
230266
const packageJSON = getPackageJSON();
231267

232-
for (const p of platformSpecificPackages) {
233-
try {
234-
if (process.platform === 'win32' && !p.rid.startsWith('win')) {
235-
console.warn(
236-
`Skipping packaging for ${p.rid} on Windows since runtime executables will not be marked executable in *nix packages.`
237-
);
238-
continue;
239-
}
240-
241-
await buildVsix(packageJSON, packedVsixOutputRoot, prerelease, p.vsceTarget, p.platformInfo);
242-
} catch (err) {
243-
const message = (err instanceof Error ? err.stack : err) ?? '<unknown error>';
244-
// NOTE: Extra `\n---` at the end is because gulp will print this message following by the
245-
// stack trace of this line. So that seperates the two stack traces.
246-
throw Error(`Failed to create package ${p.vsceTarget}. ${message}\n---`);
247-
}
268+
if (process.platform === 'win32' && !vsixPlatform?.rid.startsWith('win')) {
269+
console.warn(
270+
`Skipping packaging for ${vsixPlatform?.rid} on Windows since runtime executables will not be marked executable in *nix packages.`
271+
);
272+
return;
248273
}
249274

250-
// Also output the platform neutral VSIX using the platform neutral server bits we created before.
251-
await buildVsix(packageJSON, packedVsixOutputRoot, prerelease);
275+
if (vsixPlatform === undefined) {
276+
await buildVsix(packageJSON, packedVsixOutputRoot, prerelease);
277+
} else {
278+
await buildVsix(
279+
packageJSON,
280+
packedVsixOutputRoot,
281+
prerelease,
282+
vsixPlatform.vsceTarget,
283+
vsixPlatform.platformInfo
284+
);
285+
}
286+
} catch (err) {
287+
const message = (err instanceof Error ? err.stack : err) ?? '<unknown error>';
288+
// NOTE: Extra `\n---` at the end is because gulp will print this message following by the
289+
// stack trace of this line. So that seperates the two stack traces.
290+
throw Error(`Failed to create package ${vsixPlatform?.vsceTarget ?? 'neutral'}. ${message}\n---`);
252291
} finally {
253292
// Reset package version to the placeholder value.
254293
await nbgv.resetPackageVersionPlaceholder();
255294
}
256295
}
257296

258-
async function cleanAsync(deleteVsix: boolean) {
297+
async function cleanAsync() {
259298
await del(['install.*', '.omnisharp*', '.debugger', '.razor', languageServerDirectory]);
260-
261-
if (deleteVsix) {
262-
await del('*.vsix');
263-
}
264299
}
265300

266301
async function buildVsix(
@@ -270,8 +305,6 @@ async function buildVsix(
270305
vsceTarget?: string,
271306
platformInfo?: PlatformInformation
272307
) {
273-
await cleanAsync(false);
274-
275308
await installRoslyn(packageJSON, platformInfo);
276309

277310
if (platformInfo != null) {

0 commit comments

Comments
 (0)