Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions extractors/cds/tools/dist/cds-extractor.bundle.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions extractors/cds/tools/dist/cds-extractor.bundle.js.map

Large diffs are not rendered by default.

65 changes: 63 additions & 2 deletions extractors/cds/tools/src/packageManager/cacheInstaller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { execFileSync } from 'child_process';
import { createHash } from 'crypto';
import { existsSync, mkdirSync, writeFileSync } from 'fs';
import { join, resolve } from 'path';
import { copyFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
import { dirname, join, resolve } from 'path';

import type { CdsDependencyCombination } from './types';
import { CdsDependencyGraph, CdsProject } from '../cds/parser/types';
Expand Down Expand Up @@ -48,6 +48,61 @@ function addDependencyVersionWarning(
}
}

/**
* Find the nearest `.npmrc` file by searching the given directory and its
* ancestors up to (and including) the filesystem root. npm itself walks the
* directory tree when looking for project-level `.npmrc` files, so we mirror
* that behaviour here.
*
* @param startDir The directory from which to start the upward search.
* @returns The absolute path to the nearest `.npmrc`, or `undefined` if none is found.
*/
export function findNearestNpmrc(startDir: string): string | undefined {
let current = resolve(startDir);

// Walk up the directory tree until we find an .npmrc or reach the root

while (true) {
const candidate = join(current, '.npmrc');
if (existsSync(candidate)) {
return candidate;
}
const parent = dirname(current);
if (parent === current) {
// Reached filesystem root without finding .npmrc
return undefined;
}
current = parent;
}
}

/**
* Copy the project's `.npmrc` file (if any) into the cache directory so that
* `npm install` inside the cache respects custom registry configuration such
* as scoped registries (`@sap:registry=...`), authentication tokens, and
* `strict-ssl` settings.
*
* @param cacheDir The cache directory where dependencies will be installed.
* @param projectDir Absolute path to the project directory whose `.npmrc` should be used.
*/
export function copyNpmrcToCache(cacheDir: string, projectDir: string): void {
const npmrcPath = findNearestNpmrc(projectDir);
if (!npmrcPath) {
return;
}

const dest = join(cacheDir, '.npmrc');
try {
copyFileSync(npmrcPath, dest);
cdsExtractorLog('info', `Copied .npmrc from '${npmrcPath}' to cache directory '${cacheDir}'`);
} catch (err) {
cdsExtractorLog(
'warn',
`Failed to copy .npmrc to cache directory: ${err instanceof Error ? err.message : String(err)}`,
);
}
}
Comment thread
data-douser marked this conversation as resolved.

/**
* Install dependencies for CDS projects using a robust cache strategy with fallback logic
* @param dependencyGraph The dependency graph of the project
Expand Down Expand Up @@ -204,6 +259,12 @@ export function cacheInstallDependencies(
);
continue;
}

// Copy the project's .npmrc (if any) so npm respects custom registries
const firstProjectDir = Array.from(dependencyGraph.projects.keys())[0];
if (firstProjectDir) {
copyNpmrcToCache(cacheDir, join(sourceRoot, firstProjectDir));
}
}

Comment thread
data-douser marked this conversation as resolved.
Outdated
// Try to install dependencies in the cache directory
Expand Down
2 changes: 1 addition & 1 deletion extractors/cds/tools/src/packageManager/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Export the new robust installer functionality (preferred)
export { cacheInstallDependencies } from './cacheInstaller';
export { cacheInstallDependencies, copyNpmrcToCache, findNearestNpmrc } from './cacheInstaller';
export { needsFullDependencyInstallation, projectInstallDependencies } from './projectInstaller';
export type { CdsDependencyCombination } from './types';
export {
Expand Down
24 changes: 24 additions & 0 deletions extractors/javascript/tools/pre-finalize.cmd
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
@echo off

if not defined CODEQL_EXTRACTOR_CDS_SKIP_EXTRACTION (
echo Running database index-files for CDS (.cds) files ...

type NUL && "%CODEQL_DIST%\codeql.exe" database index-files ^
--include-extension=.cds ^
--language cds ^
Expand All @@ -9,6 +11,28 @@ if not defined CODEQL_EXTRACTOR_CDS_SKIP_EXTRACTION (
--total-size-limit=10m ^
-- ^
"%CODEQL_EXTRACTOR_JAVASCRIPT_WIP_DATABASE%"

echo Finished running database index-files for CDS (.cds) files.
)

echo Running database index-files for UI5 (.view.xml and .fragment.xml) files ...

type NUL && "%CODEQL_DIST%\codeql.exe" database index-files ^
--include-extension=.view.xml ^
--include-extension=.fragment.xml ^
Comment thread
data-douser marked this conversation as resolved.
--language xml ^
--prune **\node_modules\**\* ^
--prune **\.eslint\**\* ^
--total-size-limit=10m ^
-- ^
"%CODEQL_EXTRACTOR_JAVASCRIPT_WIP_DATABASE%"

echo Finished running database index-files for UI5 (.view.xml and .fragment.xml) files.

REM UI5 also requires *.view.json files and *.view.html files be indexed, but these are indexed by
REM default by CodeQL.

REM XSJS also requires indexing of *.xsaccess files, *.xsjs files and xs-app.json files, but these
REM are indexed by default by CodeQL.

exit /b %ERRORLEVEL%
Loading