diff --git a/Changelog.md b/Changelog.md index ca58a50b0..92999a8ba 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ ## v2.19.6 +- Special cases scans with a single VSI only filter to skip other analysis strategies ([#407](https://github.com/fossas/spectrometer/pull/407)) - Adds the ability to skip resolving dependencies from FOSSA projects discovered during VSI scans ([#435](https://github.com/fossas/spectrometer/pull/435)) ## v2.19.5 @@ -45,7 +46,7 @@ Use [`fossa-deps.{yml,json}`](docs/features/vendored-dependencies.md) file to fa ## v2.18.0 -- When applicable, fossa-cli uses the cgroup CPU quota (under cfs) to determine the number of runtime threads to use. This dramatically improves runtime speed when we're running within a cpu-limited container on a large machine with many physical processors. +- Improves performance in scenarios where cgroups are used to limit the amount of CPU time available, such as K8S containers ([#403](https://github.com/fossas/spectrometer/pull/403)) ## v2.17.3 diff --git a/src/App/Fossa/Analyze.hs b/src/App/Fossa/Analyze.hs index e29f08673..466b2ad2e 100644 --- a/src/App/Fossa/Analyze.hs +++ b/src/App/Fossa/Analyze.hs @@ -71,7 +71,7 @@ import Data.Maybe (catMaybes, fromMaybe) import Data.String.Conversion (decodeUtf8) import Data.Text (Text) import Discovery.Archive qualified as Archive -import Discovery.Filters (AllFilters, applyFilters) +import Discovery.Filters (AllFilters, applyFilters, filterIsVSIOnly) import Discovery.Projects (withDiscoveredProjects) import Effect.Exec (Exec, runExecIO) import Effect.Logger ( @@ -254,7 +254,12 @@ runAnalyzers :: Path Abs Dir -> AllFilters -> m () -runAnalyzers basedir filters = traverse_ single discoverFuncs +runAnalyzers basedir filters = do + if filterIsVSIOnly filters + then do + logInfo "Running in VSI only mode, skipping other analyzers" + pure () + else traverse_ single discoverFuncs where single (DiscoverFunc f) = withDiscoveredProjects f basedir (runDependencyAnalysis basedir filters) @@ -341,9 +346,14 @@ analyze (BaseDir basedir) destination override unpackArchives jsonOutput include -- additional source units are built outside the standard strategy flow, because they either -- require additional information (eg API credentials), or they return additional information (eg user deps). - manualSrcUnits <- Diag.context "fossa-deps" $ analyzeFossaDepsFile basedir apiOpts vsiResults <- Diag.context "analyze-vsi" $ analyzeVSI modeVSIAnalysis apiOpts basedir filters modeVSISkipResolution binarySearchResults <- Diag.context "discover-binaries" $ analyzeDiscoverBinaries modeBinaryDiscovery basedir filters + manualSrcUnits <- + if filterIsVSIOnly filters + then do + logInfo "Running in VSI only mode, skipping manual source units" + pure Nothing + else Diag.context "fossa-deps" $ analyzeFossaDepsFile basedir apiOpts let additionalSourceUnits :: [SourceUnit] additionalSourceUnits = catMaybes [manualSrcUnits, vsiResults, binarySearchResults] @@ -397,8 +407,13 @@ analyzeVSI _ _ _ _ _ = pure Nothing analyzeDiscoverBinaries :: (MonadIO m, Has Diag.Diagnostics sig m, Has (Lift IO) sig m, Has Logger sig m, Has ReadFS sig m) => BinaryDiscoveryMode -> Path Abs Dir -> AllFilters -> m (Maybe SourceUnit) analyzeDiscoverBinaries BinaryDiscoveryEnabled dir filters = do - logInfo "Discovering binary files as dependencies" - analyzeBinaryDeps dir filters + if filterIsVSIOnly filters + then do + logInfo "Running in VSI only mode, skipping binary discovery" + pure Nothing + else do + logInfo "Discovering binary files as dependencies" + analyzeBinaryDeps dir filters analyzeDiscoverBinaries _ _ _ = pure Nothing doAssertRevisionBinaries :: (Has Diag.Diagnostics sig m, Has ReadFS sig m, Has (Lift IO) sig m, Has Logger sig m) => IATAssertionMode -> ApiOpts -> Locator -> m () diff --git a/src/Discovery/Filters.hs b/src/Discovery/Filters.hs index db18edb38..2b510315e 100644 --- a/src/Discovery/Filters.hs +++ b/src/Discovery/Filters.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE RecordWildCards #-} + module Discovery.Filters ( AllFilters (..), targetFilterParser, @@ -6,6 +8,7 @@ module Discovery.Filters ( FilterMatch (..), FilterResult (..), apply, + filterIsVSIOnly, ) where import Data.List ((\\)) @@ -28,6 +31,18 @@ import Text.Megaparsec ( import Text.Megaparsec.Char (alphaNumChar, char) import Types (BuildTarget (..), FoundTargets (FoundTargets, ProjectWithoutTargets), TargetFilter (..)) +-- | filterIsVSIOnly is a very naive check for whether the user provided a filter for the VSI target *only*, at the root of the project with no path specified. +-- This decision was made because predicating VSI only scans is a stopgap until we have more broad support for *preemptive* analysis filtering. +-- VSI supports very large scans that the rest of our analysis may not. +filterIsVSIOnly :: AllFilters -> Bool +filterIsVSIOnly AllFilters{..} = do + let includes = combinedTargets includeFilters + length includes == 1 && any matches includes + where + matches f = case f of + TypeTarget name -> name == "vsi" + _ -> False + data AllFilters = AllFilters { legacyFilters :: [TargetFilter] , includeFilters :: FilterCombination