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

Add NOTICE files to source units #1466

Merged
merged 17 commits into from
Oct 7, 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
8 changes: 6 additions & 2 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# FOSSA CLI Changelog

## 3.9.37

- License Scanning: Update Themis to include NOTICE files, and parse the additional NOTICE file fields in Themis's output. ([#1466](https://github.com/fossas/fossa-cli/pull/1466))

## 3.9.36

- fossa-deps: Fixed an issue where Rocky Linux deps were not supported in the fossa-deps file ([#1473](https://github.com/fossas/fossa-cli/pull/1473))
- `fossa report`: Remove subscription type check in preflight checks ([#1474](https://github.com/fossas/fossa-cli/pull/1474))
- fossa-deps: Fixed an issue where Rocky Linux deps were not supported in the fossa-deps file ([#1473](https://github.com/fossas/fossa-cli/pull/1473))
- `fossa report`: Remove subscription type check in preflight checks ([#1474](https://github.com/fossas/fossa-cli/pull/1474))

## 3.9.35

Expand Down
1 change: 1 addition & 0 deletions src/App/Fossa/Lernie/Analyze.hs
Original file line number Diff line number Diff line change
Expand Up @@ -304,5 +304,6 @@ createLicenseUnitSingles ((path, title), licenseUnitData) =
, licenseUnitDir = ""
, licenseUnitFiles = NE.singleton (unCustomLicensePath path)
, licenseUnitData = NE.singleton licenseUnitData
, licenseUnitNoticeFiles = []
, licenseUnitInfo = LicenseUnitInfo{licenseUnitInfoDescription = Just $ "custom license search " <> unCustomLicenseTitle title}
}
4 changes: 3 additions & 1 deletion src/App/Fossa/ManualDeps.hs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ toSourceUnit root depsFile manualDeps@ManualDependencies{..} maybeApiOpts vendor
, sourceUnitType = "user-specific-yaml"
, sourceUnitBuild = build
, sourceUnitGraphBreadth = Complete
, sourceUnitNoticeFiles = []
, sourceUnitOriginPaths = [someBaseToOriginPath originPath]
, additionalData = additional
}
Expand Down Expand Up @@ -508,7 +509,8 @@ instance FromJSON CustomDependency where
<$> (obj `neText` "name")
<*> (unTextLike <$> obj `neText` "version")
<*> (obj `neText` "license")
<*> obj .:? "metadata"
<*> obj
.:? "metadata"
<* forbidMembers "custom dependencies" ["type", "path", "url"] obj

instance FromJSON RemoteDependency where
Expand Down
1 change: 1 addition & 0 deletions src/Srclib/Converter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ toSourceUnit leaveUnfiltered path dependencies projectType graphBreadth originPa
, buildDependencies = deps
}
, sourceUnitGraphBreadth = graphBreadth
, sourceUnitNoticeFiles = []
, sourceUnitOriginPaths = originPaths
, additionalData = Nothing
}
Expand Down
34 changes: 34 additions & 0 deletions src/Srclib/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Srclib.Types (
SourceUnit (..),
SourceUnitBuild (..),
SourceUnitDependency (..),
SourceUnitNoticeFile (..),
AdditionalDepData (..),
SourceUserDefDep (..),
SourceRemoteDep (..),
Expand Down Expand Up @@ -112,13 +113,36 @@ textToOriginPath = OriginPath . toString
-- Manifest?: string;
-- }

data SourceUnitNoticeFile = SourceUnitNoticeFile
{ sourceUnitNoticeFilePath :: Text
, sourceUnitNoticeFileContents :: Text
, sourceUnitNoticeFileCopyrights :: [Text]
}
deriving (Eq, Ord, Show)

instance ToJSON SourceUnitNoticeFile where
toJSON SourceUnitNoticeFile{..} =
object
[ "path" .= sourceUnitNoticeFilePath
, "contents" .= sourceUnitNoticeFileContents
, "copyrights" .= sourceUnitNoticeFileCopyrights
]

instance FromJSON SourceUnitNoticeFile where
parseJSON = withObject "SourceUnitNoticeFile" $ \obj ->
SourceUnitNoticeFile
<$> obj .: "path"
<*> obj .: "contents"
<*> obj .:? "copyrights" .!= []

data FullSourceUnit = FullSourceUnit
{ fullSourceUnitName :: Text
, fullSourceUnitType :: Text
, fullSourceUnitTitle :: Maybe Text
, fullSourceUnitManifest :: Maybe Text
, fullSourceUnitBuild :: Maybe SourceUnitBuild
, fullSourceUnitGraphBreadth :: GraphBreadth
, fullSourceUnitNoticeFiles :: [SourceUnitNoticeFile]
, fullSourceUnitOriginPaths :: [OriginPath]
, fullSourceUnitAdditionalData :: Maybe AdditionalDepData
, fullSourceUnitFiles :: Maybe (NonEmpty Text)
Expand All @@ -136,6 +160,7 @@ licenseUnitToFullSourceUnit LicenseUnit{..} =
, fullSourceUnitManifest = Nothing
, fullSourceUnitBuild = Nothing
, fullSourceUnitGraphBreadth = Complete
, fullSourceUnitNoticeFiles = licenseUnitNoticeFiles
, fullSourceUnitOriginPaths = []
, fullSourceUnitAdditionalData = Nothing
, fullSourceUnitFiles = Just licenseUnitFiles
Expand All @@ -153,6 +178,7 @@ sourceUnitToFullSourceUnit SourceUnit{..} =
, fullSourceUnitBuild = sourceUnitBuild
, fullSourceUnitGraphBreadth = sourceUnitGraphBreadth
, fullSourceUnitOriginPaths = sourceUnitOriginPaths
, fullSourceUnitNoticeFiles = sourceUnitNoticeFiles
, fullSourceUnitAdditionalData = additionalData
, fullSourceUnitFiles = Nothing
, fullSourceUnitData = Nothing
Expand All @@ -169,6 +195,7 @@ instance ToJSON FullSourceUnit where
, "Build" .= fullSourceUnitBuild
, "GraphBreadth" .= fullSourceUnitGraphBreadth
, "OriginPaths" .= fullSourceUnitOriginPaths
, "NoticeFiles" .= fullSourceUnitNoticeFiles
, "AdditionalDependencyData" .= fullSourceUnitAdditionalData
, "Files" .= fullSourceUnitFiles
, "Data" .= fullSourceUnitData
Expand Down Expand Up @@ -204,6 +231,7 @@ data LicenseUnit = LicenseUnit
, licenseUnitDir :: Text
, licenseUnitFiles :: (NonEmpty Text)
, licenseUnitData :: (NonEmpty LicenseUnitData)
, licenseUnitNoticeFiles :: [SourceUnitNoticeFile]
, licenseUnitInfo :: LicenseUnitInfo
}
deriving (Eq, Ord, Show)
Expand All @@ -217,6 +245,7 @@ emptyLicenseUnit =
, licenseUnitDir = ""
, licenseUnitFiles = "" :| []
, licenseUnitData = emptyLicenseUnitData :| []
, licenseUnitNoticeFiles = []
, licenseUnitInfo = LicenseUnitInfo{licenseUnitInfoDescription = Nothing}
}

Expand All @@ -235,6 +264,7 @@ instance ToJSON LicenseUnit where
, "Dir" .= licenseUnitDir
, "Files" .= licenseUnitFiles
, "Data" .= licenseUnitData
, "NoticeFiles" .= licenseUnitNoticeFiles
, "Info" .= licenseUnitInfo
]

Expand All @@ -247,6 +277,7 @@ instance FromJSON LicenseUnit where
<*> obj .: "Dir"
<*> obj .: "Files"
<*> obj .: "Data"
<*> obj .:? "NoticeFiles" .!= []
<*> obj .: "Info"

newtype LicenseUnitInfo = LicenseUnitInfo
Expand Down Expand Up @@ -350,6 +381,7 @@ data SourceUnit = SourceUnit
-- ^ path to manifest file
, sourceUnitBuild :: Maybe SourceUnitBuild
, sourceUnitGraphBreadth :: GraphBreadth
, sourceUnitNoticeFiles :: [SourceUnitNoticeFile]
, sourceUnitOriginPaths :: [OriginPath]
, additionalData :: Maybe AdditionalDepData
}
Expand Down Expand Up @@ -431,6 +463,7 @@ instance ToJSON SourceUnit where
, "Manifest" .= sourceUnitManifest
, "Build" .= sourceUnitBuild
, "GraphBreadth" .= sourceUnitGraphBreadth
, "NoticeFiles" .= sourceUnitNoticeFiles
, "OriginPaths" .= sourceUnitOriginPaths
, "AdditionalDependencyData" .= additionalData
]
Expand All @@ -443,6 +476,7 @@ instance FromJSON SourceUnit where
<*> obj .: "Manifest"
<*> obj .:? "Build"
<*> obj .: "GraphBreadth"
<*> obj .:? "NoticeFiles" .!= []
<*> obj .: "OriginPaths"
<*> obj .:? "AdditionalDependencyData"

