diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4fcc851..7d35cd0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,8 +42,19 @@ jobs: - name: Set up Gradle caching and instrumentation uses: gradle/actions/setup-gradle@v4 - - name: Execute build, tests, PMD, coverage, Javadoc, and distribution packaging - run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport distZip + - name: Execute build, tests, PMD, coverage, Javadoc, distribution packaging, and SBOM generation + run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport distZip cyclonedxBom + + - name: Upload SBOM + if: always() + uses: actions/upload-artifact@v4 + with: + name: sbom + path: | + build/reports/sbom/radixor-sbom.json + build/reports/sbom/radixor-sbom.xml + if-no-files-found: error + retention-days: 14 - name: Upload test reports if: always() @@ -129,11 +140,14 @@ jobs: - name: Set up Gradle caching and instrumentation uses: gradle/actions/setup-gradle@v4 - - name: Build release distribution - run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport distZip + - name: Build release distribution and SBOM + run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport distZip cyclonedxBom - name: Publish GitHub release assets uses: softprops/action-gh-release@v2 with: generate_release_notes: true - files: build/distributions/*.zip + files: | + build/distributions/*.zip + build/reports/sbom/radixor-sbom.json + build/reports/sbom/radixor-sbom.xml diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 695a59f..a3be564 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -48,7 +48,7 @@ jobs: uses: gradle/actions/setup-gradle@v4 - name: Build reports for publication - run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport pitest jmh + run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport pitest jmh cyclonedxBom - name: Prepare gh-pages worktree shell: bash @@ -100,6 +100,10 @@ jobs: JMH_CSV_LATEST_LINK='' DEPENDENCY_CHECK_LINK='' DEPENDENCY_CHECK_LATEST_LINK='' + SBOM_JSON_LINK='' + SBOM_XML_LINK='' + SBOM_JSON_LATEST_LINK='' + SBOM_XML_LATEST_LINK='' if [ -d "build/reports/jmh" ]; then cp -R build/reports/jmh "${RUN_DIR}/jmh" @@ -129,6 +133,15 @@ jobs: fi fi + if [ -d "build/reports/sbom" ]; then + cp -R build/reports/sbom "${RUN_DIR}/sbom" + cp -R build/reports/sbom "${LATEST_DIR}/sbom" + SBOM_JSON_LINK='
  • SBOM (JSON)
  • ' + SBOM_XML_LINK='
  • SBOM (XML)
  • ' + SBOM_JSON_LATEST_LINK='
  • SBOM (JSON)
  • ' + SBOM_XML_LATEST_LINK='
  • SBOM (XML)
  • ' + fi + cat > "${RUN_DIR}/index.html" < @@ -153,6 +166,8 @@ jobs:
  • PMD Report
  • Coverage Report
  • ${DEPENDENCY_CHECK_LINK:-
  • Dependency Vulnerability Report: not available
  • } + ${SBOM_JSON_LINK:-
  • SBOM (JSON): not available
  • } + ${SBOM_XML_LINK:-
  • SBOM (XML): not available
  • }
  • Mutation Testing Report
  • $( [ "${HAS_JMH}" = "true" ] && { echo "${JMH_TXT_LINK:-
  • Benchmark Results (TXT): not available
  • }"; echo "${JMH_CSV_LINK:-
  • Benchmark Results (CSV): not available
  • }"; } \ @@ -200,6 +215,8 @@ jobs:
  • PMD Report
  • Coverage Report
  • ${DEPENDENCY_CHECK_LATEST_LINK:-
  • Dependency Vulnerability Report: not currently available
  • } + ${SBOM_JSON_LATEST_LINK:-
  • SBOM (JSON): not available
  • } + ${SBOM_XML_LATEST_LINK:-
  • SBOM (XML): not available
  • }
  • Mutation Testing Report
  • $( [ "${HAS_JMH}" = "true" ] && { echo "${JMH_TXT_LATEST_LINK:-
  • Benchmark Results (TXT): not available
  • }"; echo "${JMH_CSV_LATEST_LINK:-
  • Benchmark Results (CSV): not available
  • }"; } \ diff --git a/build.gradle b/build.gradle index 51156c0..304f04d 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,7 @@ plugins { id 'info.solidsoft.pitest' version '1.19.0' id 'me.champeau.jmh' version '0.7.2' id 'org.owasp.dependencycheck' version '12.2.1' + id 'org.cyclonedx.bom' version '3.2.4' id 'com.palantir.git-version' version '4.0.0' } @@ -14,6 +15,7 @@ group = 'org.egothor.stemmer' version = gitVersion(prefix:'release@') def benchmarkReportsDirectory = layout.buildDirectory.dir('reports/jmh') +def sbomReportsDirectory = layout.buildDirectory.dir('reports/sbom') def nvdApiKey = providers.gradleProperty('nvdApiKey') .orElse(providers.environmentVariable('NVD_API_KEY')) @@ -124,6 +126,25 @@ tasks.named('check') { // no-default, only on-demand: dependsOn(tasks.named('dependencyCheckAnalyze')) } +allprojects { + tasks.matching { it.name == 'cyclonedxDirectBom' }.configureEach { + includeConfigs = ['runtimeClasspath', 'compileClasspath'] + skipConfigs = ['testRuntimeClasspath', 'testCompileClasspath', 'jmh.*', 'mockitoAgent'] + includeBomSerialNumber = true + includeLicenseText = false + includeMetadataResolution = true + includeBuildSystem = true + } +} + +tasks.named('cyclonedxBom') { + includeBomSerialNumber = true + includeLicenseText = false + includeBuildSystem = true + jsonOutput.set(sbomReportsDirectory.map { it.file('radixor-sbom.json') }) + xmlOutput.set(sbomReportsDirectory.map { it.file('radixor-sbom.xml') }) +} + pitest { pitestVersion = '1.22.1' junit5PluginVersion = '1.2.3'