Skip to content

Commit

Permalink
Add NOTICE files to source units (#1466)
Browse files Browse the repository at this point in the history
  • Loading branch information
spatten authored Oct 7, 2024
1 parent 9d8190f commit dc572c6
Show file tree
Hide file tree
Showing 14 changed files with 287 additions and 4 deletions.
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

Check warning on line 119 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / macOS-arm64-build

In the use of ‘head’

Check warning on line 119 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / macOS-intel-build

In the use of ‘head’

Check warning on line 119 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / macOS-arm64-build

In the use of ‘head’

Check warning on line 119 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / Windows-build

In the use of ‘head’

Check warning on line 119 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / macOS-intel-build

In the use of ‘head’

Check warning on line 119 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / Windows-build

In the use of ‘head’
let copyrights = sourceUnitNoticeFileCopyrights noticeFile
length copyrights `shouldBe'` 1
let copyright = head copyrights

Check warning on line 122 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / macOS-arm64-build

In the use of ‘head’

Check warning on line 122 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / macOS-intel-build

In the use of ‘head’

Check warning on line 122 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / macOS-arm64-build

In the use of ‘head’

Check warning on line 122 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / Windows-build

In the use of ‘head’

Check warning on line 122 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / macOS-intel-build

In the use of ‘head’

Check warning on line 122 in test/App/Fossa/FirstPartyScanSpec.hs

View workflow job for this annotation

GitHub Actions / Windows-build

In the use of ‘head’
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

0 comments on commit dc572c6

Please sign in to comment.