Skip to content

Commit

Permalink
feat: quarkus maven support (#1480)
Browse files Browse the repository at this point in the history
* Capture pom.xml properties

Signed-off-by: Prabhu Subramanian <[email protected]>

Solve pom.xml dependency version from properties

Signed-off-by: Prabhu Subramanian <[email protected]>

Invoke quarkus sbom goal

Signed-off-by: Prabhu Subramanian <[email protected]>

Invoke quarkus sbom goal

Signed-off-by: Prabhu Subramanian <[email protected]>

Bump version

Signed-off-by: Prabhu Subramanian <[email protected]>

* Support quarkus type

Signed-off-by: Prabhu Subramanian <[email protected]>

* Bug fix

Signed-off-by: Prabhu Subramanian <[email protected]>

* Added quarkus tests

Signed-off-by: Prabhu Subramanian <[email protected]>

* Disable go pkg license tests due to timeout

Signed-off-by: Prabhu Subramanian <[email protected]>

* Tweaks

Signed-off-by: Prabhu Subramanian <[email protected]>

---------

Signed-off-by: Prabhu Subramanian <[email protected]>
  • Loading branch information
prabhu authored Dec 5, 2024
1 parent 36791cf commit 131efeb
Show file tree
Hide file tree
Showing 14 changed files with 787 additions and 163 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/repotests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ jobs:
with:
repository: 'elastic/elasticsearch'
path: 'repotests/elasticsearch'
- uses: actions/checkout@v4
with:
repository: 'quarkusio/quarkus-quickstarts'
path: 'repotests/quarkus-quickstarts'
ref: '3.17.3'
- uses: dtolnay/rust-toolchain@stable
- name: setup sdkman
run: |
Expand Down Expand Up @@ -300,6 +305,11 @@ jobs:
shell: bash
env:
JAVA_HOME: ""
- name: repotests quarkus-quickstarts
run: |
bin/cdxgen.js -p -r -t quarkus repotests/quarkus-quickstarts -o bomresults/bom-quarkus-quickstarts-quarkus.json --no-recurse
bin/cdxgen.js -p -r -t quarkus repotests/quarkus-quickstarts -o bomresults/bom-quarkus-quickstarts-quarkus.json --no-recurse --spec-version 1.5
shell: bash
- name: repotests evidence
run: |
bin/cdxgen.js -p -t js --no-recurse -o bomresults/bom.json --evidence .
Expand Down
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cyclonedx/cdxgen",
"version": "11.0.4",
"version": "11.0.5",
"exports": "./lib/cli/index.js",
"compilerOptions": {
"lib": ["deno.window"],
Expand Down
4 changes: 2 additions & 2 deletions docs/ENV.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The following environment variables are available to configure the bom generation behavior.

| Variable | Description |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ------------------------------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| CDXGEN_DEBUG_MODE | Set to `debug` to enable debug messages |
| GITHUB_TOKEN | Specify GitHub token to prevent traffic shaping while querying license and repo information |
| MVN_CMD | Set to override maven command |
Expand Down Expand Up @@ -40,7 +40,7 @@ The following environment variables are available to configure the bom generatio
| SBOM_SIGN_ALGORITHM | Signature algorithm. Some valid values are RS256, RS384, RS512, PS256, PS384, PS512, ES256 etc |
| SBOM_SIGN_PRIVATE_KEY | Private key to use for signing |
| SBOM_SIGN_PUBLIC_KEY | Optional. Public key to include in the SBOM signature |
| CDX_MAVEN_PLUGIN | CycloneDX Maven plugin to use. Default "org.cyclonedx:cyclonedx-maven-plugin:2.7.8" |
| CDX_MAVEN_PLUGIN | CycloneDX Maven plugin to use. Default "org.cyclonedx:cyclonedx-maven-plugin:2.9.1" |
| CDX_MAVEN_GOAL | CycloneDX Maven plugin goal to use. Default makeAggregateBom. Other options: makeBom, makePackageBom |
| CDX_MAVEN_INCLUDE_TEST_SCOPE | Whether test scoped dependencies should be included from Maven projects, Default: true |
| ASTGEN_IGNORE_DIRS | Comma separated list of directories to ignore while analyzing using babel. The environment variable is also used by atom and astgen. |
Expand Down
7 changes: 4 additions & 3 deletions docs/PROJECT_TYPES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ _Note: there are multiple project types / aliases that will produce the same out
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------- |
| Node.js | `npm`, `pnpm`, `nodejs`, `js`, `javascript`, `typescript`, `ts`, `tsx`, `yarn`, `rush` | `npm-shrinkwrap.json`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `rush.js`, `bower.json`, `.min.js` | Yes, except for `.min.js` ||
| Node.js (Specific version) | `node8`, `node10`, `node12`, `node14`, `node16`, `node18`, `node20`, `node22`, `node23`, `nodejs8`, `nodejs10`, `nodejs12`, `nodejs14`, `nodejs16`, `nodejs18`, `nodejs20`, `nodejs22`, `nodejs23` | `npm-shrinkwrap.json`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `rush.js`, `bower.json`, `.min.js` | Yes, except for `.min.js` ||
| Java (Default) | `java`, `groovy`, `kotlin`, `scala`, `jvm`, `gradle`, `mvn`, `maven`, `sbt` | `pom.xml` [1], `build.gradle`, `.kts`, `sbt`, `bazel` | Yes, unless `pom.xml` is manually parsed due to unavailability of maven or errors) ||
| Java (Default) | `java`, `groovy`, `kotlin`, `scala`, `jvm`, `gradle`, `mvn`, `maven`, `sbt`, `quarkus` | `pom.xml` [1], `build.gradle`, `.kts`, `sbt`, `bazel` | Yes, unless `pom.xml` is manually parsed due to unavailability of maven or errors) ||
| Java (Specific version) | `java8`, `java11`, `java17`, `java21`, `java22`, `java23` | `pom.xml` [1], `build.gradle`, `.kts`, `sbt`, `bazel` | Yes, unless `pom.xml` is manually parsed due to unavailability of maven or errors) ||
| Android | `android`, `apk`, `aab` | `apk`, `aab` | - | - |
| JAR | `jar` | `.jar` | - | - |
Expand Down Expand Up @@ -48,8 +48,9 @@ _Note: there are multiple project types / aliases that will produce the same out

