Skip to content
Closed
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 @@ -2,6 +2,7 @@

## Unreleased

- Maven: Static analysis (`pomxml`, used when `mvn` is unavailable or with `--static-only-analysis`) no longer reports the project itself as the only direct dependency. Dependencies declared in `pom.xml` are now reported as direct and the project's own modules are removed from the graph, matching dynamic analysis.
- Diagnostics: When an error or warning group contains multiple errors, each error's `Traceback:` header is now printed on its own line instead of being glued onto the last line of the preceding error message (e.g. `...none passed validationTraceback:`). ([#1758](https://github.com/fossas/fossa-cli/pull/1758))

## 3.18.2
Expand Down
12 changes: 9 additions & 3 deletions src/Strategy/Maven.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Strategy.Maven (
mkProject,
MavenProject (..),
getDeps,
getStaticAnalysis,
) where

import App.Fossa.Analyze.LicenseAnalyze (LicenseAnalyzeProject, licenseAnalyzeProject)
Expand All @@ -18,14 +19,14 @@ import Data.Set (Set)
import Data.Set qualified as Set
import Data.Set.NonEmpty (nonEmpty, toSet)
import Data.Text hiding (group, map)
import DepTypes (Dependency)
import DepTypes (Dependency (..))
import Diag.Common (MissingDeepDeps (MissingDeepDeps), MissingEdges (MissingEdges))
import Discovery.Filters (AllFilters, MavenScopeFilters, mavenScopeFilterSet)
import Discovery.Simple (simpleDiscover)
import Effect.Exec (CandidateCommandEffs, GetDepsEffs)
import Effect.ReadFS (ReadFS)
import GHC.Generics (Generic)
import Graphing (Graphing, gmap, shrinkRoots)
import Graphing (Graphing, gmap, shrink, shrinkRoots)
import Path (Abs, Dir, Path, parent)
import Strategy.Maven.Common (MavenDependency (..), filterMavenDependencyByScope, filterMavenSubmodules, mavenDependencyToDependency)
import Strategy.Maven.DepTree qualified as DepTreeCmd
Expand Down Expand Up @@ -188,7 +189,12 @@ getStaticAnalysis submoduleTargets closure = do
let allSubmodules = PomClosure.closureSubmodules closure
(graph, graphBreadth) <- context "Static analysis" $ pure (Pom.analyze' closure, Partial)
filteredGraph <- applyMavenFilters submoduleTargets allSubmodules graph
pure (filteredGraph, graphBreadth)
pure (withoutProjectAsDep filteredGraph, graphBreadth)
where
-- The static graph is rooted at the project itself, with submodules as its children.
-- Those are the users' packages, not dependencies, so remove them and promote their
-- children to direct, like the dynamic strategies do with `shrinkRoots`.
withoutProjectAsDep = shrink (\dep -> dependencyName dep `Set.notMember` PomClosure.closureSubmodules closure)

applyMavenFilters :: (Has Diagnostics sig m, Has (Reader MavenScopeFilters) sig m) => Set Text -> Set Text -> Graphing MavenDependency -> m (Graphing Dependency)
applyMavenFilters targetSet submoduleSet graph = do
Expand Down
39 changes: 38 additions & 1 deletion test/Maven/PomClosureSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@

module Maven.PomClosureSpec (spec) where

import Control.Carrier.Reader (runReader)
import Control.Effect.Lift (sendIO)
import Data.ByteString.Char8 qualified as BS
import Data.List (find, sort)
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import Data.Text (Text)
import GraphUtil (expectDeps')
import DepTypes (DepType (MavenType), Dependency (..), VerConstraint (CEq))
import GraphUtil (expectDeps', expectDirect')
import Graphing (shrinkRoots)
import Path (Abs, Dir, Path, reldir, relfile, toFilePath, (</>))
import Path.IO qualified as PIO
import Strategy.Maven (getStaticAnalysis)
import Strategy.Maven.Plugin (Artifact (..), Edge (Edge), PluginOutput (..))
import Strategy.Maven.PluginStrategy (buildGraph)
import Strategy.Maven.Pom.Closure (
Expand All @@ -22,6 +25,7 @@ import Strategy.Maven.Pom.Closure (
)
import Strategy.Maven.Pom.PomFile (MavenCoordinate (..))
import Test.Effect (EffectStack, itWithTempDir', shouldBe')
import Test.Fixtures (mavenScopeFilterSet)
import Test.Hspec

spec :: Spec
Expand Down Expand Up @@ -106,6 +110,32 @@ spec = do
graph = shrinkRoots $ buildGraph submodules output
expectDeps' [] graph

describe "getStaticAnalysis" $ do
-- The static (pomxml) graph is rooted at the project itself with its
-- modules as children. Those are first-party and must not be reported;
-- their declared dependencies must be promoted to direct, as the dynamic
-- strategies already do via shrinkRoots.
itWithTempDir' "reports declared dependencies as direct and drops the project and its modules" $ \dir -> do
createParentlessFixture dir
closures <- findProjects dir
case find ((== rootCoord) . closureRootCoord) closures of
Nothing -> sendIO $ expectationFailure "expected a closure rooted at com.example:root-a"
Just closure -> do
(graph, _) <- runReader mavenScopeFilterSet $ getStaticAnalysis (closureSubmodules closure) closure
expectDirect' [libDep] graph
expectDeps' [libDep] graph

libDep :: Dependency
libDep =
Dependency
{ dependencyType = MavenType
, dependencyName = "org.example:lib"
, dependencyVersion = Just (CEq "1.0")
, dependencyLocations = []
, dependencyEnvironments = mempty
, dependencyTags = Map.empty
}

rootCoord :: MavenCoordinate
rootCoord = MavenCoordinate "com.example" "root-a" "1.0"

Expand Down Expand Up @@ -192,6 +222,13 @@ parentedChildPom =
, " <relativePath>../pom.xml</relativePath>\n"
, " </parent>\n"
, " <artifactId>child-parented</artifactId>\n"
, " <dependencies>\n"
, " <dependency>\n"
, " <groupId>org.example</groupId>\n"
, " <artifactId>lib</artifactId>\n"
, " <version>1.0</version>\n"
, " </dependency>\n"
, " </dependencies>\n"
, "</project>\n"
]

Expand Down
Loading