Skip to content

Commit c2d3cc7

Browse files
authored
fix: CDS extractor support for Windows OS (#360)
* CDS extractor windows fixes - 1 * Fix Windows ENOENT: add shell:true to npm/npx spawn calls On Windows, npm and npx are .cmd files. execFileSync('npm', ...) and spawnSync('npx', ...) fail with ENOENT because they bypass the shell and cannot resolve .cmd extensions. Adding shell: true fixes this on Windows while being a no-op on Linux/macOS. Affected files: - cacheInstaller.ts: execFileSync('npm', ['install', ...]) - projectInstaller.ts: execFileSync('npm', ['install', ...]) - indexer.ts: spawnSync('npx', ['--yes', ...]) * Fix Windows: shell:true for npx spawn, posix paths in LGTM_INDEX_FILTERS - compile.ts: change shell:false to shell:true so npx (a .cmd on Windows) can be resolved during CDS compilation - environment.ts: use explicit forward-slash paths ('exclude:**/*.*') instead of join() which produces backslashes on Windows, causing 'Illegal use of **' errors in the JS extractor
1 parent 6143cb5 commit c2d3cc7

File tree

13 files changed

+61
-36
lines changed

13 files changed

+61
-36
lines changed

extractors/cds/tools/cds-extractor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ try {
115115
new Set([
116116
...globSync(join(sourceRoot, '**/*.cds'), {
117117
ignore: ['**/node_modules/**', '**/.git/**'],
118+
windowsPathsNoEscape: true,
118119
}),
119120
]),
120121
);

extractors/cds/tools/dist/cds-extractor.bundle.js

Lines changed: 27 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extractors/cds/tools/dist/cds-extractor.bundle.js.map

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extractors/cds/tools/dist/compile-test-cds-lib.cjs.map

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

extractors/cds/tools/index-files.cmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ REM - assumes it is run from the root of the project source directory;
66

77
where node >nul 2>nul
88
if %ERRORLEVEL% neq 0 (
9-
echo node executable is required (in PATH) to run the 'cds-extractor.bundle.js' script. Please install Node.js and try again.
9+
echo node executable is required ^(in PATH^) to run the 'cds-extractor.bundle.js' script. Please install Node.js and try again.
1010
exit /b 2
1111
)
1212

extractors/cds/tools/src/cds/compiler/compile.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ function createSpawnOptions(
250250
): SpawnSyncOptions {
251251
const spawnOptions: SpawnSyncOptions = {
252252
cwd: projectBaseDir, // CRITICAL: Always use project base directory as cwd to ensure correct path generation
253-
shell: false, // Use shell=false to ensure proper argument handling for paths with spaces
253+
shell: true, // Required on Windows where npm/npx are .cmd files
254254
stdio: 'pipe',
255255
env: { ...process.env },
256256
};

extractors/cds/tools/src/cds/indexer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ export function runCdsIndexer(
115115
env,
116116
stdio: 'pipe',
117117
timeout: CDS_INDEXER_TIMEOUT_MS,
118+
shell: true,
118119
});
119120

120121
result.durationMs = Date.now() - startTime;

extractors/cds/tools/src/cds/parser/functions.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export function determineCdsFilesForProjectDir(
4747
const cdsFiles = sync(join(projectDir, '**/*.cds'), {
4848
nodir: true,
4949
ignore: ['**/node_modules/**', '**/*.testproj/**'],
50+
windowsPathsNoEscape: true,
5051
});
5152

5253
// Convert absolute paths to paths relative to sourceRootDir
@@ -91,11 +92,13 @@ export function determineCdsProjectsUnderSourceDir(sourceRootDir: string): strin
9192
const packageJsonFiles = sync(join(sourceRootDir, '**/package.json'), {
9293
nodir: true,
9394
ignore: ['**/node_modules/**', '**/*.testproj/**'],
95+
windowsPathsNoEscape: true,
9496
});
9597

9698
const cdsFiles = sync(join(sourceRootDir, '**/*.cds'), {
9799
nodir: true,
98100
ignore: ['**/node_modules/**', '**/*.testproj/**'],
101+
windowsPathsNoEscape: true,
99102
});
100103

101104
// Collect all potential project directories
@@ -369,7 +372,10 @@ function hasStandardCdsContent(dir: string): boolean {
369372
for (const location of standardLocations) {
370373
if (existsSync(location) && statSync(location).isDirectory()) {
371374
// Check for any .cds files at any level under these directories.
372-
const cdsFiles = sync(join(location, '**/*.cds'), { nodir: true });
375+
const cdsFiles = sync(join(location, '**/*.cds'), {
376+
nodir: true,
377+
windowsPathsNoEscape: true,
378+
});
373379
if (cdsFiles.length > 0) {
374380
return true;
375381
}
@@ -383,7 +389,7 @@ function hasStandardCdsContent(dir: string): boolean {
383389
* Check if a directory has direct CDS files.
384390
*/
385391
function hasDirectCdsContent(dir: string): boolean {
386-
const directCdsFiles = sync(join(dir, '*.cds'));
392+
const directCdsFiles = sync(join(dir, '*.cds'), { windowsPathsNoEscape: true });
387393
return directCdsFiles.length > 0;
388394
}
389395

extractors/cds/tools/src/environment.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ export function configureLgtmIndexFilters(): void {
227227
`Found $LGTM_INDEX_FILTERS already set to:
228228
${process.env.LGTM_INDEX_FILTERS}`,
229229
);
230-
const allowedExcludePatterns = [join('exclude:**', '*'), join('exclude:**', '*.*')];
230+
// Use forward slashes explicitly — join() uses backslashes on Windows
231+
// which causes 'Illegal use of **' errors in the JS extractor.
232+
const allowedExcludePatterns = ['exclude:**/*', 'exclude:**/*.*'];
231233

232234
excludeFilters =
233235
'\n' +
@@ -245,12 +247,14 @@ ${process.env.LGTM_INDEX_FILTERS}`,
245247
// The cdsExtractorMarkerFileName file is auto-created by the CDS extractor in order
246248
// to force the underlying JS extractor to see at least one .js file, which became a
247249
// requirement starting with v2.23.5 of the CodeQL CLI.
250+
// Use forward slashes explicitly — join() uses backslashes on Windows
251+
// which causes 'Illegal use of **' errors in the JS extractor.
248252
const lgtmIndexFiltersPatterns = [
249-
join('exclude:**', '*.*'),
250-
join('include:**', '*.cds.json'),
251-
join('include:**', '*.cds'),
252-
join('include:**', cdsExtractorMarkerFileName),
253-
join('exclude:**', 'node_modules', '**', '*.*'),
253+
'exclude:**/*.*',
254+
'include:**/*.cds.json',
255+
'include:**/*.cds',
256+
`include:**/${cdsExtractorMarkerFileName}`,
257+
'exclude:**/node_modules/**/*.*',
254258
].join('\n');
255259

256260
process.env.LGTM_INDEX_FILTERS = lgtmIndexFiltersPatterns + excludeFilters;

extractors/cds/tools/src/packageManager/cacheInstaller.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ function installDependenciesInCache(
497497
execFileSync('npm', ['install', '--quiet', '--no-audit', '--no-fund'], {
498498
cwd: cacheDir,
499499
stdio: 'inherit',
500+
shell: true,
500501
});
501502

502503
// Add warning diagnostic if using fallback versions

0 commit comments

Comments
 (0)