_*NOTE:*_

> - Apache maven 3.x is required for parsing pom.xml
> - gradle or gradlew is required to parse gradle projects
> - Apache maven 3.x is required for parsing pom.xml.
> - gradle or gradlew is required to parse gradle projects.
> - quarkus plugin is automatically detected and used by parsing pom.xml files (since cdxgen version 11.0.5) for java types. To explicitly specify this type, use `-t quarkus`. This is especially needed when cdxgen is invoked with `--no-recurse` argument for performance reasons.
> - sbt is required for parsing scala sbt projects. Only scala 2.10 + sbt 0.13.6+ and 2.12 + sbt 1.0+ are currently supported.
> - Alternatively, create a lock file using sbt-dependency-lock [plugin](https://github.com/stringbean/sbt-dependency-lock)
> - sdkman must be installed and setup to use the new Java with version types such as java8, java11.
Expand Down
2 changes: 1 addition & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cyclonedx/cdxgen",
"version": "11.0.4",
"version": "11.0.5",
"exports": "./lib/cli/index.js",
"include": ["*.js", "lib/**", "bin/**", "data/**", "types/**"],
"exclude": [
Expand Down
126 changes: 80 additions & 46 deletions lib/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,14 @@ function addComponent(
purl: purlString,
externalReferences: addExternalReferences(pkg),
};

if (options.specVersion >= 1.5) {
component.pedigree = pkg.pedigree || undefined;
}
if (options.specVersion >= 1.6) {
component.releaseNotes = pkg.releaseNotes || undefined;
component.modelCard = pkg.modelCard || undefined;
component.data = pkg.data || undefined;
}
component["type"] = determinePackageType(pkg);
component["bom-ref"] = decodeURIComponent(purlString);
if (
Expand Down Expand Up @@ -1264,7 +1271,6 @@ export async function createJavaBom(path, options) {
// For java, this would correctly include the cyclonedx maven plugin.
let tools = undefined;
let possible_misses = false;
let mavenDepsTreeInfoShown = false;
// war/ear mode
if (path.endsWith(".war") || path.endsWith(".jar")) {
// Check if the file exists
Expand Down Expand Up @@ -1294,6 +1300,11 @@ export async function createJavaBom(path, options) {
parentComponent,
});
}
// -t quarkus is supported
let isQuarkus = options?.projectType?.includes("quarkus");
let useMavenDepsTree = isQuarkus ? false : PREFER_MAVEN_DEPS_TREE;
// Is this a multi-module project
let rootModules;
// maven - pom.xml
const pomFiles = getAllFiles(
path,
Expand All @@ -1305,37 +1316,67 @@ export async function createJavaBom(path, options) {
pomFiles?.length &&
isPackageManagerAllowed("maven", ["bazel", "sbt", "gradle"], options)
) {
let result = undefined;
const cdxMavenPlugin =
process.env.CDX_MAVEN_PLUGIN ||
"org.cyclonedx:cyclonedx-maven-plugin:2.8.0";
const cdxMavenGoal = process.env.CDX_MAVEN_GOAL || "makeAggregateBom";
let mvnArgs = [
"-fn",
`${cdxMavenPlugin}:${cdxMavenGoal}`,
"-DoutputName=bom",
];
if (includeMavenTestScope) {
mvnArgs.push("-DincludeTestScope=true");
}
// By using quiet mode we can reduce the maxBuffer used and avoid crashes
if (!DEBUG_MODE) {
mvnArgs.push("-q");
}
// Support for passing additional settings and profile to maven
if (process.env.MVN_ARGS) {
const addArgs = process.env.MVN_ARGS.split(" ");
mvnArgs = mvnArgs.concat(addArgs);
if (!isQuarkus) {
// Quarkus projects require special treatment. To detect quarkus, we parse the first 3 maven file to look for a hit
for (const pf of pomFiles.slice(0, 3)) {
const pomMap = parsePom(pf);
if (!rootModules && pomMap?.modules?.length) {
rootModules = pomMap.modules;
}
// In quarkus mode, we cannot use the maven deps tree
if (pomMap.isQuarkus) {
isQuarkus = true;
useMavenDepsTree = false;
break;
}
}
}
// specVersion 1.4 doesn't support externalReferences.type=disribution-intake
// so we need to run the plugin with the correct version
if (options.specVersion === 1.4) {
mvnArgs = mvnArgs.concat("-DschemaVersion=1.4");
let result = undefined;
let mvnArgs;
if (isQuarkus) {
mvnArgs = ["-fn", "quarkus:dependency-sbom"];
} else {
const cdxMavenPlugin =
process.env.CDX_MAVEN_PLUGIN ||
"org.cyclonedx:cyclonedx-maven-plugin:2.9.1";
const cdxMavenGoal = process.env.CDX_MAVEN_GOAL || "makeAggregateBom";
mvnArgs = [
"-fn",
`${cdxMavenPlugin}:${cdxMavenGoal}`,
"-DoutputName=bom",
];
if (includeMavenTestScope) {
mvnArgs.push("-DincludeTestScope=true");
}
// By using quiet mode we can reduce the maxBuffer used and avoid crashes
if (!DEBUG_MODE) {
mvnArgs.push("-q");
}
// Support for passing additional settings and profile to maven
if (process.env.MVN_ARGS) {
const addArgs = process.env.MVN_ARGS.split(" ");
mvnArgs = mvnArgs.concat(addArgs);
}
// specVersion 1.4 doesn't support externalReferences.type=disribution-intake
// so we need to run the plugin with the correct version
if (options.specVersion === 1.4) {
mvnArgs = mvnArgs.concat("-DschemaVersion=1.4");
}
}
const firstPom = pomFiles.length ? pomFiles[0] : undefined;
let mavenCmd = getMavenCommand(path, path);
for (const f of pomFiles) {
const basePath = dirname(f);
if (
isQuarkus &&
!options.deep &&
rootModules?.includes(basename(basePath))
) {
if (DEBUG_MODE) {
console.log("Skipped sub-module", basePath);
}
continue;
}
const settingsXml = join(basePath, "settings.xml");
if (existsSync(settingsXml)) {
console.log(
Expand All @@ -1358,16 +1399,7 @@ export async function createJavaBom(path, options) {
}
}
// Use the cyclonedx maven plugin if there is no preference for maven deps tree
if (!PREFER_MAVEN_DEPS_TREE) {
if (!mavenDepsTreeInfoShown && DEBUG_MODE) {
console.log(
"cdxgen now supports generating SBOM with only the maven cli without the need for the cyclonedx-maven plugin. This mode works better in enterprise environments and in multi-module projects.",
);
console.log(
"Set the environment variable PREFER_MAVEN_DEPS_TREE to true to enable this.",
);
mavenDepsTreeInfoShown = true;
}
if (!useMavenDepsTree) {
console.log(
`Executing '${mavenCmd} ${mvnArgs.join(" ")}' in`,
basePath,
Expand All @@ -1381,19 +1413,23 @@ export async function createJavaBom(path, options) {
});
// Check if the cyclonedx plugin created the required bom.json file
// Sometimes the plugin fails silently for complex maven projects
bomJsonFiles = getAllFiles(path, "**/target/*.json", options);
bomJsonFiles = getAllFiles(
path,
"**/target/*{cdx,bom,cyclonedx}*.json",
options,
);
// Check if the bom json files got created in a directory other than target
if (!bomJsonFiles.length) {
bomJsonFiles = getAllFiles(
path,
"target/**/*{cdx,bom}*.json",
"target/**/*{cdx,bom,cyclonedx}*.json",
options,
);
}
}
// Also check if the user has a preference for maven deps tree command
if (
PREFER_MAVEN_DEPS_TREE ||
useMavenDepsTree ||
!bomJsonFiles.length ||
result?.status !== 0 ||
result?.error
Expand Down Expand Up @@ -1539,7 +1575,7 @@ export async function createJavaBom(path, options) {
}
} // for
// Locate and parse all bom.json files from the maven plugin
if (!PREFER_MAVEN_DEPS_TREE) {
if (!useMavenDepsTree) {
for (const abjson of bomJsonFiles) {
let bomJsonObj = undefined;
try {
Expand All @@ -1556,7 +1592,9 @@ export async function createJavaBom(path, options) {
!tools &&
bomJsonObj.metadata &&
bomJsonObj.metadata.tools &&
Array.isArray(bomJsonObj.metadata.tools)
(Array.isArray(bomJsonObj.metadata.tools) ||
bomJsonObj.metadata.tools.components ||
bomJsonObj.metadata.tools.services)
) {
tools = bomJsonObj.metadata.tools;
}
Expand Down Expand Up @@ -1621,10 +1659,6 @@ export async function createJavaBom(path, options) {
console.warn(
"Multiple errors occurred while building this project with maven. The SBOM is therefore incomplete!",
);
} else if (!PREFER_MAVEN_DEPS_TREE) {
console.log(
"Try generating an SBOM with the maven dependency tree plugin. Set the environment variable PREFER_MAVEN_DEPS_TREE to true to enable this.",
);
}
}
}
Expand Down
Loading

0 comments on commit 131efeb

Please sign in to comment.