diff --git a/Changelog.md b/Changelog.md index f9054f611f..e6f2cb1651 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,6 @@ # FOSSA CLI Changelog +## v3.8.27 +- Maven: Fix a bug that broke maven analysis if the build directory was in a non-standard location ([#1343](https://github.com/fossas/fossa-cli/pull/1343)) ## v3.8.27 - VSI: no longer reports paths inside of extracted archives with the `!_fossa.virtual_!` literal [#1345](https://github.com/fossas/fossa-cli/pull/1345) diff --git a/docs/contributing/HACKING.md b/docs/contributing/HACKING.md index 830e6fb40d..83d6752689 100644 --- a/docs/contributing/HACKING.md +++ b/docs/contributing/HACKING.md @@ -68,20 +68,21 @@ There is no supported way for Non-FOSSA users to obtain these binaries, though w Run the unit tests by running `cabal test unit-tests` in the base directory. -Integration tests require you first build test data by running `make build-test-data`. Then you can run them with `cabal test integration-tests`. Note that integration tests can take quite a while to run and do not have progress output. +Integration tests require you first build test data by running `make build-test-data`. Then you can run them with `cabal test integration-tests`. Integration tests also require `nix`. See ["Installing Nix"](#installing-nix) below for installation instructions. Note that integration tests can take quite a while to run and do not have progress output. Both test suites will be run when you execute `cabal test`. ## Tools | name | description | -| -------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +|----------------------------------------|--------------------------------------------------------------------------------------------------------------| | [ghcup][ghcup] | Used to manage installed versions of ghc and cabal-install | | ghc | The haskell compiler (installed via ghcup) | | cabal-install | The package manager we use (installed via ghcup). Accessed via `cabal` on most setups. | | [haskell-language-server][hls] ("HLS") | LSP server for haskell projects | | [hlint][hlint] | A linting + hints tool for haskell code. It provides really useful suggestions. `hlint` is bundled with HLS | | [fourmolu][fourmolu] | A haskell source code formatter. `fourmolu` is bundled with HLS | +| [nix](#installing-nix) | Used by integration tests | ### Installing haskell-language-server @@ -130,10 +131,18 @@ run `make fmt-ci`, which will mount your project into the container used for che run `make fmt` within the container. This allows you to run the formater locally without having to startup an editor or having to install the formatter yourself. This also makes sure you're using the same version as CI. +## Installing `nix` + +Our integration tests use `nix` in order to set up dependencies. For example, we run our Maven integration tests in an environment where `mvn` and `jdk11` are installed. + +If you do not have `nix` installed, then any shell commands that are attempted during the integration test will fail, even if the binaries are installed locally. This has the effect of making the integration tests fall back to static analysis, which will probably give you different results than you were expecting. + +You can tell if you have `nix` installed by trying to run `nix-shell` at the command line. If you need to install it, then consult the [`nix` installation instructions](https://nixos.org/download#nix-install-macos). + ## Docs | name | description | -| ------------------ | ------------------------------------------------------------------------------ | +|--------------------|--------------------------------------------------------------------------------| | [hoogle][hoogle] | Search for type signatures or symbols | | [hackage][hackage] | Package repository; can be used to browse individual package docs ("haddocks") | @@ -146,7 +155,7 @@ On linux, you can use [zeal](https://zealdocs.org/). (Currently there is an iss ### Cabal cheatsheet | command | description | -| ------------------------------------ | -------------------------------------------------------------------------- | +|--------------------------------------|----------------------------------------------------------------------------| | `cabal repl` | opens the ghci repl on the project | | `cabal build` | build fossa-cli | | `cabal test` | build + run tests | @@ -157,7 +166,7 @@ On linux, you can use [zeal](https://zealdocs.org/). (Currently there is an iss Use `cabal repl` to open ghci. | command | description | -| -------------------------- | ------------------------------------------------------------ | +|----------------------------|--------------------------------------------------------------| | `:r`/`:reload` | reload the project | | `:t`/`:type ` | query the type of a symbol | | `:i`/`:info ` | query info about a symbol -- docs, where it was defined, etc | diff --git a/integration-test/Analysis/MavenSpec.hs b/integration-test/Analysis/MavenSpec.hs index b76679c319..91a6d6fc80 100644 --- a/integration-test/Analysis/MavenSpec.hs +++ b/integration-test/Analysis/MavenSpec.hs @@ -56,6 +56,30 @@ guava = [reldir|maven/guava/|] [reldir|guava-31.1|] +simplePomFile :: AnalysisTestFixture Maven.MavenProject +simplePomFile = + AnalysisTestFixture + "simple-pom-file" + Maven.discover + mavenEnv + Nothing + $ FixtureArtifact + "https://github.com/fossas/example-pom-file/archive/refs/heads/main.tar.gz" + [reldir|maven/simple_pom_file/|] + [reldir|example-pom-file-main|] + +pomFileWithBuildDirOverride :: AnalysisTestFixture Maven.MavenProject +pomFileWithBuildDirOverride = + AnalysisTestFixture + "build-dir-override" + Maven.discover + mavenEnv + Nothing + $ FixtureArtifact + "https://github.com/fossas/example-pom-file/archive/refs/heads/override-build-directory.tar.gz" + [reldir|maven/build_dir_override/|] + [reldir|example-pom-file-override-build-directory|] + testKeycloak :: Spec testKeycloak = do aroundAll (withAnalysisOf keycloak) $ do @@ -76,7 +100,35 @@ testGuava = , graphType = Complete } +testSimplePomFile :: Spec +testSimplePomFile = do + testSuiteDepResultSummary + simplePomFile + Types.MavenProjectType + DependencyResultsSummary + { numDeps = 25 + , numDirectDeps = 2 + , numEdges = 23 + , numManifestFiles = 1 + , graphType = Complete + } + +testBuildDirOverride :: Spec +testBuildDirOverride = do + testSuiteDepResultSummary + pomFileWithBuildDirOverride + Types.MavenProjectType + DependencyResultsSummary + { numDeps = 25 + , numDirectDeps = 2 + , numEdges = 23 + , numManifestFiles = 1 + , graphType = Complete + } + spec :: Spec spec = do testKeycloak testGuava + testBuildDirOverride + testSimplePomFile diff --git a/src/Strategy/Maven/Plugin.hs b/src/Strategy/Maven/Plugin.hs index 16d405d9a7..b6ecbd6405 100644 --- a/src/Strategy/Maven/Plugin.hs +++ b/src/Strategy/Maven/Plugin.hs @@ -64,7 +64,6 @@ import Path ( Path, Rel, fromAbsDir, - mkRelDir, mkRelFile, (), ) @@ -130,10 +129,10 @@ execPluginAggregate dir plugin = do cmd <- mavenPluginDependenciesCmd dir plugin execPlugin (const cmd) dir plugin -execPluginReactor :: (CandidateCommandEffs sig m, Has ReadFS sig m) => Path Abs Dir -> DepGraphPlugin -> m () -execPluginReactor dir plugin = do - cmd <- mavenPluginReactorCmd dir plugin - execPlugin (const cmd) dir plugin +execPluginReactor :: (CandidateCommandEffs sig m, Has ReadFS sig m) => Path Abs Dir -> Path Abs Dir -> DepGraphPlugin -> m () +execPluginReactor projectdir outputdir plugin = do + cmd <- mavenPluginReactorCmd projectdir outputdir plugin + execPlugin (const cmd) projectdir plugin outputFile :: Path Rel File outputFile = $(mkRelFile "target/dependency-graph.txt") @@ -146,7 +145,7 @@ reactorOutputFilename :: Path Rel File reactorOutputFilename = $(mkRelFile "fossa-reactor-graph.json") parseReactorOutput :: (Has ReadFS sig m, Has Diagnostics sig m) => (Path Abs Dir) -> m ReactorOutput -parseReactorOutput dir = readContentsJson $ dir $(mkRelDir "target/") reactorOutputFilename +parseReactorOutput dir = readContentsJson $ dir reactorOutputFilename textArtifactToPluginOutput :: Has Diagnostics sig m => Tree TextArtifact -> m PluginOutput textArtifactToPluginOutput @@ -266,8 +265,10 @@ mavenPluginDependenciesCmd workdir plugin = do -- | The reactor command is documented -- [here.](https://ferstl.github.io/depgraph-maven-plugin/reactor-mojo.html) -mavenPluginReactorCmd :: (CandidateCommandEffs sig m, Has ReadFS sig m) => Path Abs Dir -> DepGraphPlugin -> m Command -mavenPluginReactorCmd workdir plugin = do +-- We set outputDirectory explicitly so that the file is written to a known spot even if the pom file +-- overrides the build directory (See FDN-82 for more details) +mavenPluginReactorCmd :: (CandidateCommandEffs sig m, Has ReadFS sig m) => Path Abs Dir -> Path Abs Dir -> DepGraphPlugin -> m Command +mavenPluginReactorCmd workdir outputdir plugin = do candidates <- mavenCmdCandidates workdir mkAnalysisCommand candidates workdir args Never where @@ -275,6 +276,7 @@ mavenPluginReactorCmd workdir plugin = do [ group plugin <> ":" <> artifact plugin <> ":" <> version plugin <> ":reactor" , "-DgraphFormat=json" , "-DoutputFileName=" <> toText reactorOutputFilename + , "-DoutputDirectory=" <> toText outputdir ] newtype ReactorArtifact = ReactorArtifact diff --git a/src/Strategy/Maven/PluginStrategy.hs b/src/Strategy/Maven/PluginStrategy.hs index 04882b5932..763e998823 100644 --- a/src/Strategy/Maven/PluginStrategy.hs +++ b/src/Strategy/Maven/PluginStrategy.hs @@ -15,6 +15,7 @@ import Control.Effect.Diagnostics ( (<||>), ) import Control.Effect.Lift (Lift) +import Control.Effect.Path (withSystemTempDir) import Control.Monad (when) import Data.Foldable (traverse_) import Data.Map.Strict (Map) @@ -74,14 +75,16 @@ analyzeLegacy' dir = analyze dir depGraphPluginLegacy runReactor :: ( CandidateCommandEffs sig m , Has ReadFS sig m + , Has (Lift IO) sig m ) => Path Abs Dir -> DepGraphPlugin -> m ReactorOutput runReactor dir plugin = context "Running plugin to get submodule names" $ - warnOnErr MayIncludeSubmodule (execPluginReactor dir plugin >> parseReactorOutput dir) - <||> pure (ReactorOutput []) + withSystemTempDir "fossa-temp" $ \tempdir -> do + warnOnErr MayIncludeSubmodule (execPluginReactor dir tempdir plugin >> parseReactorOutput tempdir) + <||> pure (ReactorOutput []) analyze :: ( CandidateCommandEffs sig m