diff --git a/.github/workflows/dockertests.yml b/.github/workflows/dockertests.yml index da912b73c..2e4bb897d 100644 --- a/.github/workflows/dockertests.yml +++ b/.github/workflows/dockertests.yml @@ -3,7 +3,6 @@ name: docker tests on: push: branches: - - master - feature/* - release/* - fix/* diff --git a/.github/workflows/repotests.yml b/.github/workflows/repotests.yml index 3ee3359be..0983f3f84 100644 --- a/.github/workflows/repotests.yml +++ b/.github/workflows/repotests.yml @@ -3,7 +3,6 @@ name: Repo tests on: push: branches: - - master - feature/* - release/* - fix/* @@ -47,6 +46,8 @@ jobs: mkdir -p denoresults env: CI: true + - name: Setup Android SDK + uses: android-actions/setup-android@v2 - uses: swift-actions/setup-swift@v1 if: matrix.os == 'ubuntu-latest' - uses: actions/checkout@v4 @@ -117,6 +118,10 @@ jobs: with: repository: 'openpbs/openpbs' path: 'repotests/openpbs' + - uses: actions/checkout@v4 + with: + repository: 'home-assistant/android' + path: 'repotests/ha-android' - name: repotests run: | bin/cdxgen.js -p -r -t java repotests/shiftleft-java-example -o bomresults/bom-java.json --generate-key-and-sign @@ -126,8 +131,8 @@ jobs: node bin/evinse.js -i bomresults/bom-ts.json -o bomresults/bom-ts.evinse.json -l javascript --with-data-flow -p repotests/shiftleft-ts-example FETCH_LICENSE=false bin/cdxgen.js -p -t js repotests/meetingsdk-vuejs-sample -o bomresults/bom-vue.json node bin/evinse.js -i bomresults/bom-vue.json -o bomresults/bom-vue.evinse.json -l javascript --with-data-flow -p repotests/meetingsdk-vuejs-sample - ASTGEN_IGNORE_DIRS="" FETCH_LICENSE=false bin/cdxgen.js -p -t js repotests/sveltejs-examples -o bomresults/bom-svelte.json - ASTGEN_IGNORE_DIRS="" node bin/evinse.js -i bomresults/bom-svelte.json -o bomresults/bom-svelte.evinse.json -l javascript --with-data-flow -p repotests/sveltejs-examples + CDXGEN_DEBUG_MODE=debug ASTGEN_IGNORE_DIRS="" FETCH_LICENSE=false bin/cdxgen.js -p -t js repotests/sveltejs-examples -o bomresults/bom-svelte.json + CDXGEN_DEBUG_MODE=debug ASTGEN_IGNORE_DIRS="" node bin/evinse.js -i bomresults/bom-svelte.json -o bomresults/bom-svelte.evinse.json -l javascript --with-data-flow -p repotests/sveltejs-examples FETCH_LICENSE=1 bin/cdxgen.js -p -t js repotests/shiftleft-ts-example --required-only -o bomresults/bom-ts.json --validate FETCH_LICENSE=false bin/cdxgen.js -p -r -t go repotests/shiftleft-go-example -o bomresults/bom-go.json --validate FETCH_LICENSE=true bin/cdxgen.js -p -r -t csharp repotests/vulnerable_net_core -o bomresults/bom-csharp2.json --validate @@ -145,6 +150,9 @@ jobs: bin/cdxgen.js -r -t yaml-manifest repotests/microservices-demo -o bomresults/bom-yaml.json --validate FETCH_LICENSE=true bin/cdxgen.js -p -r -t js repotests/shiftleft-ts-example -o bomresults/bom-ts.json --validate bin/cdxgen.js -r -t c repotests/openpbs -o bomresults/bom-openpbs.json + cd repotests/ha-android && ./gradlew assembleDebug || true && cd ../.. + bin/cdxgen.js -r -t java repotests/ha-android -o bomresults/bom-android.json + CDXGEN_DEBUG_MODE=debug bin/evinse.js -i bomresults/bom-android.json -o bomresults/bom-android.evinse.json -l java repotests/ha-android # mkdir -p jenkins # wget https://updates.jenkins.io/download/plugins/sonar/2.14/sonar.hpi # wget https://updates.jenkins.io/download/plugins/bouncycastle-api/2.26/bouncycastle-api.hpi diff --git a/docs/ADVANCED.md b/docs/ADVANCED.md index 887a150bf..dc28f2a47 100644 --- a/docs/ADVANCED.md +++ b/docs/ADVANCED.md @@ -151,3 +151,18 @@ node bin/cdxgen.js -o bom.json -t c --usages-slices-file usages.json ", diff --git a/utils.js b/utils.js index cd87e080e..2997650e5 100644 --- a/utils.js +++ b/utils.js @@ -50,6 +50,7 @@ if (!url.startsWith("file://")) { url = new URL(`file://${import.meta.url}`).toString(); } const dirNameStr = import.meta ? dirname(fileURLToPath(url)) : __dirname; +const isWin = platform() === "win32"; const licenseMapping = JSON.parse( readFileSync(join(dirNameStr, "data", "lic-mapping.json")) @@ -1870,7 +1871,8 @@ export const executeGradleProperties = function (dir, rootPath, subProject) { ); const result = spawnSync(gradleCmd, gradlePropertiesArgs, { cwd: dir, - encoding: "utf-8" + encoding: "utf-8", + shell: isWin }); if (result.status !== 0 || result.error) { if (result.stderr) { @@ -5334,7 +5336,8 @@ export const collectMvnDependencies = function ( ); const result = spawnSync(mavenCmd, copyArgs, { cwd: basePath, - encoding: "utf-8" + encoding: "utf-8", + shell: isWin }); if (result.status !== 0 || result.error) { console.error(result.stdout, result.stderr); @@ -5413,10 +5416,24 @@ export const collectJarNS = function (jarPath, pomPathMap = {}) { console.log( `About to identify class names for all jars in the path ${jarPath}` ); + const env = { + ...process.env + }; + // jar command usually would not be available in the PATH for windows + if (isWin && env.JAVA_HOME) { + env.PATH = `${env.PATH || env.Path}${_delimiter}${join( + env.JAVA_HOME, + "bin" + )}`; + } + let jarCommandAvailable = true; // Execute jar tvf to get class names const jarFiles = getAllFiles(jarPath, "**/*.jar"); if (jarFiles && jarFiles.length) { for (const jf of jarFiles) { + if (!jarCommandAvailable) { + break; + } const jarname = jf; let pomname = pomPathMap[basename(jf).replace(".jar", ".pom")] || @@ -5518,18 +5535,42 @@ export const collectJarNS = function (jarPath, pomPathMap = {}) { if (DEBUG_MODE) { console.log(`Executing 'jar tf ${jf}'`); } - const jarResult = spawnSync("jar", ["-tf", jf], { encoding: "utf-8" }); + + const jarResult = spawnSync("jar", ["-tf", jf], { + encoding: "utf-8", + shell: isWin, + maxBuffer: 50 * 1024 * 1024, + env + }); + if ( + jarResult && + jarResult.stderr && + jarResult.stderr.includes( + "is not recognized as an internal or external command" + ) + ) { + jarCommandAvailable = false; + console.log( + "jar command is not available in PATH. Ensure JDK >= 17 is installed and set the environment variables JAVA_HOME and PATH to the bin directory inside JAVA_HOME." + ); + } const consolelines = (jarResult.stdout || "").split("\n"); const nsList = consolelines .filter((l) => { return ( - l.includes(".class") && + (l.includes(".class") || + l.includes(".java") || + l.includes(".kt")) && !l.includes("-INF") && !l.includes("module-info") ); }) .map((e) => { - return e.replace(".class", "").replace(/\/$/, "").replace(/\//g, "."); + return e + .replace("\r", "") + .replace(/.(class|java|kt)/, "") + .replace(/\/$/, "") + .replace(/\//g, "."); }); jarNSMapping[purl || jf] = { jarFile: jf, @@ -5696,10 +5737,22 @@ export const extractJarArchive = function (jarFile, tempDir) { // Only copy if the file doesn't exist copyFileSync(jarFile, join(tempDir, fname), constants.COPYFILE_FICLONE); } + const env = { + ...process.env + }; + // jar command usually would not be available in the PATH for windows + if (isWin && env.JAVA_HOME) { + env.PATH = `${env.PATH || env.Path}${_delimiter}${join( + env.JAVA_HOME, + "bin" + )}`; + } if (jarFile.endsWith(".war") || jarFile.endsWith(".hpi")) { const jarResult = spawnSync("jar", ["-xf", join(tempDir, fname)], { encoding: "utf-8", - cwd: tempDir + cwd: tempDir, + shell: isWin, + env }); if (jarResult.status !== 0) { console.error(jarResult.stdout, jarResult.stderr); @@ -5736,7 +5789,9 @@ export const extractJarArchive = function (jarFile, tempDir) { } else { jarResult = spawnSync("jar", ["-xf", jf], { encoding: "utf-8", - cwd: tempDir + cwd: tempDir, + shell: isWin, + env }); } if (jarResult.status !== 0) { @@ -6076,7 +6131,8 @@ export const getMavenCommand = (srcPath, rootPath) => { const result = spawnSync(mavenCmd, ["wrapper:wrapper"], { encoding: "utf-8", cwd: rootPath, - timeout: TIMEOUT_MS + timeout: TIMEOUT_MS, + shell: isWin }); if (!result.error) { isWrapperReady = true; @@ -6139,16 +6195,26 @@ export const executeAtom = (src, args) => { const env = { ...process.env }; - env.PATH = `${env.PATH}${_delimiter}${join( - dirNameStr, - "node_modules", - ".bin" - )}`; + + if (isWin) { + env.PATH = `${env.PATH || env.Path}${_delimiter}${join( + dirNameStr, + "node_modules", + ".bin" + )}`; + } else { + env.PATH = `${env.PATH}${_delimiter}${join( + dirNameStr, + "node_modules", + ".bin" + )}`; + } const result = spawnSync(ATOM_BIN, args, { cwd, encoding: "utf-8", timeout: TIMEOUT_MS, - detached: true, + detached: !isWin && !process.env.CI, + shell: isWin, env }); if (result.stderr) { @@ -6306,7 +6372,8 @@ export const getPipFrozenTree = (basePath, reqOrSetupFile, tempVenvDir) => { !reqOrSetupFile.endsWith("poetry.lock") ) { result = spawnSync(PYTHON_CMD, ["-m", "venv", tempVenvDir], { - encoding: "utf-8" + encoding: "utf-8", + shell: isWin }); if (result.status !== 0 || result.error) { if (DEBUG_MODE) { @@ -6347,14 +6414,16 @@ export const getPipFrozenTree = (basePath, reqOrSetupFile, tempVenvDir) => { result = spawnSync("poetry", poetryConfigArgs, { cwd: basePath, encoding: "utf-8", - timeout: TIMEOUT_MS + timeout: TIMEOUT_MS, + shell: isWin }); let poetryInstallArgs = ["install", "-n", "--no-root"]; // Attempt to perform poetry install result = spawnSync("poetry", poetryInstallArgs, { cwd: basePath, encoding: "utf-8", - timeout: TIMEOUT_MS + timeout: TIMEOUT_MS, + shell: isWin }); if (result.status !== 0 || result.error) { if (result.stderr && result.stderr.includes("No module named poetry")) { @@ -6364,6 +6433,7 @@ export const getPipFrozenTree = (basePath, reqOrSetupFile, tempVenvDir) => { cwd: basePath, encoding: "utf-8", timeout: TIMEOUT_MS, + shell: isWin, env }); if (result.status !== 0 || result.error) { @@ -6392,6 +6462,7 @@ export const getPipFrozenTree = (basePath, reqOrSetupFile, tempVenvDir) => { cwd: basePath, encoding: "utf-8", timeout: TIMEOUT_MS, + shell: isWin, env }); tempVenvDir = result.stdout.replaceAll(/[\r\n]+/g, ""); @@ -6425,6 +6496,7 @@ export const getPipFrozenTree = (basePath, reqOrSetupFile, tempVenvDir) => { cwd: basePath, encoding: "utf-8", timeout: TIMEOUT_MS, + shell: isWin, env }); if (result.status !== 0 || result.error) { diff --git a/utils.test.js b/utils.test.js index 48b0b19f9..6af717344 100644 --- a/utils.test.js +++ b/utils.test.js @@ -1143,7 +1143,7 @@ test("parse github actions workflow data", async () => { dep_list = parseGitHubWorkflowData( readFileSync("./.github/workflows/repotests.yml", { encoding: "utf-8" }) ); - expect(dep_list.length).toEqual(5); + expect(dep_list.length).toEqual(6); expect(dep_list[0]).toEqual({ group: "actions", name: "checkout",