Skip to content
Draft
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
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Config: `paths.only` and `paths.exclude` in `.fossa.yml` now accept glob patterns. ([#1703](https://github.com/fossas/fossa-cli/pull/1703))
- Licensing - Fix two bad GPL matches [No PR]
- NuGet: PackageReference discovery now analyzes every `.csproj`/`.xproj`/`.vbproj`/`.dbproj`/`.fsproj` in a directory. Previously only the first match returned by the directory listing was analyzed, so sibling project files were silently dropped. ([#1712](https://github.com/fossas/fossa-cli/pull/1712))
- Go: `go list`-based analysis now tags test-only dependencies (reached via a main-module package's `TestImports`) with the testing environment. They are filtered out of uploads by default, matching prior behavior, but can now be surfaced with `--include-unused-deps`. Previously test dependencies were dropped from the graph entirely and `--include-unused-deps` had no effect for Go projects. ([#1714](https://github.com/fossas/fossa-cli/pull/1714))


## 3.17.5
Expand Down
24 changes: 22 additions & 2 deletions src/Strategy/Go/GoListPackages.hs
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,21 @@ type GoLabeledGrapher m a = LabeledGrapherC GoPackage DepEnvironment m a
-- * Removes path dependencies and their transitive deps that aren't used elsewhere in the graph.
-- The go tools give us this data but we haven't decided yet how to present it.
-- * Replaces modules according to the module's 'replacement' field.
-- * Skips over test dependencies and their children.
-- * Tags test-only dependencies (reached via 'TestImports' of a main module
-- package) with 'EnvTesting' so they can be filtered out at upload time by
-- 'shouldPublishDep'. Production dependencies are always tagged with
-- 'EnvProduction'; a module reached through both paths gets both labels.
buildGraph :: (Has Diagnostics sig m) => Path Abs Dir -> [GoPackage] -> m (Graphing.Graphing Dependency, GraphBreadth)
buildGraph goModDir rawPackages = do
g <- runLabeledGrapher . traverse_ (makeGraph EnvProduction) =<< getMainPackages
mains <- getMainPackages
-- Production traversal must run first so that any module reachable from both
-- production and test code keeps its 'EnvProduction' label and a fully
-- traversed production subtree. The subsequent test traversal short-circuits
-- when it hits an already-graphed vertex, but still appends 'EnvTesting' at
-- the vertex it re-encounters.
g <- runLabeledGrapher $ do
traverse_ (makeGraph EnvProduction) mains
traverse_ traverseTestDeps mains
fmap ((,Complete)) . uncurry pkgGraphToDepGraph $ g
where
(mainPackages, stdLibImportPaths, pkgsNoStdLibImports) = foldl' go ([], HashSet.empty, HashMap.empty) rawPackages
Expand Down Expand Up @@ -232,6 +243,15 @@ buildGraph goModDir rawPackages = do
maybeEdge :: (Has Diagnostics sig m, Has (Grapher GoPackage) sig m) => GoPackage -> Maybe GoPackage -> m ()
maybeEdge d = maybe (pure ()) (edge d)

-- For each TestImport of a main-module package, graph the imported package
-- (and its transitive 'packageDeps') tagged as 'EnvTesting', wiring it as
-- an edge from the main-module package. We do not recurse into the
-- 'testDeps' of non-main packages: when compiling tests of the main
-- module, Go does not pull in the test imports of dependencies.
traverseTestDeps :: (Has Diagnostics sig m) => GoPackage -> GoLabeledGrapher m ()
traverseTestDeps pkg@GoPackage{testDeps} =
traverse_ (lookupPackage >=> makeGraph EnvTesting >=> maybeEdge pkg) testDeps

lookupPackage :: Has Diagnostics sig m => ImportPath -> m GoPackage
lookupPackage impPath = Diagnostics.fromMaybe (MissingModuleErr getSourceLocation impPath) $ HashMap.lookup impPath pkgsNoStdLibImports

Expand Down
17 changes: 16 additions & 1 deletion test/Go/GoListPackagesSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Control.Carrier.Stack (runStack)
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import DepTypes (
DepEnvironment (EnvProduction),
DepEnvironment (EnvProduction, EnvTesting),
DepType (GoType, UnresolvedPathType),
Dependency (..),
VerConstraint (CEq),
Expand Down Expand Up @@ -294,11 +294,26 @@ pathDepPkgModule =
, dependencyTags = Map.empty
}

-- 'transitiveTestMod' is reachable only via the 'testDeps' of another test
-- dep, which we intentionally do not traverse, so it should not appear in
-- 'expectedGraph'.
testMod :: Dependency
testMod =
Dependency
{ dependencyType = GoType
, dependencyName = "testMod"
, dependencyVersion = Just $ CEq "1.0.0"
, dependencyLocations = []
, dependencyEnvironments = Set.singleton EnvTesting
, dependencyTags = Map.empty
}

expectedGraph :: Graphing.Graphing Dependency
expectedGraph =
Graphing.direct replacedModule
<> Graphing.direct moduleA
<> Graphing.direct pathModule
<> Graphing.direct testMod
<> Graphing.edge replacedModule moduleA
<> Graphing.edge pathModule pathDepPkgModule

Expand Down
Loading