Skip to content
Open
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: analysis no longer fails with `An exception occurred: /tmp/fossa-maven-... removeDirectoryRecursive:getSymbolicLinkStatus: does not exist (No such file or directory)` when the plugin's scratch directory is removed (e.g. by the OS temp reaper) before cleanup runs; the scratch directory is now cleaned up on a best-effort basis. ([#1771](https://github.com/fossas/fossa-cli/pull/1771))
- Dart: `pubspec.yaml` files using valid dependency forms the parser previously rejected no longer fail analysis with `Aeson exception: ... empty` or `failed parsing pub package's source!`: a bare dependency with no value (any version), a `version:`-only entry, the `hosted: <url>` shorthand introduced in Dart 2.15, a `hosted:` map without a `version`, and a `git:` map without a `ref`. ([#1760](https://github.com/fossas/fossa-cli/pull/1760))
- Workflows: `fossa analyze --x-workflow <path>` runs a dependency-usage workflow analyzer through the embedded ficus and records its result in the debug bundle. ([#1761](https://github.com/fossas/fossa-cli/pull/1761))
- Workflows: the `--x-workflow` result is uploaded to FOSSA against the analyzed revision once the dependency upload succeeds; `--output` runs still upload nothing. ([#1762](https://github.com/fossas/fossa-cli/pull/1762))
Expand Down
15 changes: 9 additions & 6 deletions src/Strategy/Maven/Plugin.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ module Strategy.Maven.Plugin (

import Control.Algebra (Has)
import Control.Effect.Diagnostics (Diagnostics, ToDiagnostic (renderDiagnostic), recover, warn)
import Control.Effect.Exception (Lift, bracket)
import Control.Effect.Exception (Lift)
import Control.Effect.Lift (sendIO)
import Control.Effect.Path (withSystemTempDir)
import Control.Monad (when)
import Data.Aeson (FromJSON, parseJSON, withObject, (.!=), (.:), (.:?))
import Data.ByteString (ByteString)
Expand Down Expand Up @@ -79,7 +80,6 @@ import Path (
toFilePath,
(</>),
)
import Path.IO (createTempDir, getTempDir, removeDirRecur)
import Strategy.Maven.PluginTree (TextArtifact (..), parseTextArtifacts)
import Strategy.Maven.Pom.PomFile qualified as PomFile
import System.FilePath qualified as FP
Expand Down Expand Up @@ -117,10 +117,13 @@ withUnpackedPlugin ::
(FP.FilePath -> m a) ->
m a
withUnpackedPlugin plugin act =
bracket
(sendIO (getTempDir >>= \tmp -> createTempDir tmp "fossa-maven"))
(sendIO . removeDirRecur)
go
-- 'withSystemTempDir' removes the scratch directory on a best-effort basis
-- (it ignores IO errors during cleanup). A previous hand-rolled
-- 'bracket'/'removeDirRecur' cleanup would instead escalate any cleanup
-- failure to a fatal, analysis-wide error -- e.g. when the OS temp reaper (or
-- a race) removed the directory first, the run died with
-- @An exception occurred: /tmp/fossa-maven-... removeDirectoryRecursive:getSymbolicLinkStatus: does not exist@.
withSystemTempDir "fossa-maven" go
where
go tmpDir = do
let pluginJarFilepath = fromAbsDir tmpDir FP.</> "plugin.jar"
Expand Down
20 changes: 20 additions & 0 deletions test/Maven/PluginSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ import Strategy.Maven.Plugin (
VerboseEdge (..),
VerboseGraph (..),
augmentWithDuplicateEdges,
depGraphPlugin,
deriveVerboseGraphPaths,
parsePluginOutput,
parseVerboseGraphs,
textArtifactToPluginOutput,
withUnpackedPlugin,
)
import Strategy.Maven.PluginTree (TextArtifact (..), parseTextArtifact)
import Strategy.Maven.Pom.PomFile (MavenCoordinate (..), Pom (..), PomBuild (..))
import System.Directory qualified as Dir
import System.FilePath qualified as FP
import Test.Effect (
expectFatal',
expectationFailure',
Expand All @@ -47,6 +51,22 @@ spec = do
verboseGraphCollectionSpec
deriveVerboseGraphPathsSpec
parsePluginOutputSpec
withUnpackedPluginSpec

-- | 'withUnpackedPlugin' unpacks the plugin jar into a scratch directory and
-- must clean it up on a best-effort basis. If the directory is already gone
-- when cleanup runs (e.g. an OS temp reaper removed it, or a concurrent task
-- did), cleanup must not turn that into a fatal, analysis-wide error such as
-- @An exception occurred: /tmp/fossa-maven-... removeDirectoryRecursive:getSymbolicLinkStatus: does not exist@.
withUnpackedPluginSpec :: Spec
withUnpackedPluginSpec =
describe "withUnpackedPlugin" $
it' "does not fail when the scratch directory is already gone at cleanup time" $ do
result <- withUnpackedPlugin depGraphPlugin $ \pluginJarFilepath -> do
-- Simulate the scratch directory vanishing before cleanup runs.
sendIO $ Dir.removeDirectoryRecursive (FP.takeDirectory pluginJarFilepath)
pure (42 :: Int)
result `shouldBe'` (42 :: Int)

-- | The @graph@ goal is not an aggregator: in a multi-module build it runs once
-- per reactor module, writing into each module's own build directory.
Expand Down
Loading