Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: quarkus maven support #1480

Merged
merged 6 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading