From eb3ff11070fbb5c3f1c517e387b891a64eecdb07 Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Mon, 24 Nov 2025 17:13:57 +0100 Subject: [PATCH] fix(spdx): Set the `licenseConcluded` via ORT's effective license Previously, only ORT's `concludedLicense` from a package curation was taken into account. However, if solely detected license findings were cleared via license finding curations from package configurations, that did not have any impact at all until now. To fix this, use the effective license with a custom license view of the declared and detected licenses as a fallback if no concluded license is set. Finally, the `licenseConcluded` should only be set if (human) clearance work was involved, so only set it if it differs from the `licenseDeclared`. If `licenseDeclared` already was correct from the start, then this needs to be "acknowledged" by manually setting the concluded license to the same expression. Signed-off-by: Sebastian Schuberth --- .../reporters/spdx/src/main/kotlin/Extensions.kt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/plugins/reporters/spdx/src/main/kotlin/Extensions.kt b/plugins/reporters/spdx/src/main/kotlin/Extensions.kt index 1b77b8e025399..7de4b961df180 100644 --- a/plugins/reporters/spdx/src/main/kotlin/Extensions.kt +++ b/plugins/reporters/spdx/src/main/kotlin/Extensions.kt @@ -30,6 +30,7 @@ import org.ossreviewtoolkit.model.Hash import org.ossreviewtoolkit.model.Identifier import org.ossreviewtoolkit.model.KnownProvenance import org.ossreviewtoolkit.model.LicenseFinding +import org.ossreviewtoolkit.model.LicenseSource import org.ossreviewtoolkit.model.OrtResult import org.ossreviewtoolkit.model.Package import org.ossreviewtoolkit.model.Provenance @@ -159,6 +160,14 @@ internal fun Package.toSpdxPackage( .applyChoices(ortResult.getPackageLicenseChoices(id)) .applyChoices(ortResult.getRepositoryLicenseChoices()) + val licenseDeclared = resolvedLicenseInfo.mainLicense()?.simplify() + + // Do not use `CONCLUDED_OR_DECLARED_AND_DETECTED` here to support explicitly setting the `concludedLicense` to the + // `licenseDeclared` in order to acknowledge the latter and record it as the license concluded in SPDX. + val licenseView = LicenseView(setOf(LicenseSource.DECLARED, LicenseSource.DETECTED)) + val licenseConcluded = concludedLicense ?: resolvedLicenseInfo.effectiveLicense(licenseView) + .takeUnless { it == licenseDeclared } + return SpdxPackage( spdxId = id.toSpdxId(type), checksums = when (type) { @@ -182,11 +191,10 @@ internal fun Package.toSpdxPackage( SpdxPackageType.SOURCE_PACKAGE -> SpdxConstants.NOASSERTION // Clear the concluded license as it might need to be different for the VCS location. SpdxPackageType.VCS_PACKAGE -> SpdxConstants.NOASSERTION - SpdxPackageType.PROJECT -> concludedLicense.nullOrBlankToSpdxNoassertionOrNone() - else -> concludedLicense.nullOrBlankToSpdxNoassertionOrNone() + SpdxPackageType.PROJECT -> licenseConcluded.nullOrBlankToSpdxNoassertionOrNone() + else -> licenseConcluded.nullOrBlankToSpdxNoassertionOrNone() }, - licenseDeclared = resolvedLicenseInfo.mainLicense() - ?.simplify() + licenseDeclared = licenseDeclared ?.sorted() ?.nullOrBlankToSpdxNoassertionOrNone() ?: SpdxConstants.NONE,