Skip to content

Commit 513a3a5

Browse files
authored
Expose a static only Go modules tactic. (#1486)
* Expose a static only Go modules tactic. * really for real go static analysis * Remove fallbacks. It already does that. * active voice * Document that transitive dependnecies aren't reported with Go mod static analysis. * Fix typo.
1 parent 4ed7eab commit 513a3a5

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

Changelog.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# FOSSA CLI Changelog
2+
3+
## 3.9.41
4+
- GoModules: Expose a static only analysis method for Go. ([#1468](https://github.com/fossas/fossa-cli/pull/1486))
5+
26
## 3.9.40
37
- Licensing: Fix a bug where license scanner output sometimes included log lines, which breaks JSON parsing
48

docs/references/strategies/languages/golang/gomodules.md

+4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ where:
104104
- `replace` rewrites `require`s. In this example, our requires resolve to
105105
`[github.com/example/one v1.2.3, github.com/example/other v2.0.0]`
106106

107+
108+
This strategy will attempt to fill in transitive dependencies by calling out to Go tools.
109+
If it fails or `fossa analyze` is invoked with `--static-analysis-only`, the strategy will report what it found in `go.mod` without any transitive dependencies.
110+
107111
## FAQ
108112

109113
### Why do I see a dependency in `go.mod`, but it is not reflected in FOSSA?

src/Strategy/Go/Gomod.hs

+9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module Strategy.Go.Gomod (
1414
PackageVersion (..),
1515
parsePackageVersion,
1616
gomodParser,
17+
analyzeStatic,
1718
) where
1819

1920
import Control.Algebra (Has)
@@ -396,6 +397,14 @@ analyze' file = do
396397
pure ()
397398
pure (graph, Partial)
398399

400+
-- | This variant of analyze will not attempt to fill in transitive dependencies.
401+
analyzeStatic :: (Has ReadFS sig m, Has Diagnostics sig m) => Path Abs File -> m (Graphing Dependency, GraphBreadth)
402+
analyzeStatic file = do
403+
graph <- graphingGolang $ do
404+
gomod <- readContentsParser gomodParser file
405+
context "Building dependency graph (static)" $ buildGraph gomod
406+
pure (graph, Partial)
407+
399408
buildGraph :: Has GolangGrapher sig m => Gomod -> m ()
400409
buildGraph = traverse_ go . resolve
401410
where

src/Strategy/Gomodules.hs

+20-6
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ module Strategy.Gomodules (
44
getDeps,
55
mkProject,
66
GomodulesProject (..),
7-
) where
7+
)
8+
where
89

910
import App.Fossa.Analyze.Types (AnalyzeProject (analyzeProjectStaticOnly), analyzeProject)
1011
import App.Fossa.Config.Analyze (ExperimentalAnalyzeConfig (useV3GoResolver), GoDynamicTactic (..))
1112
import App.Util (guardStrictMode)
1213
import Control.Carrier.Diagnostics (warn)
13-
import Control.Effect.Diagnostics (Diagnostics, context, fatalText, recover, (<||>))
14+
import Control.Effect.Diagnostics (Diagnostics, context, recover, (<||>))
1415
import Control.Effect.Reader (Reader, ask, asks)
1516
import Control.Monad (when)
1617
import Data.Aeson (ToJSON)
@@ -57,7 +58,7 @@ instance ToJSON GomodulesProject
5758

5859
instance AnalyzeProject GomodulesProject where
5960
analyzeProject _ proj = asks useV3GoResolver >>= getDeps proj
60-
analyzeProjectStaticOnly _ = const $ fatalText "Cannot analyze GoModule project statically"
61+
analyzeProjectStaticOnly _ = staticAnalysis
6162

6263
mkProject :: GomodulesProject -> DiscoveredProject GomodulesProject
6364
mkProject project =
@@ -71,7 +72,9 @@ mkProject project =
7172
getDeps :: (GetDepsEffs sig m) => GomodulesProject -> GoDynamicTactic -> m DependencyResults
7273
getDeps project goDynamicTactic = do
7374
mode <- ask
74-
(graph, graphBreadth) <- context "Gomodules" $ dynamicAnalysis <||> guardStrictMode mode staticAnalysis
75+
(graph, graphBreadth) <-
76+
context "Gomodules" $
77+
dynamicAnalysis <||> guardStrictMode mode goDotModAnalysis
7578
stdlib <- recover . context "Collect go standard library information" . listGoStdlibPackages $ gomodulesDir project
7679
pure $
7780
DependencyResults
@@ -86,8 +89,8 @@ getDeps project goDynamicTactic = do
8689
filterGraph Nothing deps = deps
8790
filterGraph (Just stdlib) deps = filterGoStdlibPackages stdlib deps
8891

89-
staticAnalysis :: (Has Exec sig m, Has ReadFS sig m, Has Diagnostics sig m) => m (Graphing Dependency, GraphBreadth)
90-
staticAnalysis = context "Static analysis" (Gomod.analyze' (gomodulesGomod project))
92+
goDotModAnalysis :: (Has ReadFS sig m, Has Exec sig m, Has Diagnostics sig m) => m (Graphing Dependency, GraphBreadth)
93+
goDotModAnalysis = context "Go.mod analysis" (Gomod.analyze' (gomodulesGomod project))
9194

9295
dynamicAnalysis :: (Has Exec sig m, Has Diagnostics sig m) => m (Graphing Dependency, GraphBreadth)
9396
dynamicAnalysis =
@@ -98,3 +101,14 @@ getDeps project goDynamicTactic = do
98101
\This option will be removed in a future release and result in an error."
99102

100103
context "analysis using go list (V3 Resolver)" (GoListPackages.analyze (gomodulesDir project))
104+
105+
staticAnalysis :: (Has Diagnostics sig m, Has ReadFS sig m) => GomodulesProject -> m DependencyResults
106+
staticAnalysis proj = do
107+
let projectPath = gomodulesGomod proj
108+
(graph, breadth) <- context "Go.mod analysis (static)" $ Gomod.analyzeStatic projectPath
109+
pure $
110+
DependencyResults
111+
{ dependencyGraph = graph
112+
, dependencyGraphBreadth = breadth
113+
, dependencyManifestFiles = [projectPath]
114+
}

0 commit comments

Comments
 (0)