Expand Down
2 changes: 2 additions & 0 deletions test/App/Fossa/Analyze/UploadSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ expectedMergedFullSourceUnits = NE.fromList [fullSourceUnit, fullLicenseUnit]
, fullSourceUnitFiles = Nothing
, fullSourceUnitData = Nothing
, fullSourceUnitInfo = Nothing
, fullSourceUnitNoticeFiles = []
}
fullLicenseUnit =
FullSourceUnit
Expand All @@ -102,6 +103,7 @@ expectedMergedFullSourceUnits = NE.fromList [fullSourceUnit, fullLicenseUnit]
, fullSourceUnitFiles = Just $ "" NE.:| []
, fullSourceUnitData = Just $ emptyLicenseUnitData NE.:| []
, fullSourceUnitInfo = Just LicenseUnitInfo{licenseUnitInfoDescription = Nothing}
, fullSourceUnitNoticeFiles = []
}

expectGetSuccessWithReachability :: Has MockApi sig m => m ()
Expand Down
1 change: 1 addition & 0 deletions test/App/Fossa/Container/AnalyzeNativeSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ jarsInContainerSpec = describe "Jars in Containers" $ do
}
, sourceUnitGraphBreadth = Complete
, sourceUnitOriginPaths = [textToOriginPath "package-lock.json"]
, sourceUnitNoticeFiles = []
, additionalData = Nothing
}

