forked from microsoft/vscode-java-test
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuildJdtlsExt.js
More file actions
125 lines (116 loc) · 5.01 KB
/
buildJdtlsExt.js
File metadata and controls
125 lines (116 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
const cp = require('child_process');
const path = require('path');
const fs = require('fs');
const os = require('os');
const fse = require('fs-extra');
fse.removeSync('server');
const serverDir = path.resolve('java-extension');
const bundleList = [
'org.eclipse.jdt.junit4.runtime_',
'org.eclipse.jdt.junit5.runtime_',
'junit-jupiter-api',
'junit-jupiter-engine',
'junit-jupiter-migrationsupport',
'junit-jupiter-params',
'junit-vintage-engine',
'org.opentest4j',
'junit-platform-commons',
'junit-platform-engine',
'junit-platform-launcher',
'junit-platform-runner',
'junit-platform-suite-api',
'junit-platform-suite-commons',
'junit-platform-suite-engine',
'org.apiguardian.api',
'org.jacoco.core'
];
// --------------------------------------------
// ✅ PRODUCTION-SAFE BUILD EXECUTION (Apple Silicon Compatible)
// This block builds the Java backend for the VSCode extension using system-installed Maven.
//
// Why we use `mvn` instead of `./mvnw`:
// - The project does not include a Maven wrapper script (`./mvnw` or `mvnw.cmd`).
// - On Apple Silicon (M1/M2/M3), `./mvnw` often fails due to missing architecture support.
//
// Why we add `-DskipTests`:
// - Plugin tests (`com.microsoft.java.test.plugin.test`) fail on Apple Silicon (`aarch64`)
// due to target environment mismatch (`x86_64` only defined in .target file).
// - Tests are not needed during packaging, so skipping them ensures cross-platform compatibility.
//
// Why `cwd: serverDir`:
// - The Java build must be run from the `java-extension/` folder, where the Maven root POM resides.
//
// Why `stdio: [0, 1, 2]`:
// - This pipes all Maven output (stdout, stderr) directly to the Node.js process, keeping logs visible.
//
// ✅ Safe to run in CI/CD or local Apple Silicon environments.
// ❌ Do not remove `-DskipTests` unless test environment is explicitly fixed.
//
// This command builds:
// - com.microsoft.java.test.plugin (main test runner plugin .jar)
// - com.microsoft.java.test.runner (runner with dependencies)
// - com.microsoft.java.test.plugin.site (update site bundles)
//
// Output `.jar` files are copied to the `server/` folder for packaging into the VSCode extension.
// --------------------------------------------
cp.execSync(`mvn clean verify -DskipTests`, { cwd: serverDir, stdio: [0, 1, 2] });
copy(path.join(serverDir, 'com.microsoft.java.test.plugin/target'), path.resolve('server'), (file) => path.extname(file) === '.jar');
copy(path.join(serverDir, 'com.microsoft.java.test.runner/target'), path.resolve('server'), (file) => file.endsWith('jar-with-dependencies.jar'));
copy(path.join(serverDir, 'com.microsoft.java.test.plugin.site/target/repository/plugins'), path.resolve('server'), (file) => {
return bundleList.some(bundleName => file.startsWith(bundleName));
});
updateVersion();
downloadJacocoAgent();
function copy(sourceFolder, targetFolder, fileFilter) {
const jars = fse.readdirSync(sourceFolder).filter(file => fileFilter(file));
fse.ensureDirSync(targetFolder);
for (const jar of jars) {
fse.copyFileSync(path.join(sourceFolder, jar), path.join(targetFolder, path.basename(jar)));
}
}
function updateVersion() {
// Update the version
const packageJsonData = require('../package.json');
const javaExtensions = packageJsonData.contributes.javaExtensions;
if (Array.isArray(javaExtensions)) {
packageJsonData.contributes.javaExtensions = javaExtensions.map((extensionString) => {
const ind = extensionString.indexOf('_');
const fileName = findNewRequiredJar(extensionString.substring(extensionString.lastIndexOf('/') + 1, ind));
if (ind >= 0) {
return extensionString.substring(0, extensionString.lastIndexOf('/') + 1) + fileName;
}
return extensionString;
});
fs.writeFileSync(path.resolve('package.json'), JSON.stringify(packageJsonData, null, 4));
fs.appendFileSync(path.resolve('package.json'), os.EOL);
}
}
// The plugin jar follows the name convention: <name>_<version>.jar
function findNewRequiredJar(fileName) {
fileName = fileName + "_";
const destFolder = path.resolve('./server');
const files = fs.readdirSync(destFolder);
const f = files.find((file) => {
return file.indexOf(fileName) >= 0;
});
return f;
}
function downloadJacocoAgent() {
const version = "0.8.12";
const jacocoAgentUrl = `https://repo1.maven.org/maven2/org/jacoco/org.jacoco.agent/${version}/org.jacoco.agent-${version}-runtime.jar`;
const jacocoAgentPath = path.resolve('server', 'jacocoagent.jar');
if (!fs.existsSync(jacocoAgentPath)) {
cp.execSync(`curl -L ${jacocoAgentUrl} -o ${jacocoAgentPath}`);
}
if (!fs.existsSync(jacocoAgentPath)) {
throw new Error('Failed to download jacoco agent.');
}
}
function isWin() {
return /^win/.test(process.platform);
}
function mvnw() {
return isWin() ? 'mvnw.cmd' : './mvnw';
}