diff --git a/Changelog.md b/Changelog.md index de93be0420..fcd372ed18 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,8 @@ # FOSSA CLI Changelog + +## 3.9.41 +- GoModules: Fix a bug where a static analysis method was not exposed. ([#1468](https://github.com/fossas/fossa-cli/pull/1486)) + ## 3.9.40 - Licensing: Fix a bug where license scanner output sometimes included log lines, which breaks JSON parsing diff --git a/src/Strategy/Go/Gomod.hs b/src/Strategy/Go/Gomod.hs index 15570ee9c7..e5920f77f5 100644 --- a/src/Strategy/Go/Gomod.hs +++ b/src/Strategy/Go/Gomod.hs @@ -14,6 +14,7 @@ module Strategy.Go.Gomod ( PackageVersion (..), parsePackageVersion, gomodParser, + analyzeStatic, ) where import Control.Algebra (Has) @@ -396,6 +397,14 @@ analyze' file = do pure () pure (graph, Partial) +-- | This variant of analyze will not attempt to fill in transitive dependencies. +analyzeStatic :: (Has ReadFS sig m, Has Diagnostics sig m) => Path Abs File -> m (Graphing Dependency, GraphBreadth) +analyzeStatic file = do + graph <- graphingGolang $ do + gomod <- readContentsParser gomodParser file + context "Building dependency graph (static)" $ buildGraph gomod + pure (graph, Partial) + buildGraph :: Has GolangGrapher sig m => Gomod -> m () buildGraph = traverse_ go . resolve where diff --git a/src/Strategy/Gomodules.hs b/src/Strategy/Gomodules.hs index 5172ddb6b0..2ad39d0949 100644 --- a/src/Strategy/Gomodules.hs +++ b/src/Strategy/Gomodules.hs @@ -11,7 +11,7 @@ import App.Fossa.Analyze.Types (AnalyzeProject (analyzeProjectStaticOnly), analy import App.Fossa.Config.Analyze (ExperimentalAnalyzeConfig (useV3GoResolver), GoDynamicTactic (..)) import App.Util (guardStrictMode) import Control.Carrier.Diagnostics (warn) -import Control.Effect.Diagnostics (Diagnostics, context, fatalText, recover, (<||>)) +import Control.Effect.Diagnostics (Diagnostics, context, recover, (<||>)) import Control.Effect.Reader (Reader, ask, asks) import Control.Monad (when) import Data.Aeson (ToJSON) @@ -58,7 +58,7 @@ instance ToJSON GomodulesProject instance AnalyzeProject GomodulesProject where analyzeProject _ proj = asks useV3GoResolver >>= getDeps proj - analyzeProjectStaticOnly _ proj = staticAnalysisResults proj <$> staticAnalysis proj + analyzeProjectStaticOnly _ = staticAnalysis mkProject :: GomodulesProject -> DiscoveredProject GomodulesProject mkProject project = @@ -72,7 +72,9 @@ mkProject project = getDeps :: (GetDepsEffs sig m) => GomodulesProject -> GoDynamicTactic -> m DependencyResults getDeps project goDynamicTactic = do mode <- ask - (graph, graphBreadth) <- context "Gomodules" $ dynamicAnalysis <||> guardStrictMode mode (staticAnalysis project) + (graph, graphBreadth) <- + context "Gomodules" $ + dynamicAnalysis <||> guardStrictMode mode fallbacks stdlib <- recover . context "Collect go standard library information" . listGoStdlibPackages $ gomodulesDir project pure $ DependencyResults @@ -81,12 +83,17 @@ getDeps project goDynamicTactic = do , dependencyManifestFiles = [gomodulesGomod project] } where + fallbacks :: (Has Diagnostics sig m, Has Exec sig m, Has ReadFS sig m) => m (Graphing Dependency, GraphBreadth) + fallbacks = goDotModAnalysis <||> Gomod.analyzeStatic (gomodulesGomod project) -- `go list -json -deps all` marks std lib deps with a boolean, so Strategy.Go.GoListPackages does this filtering itself. -- I think this can be removed when `go list -json -deps all` becomes the default. filterGraph :: Maybe [GoStdlibDep] -> Graphing Dependency -> Graphing Dependency filterGraph Nothing deps = deps filterGraph (Just stdlib) deps = filterGoStdlibPackages stdlib deps + goDotModAnalysis :: (Has ReadFS sig m, Has Exec sig m, Has Diagnostics sig m) => m (Graphing Dependency, GraphBreadth) + goDotModAnalysis = context "Go.mod analysis" (Gomod.analyze' (gomodulesGomod project)) + dynamicAnalysis :: (Has Exec sig m, Has Diagnostics sig m) => m (Graphing Dependency, GraphBreadth) dynamicAnalysis = context "Dynamic analysis" $ do @@ -97,13 +104,13 @@ getDeps project goDynamicTactic = do context "analysis using go list (V3 Resolver)" (GoListPackages.analyze (gomodulesDir project)) -staticAnalysis :: (Has Exec sig m, Has ReadFS sig m, Has Diagnostics sig m) => GomodulesProject -> m (Graphing Dependency, GraphBreadth) -staticAnalysis project = context "Static analysis" (Gomod.analyze' (gomodulesGomod project)) - -staticAnalysisResults :: GomodulesProject -> (Graphing Dependency, GraphBreadth) -> DependencyResults -staticAnalysisResults proj (graph, graphBreadth) = - DependencyResults - { dependencyGraph = graph - , dependencyGraphBreadth = graphBreadth - , dependencyManifestFiles = [gomodulesGomod proj] - } +staticAnalysis :: (Has Diagnostics sig m, Has ReadFS sig m) => GomodulesProject -> m DependencyResults +staticAnalysis proj = do + let projectPath = gomodulesGomod proj + (graph, breadth) <- context "Go.mod analysis (static)" $ Gomod.analyzeStatic projectPath + pure $ + DependencyResults + { dependencyGraph = graph + , dependencyGraphBreadth = breadth + , dependencyManifestFiles = [projectPath] + }