Expand Down
27 changes: 26 additions & 1 deletion test/App/Fossa/FirstPartyScanSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import Control.Effect.FossaApiClient (FossaApiClientF (..))
import Data.List qualified as List
import Data.List.NonEmpty qualified as NE
import Data.Maybe (isJust)
import Data.Text (strip)
import Fossa.API.Types (Organization (..))
import Path (Dir, Path, Rel, mkRelDir, (</>))
import Path.IO (getCurrentDir)
import Srclib.Types (LicenseSourceUnit (..), LicenseUnit (licenseUnitData, licenseUnitName), LicenseUnitData (licenseUnitDataContents))
import Srclib.Types (LicenseSourceUnit (..), LicenseUnit (..), LicenseUnitData (licenseUnitDataContents), SourceUnitNoticeFile (..))
import Test.Effect (expectFatal', expectationFailure', it', shouldBe')
import Test.Fixtures qualified as Fixtures
import Test.Hspec (Spec, describe, runIO)
Expand All @@ -25,12 +26,16 @@ fixtureDir = $(mkRelDir "test/App/Fossa/VendoredDependency/testdata/repo")
fixtureDirWithVendoredDeps :: Path Rel Dir
fixtureDirWithVendoredDeps = $(mkRelDir "test/App/Fossa/VendoredDependency/testdata/firstparty")

fixtureDirWithNoticeFiles :: Path Rel Dir
fixtureDirWithNoticeFiles = $(mkRelDir "test/App/Fossa/VendoredDependency/testdata/firstparty-with-notice")

spec :: Spec
spec = do
describe "runFirstPartyScan" $ do
currDir <- runIO getCurrentDir
let scanDir = currDir </> fixtureDir
let scanDirWithVendoredDeps = currDir </> fixtureDirWithVendoredDeps
let scanDirWithNoticeFiles = currDir </> fixtureDirWithNoticeFiles

it' "should fail if the organization does not support first party scans and you force it on" $ do
expectGetOrganizationThatDoesNotSupportFirstPartyScans
Expand Down Expand Up @@ -99,6 +104,26 @@ spec = do
licenseUnitName secondUnit `shouldBe'` "apache-2.0"
licenseUnitDataContents unitData `shouldBe'` Nothing

it' "should find notice files" $ do
expectGetOrganizationThatDefaultsToFirstPartyScans
licenseSourceUnit <- firstPartyScanWithOrgInfo scanDirWithNoticeFiles Fixtures.standardAnalyzeConfig
case licenseSourceUnit of
Nothing -> expectationFailure' "first party scan should have run"
Just LicenseSourceUnit{licenseSourceUnitLicenseUnits = units} -> do
length units `shouldBe'` 3
let noticeUnit = NE.head units
licenseUnitName noticeUnit `shouldBe'` ""
licenseUnitType noticeUnit `shouldBe'` "NoticeFileMatches"
let noticeFiles = licenseUnitNoticeFiles noticeUnit
length noticeFiles `shouldBe'` 1
let noticeFile = head noticeFiles
let copyrights = sourceUnitNoticeFileCopyrights noticeFile
length copyrights `shouldBe'` 1
let copyright = head copyrights
copyright `shouldBe'` "2024 Frank Frankson"
strip (sourceUnitNoticeFileContents noticeFile) `shouldBe'` "This is a notice file that is copyright 2024 Frank Frankson"
sourceUnitNoticeFilePath noticeFile `shouldBe'` "NOTICE.txt"

-- The default org defaults to not running first party scans but has first-party scans enabled
expectGetOrganizationThatDefaultsToNoFirstPartyScans :: Has MockApi sig m => m ()
expectGetOrganizationThatDefaultsToNoFirstPartyScans = GetOrganization `alwaysReturns` Fixtures.organization
Expand Down
1 change: 1 addition & 0 deletions test/App/Fossa/LernieSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ expectedLicenseUnit =
, licenseUnitFiles = NE.singleton $ toText . toFilePath $ absDir </> $(mkRelDir "two.txt")
, licenseUnitData = NE.singleton expectedUnitData
, licenseUnitInfo = LicenseUnitInfo{licenseUnitInfoDescription = Just "custom license search Proprietary License"}
, licenseUnitNoticeFiles = []
}

expectedDoubleSourceUnit :: LicenseSourceUnit
Expand Down
3 changes: 3 additions & 0 deletions test/App/Fossa/LicenseScannerSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ unitOne =
, licenseUnitFiles =
NE.fromList ["foo/bar/LICENSE", "foo/bar/one.txt"]
, licenseUnitInfo = info
, licenseUnitNoticeFiles = []
}

unitTwo :: LicenseUnit
Expand All @@ -55,6 +56,7 @@ unitTwo =
, licenseUnitData = NE.fromList [emptyLicenseUnitData{licenseUnitDataPath = "foo/bar/baz/ANOTHER_LICENSE"}, emptyLicenseUnitData{licenseUnitDataPath = "foo/bar/baz/two.txt"}]
, licenseUnitFiles = NE.fromList ["foo/bar/baz/ANOTHER_LICENSE", "foo/bar/baz/two.txt"]
, licenseUnitInfo = info
, licenseUnitNoticeFiles = []
}
expectedCombinedUnit :: LicenseUnit
expectedCombinedUnit =
Expand All @@ -78,6 +80,7 @@ expectedCombinedUnit =
, "foo/bar/one.txt"
]
, licenseUnitInfo = info
, licenseUnitNoticeFiles = []
}

fixtureDir :: Path Rel Dir
Expand Down
Loading
Loading