├── .github └── workflows │ └── install-script-test.yml ├── .gitignore ├── Changelog.md ├── LICENSE ├── README.md ├── docs ├── README.md ├── concepts │ └── analysis-and-analyzers.md ├── contributing │ ├── HACKING.md │ ├── README.md │ ├── STYLE-GUIDE.md │ ├── buildtools │ │ └── yarnv2.org │ ├── graph-hydration.md │ ├── graph-hydration │ │ ├── hydrate-after.gv │ │ ├── hydrate-after.svg │ │ ├── hydrate-before.gv │ │ └── hydrate-before.svg │ ├── parsing-best-practices.md │ ├── replay-logging.md │ └── writing-docs.md ├── differences-from-v1.md ├── features │ ├── manual-dependencies.md │ └── vendored-dependencies.md ├── glossary.md ├── references │ ├── files │ │ ├── fossa-deps.md │ │ ├── fossa-deps.schema.json │ │ ├── fossa-yml.md │ │ └── fossa-yml.v3.schema.json │ ├── strategies │ │ ├── README.md │ │ ├── languages │ │ │ ├── clojure │ │ │ │ ├── clojure.md │ │ │ │ └── leiningen.md │ │ │ ├── dart │ │ │ │ ├── dart-resolved-graph-with-lock-cmd.svg │ │ │ │ ├── dart-resolved-graph-without-cmd.svg │ │ │ │ ├── dart.md │ │ │ │ └── pub.md │ │ │ ├── dotnet │ │ │ │ ├── README.md │ │ │ │ ├── nuget.md │ │ │ │ ├── nuspec.md │ │ │ │ ├── packagereference.md │ │ │ │ ├── packagesconfig.md │ │ │ │ ├── paket-qr.md │ │ │ │ ├── paket.md │ │ │ │ ├── projectassetsjson.md │ │ │ │ └── projectjson.md │ │ │ ├── elixir │ │ │ │ ├── elixir.md │ │ │ │ ├── mix-resolved-graph.svg │ │ │ │ └── mix.md │ │ │ ├── erlang │ │ │ │ ├── erlang.md │ │ │ │ └── rebar3.md │ │ │ ├── fortran │ │ │ │ └── fortran.md │ │ │ ├── golang │ │ │ │ ├── glide-qr.md │ │ │ │ ├── glide.md │ │ │ │ ├── godep-qr.md │ │ │ │ ├── godep.md │ │ │ │ ├── golang.md │ │ │ │ ├── gomodules-qr.md │ │ │ │ └── gomodules.md │ │ │ ├── gradle │ │ │ │ └── gradle.md │ │ │ ├── haskell │ │ │ │ ├── README.md │ │ │ │ ├── cabal-qr.md │ │ │ │ ├── cabal.md │ │ │ │ ├── stack-qr.md │ │ │ │ └── stack.md │ │ │ ├── maven │ │ │ │ ├── maven-qr.md │ │ │ │ ├── maven.md │ │ │ │ ├── mavenplugin.md │ │ │ │ └── pomxml.md │ │ │ ├── nodejs │ │ │ │ ├── nodejs.md │ │ │ │ ├── npm.md │ │ │ │ ├── npmcli.md │ │ │ │ ├── packagejson.md │ │ │ │ ├── yarn-qr.md │ │ │ │ └── yarn.md │ │ │ ├── perl │ │ │ │ └── perl.md │ │ │ ├── php │ │ │ │ └── composer.md │ │ │ ├── python │ │ │ │ ├── conda.md │ │ │ │ ├── pipenv-graph.svg │ │ │ │ ├── pipenv-qr.md │ │ │ │ ├── pipenv.dot │ │ │ │ ├── pipenv.md │ │ │ │ ├── piplist.md │ │ │ │ ├── poetry-with-lock.svg │ │ │ │ ├── poetry-without-lock.svg │ │ │ │ ├── poetry.md │ │ │ │ ├── python.md │ │ │ │ ├── setuptools-qr.md │ │ │ │ └── setuptools.md │ │ │ ├── ruby │ │ │ │ ├── bundler.md │ │ │ │ └── ruby.md │ │ │ ├── rust │ │ │ │ ├── cargo.md │ │ │ │ └── rust.md │ │ │ └── scala │ │ │ │ ├── sbt-qr.md │ │ │ │ └── sbt.md │ │ ├── platforms │ │ │ ├── conda │ │ │ │ └── conda.md │ │ │ └── ios │ │ │ │ ├── carthage-qr.md │ │ │ │ ├── carthage.md │ │ │ │ ├── cocoapods-qr.md │ │ │ │ ├── cocoapods.md │ │ │ │ ├── ios.md │ │ │ │ └── swift.md │ │ └── system │ │ │ └── rpm │ │ │ └── rpm.md │ └── subcommands │ │ ├── analyze.md │ │ ├── list-targets.md │ │ ├── report.md │ │ └── test.md └── walkthroughs │ ├── analysis-target-configuration.md │ ├── custom-integrating-with-bower-example.md │ ├── debugging-your-integration.md │ └── integrating.md ├── install.ps1 └── install.sh /.github/workflows/install-script-test.yml: -------------------------------------------------------------------------------- 1 | name: Test Installation Scripts 2 | on: push 3 | 4 | jobs: 5 | test-nix: 6 | runs-on: ${{ matrix.os }} 7 | strategy: 8 | matrix: 9 | os: [ubuntu-latest, macos-latest] 10 | steps: 11 | - uses: actions/checkout@v2 12 | 13 | - name: install script performs installation 14 | shell: bash 15 | run: | 16 | ./install.sh -b . 17 | ./fossa --version 18 | rm fossa 19 | 20 | test-windows: 21 | runs-on: 'windows-latest' 22 | steps: 23 | - uses: actions/checkout@v2 24 | 25 | - name: install script performs installation for v3 26 | shell: pwsh 27 | run: | 28 | Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine 29 | .\install.ps1 30 | 31 | $cliVersionCmdOutput = cmd /c 'fossa.exe' '--version' 32 | $cliVersion = $cliVersionCmdOutput.Split(" ")[2] 33 | $cliVersionMajor = $cliVersion.Split(".")[0] 34 | 35 | if (-Not $cliVersionMajor -eq "3") { 36 | Write-Output "Got: $cliVersionMajor instead!" 37 | exit 1 38 | } 39 | Remove-Item -Path (Get-Command "fossa.exe").Path -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # cabal-install 2 | cabal.project.local 3 | cabal.project.local~ 4 | dist/ 5 | dist-newstyle/ 6 | 7 | # profiling 8 | *.prof 9 | *.hp 10 | 11 | # Development files/directories 12 | vendor/ 13 | vendor-bins/ 14 | .vscode/ 15 | 16 | # Executables 17 | /fossa 18 | /fossa-?dev 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Spectrometer code repository is now merged with [fossa-cli](https://github.com/fossas/fossa-cli/). Moving forward, all dev work will occur in [fossa-cli](https://github.com/fossas/fossa-cli/). 2 | # Spectrometer 3 | 4 | Spectrometer is a zero-configuration polyglot dependency analysis tool. You can point Spectrometer at any codebase or build, and it will automatically detect dependencies being used by your project. Spectrometer is now merged with fossa-cli. 5 | 6 | ## Installation 7 | 8 | Please migrate to using latest installation scripts provided at [fossa-cli](https://github.com/fossas/fossa-cli#installation). -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # User Manual 2 | 3 | For most users, the fossa-cli will work out-of-the-box without any configuration. Get an API key, run `fossa analyze`, and view your results in the FOSSA web application. 4 | 5 | If you haven't read the [Getting Started](../README.md#getting-started) section in the README yet, we highly recommend starting there first. 6 | 7 | This manual is organized into three sections: 8 | 9 | 10 | 11 | 1. **Walkthroughs** explain how to accomplish common use cases, including common troubleshooting steps and follow-ups. 12 | 13 | 2. **Features** explain specific CLI features and how to use them. 14 | 15 | 3. **References** provide an exhaustive listing and explanation of all CLI functionality. 16 | 17 | Every piece of documentation is accessible via hyperlink from this user manual. You should never need to manually explore `docs/` to find the page you need. 18 | 19 | ## Table of Contents 20 | 21 | 22 | 1. [Walkthroughs](#walkthroughs) 23 | 1. [Features](#features) 24 | 1. [References](#references) 25 | 26 | 35 | 36 | ## Walkthroughs 37 | 38 | Walkthrough guides explain how to accomplish specific tasks. They also include troubleshooting steps answer common questions. 39 | 40 | - [Integrating a project](./walkthroughs/integrating.md) 41 | - [Debugging a strategy](./walkthroughs/debugging-your-integration.md) 42 | 43 | ## Features 44 | 45 | Feature guides explain how to use specific features. These are most useful if there is a specific feature that a walkthrough has pointed you to. 46 | 47 | - [Manual dependencies](./features/manual-dependencies.md) 48 | - [Vendored dependencies](./features/vendored-dependencies.md) 49 | 50 | ## References 51 | 52 | Reference guides provide an exhaustive listing of all CLI functionality. If you can't find documentation on how something works elsewhere, it should be here. 53 | 54 | - CLI commands 55 | - [`fossa analyze`](./references/subcommands/analyze.md) 56 | - [`fossa test`](./references/subcommands/test.md) 57 | - [`fossa report`](./references/subcommands/report.md) 58 | - [`fossa list-targets`](./references/subcommands/list-targets.md) 59 | 61 | - CLI configuration files 62 | - [`.fossa.yml`](./references/files/fossa-yml.md) 63 | - [`fossa-deps.{yml,json}`](./references/files/fossa-deps.md) 64 | - [CLI analysis strategies](./references/strategies/README.md) 65 | -------------------------------------------------------------------------------- /docs/concepts/analysis-and-analyzers.md: -------------------------------------------------------------------------------- 1 | # Analysis Strategies 2 | 3 | The CLI performs dependency analysis using a set of "strategies". 4 | 5 | Strategies define how to identify user projects and how to determine the dependencies of each project. Each strategy corresponds to roughly one tool, language, or ecosystem. 6 | 7 | 8 | ## Table of contents 9 | 10 | - [Anatomy of a strategy](#anatomy-of-a-strategy) 11 | - [Analysis targets](#analysis-targets) 12 | - [Discovery and analysis](#discovery-and-analysis) 13 | - [Tactics](#tactics) 14 | - [Supported strategies](#supported-strategies) 15 | 16 | ## Anatomy of a strategy 17 | 18 | ### Analysis targets 19 | 20 | When the CLI identifies user projects to analyze, it groups these projects into "analysis targets". The exact semantics of an analysis target depends on the language, but usually a target is a single module, package, library, or program. Usually, an analysis target is equivalent to whatever you would create a dependency manifest file for. 21 | 22 | Analysis targets have exactly one type (which identifies which strategy is used to analyze the target) and produce exactly one dependency graph. 23 | 24 | A single Analysis (i.e. a single run of the CLI) includes every analysis target discovered in the folder being analyzed. 25 | 26 | ### Discovery and analysis 27 | 28 | Strategies usually have two phases: 29 | 30 | 1. A _discovery_ phase, to determine which user projects are in the folder being analyzed. 31 | 2. An _analysis_ phase, where dependencies of discovered user projects are analyzed. 32 | 33 | _Discovery_ usually works by examining the file system for special files that indicate the presence of a project. For example, a `package.json` usually indicates the presence of an NPM project, or a `pom.xml` usually indicates the presence of a Maven project. 34 | 35 | _Analysis_ usually works by running through a series of _tactics_ for each strategy. For example, to analyze the dependencies of an NPM project, we might try to parse `package-lock.json` or execute `npm ls`. 36 | 37 | Each strategy defines its own logic for how it does discovery, and its own logic for which tactics it uses to analyze dependencies. 38 | 39 | ### Tactics 40 | 41 | Strategies use one or more _tactics_ to analyze the dependencies or discovered projects. 42 | 43 | Each strategy defines its own tactics. Strategies generally have multiple tactics, and will automatically select between tactics depending on what information is available. 44 | 45 | Tactics tend to vary across two axes: 46 | 47 | 1. What _requirements_ must be fulfilled for the tactic to succeed? 48 | 2. What _structure_ does the tactic provide in its output? 49 | 50 | The relevant questions for _requirements_ are usually: 51 | 52 | 1. Does this tactic perform dynamic or static analysis? Tactics that do dynamic analysis usually require a functioning build environment and a CI integration, while tactics that only do static analysis only require a copy of the source code. 53 | 2. What files are necessary? Some tactics require files such as lockfiles that are not always present by default. 54 | 3. What build environment is necessary? Some tactics require running after successful builds, or being able to install build plugins. 55 | 56 | The relevant questions for _structure_ are usually: 57 | 58 | 1. Does this tactic provide all dependencies? Some tactics are only able to provide direct dependencies, installed dependencies, or some other subset of dependencies. 59 | 2. Does this tactic provide a graph or a list? Some tactics don't provide edge information between dependencies. 60 | 3. Does this tactic provide additional dependency metadata? Some tactics are able to tag dependencies with metadata, such as whether they're test dependencies. 61 | 62 | Each strategy's documentation contains information about its tactics and how it chooses between them. 63 | 64 | ## Supported strategies 65 | 66 | 69 | 70 | The CLI supports the following strategies: 71 | 72 | - [clojure](../references/strategies/languages/golang/golang.md) (lein) 73 | - [dart](../references/strategies/languages/dart/dart.md) (pub) 74 | - [elixir](../references/strategies/languages/elixir/elixir.md) (mix) 75 | - [erlang](../references/strategies/languages/erlang/erlang.md) (rebar3) 76 | - [fortran](../references/strategies/languages/fortran/fortran.md) 77 | - [golang](../references/strategies/languages/golang/golang.md) (gomodules, dep, glide) 78 | - [gradle](../references/strategies/languages/gradle/gradle.md) 79 | - [haskell](../references/strategies/languages/haskell/README.md) (cabal, stack) 80 | - [iOS](../references/strategies/platforms/ios/ios.md) (Carthage, Cocoapods, Swift package manager) 81 | - [maven](../references/strategies/languages/maven/maven.md) 82 | - [nodejs](../references/strategies/languages/nodejs/nodejs.md) (yarn, npmcli) 83 | - [php](../references/strategies/languages/php/composer.md) (composer) 84 | - [python](../references/strategies/languages/python/python.md) (conda, pipenv, setuptools) 85 | - [rpm](../references/strategies/system/rpm/rpm.md) (spec files) 86 | - [ruby](../references/strategies/languages/ruby/ruby.md) (bundler) 87 | - [rust](../references/strategies/languages/rust/rust.md) (cargo) 88 | - [sbt](../references/strategies/languages/scala/sbt.md) (sbt) 89 | - [.NET](../references/strategies/languages/dotnet/nuget.md) (NuGet, Paket) -------------------------------------------------------------------------------- /docs/contributing/HACKING.md: -------------------------------------------------------------------------------- 1 | # Hacking 2 | 3 | [Back to development doc homepage](README.md) 4 | 5 | ## Quickstart 6 | 7 | Use [ghcup][ghcup] to install the `cabal` cli tool and the ghc version we're using: 8 | 9 | ```sh 10 | $ ghcup install ghc 8.10 11 | 12 | $ ghcup set ghc 8.10 13 | $ cabal update 14 | $ cabal build 15 | ``` 16 | 17 | ### Quickstart Explanation 18 | 19 | Ok, the quickstart worked for you, but why, and how? 20 | 21 | > `ghcup install ghc 8.10` 22 | 23 | When you install `ghcup`, `ghc` and `cabal-install` are installed automatically as part of the initial installation (see [Tools](#Tools) for descriptions of `ghc` and `cabal-install`). 24 | The `ghc` version that is automatically installed may not be the correct version we use (though it may work just fine). So we install the correct version with `ghcup install ghc 8.10`. 25 | Currently, the best place to check the correct version is our CI build files (try `.github/workflows/build.yml`). 26 | 27 | > `ghcup set ghc 8.10` 28 | 29 | `ghcup` works by setting symlinks to the "active" version of the tool you're using. Here, we're telling `ghcup` to set GHC 8.10 as the active GHC version. 30 | Now, when you run `ghc`, you'll be running GHC 8.10. 31 | 32 | > `cabal update` 33 | 34 | Cabal caches a local index of packages (and their metadata) to try to resolve dependencies for builds. 35 | This cache often goes out of date since new package versions are released often. `cabal update` will refresh this cache. 36 | 37 | > `cabal build` 38 | 39 | This builds the actual project, and is a perfect sanity check for checking that you have the correct tools installed. 40 | You'll use this command a lot. 41 | 42 | ### Building 43 | 44 | In the base directory, run `cabal build` 45 | 46 | ### Running tests 47 | 48 | In the base directory, run `cabal test` 49 | 50 | ## Tools 51 | 52 | | name | description | 53 | | ---- | ----------- | 54 | | [ghcup][ghcup] | Used to manage installed versions of ghc and cabal-install | 55 | | ghc | The haskell compiler (installed via ghcup) | 56 | | cabal-install | The package manager we use (installed via ghcup). Accessed via `cabal` on most setups. | 57 | | [haskell-language-server][hls] ("HLS") | LSP server for haskell projects | 58 | | [hlint][hlint] | A linting + hints tool for haskell code. It provides really useful suggestions. `hlint` is bundled with HLS | 59 | | [fourmolu][fourmolu] | A haskell source code formatter. `fourmolu` is bundled with HLS | 60 | 61 | ### Installing haskell-language-server 62 | 63 | In VSCode: 64 | 65 | - Install the "Haskell Language Server" (`haskell.haskell`) plugin in VSCode. 66 | - In the Haskell extension settings, under `Haskell: Formatting Provider`, choose `fourmolu` 67 | 68 | If you installed HLS in the old, complicated way, you can safely remove it. HLS now bundles all of its needed tools. 69 | 70 | ## Linting 71 | 72 | `hlint` is built into HLS, and is enabled by default. hlint suggestions appear as warnings in the editor. 73 | 74 | You can also use `make lint` to run the linter. 75 | 76 | `make lint` is run in CI, any errors will prevent merging. 77 | 78 | ## Formatting 79 | 80 | Built into HLS, we use `fourmolu` for formatting source code files. In the VSCode Haskell extension settings, under `Haskell: Formatting Provider`, choose `fourmolu`. 81 | 82 | In VSCode, the formatter can be activated with the standard format-file and format-region actions. 83 | 84 | Make sure to run the formatter on any files you modify. Enabling `Editor: Format On Save` in VSCode can make satisfying this requirement easier. 85 | 86 | You can run `make fmt` to run the formatter on the entire codebase, or `make check-fmt` to dry-run the formatter. 87 | 88 | `make fmt` is run in CI, any formatting errors will prevent merging. 89 | 90 | ## Docs 91 | 92 | | name | description | 93 | | ---- | ----------- | 94 | | [hoogle][hoogle] | Search for type signatures or symbols | 95 | | [hackage][hackage] | Package repository; can be used to browse individual package docs ("haddocks") | 96 | 97 | If on macOS, [dash](https://kapeli.com/dash) is a great tool that allows for downloading searchable package haddocks 98 | 99 | On linux, you can use [zeal](https://zealdocs.org/). (Currently there is an issue with building third-party docsets, if you discover a solution to get e.g.: `aeson` docs in `zeal`, please file an issue or submit a PR to fix these docs.) 100 | 101 | ## Cheatsheets 102 | 103 | ### Cabal cheatsheet 104 | 105 | | command | description | 106 | | ------- | ----------- | 107 | | `cabal repl` | opens the ghci repl on the project | 108 | | `cabal build` | build spectrometer | 109 | | `cabal test` | build + run tests | 110 | | `cabal run binary-name -- arg1 arg2` | build + run an executable named `binary-name`, and with args `arg1` `arg2` | 111 | 112 | ### GHCI cheatsheet 113 | 114 | Use `cabal repl` to open ghci. 115 | 116 | | command | description | 117 | | ------- | ----------- | 118 | | `:r`/`:reload` | reload the project | 119 | | `:t`/`:type ` | query the type of a symbol | 120 | | `:i`/`:info ` | query info about a symbol -- docs, where it was defined, etc | 121 | | `:l`/`:load ` | load a specific file into the repl | 122 | 123 | ## FAQ/Troubleshooting 124 | 125 | ### Cabal is complaining about dependencies, and I don't understand it 126 | 127 | Yeah, haskell tools can be a little over-explainy and use too many technicalities. Try these steps (one at a time): 128 | 129 | - Run `cabal update`. This solves most problems with dependencies and should be a go-to for these issues. 130 | - Check your GHC version. Some dependencies are baked-in (sort of) to the compiler, so make sure you're using the correct version. 131 | - Update `ghcup`, then re-check all of your haskell tools' versions. `ghcup tui` is a great interface for this, but you can use normal commands. 132 | 133 | ### I tried using fourmolu/hlint, and it choked on some syntax that builds fine 134 | 135 | We use a fair amount of GHC extensions, which can greatly change the syntax of a file. When the extensions are listed at the top of a file 136 | using `{#- LANGUAGE GADTs -#}`-style syntax, these tools can easily pick that up. But some extensions, like `TypeApplications`, are so ubiquitous 137 | that we define them everywhere using cabal's `default-extensions` feature. If these also extensions modify syntax (like `TypeApplications` does), then 138 | these tools can choke, and sometimes pretty poorly. 139 | 140 | Using these tools through HLS should prevent these issues, since HLS checks for build-system-provided extensions. The `makefile` is also set up to 141 | include the correct extensions where necessary, so running `make lint` or `make fmt` can be easier than running `hlint` or `fourmolu` directly. 142 | 143 | ### GHC/hlint is telling me to add/remove a language extension. Is that safe? 144 | 145 | Yes. Missing language extensions are usually compile-time errors, and will be caught in CI. Unused extensions are caught by hlint, and can be safely removed. 146 | If, for any reason, GHC tells you add an extension, and hlint tells you to remove the extension you just added, keep it there and ignore hlint. You should also file 147 | an issue in this repository for that scenario, since we may be able to fix that. 148 | 149 | [fourmolu]: https://github.com/fourmolu/fourmolu 150 | [ghcup]: https://www.haskell.org/ghcup 151 | [hackage]: https://hackage.haskell.org/ 152 | [hlint]: https://github.com/ndmitchell/hlint 153 | [hls]: https://github.com/haskell/haskell-language-server 154 | [hoogle]: https://hoogle.haskell.org/ 155 | -------------------------------------------------------------------------------- /docs/contributing/README.md: -------------------------------------------------------------------------------- 1 | # Development Docs 2 | 3 | This is a collection of development-related docs for working on the spectrometer repo. 4 | 5 | ## Building and Running the project 6 | 7 | The [HACKING](HACKING.md) doc describes our current dev tools and build practices, as well 8 | as providing som info about our CI setup. 9 | 10 | ## Style Guide 11 | 12 | Our [Style Guide](STYLE-GUIDE.md) las out stylistic and idiomatic standards for all contributions. 13 | We are in the process of fully aligning to that guide, but any new contributions should follow the style guide. 14 | 15 | ## Parsing and best practices 16 | 17 | Parsing in haskell requires a lot less boilerplate than may other languages, but comes with some caveats. 18 | The [best practices guide](parsing-best-practices.md) illustrates some important information about how to write 19 | parsers correctly, and links to a few tutorials. 20 | 21 | ## Record/Replay 22 | 23 | Because of magic (not really, [but...][3laws]), we are able to track what files we have read (and their contents), 24 | as well as the output of any commands executed during analysis. This is called [`replay logging`](replay-logging.md), 25 | and is a very useful debugging tool. 26 | 27 | [3laws]: https://en.wikipedia.org/wiki/Clarke%27s_three_laws 28 | 29 | ## Graph Hydration 30 | 31 | If a top-level component of a graph of dependencies is a test dependency, then its direct children are also test 32 | dependencies, as are their direct children, and so on. In some cases, the build tool/manifest files/lock files will 33 | tell us this information, but sometimes, we have to propogate these environments downwards ourselves. This is called 34 | [`graph hydration`](graph-hydration.md), and is handled by the `Graphing.Hydrate` module. 35 | 36 | ## Testing with effects 37 | 38 | -- 39 | -------------------------------------------------------------------------------- /docs/contributing/buildtools/yarnv2.org: -------------------------------------------------------------------------------- 1 | 2 | * Overview 3 | Yarn is a buildtool primarily used for building and managing javascript projects. It's functionally a superset of the =npm= cli. 4 | 5 | Yarn uses the same package manifest file as =npm= -- =package.json= -- but uses a novel lockfile format to pin dependencies, saved as =yarn.lock=. 6 | 7 | For dependency analysis, we focus exclusively on the lockfile. 8 | 9 | * Lockfile (=yarn.lock=) 10 | As part of the update from Yarn v1 to Yarn v2, some major changes were made to the lockfile. Most notably: 11 | 12 | + The lockfile [[https://dev.to/arcanis/introducing-yarn-2-4eh1#new-lockfile-format][is now real yaml]]. Yarn v1 used an almost-but-not-quite pseudo-yaml format. 13 | + While Yarn v1's lockfile contained information only about dependencies of user projects, Yarn v2's lockfile is much more information-rich. It contains information about first-party user projects ("workspaces"), the version ranges specified in =package.json= for dependencies ("descriptors"), and the resolved version for each dependency ("locators") 14 | 15 | ** Concepts 16 | *** Workspaces 17 | Workspaces are first-party package directories (directories that contain =package.json=). Workspaces are always available locally on disk, and are specified by a relative reference to a directory (e.g., =.= or =./foo/bar= or =../baz=) 18 | 19 | A yarn project can have several workspaces, where workspaces may (but *are not required to*) depend on each other in a DAG. This is similar to "multi-module projects" in other buildtools like maven or gomodules. 20 | 21 | Every yarn project will contain at least one workspace. 22 | 23 | See: [[https://yarnpkg.com/features/workspaces]] 24 | 25 | *** Locators 26 | /Somewhat/ similar to fossa locators, a yarn locator is an unambiguous reference to a specific version of a package and where to find it. 27 | 28 | Locators have three components: 29 | + Package scope (optional) -- like =@babel= -- a scope on npm. 30 | + Package name -- like =underscore=. 31 | + Package reference -- which can vary in shape depending on where the package is coming from. For example, this could be a pointer to specific package version on the npm registry, a pointer to a git repo at a specific commit, or a link to a tarball. 32 | 33 | Package scope and name in a locator, for the purposes of dependency resolution, *are unused*. Only the package reference matters. 34 | 35 | Yarn supports a handful of reference types by default, and plugins can be added to support new reference types. See the =Resolvers= section below. 36 | 37 | See: https://yarnpkg.com/advanced/lexicon#locator 38 | 39 | *** Descriptors 40 | Descriptors are similar to locators, but may point to a /range/ of package versions. For the purposes of dependency analysis, we don't care much about the shape and content of descriptors. 41 | 42 | Descriptors have three components: 43 | + Package scope (optional) -- like =@babel= -- a scope on npm 44 | + Package name -- like =underscore= 45 | + Package range -- which can vary in shape depending on where the package is coming from. For example, this could be a semver for a package on the npm registry, a pointer to a git repo on a branch, or a link to a tarball 46 | 47 | All locators are valid descriptors; not all descriptors are valid locators. 48 | 49 | See: https://yarnpkg.com/advanced/lexicon#descriptor 50 | 51 | *** Resolvers 52 | Plugins are the yarn v2 mechanism used to add support for, among other things, new types of locators. 53 | 54 | A plugin can export zero or more "Resolvers", each of which can add support for new types of locator. Yarn itself implements support for "built-in" locator types (npm dependencies, git dependencies, etc) as resolvers in bundled plugins. 55 | 56 | For dependency analysis, we support locators produced by [[https://github.com/yarnpkg/berry/blob/8afcaa2a954e196d6cd997f8ba506f776df83b1f/packages/yarnpkg-cli/package.json#L68-L82][all of the built-in plugins]]. 57 | 58 | See: https://yarnpkg.com/advanced/lexicon#resolver 59 | ** Format 60 | #+BEGIN_SRC yaml 61 | # This file is generated by running "yarn install" inside your project. 62 | # Manual changes might be lost - proceed with caution! 63 | 64 | __metadata: 65 | version: 4 66 | cacheKey: 7 67 | 68 | "bar@workspace:bar": 69 | version: 0.0.0-use.local 70 | resolution: "bar@workspace:bar" 71 | dependencies: 72 | underscore: 1.13.1 73 | languageName: unknown 74 | linkType: soft 75 | 76 | "foo@workspace:foo": 77 | version: 0.0.0-use.local 78 | resolution: "foo@workspace:foo" 79 | dependencies: 80 | underscore: ^1.13.0 81 | languageName: unknown 82 | linkType: soft 83 | 84 | "quux@workspace:quux": 85 | version: 0.0.0-use.local 86 | resolution: "quux@workspace:quux" 87 | dependencies: 88 | underscore: "jashkenas/underscore#tag=1.13.1" 89 | languageName: unknown 90 | linkType: soft 91 | 92 | "toplevel@workspace:.": 93 | version: 0.0.0-use.local 94 | resolution: "toplevel@workspace:." 95 | languageName: unknown 96 | linkType: soft 97 | 98 | "underscore@jashkenas/underscore#tag=1.13.1": 99 | version: 1.13.1 100 | resolution: "underscore@https://github.com/jashkenas/underscore.git#commit=cbb48b79fc1205aa04feb03dbc055cdd28a12652" 101 | checksum: 560609fdb4ba2c30e79db95ea37269982d1a2788d49b78f0de4f391da711bc2495d5fbddd6d24e7716fccf69959e445916af83eb5de1ad137b215777e2d32e4d 102 | languageName: node 103 | linkType: hard 104 | 105 | "underscore@npm:1.13.1, underscore@npm:^1.13.0": 106 | version: 1.13.1 107 | resolution: "underscore@npm:1.13.1" 108 | checksum: 19527b2db3d34f783c3f2db9716a2c1221fef2958866925545697c46f430f59d1b384b8105cc7e7c809bdf0dc9075f2bfff90b8fb270b9d3a6c58347de2dd79d 109 | languageName: node 110 | linkType: hard 111 | 112 | #+END_SRC 113 | 114 | Ignoring the =__metadata= field, the yarn lockfile is a mapping from =a comma-separated list of descriptors= to a =package description=. 115 | 116 | *** Package description fields 117 | 118 | Of a package's fields, we only care about =resolution= and =dependencies= 119 | 120 | **** =resolution= 121 | The locator used for this package 122 | 123 | **** =dependencies= 124 | An optional field containing =package: descriptor-range= mappings for each dependency of the package. *This includes dev dependencies* if they were included when running =yarn install=. 125 | 126 | This field is copied functionally identically from a package's =dependencies= and =devDependencies= fields in =package.json=. The code that parses a =Package description= [[https://github.com/yarnpkg/berry/blob/0d9834036d6a3747d6c0dbb5c11e27568f7194dc/packages/yarnpkg-core/sources/Project.ts#L284][is the same code]] that parses dependencies in a =package.json= file 127 | 128 | Full dependency descriptors [[https://github.com/yarnpkg/berry/blob/0d9834036d6a3747d6c0dbb5c11e27568f7194dc/packages/yarnpkg-core/sources/Manifest.ts#L307-L326][can be reconstructed]] by joining key-value pairs on =@=: =underscore: ^1.13.0= is =underscore@^1.13.0=. Each dependency's descriptor is a key for a package at the top level of the yarn lockfile 129 | 130 | #+BEGIN_QUOTE 131 | *NOTE*: a fun note about dependency descriptors 132 | 133 | A keen eye may notice that in the lockfile above, some descriptor keys contain =npm:= at the top-level. For example, there's =underscore@npm:1.13.1= -- but that descriptor isn't used anywhere as a dependency. The closest is =underscore@1.13.1=, a dependency of the =bar= workspace. 134 | 135 | In an interesting design decision, yarn makes the default resolver for packages configurable. When a user provides a raw version (e.g., =1.13.1=) or semver (=^1.13.1=) for a dependency in =package.json=, a "default protocol" string is prepended to the descriptor range. This option [[https://next.yarnpkg.com/configuration/yarnrc#defaultProtocol][is configured]] as =defaultProtocol=, which defaults to =npm:=. 136 | 137 | As a workaround, when using a descriptor =name@range= to look up a package in the lockfile, we must also try =name@npm:range= 138 | #+END_QUOTE 139 | 140 | *** Lockfile sources 141 | The above lockfile was generated from the following files 142 | 143 | =package.json= 144 | #+BEGIN_SRC json 145 | { 146 | "name": "toplevel", 147 | "private": true, 148 | "workspaces": [ 149 | "foo", 150 | "bar", 151 | "quux" 152 | ] 153 | } 154 | #+END_SRC 155 | 156 | =foo/package.json= 157 | #+BEGIN_SRC json 158 | { 159 | "name": "foo", 160 | "version": "1.0.0", 161 | "dependencies": { 162 | "underscore": "^1.13.0" 163 | } 164 | } 165 | #+END_SRC 166 | 167 | =bar/package.json= 168 | #+BEGIN_SRC json 169 | { 170 | "name": "bar", 171 | "version": "1.0.0", 172 | "dependencies": { 173 | "underscore": "1.13.1" 174 | } 175 | } 176 | #+END_SRC 177 | 178 | =quux/package.json= 179 | 180 | Note that =name/repo= is implicitly treated as a github repo reference 181 | #+BEGIN_SRC json 182 | { 183 | "name": "quux", 184 | "version": "1.0.0", 185 | "dependencies": { 186 | "underscore": "jashkenas/underscore#tag=1.13.1" 187 | } 188 | } 189 | #+END_SRC 190 | -------------------------------------------------------------------------------- /docs/contributing/graph-hydration.md: -------------------------------------------------------------------------------- 1 | # Graph Hydration 2 | 3 | To explain this feature, assume that red dependencies are Production, blue dependencies are Development, 4 | and yellow dependencies are Test. 5 | 6 | Here's our starting point after building a graph. 7 | 8 | ![Before Hydration](graph-hydration/hydrate-before.svg) 9 | 10 | When building the graph, we couldn't know that `ProdChild` should have been red. We only 11 | knew for sure that `TopProd` should be red. The same principle applies to `TopDev` being 12 | blue, and `TopIsolated` being yellow. 13 | 14 | In this graph, `MutualChild` and `MutualGrandChild` are connected (either directly or 15 | transitively) to both red and blue, so we want them to become both red and blue (we'll 16 | use purple to represent that). 17 | 18 | If we *hydrate* the graph, we can let all of the associated data (color) flow through the edges 19 | in the graph, recursively (we don't actually use recursion, because there may be cycles). 20 | 21 | Here's what the graph looks like after hydration: 22 | 23 | ![After Hydration](graph-hydration/hydrate-after.svg) 24 | 25 | There are 4 things to note: 26 | 27 | - In our case, we combine colors, though we could choose to just take the first color or latest 28 | color for any node. That's left to the user (read: author of the instance of the typeclass) to decide. 29 | - In the main graph, with `TopDev` and `TopProd`, the results are predictable. Red and blue 30 | both flow downwards, creating purple when they join. 31 | - In the yellow isolated graph, we have no trace of blue or red anywhere, meaning that graph hydration 32 | allows for isolation of subgraphs. 33 | - In the cyclic graph, we ended up with all nodes being the same color. This is again due to combining 34 | the colors, but if we defined the behvior to overwrite existing colors (or to reject all colors after 35 | the first), we could end up with VERY different graphs. 36 | 37 | Graph hydration is handled through the `Hydrateable` typeclass, in the `Graphing.Hydrate` module. 38 | The tests, which can be found in `test/Graphing/HydrateSpec.hs`, should closely resemble these images. 39 | -------------------------------------------------------------------------------- /docs/contributing/graph-hydration/hydrate-after.gv: -------------------------------------------------------------------------------- 1 | digraph G { 2 | style="filled" 3 | 4 | TopProd -> ProdChild -> MutualGrandChild; 5 | TopDev -> DevChild -> MutualGrandChild; 6 | TopProd -> MutualChild; 7 | TopDev -> MutualChild; 8 | TopIsolated -> IsolatedChild; 9 | 10 | CycleRed -> CycleBlue -> CycleRed; 11 | 12 | TopProd [style = filled, fillcolor = red] 13 | TopDev [style = filled, fillcolor = blue] 14 | TopIsolated [style = filled, fillcolor = yellow] 15 | ProdChild [style = filled, fillcolor = red] 16 | DevChild [style = filled, fillcolor = blue] 17 | MutualChild [style = filled, fillcolor = purple] 18 | MutualGrandChild [style = filled, fillcolor = purple] 19 | IsolatedChild [style = filled, fillcolor = yellow] 20 | CycleRed [style = filled, fillcolor = purple] 21 | CycleBlue [style = filled, fillcolor = purple] 22 | } -------------------------------------------------------------------------------- /docs/contributing/graph-hydration/hydrate-after.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | G 11 | 12 | 13 | 14 | TopProd 15 | 16 | TopProd 17 | 18 | 19 | 20 | ProdChild 21 | 22 | ProdChild 23 | 24 | 25 | 26 | TopProd->ProdChild 27 | 28 | 29 | 30 | 31 | 32 | MutualChild 33 | 34 | MutualChild 35 | 36 | 37 | 38 | TopProd->MutualChild 39 | 40 | 41 | 42 | 43 | 44 | MutualGrandChild 45 | 46 | MutualGrandChild 47 | 48 | 49 | 50 | ProdChild->MutualGrandChild 51 | 52 | 53 | 54 | 55 | 56 | TopDev 57 | 58 | TopDev 59 | 60 | 61 | 62 | DevChild 63 | 64 | DevChild 65 | 66 | 67 | 68 | TopDev->DevChild 69 | 70 | 71 | 72 | 73 | 74 | TopDev->MutualChild 75 | 76 | 77 | 78 | 79 | 80 | DevChild->MutualGrandChild 81 | 82 | 83 | 84 | 85 | 86 | TopIsolated 87 | 88 | TopIsolated 89 | 90 | 91 | 92 | IsolatedChild 93 | 94 | IsolatedChild 95 | 96 | 97 | 98 | TopIsolated->IsolatedChild 99 | 100 | 101 | 102 | 103 | 104 | CycleRed 105 | 106 | CycleRed 107 | 108 | 109 | 110 | CycleBlue 111 | 112 | CycleBlue 113 | 114 | 115 | 116 | CycleRed->CycleBlue 117 | 118 | 119 | 120 | 121 | 122 | CycleBlue->CycleRed 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /docs/contributing/graph-hydration/hydrate-before.gv: -------------------------------------------------------------------------------- 1 | digraph G { 2 | TopProd -> ProdChild -> MutualGrandChild; 3 | TopDev -> DevChild -> MutualGrandChild; 4 | TopProd -> MutualChild; 5 | TopDev -> MutualChild; 6 | TopIsolated -> IsolatedChild; 7 | 8 | CycleRed -> CycleBlue -> CycleRed; 9 | 10 | TopProd [style = filled, fillcolor = red] 11 | TopDev [style = filled, fillcolor = blue] 12 | TopIsolated [style = filled, fillcolor = yellow] 13 | CycleRed [style = filled, fillcolor = red] 14 | CycleBlue [style = filled, fillcolor = blue] 15 | } -------------------------------------------------------------------------------- /docs/contributing/graph-hydration/hydrate-before.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | G 11 | 12 | 13 | 14 | TopProd 15 | 16 | TopProd 17 | 18 | 19 | 20 | ProdChild 21 | 22 | ProdChild 23 | 24 | 25 | 26 | TopProd->ProdChild 27 | 28 | 29 | 30 | 31 | 32 | MutualChild 33 | 34 | MutualChild 35 | 36 | 37 | 38 | TopProd->MutualChild 39 | 40 | 41 | 42 | 43 | 44 | MutualGrandChild 45 | 46 | MutualGrandChild 47 | 48 | 49 | 50 | ProdChild->MutualGrandChild 51 | 52 | 53 | 54 | 55 | 56 | TopDev 57 | 58 | TopDev 59 | 60 | 61 | 62 | DevChild 63 | 64 | DevChild 65 | 66 | 67 | 68 | TopDev->DevChild 69 | 70 | 71 | 72 | 73 | 74 | TopDev->MutualChild 75 | 76 | 77 | 78 | 79 | 80 | DevChild->MutualGrandChild 81 | 82 | 83 | 84 | 85 | 86 | TopIsolated 87 | 88 | TopIsolated 89 | 90 | 91 | 92 | IsolatedChild 93 | 94 | IsolatedChild 95 | 96 | 97 | 98 | TopIsolated->IsolatedChild 99 | 100 | 101 | 102 | 103 | 104 | CycleRed 105 | 106 | CycleRed 107 | 108 | 109 | 110 | CycleBlue 111 | 112 | CycleBlue 113 | 114 | 115 | 116 | CycleRed->CycleBlue 117 | 118 | 119 | 120 | 121 | 122 | CycleBlue->CycleRed 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /docs/contributing/parsing-best-practices.md: -------------------------------------------------------------------------------- 1 | # Writing good parsers 2 | 3 | [Back to development doc homepage](README.md) 4 | 5 | We use `megaparsec` for text parsing. There are [several][tut1] [good][tut2] [tutorials][tut3] out there, and those are just the top 3 6 | [google results](https://www.google.com/search?q=megaparsec+tutorial). *Note: FOSSA employees can also talk to the analysis team directly, we can walk you through this.* 7 | 8 | [tut1]: https://markkarpov.com/tutorial/megaparsec.html 9 | [tut2]: https://mmhaskell.com/parsing/megaparsec 10 | [tut3]: https://github.com/mrkkrp/megaparsec-site/blob/master/tutorials/parsing-simple-imperative-language.md 11 | 12 | Some of this advice is directly given in the first tutorial, and is repeated here for emphasis. PLEASE READ THE TUTORIALS. 13 | 14 | ## Define a `Parser` type alias 15 | 16 | Usually, you should add `type Parser = Parsec Void Text` to your parsing module, so that your parser functions can be of type `Parser a`, rather than 17 | the long-form `Parsec` version, or worse, the fully-verbose `ParsecT` version. 18 | 19 | ## Use `sc`, `scn`, `symbol`, and `lexeme` 20 | 21 | When writing a non-trivial text parser, you should create the following helper functions: 22 | 23 | - `sc`/`scn` - Space Consumer (or Space Consumer with Newlines) 24 | - Use [`Lexer.space`](https://hackage.haskell.org/package/megaparsec-9.1.0/docs/Text-Megaparsec-Char-Lexer.html#v:space) to create your whitespace consumer. 25 | - READ THE DOCS FOR THAT FUNCTION IF YOU HAVEN'T YET! There's a lot of useful info there, and you'll need to know it. 26 | - You don't always need to create both `sc` and `scn`, but you'll almost always need at least one. 27 | - `symbol` - Parser for verbatim text strings. 28 | - Use [`Lexer.symbol`](https://hackage.haskell.org/package/megaparsec-9.1.0/docs/Text-Megaparsec-Char-Lexer.html#v:symbol) to create this helper. 29 | - Use your `sc` or `scn` function for the whitespace consumer. 30 | - You can use `Lexer.symbol'` if your text is case-insensitive. 31 | - `lexeme` - Parser for any basic unit of the language. While `symbol` is for verbatim text parsing, `lexeme` is used with any parser that should consume space 32 | after finishing. For example, `Lexer.symbol` is implemented via `Lexer.lexeme`. 33 | - Use [`Lexer.lexeme`](https://hackage.haskell.org/package/megaparsec-9.1.0/docs/Text-Megaparsec-Char-Lexer.html#v:lexeme) to define this helper. 34 | - Use your `sc` or `scn` function for the whitespace consumer. 35 | 36 | ### Don't directly consume whitespace 37 | 38 | Don't use space parsers directly, since space is usually consumed by the helpers listed above. 39 | You can do this if absolutely necessary, but it is not likely to be necessary in the first place. 40 | 41 | Instead, `lexeme` and `symbol` will consume all whitespace after their parser automatically. 42 | 43 | There are some known exceptions, like HTTP messages, which require exactly two consecutive newlines to 44 | separate the header section from the body. Parsing arbitrary amounts of whitespace would be incorrect 45 | for an HTTP message parser. In this case, you should directly parse the newlines. 46 | 47 | ## Always Consume SOMETHING 48 | 49 | Every parser must consume something, or fail. Successfully parsing after consuming no input commonly leads to 50 | infinite parsing loops. Using `pure` in an applicative parser is a sign that you may be consuming nothing, but 51 | indicating success. 52 | 53 | ## Terminate parsers with `eof` 54 | 55 | Usually, you're writing a parser which must consume an entire file. In this case, you should terminate the top-level parser with 56 | `eof`, which forces a parser to reach the end of input while successfully parsing along the way. 57 | -------------------------------------------------------------------------------- /docs/contributing/replay-logging.md: -------------------------------------------------------------------------------- 1 | # Replay Logging 2 | 3 | [Back to development doc homepage](README.md) 4 | 5 | Replay Logging is a feature of `fossa analyze` that can aid in reproducing/resolving analysis issues. 6 | 7 | It leverages some unique properties of haskell that allow us to "record" an end-to-end analysis execution in a customer's environment, and "replay" the analysis in our local development environment, with all of the tools normally available to us as developers (allowing us to print-debug, make other code changes, etc). 8 | 9 | ## Recording 10 | 11 | The `--debug` flag is used to run `fossa analyze` in record mode. The analysis will run normally (if a bit slower), and create a file called `fossa.debug.json`. 12 | 13 | In addition to some basic metadata, `fossa.debug.json` contains the arguments and results of each method invocation from our `ReadFS` and `Exec` effects within the `journals` key: 14 | 15 | ```json 16 | { 17 | "system": {...}, 18 | "workdir": "/foo", 19 | "args": ["analyze", "--record"], 20 | "journals": { 21 | "ReadFS": [...] 22 | "Exec": [...] 23 | } 24 | } 25 | ``` 26 | 27 | ## Replaying 28 | 29 | **Replay mode is temporarily unavailable.** 30 | 31 | The `--replay ` flag is used to run `fossa analyze` in replay mode. Rather than reading from real files with our `ReadFS` effect or running real commands with our `Exec` effect, we stub in the recorded effect calls from `fossa.debug.json`. 32 | 33 | For replay mode to work, we need to "run analysis" in the same directory (or a subdirectory) of the one used when recording `fossa.debug.json`. In the example above, this directory is `/foo`: `fossa analyze --replay fossa.debug.json /foo`. It's recommended to also use the same CLI commit and arguments (minus `--record`, of course). 34 | 35 | Replay mode has some substantial benefits over normal debug logs: 36 | 37 | - We can reproduce analysis issues as they occurred in a customer's environment, without the files and buildtools necessary for analysis. 38 | - We can make code changes and see how they'd affect the analysis. 39 | - For certain classes of issues, we can make code changes to resolve them, and confidently deliver bug fixes as a result. 40 | 41 | There are some caveats: 42 | 43 | - Any code changes that would require reading new files or running new/modified commands will not work under replay mode. 44 | - `--unpack-archives` doesn't work with replay logging. 45 | -------------------------------------------------------------------------------- /docs/contributing/writing-docs.md: -------------------------------------------------------------------------------- 1 | `references/strategies/$FOO` folders should correspond 1:1 to a literal analyzer 2 | 3 | the index of the folder should be `README.md` 4 | 5 | one-doc folders are okay 6 | -------------------------------------------------------------------------------- /docs/features/manual-dependencies.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Manually specifying dependencies 4 | 5 | FOSSA offers a way to manually upload dependencies provided we support the dependency type. Manually specifying dependencies is very helpful in the event your package manager is unsupported or you are using a custom and nonstandard dependency management solution. 6 | 7 | The FOSSA CLI will automatically read a `fossa-deps.yml` or a `fossa-deps.json` file in the root directory (usually the current working directory) when `fossa analyze` is run and parse dependencies from it. These dependencies will be added to the dependencies that are normally found when `fossa analyze` is run in the directory. 8 | 9 | > Tip: Use a script to generate this file before running `fossa analyze` to keep your results updated. 10 | 11 | To manually specify a dependency, you must provide the package type, package name, and optionally a package version, under the `referenced-dependencies` array, as shown here: 12 | 13 | ```yaml 14 | referenced-dependencies: 15 | - type: gem 16 | name: iron 17 | - type: pypi 18 | name: Django 19 | version: 2.1.7 20 | ``` 21 | 22 | The `name` and `type` fields are required and specify the name of the dependency and where to find it. The `version` field is optional and specifies the preferred version of dependency. 23 | 24 | Supported dependency types: 25 | 26 | - `bower` - Bower dependencies that are typically found at found at [bower.io](https://registry.bower.io). 27 | 28 | - `cargo` - Rust dependencies that are typically found at [crates.io](https://crates.io/). 29 | - `carthage` - Dependencies as specified by the [Carthage](https://github.com/Carthage/Carthage) package manager. 30 | - `composer` - Dependencies specified by the PHP package manager [Composer](https://getcomposer.org/), which are located on [Packagist](https://packagist.org/). 31 | - `cpan` - Dependencies located on the [CPAN package manager](https://www.cpan.org/). 32 | - `gem` - Dependencies which can be found at [RubyGems.org](https://rubygems.org/). 33 | - `git` - Github projects (which appear as dependencies in many package managers). Specified as the full github repository `https://github.com/fossas/spectrometer`. 34 | - `go` - Golang specific dependency. Many golang dependencies are located on Github, but there are some which look like the following `go.mongodb.org/mongo-driver` that have custom golang URLs. 35 | - `hackage` - Haskell dependencies found at [Hackage](https://hackage.haskell.org/). 36 | - `hex` - Erlang and Elixir dependencies that are found at [Hex.pm](https://hex.pm/). 37 | - `maven` - Maven dependencies that can be found at many different sources. Specified as `name: javax.xml.bind:jaxb-api` where the convention is `groupId:artifactId`. 38 | - `npm` - Javascript dependencies found at [npmjs.com](https://www.npmjs.com/). 39 | - `nuget` - .NET dependencies found at [NuGet.org](https://www.nuget.org/). 40 | - `paket` - .NET dependencies found at [fsprojects.github.io/Paket/](https://fsprojects.github.io/Paket/). 41 | - `pub` - Dart dependencies found at [pub.dev](https://www.pub.dev/). 42 | - `pypi` - Python dependencies that are typically found at [Pypi.org](https://pypi.org/). 43 | - `cocoapods` - Swift and Objective-C dependencies found at [Cocoapods.org](https://cocoapods.org/). 44 | - `url` - The URL type allows you to specify only the download location of an archive (e.g.: `.zip`, .`tar.gz`, etc.) in the `name` field and the FOSSA backend will attempt to download and scan it. Example for a github source dependency `https://github.com/fossas/spectrometer/archive/refs/tags/v2.7.2.tar.gz`. The `version` field will be silently ignored for `url` type dependencies. 45 | 46 | ### Custom dependencies 47 | 48 | FOSSA supports users that have dependencies that can't be automatically discovered or identified, by offering the ability to define new dependencies. 49 | 50 | To do this, you must supply the name, version, and license of the dependency. This creates a stub package which requires no source code or linkage to any other system, but still acts as a normal dependency in other areas of FOSSA, like reports and the dependency views. 51 | You may also supply a description and/or url, but both are optional. Note that these fields reference the dependency itself, and do not reference the parent project (the one at the current analysis directory), or the individual versions of the dependency. 52 | 53 | ```yaml 54 | custom-dependencies: 55 | # Custom dependencies need name, version, and license 56 | - name: foo 57 | version: 1.2.3 58 | license: "MIT or Apache-2.0" 59 | # You can also provide a description and/or homepage. These values populate metadata fields in reports in the FOSSA web UI. 60 | - name: foo-wrapper 61 | version: 1.2.3 62 | license: MIT 63 | metadata: 64 | homepage: https://www.foowrapper.com/about 65 | description: Provides foo and a helpful interface around foo-like tasks. 66 | ``` 67 | 68 | ### Remote dependencies 69 | 70 | FOSSA also supports dependencies that can't be automatically discovered or identified, but where the user has a URL where FOSSA can download the source code of the dependency. 71 | 72 | To specify a remote dependency, you must provide the name, version, and download URL of the dependency. The FOSSA backend will attempt to download and scan any source code contained in an archive hosted at this URL. 73 | 74 | For example, for a dependency released on a GitHub release, your URL might look like: `https://github.com/fossas/spectrometer/archive/refs/tags/v2.7.2.tar.gz`. 75 | 76 | You can also optionally add metadata fields ("description" and "homepage") to populate these fields in the FOSSA web UI (these fields can be displayed when generating reports). 77 | 78 | ```yaml 79 | remote-dependencies: 80 | # Remote dependencies need name, version, and url 81 | - name: foo 82 | version: 1.2.3 83 | url: https://www.fooarchive.tar.gz 84 | # You can also provide a description and/or homepage. These values populate metadata fields in reports in the FOSSA web UI. 85 | - name: foo-wrapper 86 | version: 1.2.3 87 | url: https://www.foowrapper.tar.gz 88 | metadata: 89 | description: Provides foo and a helpful interface around foo-like tasks. 90 | homepage: https://www.foowrapper-home.com 91 | ``` 92 | -------------------------------------------------------------------------------- /docs/features/vendored-dependencies.md: -------------------------------------------------------------------------------- 1 | ### License scanning local dependencies 2 | 3 | Fossa offers the ability to license scan your code directly. This is used primarily if a package manager is not yet supported or if you are vendoring dependencies. Using the license scanning feature will allow you to capture the licenses for dependencies that may otherwise be missed from normal fossa analysis that relies on package manager information. 4 | 5 | In order to specify a file path, modify your `fossa-deps.yml` file and add a `vendored-dependencies` section like the following: 6 | 7 | ```yml 8 | # Example full `fossa.deps.yml` file. 9 | referenced-dependencies: 10 | - type: gem 11 | name: rubyXL 12 | version: 3.4.16 13 | 14 | vendored-dependencies: 15 | - name: Django 16 | path: vendor/Django-3.4.16.zip # path can be either a file or a folder. 17 | version: 3.4.16 # revision will be set to the MD5 hash of the filepath if left unspecified. 18 | ``` 19 | 20 | > Note: License scanning currently operates by uploading the files at the specified path to a secure S3 bucket. All files that do not contain licenses are then removed after 2 weeks. 21 | 22 | We also support json-formatted dependencies: 23 | 24 | ```json 25 | { 26 | "referenced-dependencies": [ 27 | { 28 | "type": "gem", 29 | "name": "iron" 30 | }, { 31 | "type": "pypi", 32 | "name": "Django", 33 | "version": "2.1.7" 34 | } 35 | ], 36 | "custom-dependencies": [ 37 | { 38 | "name": "foo", 39 | "version": "1.2.3", 40 | "license": "MIT" 41 | }, { 42 | "name": "foo-wrapper", 43 | "version": "1.0.2", 44 | "license": "MIT or Apache-2.0", 45 | "metadata": { 46 | "description": "Provides a help wrapper for foo-related tasks", 47 | "homepage": "https://foo-project.org/homepage" 48 | } 49 | } 50 | ], 51 | "vendored-dependencies": [ 52 | { 53 | "name": "lodash", 54 | "path": "lodash-4.17.21" 55 | }, { 56 | "name": "winston", 57 | "path": "vendor/winston.tar.gz", 58 | "version": "5.0.0-alpha" 59 | } 60 | ], 61 | "remote-dependencies": [ 62 | { 63 | "name": "foo-url", 64 | "version": "1.2.3", 65 | "url": "www.foo.tar.gz", 66 | "metadata": { 67 | "description": "foo archive", 68 | "homepage": "https://foo-url.org/homepage" 69 | } 70 | } 71 | ] 72 | } 73 | ``` 74 | -------------------------------------------------------------------------------- /docs/glossary.md: -------------------------------------------------------------------------------- 1 | # Table of Contents 2 | 3 | # Dependency topics 4 | 5 | - Direct 6 | - Transitive 7 | 8 | # Graph topics 9 | 10 | - Vertex 11 | - Node 12 | - Edge 13 | - Successor 14 | - Neighbor 15 | 16 | # FOSSA topics 17 | 18 | - Issue 19 | - Policy 20 | - Project 21 | - Scan 22 | - Dependency Scan 23 | - Prefer "Analysis" 24 | - Issue Scan 25 | - License Scan 26 | -------------------------------------------------------------------------------- /docs/references/files/fossa-deps.md: -------------------------------------------------------------------------------- 1 | # `fossa-deps` 2 | 3 | Fossa-deps file is a file named `fossa-deps.{yaml, yml, json}` at the root of the project. It can be used to provide manual and vendor dependencies. 4 | 5 | ## Fields 6 | 7 | ### `referenced-dependencies:` 8 | 9 | Denotes listing of dependencies, which are to be analyzed in conjunction with the analysis. 10 | 11 | - `type`: Type of dependency. (Required) 12 | - `name`: Name of the dependency. It should be the same name as listed in dependencies registry. (Required) 13 | - `version`: Revision of the dependency. If left unspecified, the latest version discovered from the registry will be used. 14 | 15 | ```yaml 16 | referenced-dependencies: 17 | - type: gem 18 | name: iron 19 | - type: pypi 20 | name: Django 21 | version: 2.1.7 22 | ``` 23 | 24 | For more details, please refer to the [feature](../../features/manual-dependencies.md) walk through. 25 | 26 | ### `custom-dependencies:` 27 | 28 | Denotes listing of dependencies, which can't be automatically discovered or identified but are to be stubbed and included in the analysis. 29 | 30 | - `name`: Name of the dependency. (Required) 31 | - `version`: Revision of the dependency. (Required) 32 | - `license`: Licence of the dependency. (Required) 33 | - `metadata.homepage`: Homepage of the dependency. This metadata is used to enrich reporting provided in FOSSA's web interface. 34 | - `metadata.description`: Description of the dependency. This metadata is used to enrich reporting provided in FOSSA's web interface. 35 | 36 | Example: 37 | ```yaml 38 | - name: foo-wrapper 39 | version: 1.2.3 40 | license: MIT 41 | metadata: 42 | homepage: https://www.foowrapper.com/about 43 | description: Provides foo and a helpful interface around foo-like tasks. 44 | ``` 45 | 46 | For more details, please refer to the [feature](../../features/manual-dependencies.md) walk through. 47 | 48 | ### `remote-dependencies:` 49 | 50 | Denotes listing of dependencies, whose source code is to be downloaded from provided URL, and analyzed for license scanning in FOSSA backend. 51 | 52 | - `name`: Name of the dependency. (Required) 53 | - `version`: Revision of the dependency. (Required) 54 | - `url`: URL of archived source code. (Required) 55 | - `metadata.homepage`: Homepage of the dependency. This metadata is used to enrich reporting provided in FOSSA's web interface. 56 | - `metadata.description`: Description of the dependency. This metadata is used to enrich reporting provided in FOSSA's web interface. 57 | 58 | For more details, please refer to the [feature](../../features/manual-dependencies.md) walk through. 59 | 60 | ### `vendored-dependencies:` 61 | 62 | Denotes listing of files or directories, which are to be archived and uploaded to FOSSA backend for license scanning. 63 | 64 | - `name`: Name of the dependency (Required) 65 | - `path`: Local path to a file, or a directory (Required) 66 | - `version`: Revision of the dependency. If not specified, the md5 hash of the file path will be used. 67 | 68 | ```yaml 69 | vendored-dependencies: 70 | - name: Django 71 | path: vendor/Django-3.4.16.zip 72 | version: 3.4.16 73 | ``` 74 | > Note: License scanning currently operates by uploading the files at the specified path to a secure S3 bucket. All files that do not contain licenses are then removed after 2 weeks. 75 | 76 | For more details, please refer to the [feature](../../features/vendored-dependencies.md) walk through. 77 | 78 | ## Errors in the `fossa-deps` file 79 | 80 | The `fossa-deps` scanner tries to report clear error messages when fields are missing, incorrect, or invalid. For example: 81 | 82 | ```yaml 83 | referenced-dependencies: 84 | - type: pypi 85 | name: flask 86 | version: "2.0.1" 87 | license: MIT # Error! "license" is only allowed for custom-dependencies 88 | 89 | custom-dependencies: 90 | - type: custom # Error! "type" is only allowed for referenced-dependencies 91 | name: mydep 92 | version: "3.14.15" 93 | license: GPL-3.0 94 | 95 | remote-dependencies: 96 | - name: mydep 97 | version: "3.14.15" 98 | license: GPL-3.0 # Error! "license" is only allowed for custom-dependencies 99 | ``` 100 | 101 | This would return an error with a message explaining what went wrong, and where. However, we don't check for everything (yet!): 102 | 103 | ```yaml 104 | referenced-dependencies: 105 | - type: cargo 106 | name: bitflags 107 | some-unexpected-field: hello # Has no effect, will be considered an error in future versions. 108 | ``` 109 | 110 | The `fossa-deps` scanner also requires at least one valid dependency if the file exists. This prevents the file from being created with the wrong array names and us silently ignoring them. 111 | 112 | If you see an error message that isn't clear, file an issue in this repository! Clear error messages are a priority for us, and we want to know where we're lacking. 113 | -------------------------------------------------------------------------------- /docs/references/files/fossa-deps.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "fossa-deps", 4 | "description": "fossa-deps for dependency specification for FOSSA CLI", 5 | "$defs": { 6 | "referenced-dependency": { 7 | "properties": { 8 | "name": { 9 | "type": "string", 10 | "minLength": 1, 11 | "description": "Name of the dependency. This name will be used to search for dependency in relevant registries." 12 | }, 13 | "type": { 14 | "enum": [ 15 | "cargo", 16 | "carthage", 17 | "composer", 18 | "cpan", 19 | "gem", 20 | "git", 21 | "go", 22 | "hackage", 23 | "hex", 24 | "maven", 25 | "npm", 26 | "nuget", 27 | "paket", 28 | "pub", 29 | "pypi", 30 | "cocoapods", 31 | "swift", 32 | "url" 33 | ], 34 | "description": "Type of the dependency. It informs FOSSA which relevant registries to search for dependency's distribution." 35 | }, 36 | "version": { 37 | "type": "string", 38 | "description": "Version of the dependency. It informs FOSSA which version of the dependency to scan. If not provided, latest version will be used." 39 | } 40 | }, 41 | "required": [ 42 | "name", 43 | "type" 44 | ], 45 | "additionalProperties": false 46 | }, 47 | "custom-dependency": { 48 | "properties": { 49 | "name": { 50 | "type": "string", 51 | "description": "Name of the dependency. This will be the name used in FOSSA's dashboard.", 52 | "minLength": 1 53 | }, 54 | "version": { 55 | "type": "string", 56 | "description": "Version of the dependency. This will be the version used in FOSSA's dashboard.", 57 | "minLength": 1 58 | }, 59 | "licence": { 60 | "type": "string", 61 | "description": "Licence of the dependency. This string will be used to infer licence type.", 62 | "minLength": 1 63 | }, 64 | "metadata": { 65 | "type": "object", 66 | "properties": { 67 | "description": { 68 | "type": "string", 69 | "description": "Description of the dependency (if any)" 70 | }, 71 | "homepage": { 72 | "type": "string", 73 | "description": "Homepage of the dependency. This should be web address." 74 | } 75 | } 76 | } 77 | }, 78 | "required": [ 79 | "name", 80 | "version", 81 | "licence" 82 | ], 83 | "additionalProperties": false 84 | }, 85 | "vendored-dependency": { 86 | "properties": { 87 | "name": { 88 | "type": "string", 89 | "description": "Name of the dependency. This will be the name associated with this vendored dependency in FOSSA's dashboard", 90 | "minLength": 1 91 | }, 92 | "path": { 93 | "type": "string", 94 | "description": "Path to directory, which will be archived and upload to provided endpoint for licence scanning.", 95 | "minLength": 1 96 | }, 97 | "version": { 98 | "type": "string", 99 | "description": "Version of the dependency. This will be the version associated with this vendored dependency in FOSSA's dashboard", 100 | } 101 | }, 102 | "required": [ 103 | "name", 104 | "path" 105 | ], 106 | "additionalProperties": false 107 | }, 108 | "remote-dependency": { 109 | "properties": { 110 | "name": { 111 | "type": "string", 112 | "description": "Name of the dependency. This will be the version used in FOSSA's dashboard.", 113 | "minLength": 1 114 | }, 115 | "url": { 116 | "type": "string", 117 | "description": "Url of the dependency's source code. This will be the downloaded by FOSSA for scanning with the analysis.", 118 | "minLength": 1 119 | }, 120 | "version": { 121 | "type": "string", 122 | "description": "Version of the dependency." 123 | }, 124 | "metadata": { 125 | "type": "object", 126 | "properties": { 127 | "description": { 128 | "type": "string", 129 | "description": "Description of the dependency (if any)" 130 | }, 131 | "homepage": { 132 | "type": "string", 133 | "description": "Homepage of the dependency. This should be web address." 134 | } 135 | } 136 | } 137 | }, 138 | "required": [ 139 | "name", 140 | "url", 141 | "version" 142 | ], 143 | "additionalProperties": false 144 | } 145 | }, 146 | "type": "object", 147 | "properties": { 148 | "version": { 149 | "type": "integer" 150 | }, 151 | "referenced-dependencies": { 152 | "type": "array", 153 | "description": "Reference dependency to locate from registry and include it project's dependency and licence scanning.", 154 | "items": { 155 | "$ref": "#/$defs/referenced-dependency" 156 | } 157 | }, 158 | "custom-dependencies": { 159 | "type": "array", 160 | "description": "Custom dependency and their licence for project", 161 | "items": { 162 | "$ref": "#/$defs/custom-dependency" 163 | } 164 | }, 165 | "vendored-dependencies": { 166 | "type": "array", 167 | "description": "Local dependencies upload to server for licence scanning", 168 | "items": { 169 | "$ref": "#/$defs/vendored-dependency" 170 | } 171 | }, 172 | "remote-dependencies": { 173 | "type": "array", 174 | "description": "Remote dependencies to licence scanning", 175 | "items": { 176 | "$ref": "#/$defs/remote-dependency" 177 | } 178 | } 179 | }, 180 | "required": [] 181 | } -------------------------------------------------------------------------------- /docs/references/strategies/README.md: -------------------------------------------------------------------------------- 1 | # Strategies 2 | 3 | 17 | 18 | ## Supported Languages 19 | 20 | ### clojure 21 | 22 | - [leiningen](languages/clojure/leiningen.md) 23 | 24 | ### dart 25 | 26 | - [pub](languages/dart/pub.md) 27 | 28 | ### erlang 29 | 30 | - [rebar3](languages/erlang/erlang.md) 31 | 32 | ### elixir 33 | 34 | - [mix](languages/elixir/mix.md) 35 | 36 | ### fortran 37 | 38 | - [fortran](languages/fortran/fortran.md) 39 | 40 | ### golang 41 | 42 | - [gomodules (`go mod`)](languages/golang/gomodules.md) 43 | - [dep](languages/golang/godep.md) 44 | - [glide](languages/golang/glide.md) 45 | 46 | ### haskell 47 | 48 | - [cabal](languages/haskell/cabal.md) 49 | - [stack](languages/haskell/stack.md) 50 | 51 | ### java 52 | 53 | - [maven](languages/maven/maven.md) 54 | - [gradle](languages/gradle/gradle.md) 55 | 56 | ### javascript/typescript 57 | 58 | - [yarn](languages/nodejs/yarn.md) 59 | - [npm](languages/nodejs/npm.md) 60 | 61 | ### .NET 62 | 63 | - [NuGet](languages/dotnet/nuget.md) 64 | - [Paket](languages/dotnet/paket.md) 65 | 66 | ### objective-c 67 | 68 | - [carthage](platforms/ios/carthage.md) 69 | - [cocoapods](platforms/ios/cocoapods.md) 70 | 71 | ### perl 72 | 73 | - [perl](languages/perl/perl.md) 74 | 75 | ### php 76 | 77 | - [php](languages/php/composer.md) 78 | 79 | ### python 80 | 81 | - [conda](platforms/conda/conda.md) 82 | - [`requirements.txt`/`setup.py`](languages/python/python.md) 83 | - [pipenv](languages/python/pipenv.md) 84 | 85 | ### ruby 86 | 87 | - [bundler](languages/ruby/bundler.md) 88 | 89 | ### rust 90 | 91 | - [cargo](languages/rust/cargo.md) 92 | 93 | ### scala 94 | 95 | - [sbt](languages/scala/sbt.md) 96 | - [gradle](languages/gradle/gradle.md) 97 | - [maven](languages/maven/maven.md) 98 | 99 | ### swift 100 | 101 | - [carthage](platforms/ios/carthage.md) 102 | - [cocoapods](platforms/ios/cocoapods.md) 103 | - [swiftPM](platforms/ios/swift.md) 104 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/clojure/clojure.md: -------------------------------------------------------------------------------- 1 | # Clojure Analysis 2 | 3 | When developing in Clojure, [leiningen](https://leiningen.org/) is the most common package manager. Dependencies are specified in a manifest file by users which is used by the `lein` tool to build a dependency graph and download the correct dependencies. 4 | 5 | 6 | | Strategy | Direct Deps | Deep Deps | Edges | 7 | | -------- | ----------- | --------- | ----- | 8 | | `lein deps` | ✅ | ✅ | ✅ | 9 | 10 | ## Project Discovery 11 | 12 | In order to find Leiningen projects, we look for `project.clj` files which specify the root of a Leiningen project. Once we find a `leiningen` file we quit walking the file tree because the downloaded dependencies will have their own `project.clj` files in subdirectories which would create an incorrect dep graph if scanned. 13 | 14 | ## Analysis 15 | 16 | 1. run `lein deps :tree-data` and generate output similar to: 17 | ``` 18 | {[clojure-complete "0.2.5" :exclusions [[org.clojure/clojure]]] nil, 19 | [koan-engine "0.2.5"] {[fresh "1.0.2"] nil}, 20 | [lein-koan "0.1.5" :scope "test"] nil, 21 | [nrepl "0.6.0" :exclusions [[org.clojure/clojure]]] nil, 22 | [org.clojure/clojure "1.10.0"] 23 | {[org.clojure/core.specs.alpha "0.2.44"] nil, 24 | [org.clojure/spec.alpha "0.2.176"] nil}} 25 | ``` 26 | 2. Parse this output to determine the full dependency graph and dependency versions. 27 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/clojure/leiningen.md: -------------------------------------------------------------------------------- 1 | # Quick reference: leiningen 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | 7 | - `lein` buildtool installed locally 8 | - `project.clj` file present in your project and Leiningen installed. 9 | 10 | ## Project discovery 11 | 12 | Directories containing `project.clj` are considered Clojure projects. 13 | 14 | Subdirectory scans are not affected by the discovery of a Clojure project. 15 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/dart/dart-resolved-graph-without-cmd.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 00 13 | 14 | https://github.com/leocavalcante/encrypt.git(=HEAD) 16 | 17 | 18 | 19 | 01 20 | 21 | path(=1.8.0) 23 | 24 | 25 | 26 | 02 27 | 28 | provider(=5.0.0) 30 | 31 | 32 | 33 | 03 34 | 35 | quiver(=3.0.1) 37 | 38 | 39 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/dart/dart.md: -------------------------------------------------------------------------------- 1 | # Dart 2 | 3 | Dart ecosystem uses pub package manager to manage shared [packages and libraries](https://dart.dev/guides/packages). Packages can be sourced from [registry](https://pub.dev/), [git repository](https://dart.dev/tools/pub/dependencies#git-packages), or from [local file system](https://dart.dev/tools/pub/dependencies#path-packages). 4 | 5 | ## Project Discovery 6 | 7 | Find file named `pubspec.yaml`. 8 | 9 | ## Analysis 10 | 11 | We attempt to perform all of the strategies below, we select the result of succeeded strategies which has the highest preference. 12 | 13 | | Preference | Strategy | Direct Deps | Deep Deps | Edges | 14 | | ---------- | ------------------------------------------------------------------------------------------------------ | ------------------ | ------------------ | ------------------ | 15 | | Highest | 1. `pubspec.yaml` and `pubspec.lock` are discovered, and `flutter pub deps -s compact` can be executed | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | 16 | | | 2. `pubspec.yaml` and `pubspec.lock` are discovered, and `dart pub deps -s compact` can be executed | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | 17 | | | 3. `pubspec.yaml` and `pubspec.lock` are discovered, and `pub deps -s compact` can be executed | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | 18 | | | 4. `pubspec.yaml` and `pubspec.lock` are discovered | :heavy_check_mark: | :x: | :x: | 19 | | Lowest | 5. Only `pubspec.yaml` is discovered | :heavy_check_mark: | :x: | :x: | 20 | 21 | Where, 22 | 23 | * :heavy_check_mark: - Supported in all projects 24 | * :x: - Not Supported 25 | 26 | It is recommended that, `pub deps get` is executed prior to analyzing dart project. This ensures dependencies are retrieved, so `pub deps -s compact` command can produce edges between direct, and deep dependencies. 27 | 28 | ### Limitations 29 | 30 | * [Path dependencies](https://dart.dev/tools/pub/dependencies#path-packages) are not reported, and will be ignored in analyses. All descendant dependencies of the path dependency will be promoted to the ancestor of the path dependency. 31 | * [Sdk dependencies](https://dart.dev/tools/pub/dependencies#sdk) are not reported, and will be ignored in analyses. All descendant dependencies of the sdk dependency will be promoted to the ancestor of the sdk dependency. 32 | 33 | # Example 34 | 35 | Create new dart project by creating `pubspec.yaml` file. 36 | 37 | ```yaml 38 | name: some_example 39 | description: some example description 40 | version: 1.0.0+1 41 | 42 | environment: 43 | sdk: ">=2.0.0 <3.0.0" 44 | 45 | dependencies: 46 | path: ">= 1.2.0 <3.0.0" 47 | encrypt: 48 | git: https://github.com/leocavalcante/encrypt.git 49 | flutter: 50 | sdk: flutter 51 | provider: ^5.0.0 52 | quiver: any 53 | 54 | flutter: 55 | uses-material-design: true 56 | ``` 57 | 58 | Execute `dart pub get` to retrieve packages from the spec file. When performed, it will create `pubspec.lock` file. 59 | 60 | ```text 61 | # Generated by pub 62 | # See https://dart.dev/tools/pub/glossary#lockfile 63 | packages: 64 | args: 65 | dependency: transitive 66 | description: 67 | name: args 68 | url: "https://pub.dartlang.org" 69 | source: hosted 70 | version: "2.2.0" 71 | asn1lib: 72 | dependency: transitive 73 | description: 74 | name: asn1lib 75 | url: "https://pub.dartlang.org" 76 | source: hosted 77 | version: "1.0.2" 78 | characters: 79 | dependency: transitive 80 | description: 81 | name: characters 82 | url: "https://pub.dartlang.org" 83 | source: hosted 84 | version: "1.1.0" 85 | clock: 86 | dependency: transitive 87 | description: 88 | name: clock 89 | url: "https://pub.dartlang.org" 90 | source: hosted 91 | version: "1.1.0" 92 | collection: 93 | dependency: transitive 94 | description: 95 | name: collection 96 | url: "https://pub.dartlang.org" 97 | source: hosted 98 | version: "1.15.0" 99 | convert: 100 | dependency: transitive 101 | description: 102 | name: convert 103 | url: "https://pub.dartlang.org" 104 | source: hosted 105 | version: "3.0.1" 106 | crypto: 107 | dependency: transitive 108 | description: 109 | name: crypto 110 | url: "https://pub.dartlang.org" 111 | source: hosted 112 | version: "3.0.1" 113 | encrypt: 114 | dependency: "direct main" 115 | description: 116 | path: "." 117 | ref: HEAD 118 | resolved-ref: bc2a3f44339574edb5c374b991b6386c495a1bbb 119 | url: "https://github.com/leocavalcante/encrypt.git" 120 | source: git 121 | version: "5.0.1" 122 | flutter: 123 | dependency: "direct main" 124 | description: flutter 125 | source: sdk 126 | version: "0.0.0" 127 | js: 128 | dependency: transitive 129 | description: 130 | name: js 131 | url: "https://pub.dartlang.org" 132 | source: hosted 133 | version: "0.6.3" 134 | matcher: 135 | dependency: transitive 136 | description: 137 | name: matcher 138 | url: "https://pub.dartlang.org" 139 | source: hosted 140 | version: "0.12.11" 141 | meta: 142 | dependency: transitive 143 | description: 144 | name: meta 145 | url: "https://pub.dartlang.org" 146 | source: hosted 147 | version: "1.7.0" 148 | nested: 149 | dependency: transitive 150 | description: 151 | name: nested 152 | url: "https://pub.dartlang.org" 153 | source: hosted 154 | version: "1.0.0" 155 | path: 156 | dependency: "direct main" 157 | description: 158 | name: path 159 | url: "https://pub.dartlang.org" 160 | source: hosted 161 | version: "1.8.0" 162 | pointycastle: 163 | dependency: transitive 164 | description: 165 | name: pointycastle 166 | url: "https://pub.dartlang.org" 167 | source: hosted 168 | version: "3.3.0" 169 | provider: 170 | dependency: "direct main" 171 | description: 172 | name: provider 173 | url: "https://pub.dartlang.org" 174 | source: hosted 175 | version: "5.0.0" 176 | quiver: 177 | dependency: "direct main" 178 | description: 179 | name: quiver 180 | url: "https://pub.dartlang.org" 181 | source: hosted 182 | version: "3.0.1" 183 | sky_engine: 184 | dependency: transitive 185 | description: flutter 186 | source: sdk 187 | version: "0.0.99" 188 | stack_trace: 189 | dependency: transitive 190 | description: 191 | name: stack_trace 192 | url: "https://pub.dartlang.org" 193 | source: hosted 194 | version: "1.10.0" 195 | typed_data: 196 | dependency: transitive 197 | description: 198 | name: typed_data 199 | url: "https://pub.dartlang.org" 200 | source: hosted 201 | version: "1.3.0" 202 | vector_math: 203 | dependency: transitive 204 | description: 205 | name: vector_math 206 | url: "https://pub.dartlang.org" 207 | source: hosted 208 | version: "2.1.0" 209 | sdks: 210 | dart: ">=2.12.0 <3.0.0" 211 | flutter: ">=1.16.0" 212 | ``` 213 | 214 | Dependencies can be inspected using `dart pub deps -s compact`: 215 | 216 | ```text 217 | Dart SDK 2.14.0-301.0.dev 218 | Flutter SDK 2.4.0-4.0.pre 219 | some_example 1.0.0+1 220 | 221 | dependencies: 222 | - encrypt 5.0.1 [args asn1lib clock collection crypto pointycastle] 223 | - flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine] 224 | - path 1.8.0 225 | - provider 5.0.0 [collection flutter nested] 226 | - quiver 3.0.1 [matcher] 227 | 228 | transitive dependencies: 229 | - args 2.2.0 230 | - asn1lib 1.0.2 231 | - characters 1.1.0 232 | - clock 1.1.0 233 | - collection 1.15.0 234 | - convert 3.0.1 [typed_data] 235 | - crypto 3.0.1 [collection typed_data] 236 | - js 0.6.3 237 | - matcher 0.12.11 [stack_trace] 238 | - meta 1.7.0 239 | - nested 1.0.0 [flutter] 240 | - pointycastle 3.3.0 [collection convert js] 241 | - sky_engine 0.0.99 242 | - stack_trace 1.10.0 [path] 243 | - typed_data 1.3.0 [collection] 244 | - vector_math 2.1.0 245 | ``` 246 | 247 | When pub deps command is successfully executed, and lockfile id discovered (strategy 1, 2, or 3) analyses would yield following dependency graph: 248 | 249 | ![With lock file and deps command](dart-resolved-graph-with-lock-cmd.svg) 250 | 251 | Note: Dependencies in yellow boxes are direct dependencies, rest are deep dependencies. All descendent dependencies of sdk dependencies are promoted to their ancestor - e.g. characters, collection, meta, typed_data, and vector_math. 252 | 253 | If pub deps command is not successfully executed: 254 | 255 | ![Without deps command](dart-resolved-graph-without-cmd.svg) 256 | 257 | ## FAQ 258 | 259 | ### How do I *only* analyze dart projects? 260 | 261 | You can explicitly specify analyses target in `.fossa.yml` file. 262 | 263 | Example below, will exclude all analyses targets except pub. 264 | 265 | ```yaml 266 | # .fossa.yml 267 | 268 | version: 3 269 | targets: 270 | only: 271 | - type: pub 272 | ``` 273 | 274 | ## References 275 | 276 | * [Pub](https://dart.dev/tools/pub/cmd) 277 | * [Dart](https://dart.dev/tools/pub/cmd) 278 | * [Flutter](https://flutter.dev/) 279 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/dart/pub.md: -------------------------------------------------------------------------------- 1 | # Quick reference: pub 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | - `dart` installed locally 7 | - `pubspec.yaml` file present in your project 8 | - `pubspec.lock` file present in your project, with dependencies already retrieved and resolved 9 | 10 | ## Project discovery 11 | 12 | Directories containing `pubspec.yaml` files are considered dart projects. -------------------------------------------------------------------------------- /docs/references/strategies/languages/dotnet/README.md: -------------------------------------------------------------------------------- 1 | # .NET Analysis 2 | 3 | There are several different methods of .NET analysis, that use both the `NuGet` (`nuspec`, `PackageReference`, `packages.config`, `project.json`, `project.assets.json`) and `Paket` package managers. 4 | 5 | | Strategy | Direct Deps | Deep Deps | Edges | 6 | | ---------------------------------------- | ----------- | --------- | ----- | 7 | | [nuspec][nuspec] | ✅ | ❌ | ❌ | 8 | | [PackageReference][packagereference] | ✅ | ❌ | ❌ | 9 | | [packages.config][packagesconfig] | ✅ | ❌ | ❌ | 10 | | [paket][paket] | ✅ | ✅ | ✅ | 11 | | [project.assets.json][projectassetsjson] | ✅ | ✅ | ✅ | 12 | | [project.json][projectjson] | ✅ | ❌ | ❌ | 13 | 14 | [nuspec](nuspec.md) 15 | [packagereference](packagereference.md) 16 | [packagesconfig](packagesconfig.md) 17 | [paket](paket.md) 18 | [projectassetsjson](projectassetsjson.md) 19 | [projectjson](projectjson.md) -------------------------------------------------------------------------------- /docs/references/strategies/languages/dotnet/nuget.md: -------------------------------------------------------------------------------- 1 | # Quick reference: NuGet 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | 7 | One more more of the following: 8 | 9 | - [`.nuspec`](https://docs.microsoft.com/en-us/nuget/reference/nuspec) formatted file in your directory. 10 | - [Package reference](https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files) file present in your project. Commonly with an ending such as `.csproj`, `xproj`, `vbproj` and others. 11 | - `project.assets.json` 12 | - `packages.config` 13 | - `project.json` 14 | 15 | ## Project discovery 16 | 17 | Directories containing any of the files listed above are considered NuGet projects. 18 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/dotnet/nuspec.md: -------------------------------------------------------------------------------- 1 | # nuspec 2 | 3 | A `.nuspec` file is an XML manifest that contains package metadata for Nuget packages. This manifest is used both to build the package and to provide information to consumers. 4 | 5 | ## Project Discovery 6 | 7 | Walk the directory and find all files with a `.nuspec` suffix 8 | 9 | ## Analysis 10 | 11 | Depending on the version of Nuget in use, dependencies can be specified in two ways 12 | 13 | TODO: do we ONLY look at dependency groups???? 14 | ### Dependencies element 15 | 16 | The element within contains any number of elements that identify other packages upon which the top-level package depends. Example: 17 | 18 | ``` 19 | 20 | 21 | 22 | GenericServices 23 | 1.0.10 24 | GenericServices 25 | Jon Smith 26 | Jon Smith 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | ``` 36 | 37 | ### Dependency groups 38 | 39 | As an alternative to a single flat list, dependencies can be specified according to the framework profile of the target project using elements within . 40 | 41 | ``` 42 | 43 | 44 | 45 | GenericServices 46 | 1.0.10 47 | GenericServices 48 | Jon Smith 49 | Jon Smith 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | ``` -------------------------------------------------------------------------------- /docs/references/strategies/languages/dotnet/packagereference.md: -------------------------------------------------------------------------------- 1 | # PackageReference 2 | 3 | Package references, using the `PackageReference` node, manage NuGet dependencies directly within project files (as opposed to a separate `packages.config` file) 4 | 5 | ## Project Discovery 6 | 7 | Walk the directory and find all NuGet project files, i.e. files with the suffix of `.csproj`, `.xproj`, `.vbproj`, `.dbproj`, or `.fsproj`. 8 | 9 | ## Analysis 10 | 11 | Parse the XML project files, and collect dependency data from all `PackageReference` tags: 12 | 13 | ``` 14 | 15 | 16 | 17 | 18 | 19 | ``` -------------------------------------------------------------------------------- /docs/references/strategies/languages/dotnet/packagesconfig.md: -------------------------------------------------------------------------------- 1 | # packages.config 2 | 3 | The `packages.config` XML file is used in some project types to maintain the list of packages referenced by the project. 4 | 5 | Note: projects that use `PackageReference` do not use `packages.config`. 6 | 7 | ## Project Discovery 8 | 9 | Walk the directory and find all files names `packages.config` 10 | 11 | ## Analysis 12 | 13 | Parse the XML file, and collect dependency data from all `package` tags within the `packages` section: 14 | 15 | ``` 16 | 17 | 18 | 19 | 20 | 21 | ``` -------------------------------------------------------------------------------- /docs/references/strategies/languages/dotnet/paket-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: Paket 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | 7 | - `paket.lock` file 8 | 9 | ## Project discovery 10 | 11 | Directories containing any of the files listed above are considered Paket projects 12 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/dotnet/paket.md: -------------------------------------------------------------------------------- 1 | # Paket 2 | 3 | Paket is a dependency manager for .NET projects. Paket enables precise and predictable control over your dependencies 4 | 5 | Paket manages your dependencies with three core file types: 6 | 7 | `paket.dependencies`, where you specify your dependencies and their versions for your entire codebase. 8 | `paket.references`, a file that specifies a subset of your dependencies for every project in a solution. 9 | `paket.lock`, a lock file that Paket generates when it runs. When you check it into source control, you get reproducible builds. 10 | 11 | ## Project Discovery 12 | 13 | Walk the directory and find all lock files (`paket.lock`) 14 | 15 | ## Analysis 16 | Parse the lock file, and construct a dependency graph: 17 | 18 | ``` 19 | NUGET 20 | remote: nuget.com 21 | one (1.0.0) 22 | two (>1.0.0) 23 | two (2.0.0) 24 | 25 | HTTP 26 | remote: custom-site.com 27 | three (3.0.0) 28 | ``` 29 | 30 | dependencies can come from either NuGet, Github, or a specified remote URL. -------------------------------------------------------------------------------- /docs/references/strategies/languages/dotnet/projectassetsjson.md: -------------------------------------------------------------------------------- 1 | # project.assets.json 2 | 3 | The `project.assets.json` file is used in `.NET Core` projects to manage dependencies and other resources 4 | 5 | ## Project Discovery 6 | 7 | Walk the directory and find all files names `project.assets.json` 8 | 9 | ## Analysis 10 | 11 | Parse the JSON file, and construct a full dependency graph (direct and transitive dependencies). 12 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/dotnet/projectjson.md: -------------------------------------------------------------------------------- 1 | # project.json 2 | 3 | The `project.json` file maintains a list of packages used in a project, known as a package management format. It supersedes `packages.config` but is in turn superseded by `PackageReference` with NuGet 4.0+. 4 | 5 | ## Project Discovery 6 | 7 | Walk the directory and find all files names `project.json` 8 | 9 | ## Analysis 10 | 11 | Parse the JSON file and search for the `dependencies` section: 12 | 13 | ``` 14 | "dependencies": { 15 | "Microsoft.NETCore": "5.0.0", 16 | "System.Runtime.Serialization.Primitives": "4.0.10" 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/elixir/elixir.md: -------------------------------------------------------------------------------- 1 | # Elixir Analysis 2 | 3 | When developing in Elixir, [Mix](https://hexdocs.pm/mix/Mix.html) and [Hex](https://hex.pm/) are most commonly used to manage dependencies. 4 | 5 | | Strategy | Direct Deps | Deep Deps | Edges | 6 | | -------- | ------------------ | ------------------ | ------------------ | 7 | | mix deps | :white_check_mark: | :white_check_mark: | :white_check_mark: | 8 | 9 | ## Project Discovery 10 | 11 | In order to find elixir projects, we look for `mix.exs` file, which specifies the root of an elixir project. When we find an elixir project, we do not descend into any `deps` or `_build` subdirectories to look for more elixir projects. 12 | 13 | ## Analysis 14 | 15 | 1. Run `mix deps.tree --format plain --only prod` and generate output similar to: 16 | ``` 17 | ├─ one─1.0.0 (github.com/dep/one) 18 | │ ├─ two─2.0.0 (hex package) 19 | │ │ └─ three─3.0.0 (hex package) 20 | │ └─ four─4.0.0 (github.com/dep/four) 21 | └─ five─5.0.0 (hex package) 22 | ``` 23 | 2. Run `mix deps --all` and generate output similar to: 24 | ``` 25 | * one 1.0.0 (Hex package) (mix) 26 | locked at 1.0.0 (one) 3ad58ae7 27 | ok 28 | * two 1.0.0 (Hex package) (mix) 29 | locked at 1.0.0 (two) eaf3c2aa 30 | ok 31 | * three 1.0.0 (Hex package) (mix) 32 | locked at 1.0.0 (three) ce708e5f 33 | ok 34 | * four 1.0.0 (Hex package) (mix) 35 | locked at 1.0.0 (four) 08eb32d6 36 | ok 37 | * four 4.0.0 (github.com/dep/four) (mix) 38 | locked at 9554589 39 | ok 40 | * five 1.0.0 (Hex package) (mix) 41 | locked at 1.0.0 (five) 4964996d 42 | ok 43 | ..... 44 | ``` 45 | 3. Parse these outputs to determine the dependency graph and the locations of each dependency. 46 | 47 | ## Limitations 48 | 49 | * Dependencies from private hex repositories are not supported currently. 50 | * Dependencies must be sourced from git, or from hex. 51 | * Dependencies must have been resolved `mix deps.get` and compiled `mix compile` (or at least `mix deps.compile`) prior to performing the analyses. 52 | 53 | ## Example 54 | 55 | 1. Create a new mix project, using `mix init hello_world`. Now modify `mix.exs` to add dependencies (final file shown below) 56 | 57 | ```elixir 58 | defmodule HelloWorld.MixProject do 59 | use Mix.Project 60 | 61 | def project do 62 | [ 63 | app: :hello_world, 64 | version: "0.1.0", 65 | elixir: "~> 1.12", 66 | elixirc_options: [warnings_as_errors: false], 67 | start_permanent: Mix.env() == :prod, 68 | deps: deps() 69 | ] 70 | end 71 | 72 | # Run "mix help compile.app" to learn about applications. 73 | def application do 74 | [ 75 | extra_applications: [:logger, :public_key] 76 | ] 77 | end 78 | 79 | # Run "mix help deps" to learn about dependencies. 80 | defp deps do 81 | [ 82 | {:phoenix, git: "https://github.com/phoenixframework/phoenix", tag: "v1.5.1"}, 83 | {:plug, ">= 0.4.0"}, 84 | {:ecto, "~> 2.0"}, 85 | {:postgrex, ">= 0.8.1 and <3.0.0"}, 86 | {:faker, "~> 0.16.0"}, 87 | {:ex_doc, "~> 0.23"}, 88 | {:jason, "~> 1.0"} 89 | ] 90 | end 91 | end 92 | ``` 93 | 94 | You may need to add `config/config.exs` file with following content to ensure phoenix does not throw complier warnings due to missing configs. 95 | 96 | ```elixir 97 | use Mix.Config 98 | 99 | config :phoenix, :json_library, Jason 100 | ``` 101 | 102 | 1. Run `mix deps.get` to get and resolve dependencies 103 | 2. Run `mix compile` to compile project - you may see few compiler warnings for deprecations and configs 104 | 105 | Corresponding mix.lock file should now be generated in the project directory (example file shown below) 106 | ```elixir 107 | %{ 108 | "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"}, 109 | "db_connection": {:hex, :db_connection, "1.1.3", "89b30ca1ef0a3b469b1c779579590688561d586694a3ce8792985d4d7e575a61", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm", "5f0a16a58312a610d5eb0b07506280c65f5137868ad479045f2a2dc4ced80550"}, 110 | "decimal": {:hex, :decimal, "1.9.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"}, 111 | "earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"}, 112 | "ecto": {:hex, :ecto, "2.2.12", "ce7f619c1451daad0f59e8f01fd8e2584226171dc273e3346444446a13d93943", [:mix], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm", "d5d01f3ec33e3853ac8ca80dcaf9b154a348b9eaa70009d2b9ad25c45262fdea"}, 113 | "ex_doc": {:hex, :ex_doc, "0.24.2", "e4c26603830c1a2286dae45f4412a4d1980e1e89dc779fcd0181ed1d5a05c8d9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "e134e1d9e821b8d9e4244687fb2ace58d479b67b282de5158333b0d57c6fb7da"}, 114 | "faker": {:hex, :faker, "0.16.0", "1e2cf3e8d60d44a30741fb98118fcac18b2020379c7e00d18f1a005841b2f647", [:mix], [], "hexpm", "fbcb9bf1299dff3c9dd7e50f41802bbc472ffbb84e7656394c8aa913ec315141"}, 115 | "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, 116 | "makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"}, 117 | "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, 118 | "mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"}, 119 | "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, 120 | "phoenix": {:git, "https://github.com/phoenixframework/phoenix", "cfd5a6e91b0d60c5dc84ad5874506444f5d65251", [tag: "v1.5.8"]}, 121 | "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, 122 | "plug": {:hex, :plug, "1.11.1", "f2992bac66fdae679453c9e86134a4201f6f43a687d8ff1cd1b2862d53c80259", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "23524e4fefbb587c11f0833b3910bfb414bf2e2534d61928e920f54e3a1b881f"}, 123 | "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"}, 124 | "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, 125 | "postgrex": {:hex, :postgrex, "0.13.5", "3d931aba29363e1443da167a4b12f06dcd171103c424de15e5f3fc2ba3e6d9c5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "a19b61193379cdee04b5b2361bf93d1eb170cd2eec0b18042617b07e1e15fbfb"}, 126 | "telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"}, 127 | } 128 | ``` 129 | 130 | 3. To perform the analyses, run `fossa analyze ./../myElixirProjectDir/` 131 | 4. To perform the analyses and view it's output only, run `fossa analyze ./../myElixirProjectDir/ --output` 132 | 133 | Here is the dependency graph produced from the above project. Dependencies in yellow are direct dependencies. 134 | 135 | ![Mix Dependency Graph](mix-resolved-graph.svg) 136 | 137 | ## F.A.Q 138 | 139 | ### How do I exclude downloaded rebar3 dependency artifacts from the analyses? 140 | 141 | You can explicitly specify analyses target in `.fossa.yml` file. 142 | 143 | Example below, will exclude all analyses targets except mix. 144 | 145 | ```yaml 146 | # .fossa.yml 147 | 148 | version: 3 149 | targets: 150 | only: 151 | - type: mix 152 | ``` 153 | 154 | Or, you can exclude all rebar3 targets under specific directory. 155 | 156 | ```yaml 157 | # .fossa.yml 158 | # Exclude rebar3 targets found in ./deps/ directory from the analyses. 159 | 160 | version: 3 161 | targets: 162 | exclude: 163 | - type: rebar3 164 | target: ./deps/ 165 | ``` -------------------------------------------------------------------------------- /docs/references/strategies/languages/elixir/mix.md: -------------------------------------------------------------------------------- 1 | # Quick reference: mix 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | - `mix` installed locally 7 | - `mix.exs` and `mix.lock` file present in your project 8 | 9 | ## Project discovery 10 | 11 | Directories containing `mix.exs` files are considered. -------------------------------------------------------------------------------- /docs/references/strategies/languages/erlang/erlang.md: -------------------------------------------------------------------------------- 1 | # Erlang Analysis 2 | 3 | When developing in Erlang, [Rebar](https://www.rebar3.org/) is the most common package manager. Dependencies are specified in a manifest file by users which is used by the `rebar3` tool to build a dependency graph and download the correct dependencies. 4 | 5 | 6 | | Strategy | Direct Deps | Deep Deps | Edges | 7 | | -------- | ----------- | --------- | ----- | 8 | | rebar3 | ✅ | ✅ | ✅ | 9 | 10 | ## Project Discovery 11 | 12 | In order to find Rebar projects, we look for `rebar.config` files which specify the root of a Rebar project. Once we find a `rebar.config` file we quit walking the file tree because the downloaded dependencies will have their own `rebar.config` files in subdirectories. 13 | 14 | ## Analysis 15 | 16 | 1. run `rebar3 tree -v` and generate output similar to: 17 | ``` 18 | ├─ one─1.0.0 (https://github.com/dep/one) 19 | │ ├─ two─2.0.0 (hex package) 20 | │ │ └─ three─3.0.0 (hex package) 21 | │ └─ four─4.0.0 (https://github.com/dep/four) 22 | └─ five─5.0.0 (hex package) 23 | ``` 24 | 2. Parse this output to determine the dependency graph and the locations of each dependency. 25 | 26 | ## Limitations 27 | 28 | #### Dependency name aliasing 29 | `rebar.config` allows users to alias dependencies in a format similar to `{deps, [{chatterbox, {pkg, ts_chatterbox}},`. This format is not currently handled in the CLI and will result in unknown dependencies being shown in the FOSSA UI. The team is aware of this limitation and a fix is planned. 30 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/erlang/rebar3.md: -------------------------------------------------------------------------------- 1 | # Quick reference: rebar3 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | - `rebar3` installed locally 7 | - `rebar.config` file present in your project 8 | 9 | ## Project discovery 10 | 11 | Directories containing `rebar.config` files are considered 12 | Erlang projects. `rebar.config` files in project subdirectories are ignored. 13 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/fortran/fortran.md: -------------------------------------------------------------------------------- 1 | # Fortran Analysis 2 | 3 | Currently, we only support analysis of fortran project which are using [fortran package manager](https://github.com/fortran-lang/fpm). 4 | 5 | | Strategy | Direct Deps | Deep Deps | Edges | Classifies Dev & Test Deps | 6 | | -------- | ------------------ | --------- | ----- | -------------------------- | 7 | | fpm | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | 8 | 9 | ## Project Discovery 10 | 11 | Find a file named `fpm.toml`. If `fpm.toml` is found, we do not scan in the `build` directory for more Fortran projects. 12 | 13 | ## Analysis 14 | 15 | 1. Parse `fpm.toml` file to identify direct dependencies. 16 | 17 | ## Limitations 18 | 19 | - We do not report [path dependencies](https://github.com/fortran-lang/fpm/blob/main/manifest-reference.md#local-dependencies). 20 | - We do not report test or [development dependencies](https://github.com/fortran-lang/fpm/blob/main/manifest-reference.md#development-dependencies). 21 | - We only report direct dependencies. 22 | 23 | ## Example 24 | 25 | Create a Fortran project managed by `fpm`. Execute `fpm new project_name`. This will create a directory named project_name with a manifest file, and a few example source files. 26 | 27 | Modify `fpm.toml` file to include direct dependency: 28 | 29 | ```toml 30 | name = "fortran_example" 31 | version = "0.1.0" 32 | license = "license" 33 | author = "Jane Doe" 34 | maintainer = "jane.doe@example.com" 35 | copyright = "Copyright 2021, Jane Doe" 36 | 37 | [build] 38 | auto-executables = true 39 | auto-tests = true 40 | auto-examples = true 41 | 42 | [install] 43 | library = false 44 | 45 | [dependencies] 46 | toml-f = { git = "https://github.com/toml-f/toml-f", tag = "v0.2.1" } 47 | ``` 48 | 49 | Now modify `app/main.f90` to use `tomlf`: 50 | 51 | ```fortran 52 | program main 53 | use tomlf, only: get_tomlf_version 54 | implicit none 55 | 56 | integer :: major 57 | integer :: minor 58 | integer :: patch 59 | call get_tomlf_version(major, minor, patch) 60 | 61 | print *, "tomlf's major version is: ", major 62 | print *, "tomlf's minor version is: ", minor 63 | print *, "tomlf's patch version is: ", patch 64 | end program main 65 | ``` 66 | 67 | Execute `fpm build` to build the fortran project. 68 | 69 | Now you can call `fpm run` to execute the built application, here is an example output from this application: 70 | ``` 71 | tomlf's major version is: 0 72 | tomlf's minor version is: 2 73 | tomlf's patch version is: 1 74 | ``` 75 | 76 | To analyze this project using fossa CLI, execute `fossa analyze --output --debug`. This will print identified dependency graphs and debug logs only. It will not upload the performed analysis to any endpoint. 77 | 78 | ## References 79 | 80 | - [Fortran Package Manager](https://github.com/fortran-lang/fpm) -------------------------------------------------------------------------------- /docs/references/strategies/languages/golang/glide-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: glide 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | 7 | - `glide.lock` file present in your project 8 | 9 | ## Project discovery 10 | 11 | Directories containing `glide.lock` files are considered glide projects. 12 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/golang/glide.md: -------------------------------------------------------------------------------- 1 | # Glide 2 | 3 | Glide is very commonly encountered as a buildtool for older golang projects. 4 | Though deprecated, it's prevalent enough among existing projects that it 5 | warrants support in spectrometer. 6 | 7 | ## Project Discovery 8 | 9 | Find all files named `glide.lock` 10 | 11 | ## Analysis 12 | 13 | `glide.lock` is a yaml-formatted file containing pinned package versions: 14 | 15 | ```yaml 16 | hash: 12345 17 | updated: 2018-10-12T14:37:49.968644-07:00 18 | imports: 19 | - name: github.com/pkg/one 20 | version: 100 21 | subpackages: 22 | - compute 23 | - name: github.com/pkg/three/v3 24 | version: 300 25 | repo: fossas/privatefork 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/golang/godep-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: godep 2 | 3 | ## Requirements 4 | 5 | **Ideal** 6 | 7 | - `Gopkg.lock` file present in your project 8 | 9 | **Minimum** 10 | 11 | - `Gopkg.toml` file present in your project 12 | 13 | ## Project discovery 14 | 15 | Directories containing one (or both) of `Gopkg.toml` and `Gopkg.lock` are considered godep projects. 16 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/golang/godep.md: -------------------------------------------------------------------------------- 1 | # Dep 2 | 3 | Dep is an alternative toolchain for golang dependency management. Though go 4 | modules are the blessed form of dependency management, dep is exploring 5 | alternatives in the dependency management space, and hasn't been deprecated. 6 | 7 | ## Project Discovery 8 | 9 | `gopkglock`: Find all files named `Gopkg.lock` 10 | 11 | `gopkgtoml`: Find all files named `Gopkg.toml` 12 | 13 | ## Analysis: gopkglock 14 | 15 | We parse [projects][depprojects] from Gopkg.lock. This is more comprehensive 16 | than GopkgToml, as it contains pinned versions of all of our direct _and_ 17 | transitive dependencies. We also pick up on `source` locations from GopkgLock 18 | 19 | [depprojects]: https://golang.github.io/dep/docs/Gopkg.toml.html#dependency-rules-constraint-and-override 20 | 21 | ## Analysis: gopkgtoml 22 | 23 | We parse [dependency rules][deprules] from Gopkg.toml. `override`s are similar 24 | to [gomod replaces](gomodules.md). 25 | 26 | [deprules]: https://golang.github.io/dep/docs/Gopkg.toml.html#dependency-rules-constraint-and-override 27 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/golang/golang.md: -------------------------------------------------------------------------------- 1 | # Golang Analysis 2 | 3 | Historically, the Golang buildtool ecosystem has been very fragmented: many 4 | tools like dep, Glide, Govendor, etc have tried to address issues around build 5 | reproducibility, versioning and vendoring of dependencies. 6 | 7 | As of Golang 1.11, we have first-class support for "modules", which solves 8 | issues previously seen around versioning and build reproducibility. 9 | 10 | Because modules address those issues so well, the other tooling has largely gone 11 | into maintenance mode, with the notable exception of dep. As such, golang 12 | analysis in spectrometer primarily targets Golang 1.11+ modules and dep. Support 13 | for Glide is also included, because it's still commonly used. 14 | 15 | | Strategy | Direct Deps | Deep Deps | Edges | 16 | | --- | --- | --- | --- | 17 | | [golist][gomodules] (golang modules) | ✅ | ✅ | 🔶 | 18 | | [gomod][gomodules] (golang modules) | ✅ | ❌ | 🔶 | 19 | | [gopkglock][godep] (dep) | ✅ | ✅ | 🔶 | 20 | | [gopkgtoml][godep] (dep) | ✅ | 🔶 | 🔶 | 21 | | [glide][glide] | ✅ | ✅ | ❌ | 22 | 23 | [gomodules](gomodules.md) 24 | [godep](godep.md) 25 | [glide](glide.md) 26 | 27 | ## 🔶 Edges and deep dependencies 28 | 29 | Most strategies (except for gomod, where it would be redundant -- golist 30 | supersedes gomod) use `go list -json all` to hydrate edges and transitive 31 | dependencies. Package imports are recursively traversed, ignoring `Standard` 32 | (system) packages. 33 | 34 | `go list` behaves slightly differently depending on the context: 35 | 36 | - in a gomodules project, packages can contain a `Module` field that contains a 37 | pinned `Version`. The version will otherwise be unspecified 38 | - `go list` includes vendored packages in both gomodules and non-gomodules projects. 39 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/golang/gomodules-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: gomodules 2 | 3 | ## Requirements 4 | 5 | **Ideal** 6 | 7 | - `go` buildtool installed 8 | - `go.mod` file present in your project 9 | 10 | **Minimum** 11 | 12 | - `go.mod` file present in your project 13 | 14 | ## Project discovery 15 | 16 | Directories containing `go.mod` files are considered gomodules projects. 17 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/golang/gomodules.md: -------------------------------------------------------------------------------- 1 | # Golang Modules 2 | 3 | Golang 1.11 has first-class support for "modules", which is now the preferred 4 | way to do dependency management. 5 | 6 | ## Project Discovery 7 | 8 | Find all files named `go.mod` 9 | 10 | ## Analysis: golist 11 | 12 | Discovery: find go.mod files 13 | 14 | We run `go list -m -json all`, which produces, e.g.,: 15 | 16 | ```json 17 | { 18 | "Path": "example.com/foo/bar", 19 | "Main": true, 20 | "Dir": "/Users/example/Codes/golang/simple", 21 | "GoMod": "/Users/example/Codes/golang/simple/go.mod", 22 | "GoVersion": "1.16" 23 | } 24 | { 25 | "Path": "github.com/kr/pretty", 26 | "Version": "v0.1.0", 27 | "Time": "2018-05-06T08:33:45Z", 28 | "Indirect": true, 29 | "Dir": "/Users/example/go/pkg/mod/github.com/kr/pretty@v0.1.0", 30 | "GoMod": "/Users/example/go/pkg/mod/cache/download/github.com/kr/pretty/@v/v0.1.0.mod" 31 | } 32 | ``` 33 | 34 | - To infer direct dependencies, we filter out any module, which has `Main` field with value of true, and `Indirect` field with value of true. 35 | - To infer transitive dependencies, we execute `go list -json all`, and parse it's output for `Imports`, `ImportPath`, `Module`, `Standard` data, and fill in the transitive dependencies. 36 | 37 | For package dependencies that aren't using gomodules, a pseudo-version (`v0.0.0-TIMESTAMP-COMMITID`) is present instead. We use the commit ID as the version. 38 | 39 | ## Analysis: gomod 40 | 41 | We parse the go.mod file, which looks something like: 42 | 43 | ``` 44 | module our/package/path 45 | 46 | require ( 47 | github.com/example/one v1.2.3 48 | github.com/example/two v2.3.4 49 | ) 50 | 51 | replace github.com/example/two => github.com/example/other v2.0.0 52 | ``` 53 | 54 | where: 55 | 56 | - `replace` rewrites `require`s. In this example, our requires resolve to 57 | `[github.com/example/one v1.2.3, github.com/example/other v2.0.0]` 58 | 59 | 60 | ## FAQ 61 | 62 | ### Why `go list -m -json all` is used instead of `go list -json -deps` to infer dependencies? 63 | 64 | We use `go list -m -json all` in combination with the `go list -json all`, to infer direct and transitive dependencies. The reason, we do not use solely use `go list -json -deps` command at this moment, is because it does not include transitive dependencies imported with test imports. 65 | 66 | This go module functionality is actively being worked on, such that we can label dependencies environment (e.g. Test) correctly, for all types of golang project configurations. -------------------------------------------------------------------------------- /docs/references/strategies/languages/haskell/README.md: -------------------------------------------------------------------------------- 1 | # Haskell Analysis 2 | 3 | The haskell buildtool ecosystem consists of two major toolchains: the `cabal`-the-tool and `stack` 4 | 5 | | Strategy | Direct Deps | Deep Deps | Edges | 6 | | --- | --- | --- | --- | 7 | | [cabal][cabal] | ✅ | ✅ | ✅ | 8 | | [stack][stack] | ✅ | ✅ | ✅ | 9 | 10 | [cabal](cabal.md) 11 | [stack](stack.md) 12 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/haskell/cabal-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: cabal 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | 7 | At least one of: 8 | 9 | - `cabal.project` file present in your project 10 | - `*.cabal` file present in your project 11 | 12 | ## Project discovery 13 | 14 | Directories containing one of the above files are considered cabal projects. 15 | Subdirectories are not considered once a project is found. 16 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/haskell/cabal.md: -------------------------------------------------------------------------------- 1 | # Cabal 2 | 3 | ## Project Discovery 4 | 5 | Find all directories with a `cabal.project` file or a file with a `.cabal` 6 | extension. When one is found, skip all subdirectories. 7 | 8 | *NOTE: We don't actually examine the cabal files, we just use their existence* 9 | *to determine that we are woking with a cabal project. As a result, we can* 10 | *handle multiple `*.cabal` files, even though `cabal` cannot.* 11 | 12 | ## Analysis 13 | 14 | From the project root, we open the `./dist-newstyle/cache/plan.json` file, 15 | created by `cabal`. The relevant items in the file take the following form: 16 | 17 | *Extra data removed for brevity* 18 | 19 | ``` json 20 | { 21 | "install-plan": [ 22 | { 23 | "type": "configured", 24 | "id": "with-components-1.0.2.3-efgh", 25 | "pkg-name": "with-components", 26 | "pkg-version": "1.0.2.3", 27 | "style": "global", 28 | "components": { 29 | "lib": { 30 | "depends": [ 31 | "base-4.13.0.0" 32 | ] 33 | }, 34 | "setup": { 35 | "depends": [ 36 | "rts" 37 | ] 38 | } 39 | } 40 | }, 41 | { 42 | "type": "pre-existing", 43 | "id": "rts", 44 | "pkg-name": "rts", 45 | "pkg-version": "1.0", 46 | "depends": [] 47 | }, 48 | { 49 | "type": "configured", 50 | "id": "spectrometer-0.1.0.0-inplace", 51 | "pkg-name": "spectrometer", 52 | "pkg-version": "0.1.0.0", 53 | "style": "local", 54 | "depends": [ 55 | "aeson-1.5.2.0-abcd", 56 | "base-4.13.0.0", 57 | "with-components-1.0.2.3-efgh" 58 | ] 59 | } 60 | ] 61 | } 62 | ``` 63 | 64 | Analysis has two notable parts: matching `id` fields from the strings in 65 | `depends` and `components.*.depends`, and noting the package `type` and 66 | `style`. `pre-existing` types refer to builtin, ghc-provided packages, while 67 | `configured` packages have two `style`s of their own: `local`, referring to the 68 | current project, and `global`, referring to packages obtained from a remote 69 | source like [hackage](https://hackage.haskell.org/). 70 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/haskell/stack-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: stack 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | - `stack` buildtool install 7 | - `stack.yaml` file present in your project 8 | 9 | ## Project discovery 10 | 11 | Directories containing a `stack.yaml` file are considered stack projects. 12 | Subdirectories are not considered once a project is found. 13 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/haskell/stack.md: -------------------------------------------------------------------------------- 1 | # Stack 2 | 3 | ## Project Discovery 4 | 5 | Find all directories with a `stack.yaml` file. When one is found, skip all 6 | subdirectories. 7 | 8 | ## Analysis 9 | 10 | From the project root, we run `stack ls dependencies json`, which outputs JSON 11 | in the following format. 12 | 13 | *Extra data removed for brevity* 14 | 15 | ``` json 16 | [ 17 | { 18 | "location": { 19 | "type": "hackage" 20 | }, 21 | "name": "remote", 22 | "version": "remote-ver", 23 | "dependencies": [ 24 | "deep" 25 | ] 26 | }, 27 | { 28 | "location": { 29 | "type": "project package" 30 | }, 31 | "name": "local", 32 | "version": "local-ver", 33 | "dependencies": [ 34 | "remote", 35 | "builtin" 36 | ] 37 | }, 38 | { 39 | "location": { 40 | "type": "hackage" 41 | }, 42 | "name": "deep", 43 | "version": "deep-ver", 44 | "dependencies": [] 45 | }, 46 | { 47 | "name": "builtin", 48 | "version": "builtin-ver" 49 | } 50 | ] 51 | ``` 52 | 53 | Analysis has two notable parts: matching `name` fields from the strings in 54 | `dependencies`, and noting the package's `location.type`. A package with a 55 | missing `location.type` refers to a builtin, ghc-provided package, and a 56 | present field takes one of two forms: remote and local, which have different 57 | sets of string associated with them. Local packages are references to the 58 | current project, while remote references are pointers to package or source 59 | repositories. 60 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/maven/maven-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: maven 2 | 3 | ## Requirements 4 | 5 | **Ideal** 6 | 7 | - `maven` buildtool installed 8 | - `pom.xml` files present in your project 9 | 10 | **Minimum** 11 | 12 | - `pom.xml` files present in your project 13 | 14 | ## Project discovery 15 | 16 | We do a complete directory traversal looking for files named `pom.xml`, and link related poms together into projects. 17 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/maven/maven.md: -------------------------------------------------------------------------------- 1 | # Maven Analysis 2 | 3 | For maven projects, we offer a more-accurate strategy (mavenplugin), and a strategy with zero requirements (pomxml) 4 | 5 | | Strategy | Direct Deps | Deep Deps | Edges | 6 | | --- | --- | --- | --- | 7 | | [mavenplugin][mavenplugin] | ✅ | ✅ | ✅ | 8 | | [pomxml][pomxml] | ✅ | ❌ | ❌ | 9 | 10 | [mavenplugin](mavenplugin.md) 11 | [pomxml](pomxml.md) 12 | 13 | 30 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/maven/mavenplugin.md: -------------------------------------------------------------------------------- 1 | # Maven plugin 2 | 3 | Maven projects are notoriously difficult to resolve into final dependency 4 | graphs. While many dependencies are declared as XML, these dependency 5 | declarations can span many buildscripts and user settings files. What's worse: 6 | maven plugins are often used to apply dependencies to the project, and some 7 | maven plugins allow arbitrary executable code -- similar to gradle. 8 | 9 | To work around this, we're using the maven cli in conjunction with the [depgraph 10 | maven plugin](https://github.com/ferstl/depgraph-maven-plugin), version 3.3.0. 11 | This plugin is used by some Jenkins and Apache projects, so we can expect it to 12 | be pretty solid. 13 | 14 | ## Project Discovery 15 | 16 | Find `pom.xml` files, and treat those as maven projects. Skip all subdirectories. 17 | 18 | ## Analysis 19 | 20 | 1. unpack the embedded plugin to a temporary directory 21 | 2. install it to the local maven repository (`mvn install:install-file ...`) 22 | 3. invoke the plugin in the top-level project 23 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/maven/pomxml.md: -------------------------------------------------------------------------------- 1 | # Maven pom.xml 2 | 3 | Maven projects use `pom.xml` files to declare dependencies and multi-project relationships. 4 | 5 | In a multi-project maven structure, sub-projects usually inherit dependencies, or can reference other sub-projects as dependencies. 6 | 7 | ## Project discovery 8 | 9 | Do a complete directory traversal looking for files named `pom.xml`. 10 | 11 | There's no guarantee that a maven pom will be called `pom.xml`. To accomodate for this, we use `` directives in `` declarations to include additional poms. 12 | 13 | poms are linked together by their `` references into multi-project projects. 14 | 15 | ## Analysis 16 | 17 | Each project in the single- or multi-project structure has its pom information overlayed on top of parent poms, and a dependency graph is gathered from each project. 18 | 19 | We have limited support for naive `${property}` interpolation. 20 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/nodejs/nodejs.md: -------------------------------------------------------------------------------- 1 | # NodeJS Analysis 2 | 3 | The nodejs buildtool ecosystem consists of two major toolchains: the `npm` cli and `yarn` 4 | 5 | | Strategy | Direct Deps | Deep Deps | Edges | 6 | | --- | --- | --- | --- | 7 | | [yarnlock][yarn] | ✅ | ✅ | ✅ | 8 | | [npmlock][npm] (npmcli) | ✅ | ✅ | ✅ | 9 | | [packagejson][packagejson] | ✅ | ❌ | ❌ | 10 | 11 | [yarn](yarn.md) 12 | [npm](npmcli.md) 13 | [packagejson](packagejson.md) 14 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/nodejs/npm.md: -------------------------------------------------------------------------------- 1 | # Quick reference: npm 2 | 3 | ## Requirements 4 | 5 | **Ideal** 6 | 7 | At least one of: 8 | - `npm` tool installed 9 | - `package-lock.json` file present in your project 10 | 11 | **Minimum** 12 | 13 | - `package.json` file present in your project 14 | 15 | ## Project discovery 16 | 17 | Directories containing `package-lock.json`/`package.json` files are considered npm projects. `node_modules` subdirectories are skipped. 18 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/nodejs/npmcli.md: -------------------------------------------------------------------------------- 1 | # Npm (cli) 2 | 3 | The npm cli is the canonical package manager for nodejs projects. 4 | 5 | ## Project Discovery 6 | 7 | `npmlock`: Find all files named `package-lock.json`, not descending into 8 | directories named `node_modules` 9 | 10 | ## Analysis: npmlock 11 | 12 | The package lock json file is generated when npm modifies `node_modules` or 13 | `package.json` and describes the exact dependency tree generated. 14 | 15 | > Note: In old versions of npm, package-lock.json was only modified when dependencies were installed. 16 | 17 | This dependency tree contains information about a dependency's version, its transitive dependencies, the URL where the dependency is located at, and whether or not the dependency is used as a development dependency or not. The transitive dependency information is listed in an unintuitive way. Under each dependency there may be two fields, `requires` and `dependencies` as in the following example: 18 | 19 | ```json 20 | "babel-code-frame": { 21 | "version": "6.26.0", 22 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", 23 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", 24 | "requires": { 25 | "chalk": "1.1.3", 26 | "esutils": "2.0.3", 27 | "js-tokens": "3.0.2" 28 | }, 29 | "dependencies": { 30 | "ansi-styles": { 31 | "version": "2.2.1", 32 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 33 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 34 | }, 35 | "js-tokens": { 36 | "version": "3.0.2", 37 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 38 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" 39 | } 40 | } 41 | } 42 | ``` 43 | 44 | The `requires` field signifies all of the dependencies that are needed by the dependency in order to properly function. 45 | 46 | The `dependencies` field signifies all of the dependencies included in `babel-code-frame`'s `node_modules` folder within the top level `node_modules` folder. Notice that these dependencies are not always included in the `requires` section. 47 | 48 | > Note: `npm-shrinkwrap.json` is an identically formatted file that can be used for [publishing packages](https://docs.npmjs.com/cli/shrinkwrap). 49 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/nodejs/packagejson.md: -------------------------------------------------------------------------------- 1 | # package.json 2 | 3 | package.json is a common build manifest used by both yarn and npmcli. 4 | 5 | ## Project Discovery 6 | 7 | `npm`: Find all files named `package.json`, not descending into directories 8 | named `node_modules` 9 | 10 | ## Analysis 11 | 12 | `package.json` is a user modified file that specifies which dependencies are 13 | mandatory in order to run your project. This file lists dependencies with their 14 | version specifier. These dependencies are user specified and map nearly 1:1 with 15 | direct dependencies, however users may also specify their desired version for 16 | transitive dependencies which would invalidate the assumption that all 17 | dependencies specified here are direct. 18 | 19 | There is also a different block for development dependencies which allows us to 20 | accurately determine part of the tags available for node. 21 | 22 | As of _v2.19.x_, we also combine `package.json` files that are members of the 23 | same workspace. The files are treated as though all dependencies were found 24 | from the same file, though we report the origins of the deps as a set of all 25 | files. 26 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/nodejs/yarn-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: yarn 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | 7 | - `yarn.lock` file present in your project 8 | - `package.json` file present in your project 9 | 10 | ## Project discovery 11 | 12 | Directories containing `yarn.lock`/`package.json` files are considered yarn projects. `node_modules` subdirectories are skipped. 13 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/nodejs/yarn.md: -------------------------------------------------------------------------------- 1 | # Yarn 2 | 3 | Yarn is a spiritual successor to the npm cli. Yarn automatically updates the 4 | `yarn.lock` file when the yarn CLI is used to modify the dependencies present in 5 | the project. The `yarn.lock` file contains information about a dependency's 6 | transitive dependencies, its location, and its resolved version. 7 | 8 | ## Project Discovery 9 | 10 | Find all files named `yarn.lock`, as well as any associated `package.json` files. 11 | 12 | ## Analysis 13 | 14 | yarn.lock has its own bespoke format. Dependencies typically look something 15 | like: 16 | 17 | ```yarn-lock 18 | "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": 19 | version "7.5.5" 20 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" 21 | integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== 22 | dependencies: 23 | "@babel/highlight" "^7.0.0" 24 | ``` 25 | 26 | where: 27 | 28 | - `resolved` is the exact location of the dependency 29 | - `version` is a pinned dependency 30 | - the section "keys" contain constraints used by other packages to refer to this 31 | dependency 32 | - `dependencies` is a list of constraints for dependencies of this package 33 | 34 | We also support yarn V2, which uses a similar, though mechanically different 35 | schema, but uses standard YAML rather than a bespoke format. 36 | 37 | As of _v2.19.x_, we also support yarn workspaces. In practice, this means that 38 | the `package.json` files used to build the `yarn.lock` file are also checked, 39 | and the knowledge of both is combined to form a (usually) complete picture of 40 | the full graph of dependencies. 41 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/perl/perl.md: -------------------------------------------------------------------------------- 1 | # Perl Analysis 2 | 3 | | Strategy | Direct Deps | Deep Deps | Edges | Classifies Dev Dependencies | 4 | | ------------------ | ------------------ | ------------------ | ----- | --------------------------- | 5 | | `*META.{yml, json} | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | 6 | 7 | ## Project Discovery 8 | 9 | Find a file named `MYMETA.json`, `MYMETA.yml`, `META.json`, or `META.yml`. 10 | 11 | ## Analysis 12 | 13 | 1. Parse `MYMETA.{yml, json}` or `META.{yml, json}` to identify dependencies. 14 | 15 | ## Limitation 16 | 17 | - Dependency required for `runtime` only will be reported. 18 | - Reported analysis will not have any edges. 19 | 20 | ## Example 21 | 22 | 1. Build your perl target. When you do this, you should have `MYMETA.yml` and `MYMETA.json`. 23 | 2. Execute `fossa analyze -o` on the project to print analyzed dependency graphing (this will not upload any analysis to any endpoint) 24 | 25 | ## FAQ 26 | 27 | ### How do I *only perform analysis* for Perl? 28 | 29 | You can explicitly specify an analysis target in `.fossa.yml` file. The example below will exclude all analysis targets except for the composer. 30 | 31 | ```yaml 32 | # .fossa.yml 33 | 34 | version: 3 35 | targets: 36 | only: 37 | - type: perl 38 | ``` -------------------------------------------------------------------------------- /docs/references/strategies/languages/php/composer.md: -------------------------------------------------------------------------------- 1 | # Composer Analysis 2 | 3 | When developing in PHP, [composer](https://getcomposer.org/) is commonly used to manage dependencies. 4 | 5 | | Strategy | Direct Deps | Deep Deps | Edges | Classifies Dev Dependencies | 6 | | ------------- | ------------------ | ------------------ | ------------------ | --------------------------- | 7 | | composer.lock | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | 8 | 9 | ## Project Discovery 10 | 11 | Find a file named `composer.lock`. 12 | 13 | ## Analysis 14 | 15 | 1. Parse `composer.lock` to identify direct and deep dependencies. 16 | 17 | ## Example 18 | 19 | 1. Execute `composer init` to create a new project or create `composer.json` manually: 20 | 21 | Example composer.json: 22 | ```json 23 | { 24 | "name": "fossa/php-project", 25 | "description": "example php project", 26 | "require": { 27 | "michelf/php-markdown": "^1.9" 28 | }, 29 | "require-dev": { 30 | "webmozart/assert": "^1.10" 31 | }, 32 | "authors": [ 33 | { 34 | "name": "Megh", 35 | "email": "megh@fossa.com" 36 | } 37 | ] 38 | } 39 | ``` 40 | 41 | 3. Execute `composer update` to install and pin dependencies - this will create (or modify) the `composer.lock` file. 42 | 4. Execute `fossa analyze -o` on the project to print analyzed dependency graphing (this will not upload any analysis to any endpoint) 43 | 44 | ## FAQ 45 | 46 | ### How do I *only perform analysis* for the composer? 47 | 48 | You can explicitly specify an analysis target in `.fossa.yml` file. The example below will exclude all analysis targets except for the composer. 49 | 50 | ```yaml 51 | # .fossa.yml 52 | 53 | version: 3 54 | targets: 55 | only: 56 | - type: composer 57 | ``` -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/conda.md: -------------------------------------------------------------------------------- 1 | # Conda Analysis 2 | 3 | While originally created for Python programs, Conda can package and distribute software for any language. It provides a full list of all dependencies installed in the environment, without providing a dependency graph. 4 | 5 | ## Project Discovery 6 | 7 | Find the first file named `environment.yml` 8 | 9 | ## Analysis: conda list 10 | 11 | We run `conda list --json` in order to get a complete list of all installed conda packages in the conda environment. 12 | 13 | ## Analysis: environment.yml 14 | 15 | If the `conda list --json` operation does not succeed, we fall back to parsing the `environment.yml`, and getting the list of dependencies from the `dependencies` section of this file. 16 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/pipenv-graph.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | G 11 | 12 | 13 | 14 | requests 15 | 16 | requests 17 | 18 | 19 | 20 | certifi 21 | 22 | certifi 23 | 24 | 25 | 26 | requests->certifi 27 | 28 | 29 | 30 | 31 | 32 | chardet 33 | 34 | chardet 35 | 36 | 37 | 38 | requests->chardet 39 | 40 | 41 | 42 | 43 | 44 | idna 45 | 46 | idna 47 | 48 | 49 | 50 | requests->idna 51 | 52 | 53 | 54 | 55 | 56 | urllib3 57 | 58 | urllib3 59 | 60 | 61 | 62 | requests->urllib3 63 | 64 | 65 | 66 | 67 | 68 | pytest 69 | 70 | pytest 71 | 72 | 73 | 74 | attrs 75 | 76 | attrs 77 | 78 | 79 | 80 | pytest->attrs 81 | 82 | 83 | 84 | 85 | 86 | importlib-metadata 87 | 88 | importlib-metadata 89 | 90 | 91 | 92 | pytest->importlib-metadata 93 | 94 | 95 | 96 | 97 | 98 | iniconfig 99 | 100 | iniconfig 101 | 102 | 103 | 104 | pytest->iniconfig 105 | 106 | 107 | 108 | 109 | 110 | pluggy 111 | 112 | pluggy 113 | 114 | 115 | 116 | pytest->pluggy 117 | 118 | 119 | 120 | 121 | 122 | py 123 | 124 | py 125 | 126 | 127 | 128 | pytest->py 129 | 130 | 131 | 132 | 133 | 134 | toml 135 | 136 | toml 137 | 138 | 139 | 140 | pytest->toml 141 | 142 | 143 | 144 | 145 | 146 | typing-extensions 147 | 148 | typing-extensions 149 | 150 | 151 | 152 | importlib-metadata->typing-extensions 153 | 154 | 155 | 156 | 157 | 158 | zipp 159 | 160 | zipp 161 | 162 | 163 | 164 | importlib-metadata->zipp 165 | 166 | 167 | 168 | 169 | 170 | pluggy->importlib-metadata 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/pipenv-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: pipenv 2 | 3 | ## Requirements 4 | 5 | **Ideal** 6 | 7 | - `pipenv` buildtool installed 8 | - `Pipfile.lock` file present in your project 9 | 10 | **Minimum** 11 | 12 | - `Pipfile.lock` file present in your project 13 | 14 | ## Project discovery 15 | 16 | Directories containing `Pipfile.lock` files are considered pipenv projects. 17 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/pipenv.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | requests -> {certifi chardet idna urllib3}; 3 | pytest -> {attrs "importlib-metadata" iniconfig pluggy py toml}; 4 | "importlib-metadata" -> {"typing-extensions" zipp}; 5 | pluggy -> "importlib-metadata"; 6 | } -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/piplist.md: -------------------------------------------------------------------------------- 1 | # Piplist 2 | 3 | This is a really poor strategy that's used only in the worst-case: it includes 4 | packages found in the global environment, and may not contain project 5 | dependencies if `pip install` hasn't yet been run. 6 | 7 | ## Project Discovery 8 | 9 | Find directories containing `setup.py` or `requirements.txt` 10 | 11 | ## Analysis 12 | 13 | We run `pip list --format=json` and parse the output -- in the worst case, this 14 | only provides global dependencies; in the best case, the global dependencies 15 | will include our project's direct and deep dependencies. 16 | 17 | ## Example 18 | 19 | Output from the `pip list --format=json` call: 20 | *This command was run in a fresh virtualenv, after running `pip install requests`. You may see different versions or dependencies, this example is only provided as a reference.* 21 | 22 | ```json 23 | [ 24 | { 25 | "name": "certifi", 26 | "version": "2021.5.30" 27 | }, 28 | { 29 | "name": "chardet", 30 | "version": "4.0.0" 31 | }, 32 | { 33 | "name": "idna", 34 | "version": "2.10" 35 | }, 36 | { 37 | "name": "pip", 38 | "version": "21.1.3" 39 | }, 40 | { 41 | "name": "requests", 42 | "version": "2.25.1" 43 | }, 44 | { 45 | "name": "setuptools", 46 | "version": "57.0.0" 47 | }, 48 | { 49 | "name": "urllib3", 50 | "version": "1.26.6" 51 | }, 52 | { 53 | "name": "wheel", 54 | "version": "0.36.2" 55 | } 56 | ] 57 | ``` 58 | 59 | Notice that `pip`, `setuptools` and `wheel` are discovered, even though they are only used to power `pip` commands. 60 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/poetry-with-lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 00 13 | 14 | https://github.com/networkx/networkx.git(=v1.10) 16 | 17 | 18 | 19 | 01 20 | 22 | decorator(=5.0.9) 24 | 25 | 26 | 27 | 00->01 28 | 29 | 30 | 31 | 32 | 33 | 02 34 | 35 | flake8(=3.9.2) 37 | 38 | 39 | 40 | 03 41 | 43 | mccabe(=0.6.1) 45 | 46 | 47 | 48 | 02->03 49 | 50 | 51 | 52 | 53 | 54 | 04 55 | 57 | pycodestyle(=2.7.0) 59 | 60 | 61 | 62 | 02->04 63 | 64 | 65 | 66 | 67 | 68 | 05 69 | 71 | pyflakes(=2.3.1) 73 | 74 | 75 | 76 | 02->05 77 | 78 | 79 | 80 | 81 | 82 | 06 83 | 84 | loguru(=0.5.3) 86 | 87 | 88 | 89 | 07 90 | 92 | colorama(=0.4.4) 94 | 95 | 96 | 97 | 06->07 98 | 99 | 100 | 101 | 102 | 103 | 08 104 | 106 | win32-setctime(=1.0.3) 108 | 109 | 110 | 111 | 06->08 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/poetry-without-lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 00 13 | 14 | https://github.com/networkx/networkx.git(=v1.10) 16 | 17 | 18 | 19 | 01 20 | 21 | flake8(=3.9.2) 23 | 24 | 25 | 26 | 02 27 | 28 | loguru(~0.5) 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/poetry.md: -------------------------------------------------------------------------------- 1 | # Poetry 2 | 3 | [Poetry](https://python-poetry.org/) is a tool for dependency management and packaging in Python. 4 | 5 | ## Project Discovery 6 | 7 | Find files named `pyproject.toml` and `poetry.lock`. Pyproject must also use poetry for the [build system](https://python-poetry.org/docs/pyproject/#poetry-and-pep-517). If Pyproject does not use poetry build system - project will not be discovered. 8 | 9 | ## Analysis 10 | 11 | We parse `pyproject.toml` to find direct dependencies and their [version constraints](https://python-poetry.org/docs/dependency-specification/): 12 | 13 | - `[tool.poetry.dependencies]` - production dependencies 14 | - `[tool.poetry.dev-dependencies]` - development dependencies 15 | 16 | If `poetry.lock` file is discovered, following will be analyzed from lockfile to supplement the analyses: 17 | 18 | - `[package.dependencies]` - package's dependencies 19 | - `package.category` - package's environment (dev, test, etc.) 20 | - `package.name` - name of the package 21 | - `package.version` - resolved version of the package 22 | 23 | If `poetry.lock` file is not discovered, we fallback to reporting only direct dependencies parsed from `pyproject.toml`. 24 | 25 | | Strategy | Direct Deps | Deep Deps | Edges | 26 | | ------------------------------------------------- | ------------------ | ------------------ | ------------------ | 27 | | `pyproject.toml` and `poetry.lock` are discovered | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | 28 | | Only `pyproject.toml` is discovered | :heavy_check_mark: | :x: | :x: | 29 | | Only `poetry.lock` is discovered | :x: | :x: | :x: | 30 | 31 | - :heavy_check_mark: - Supported in all projects 32 | - :x: - Not Supported 33 | 34 | ### Limitations 35 | 36 | - For poetry project, build system's `build-backend` must be set to `poetry.core.masonry.api` or `poetry.masonry.api` in `pyproject.toml`. If not done so, it will not discover the project. Refer to [Poetry and PEP-517](https://python-poetry.org/docs/pyproject/#poetry-and-pep-517) for more details. 37 | - All extras specified in `[tool.poetry.extras]` are currently not reported. 38 | - Any [path dependencies](https://python-poetry.org/docs/dependency-specification/#path-dependencies) will not be reported. 39 | 40 | ## Example 41 | 42 | `pyproject.toml` file (created by `poetry init` and adding relevant dependencies) 43 | 44 | ```toml 45 | [tool.poetry] 46 | authors = ["User "] 47 | description = "Example poetry usage" 48 | name = "example-poetry-usage" 49 | version = "0.1.0" 50 | 51 | [tool.poetry.dependencies] 52 | loguru = "^0.5" 53 | networkx = {git = "https://github.com/networkx/networkx.git", branch = "v1.10"} 54 | python = "^3.9" 55 | 56 | [tool.poetry.dev-dependencies] 57 | flake8 = "3.9.2" 58 | 59 | [build-system] 60 | build-backend = "poetry.core.masonry.api" 61 | requires = ["poetry-core>=1.0.0"] 62 | ``` 63 | 64 | and accompanying poetry.lock file (created by poetry at time of dependency resolution) 65 | 66 | ```toml 67 | [[package]] 68 | name = "colorama" 69 | version = "0.4.4" 70 | description = "Cross-platform colored terminal text." 71 | category = "main" 72 | optional = false 73 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 74 | 75 | [[package]] 76 | name = "decorator" 77 | version = "5.0.9" 78 | description = "Decorators for Humans" 79 | category = "main" 80 | optional = false 81 | python-versions = ">=3.5" 82 | 83 | [[package]] 84 | name = "flake8" 85 | version = "3.9.2" 86 | description = "the modular source code checker: pep8 pyflakes and co" 87 | category = "dev" 88 | optional = false 89 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 90 | 91 | [package.dependencies] 92 | mccabe = ">=0.6.0,<0.7.0" 93 | pycodestyle = ">=2.7.0,<2.8.0" 94 | pyflakes = ">=2.3.0,<2.4.0" 95 | 96 | [[package]] 97 | name = "loguru" 98 | version = "0.5.3" 99 | description = "Python logging made (stupidly) simple" 100 | category = "main" 101 | optional = false 102 | python-versions = ">=3.5" 103 | 104 | [package.dependencies] 105 | colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} 106 | win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} 107 | 108 | [package.extras] 109 | dev = ["codecov (>=2.0.15)", "colorama (>=0.3.4)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "tox-travis (>=0.12)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "Sphinx (>=2.2.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "black (>=19.10b0)", "isort (>=5.1.1)"] 110 | 111 | [[package]] 112 | name = "mccabe" 113 | version = "0.6.1" 114 | description = "McCabe checker, plugin for flake8" 115 | category = "dev" 116 | optional = false 117 | python-versions = "*" 118 | 119 | [[package]] 120 | name = "networkx" 121 | version = "1.10" 122 | description = "Python package for creating and manipulating graphs and networks" 123 | category = "main" 124 | optional = false 125 | python-versions = "*" 126 | develop = false 127 | 128 | [package.dependencies] 129 | decorator = ">=3.4.0" 130 | 131 | [package.source] 132 | type = "git" 133 | url = "https://github.com/networkx/networkx.git" 134 | reference = "v1.10" 135 | resolved_reference = "4d364bfcee7b24f3df137e8dcd36f7a547892e55" 136 | 137 | [[package]] 138 | name = "pycodestyle" 139 | version = "2.7.0" 140 | description = "Python style guide checker" 141 | category = "dev" 142 | optional = false 143 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 144 | 145 | [[package]] 146 | name = "pyflakes" 147 | version = "2.3.1" 148 | description = "passive checker of Python programs" 149 | category = "dev" 150 | optional = false 151 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 152 | 153 | [[package]] 154 | name = "win32-setctime" 155 | version = "1.0.3" 156 | description = "A small Python utility to set file creation time on Windows" 157 | category = "main" 158 | optional = false 159 | python-versions = ">=3.5" 160 | 161 | [package.extras] 162 | dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"] 163 | 164 | [metadata] 165 | lock-version = "1.1" 166 | python-versions = "^3.9" 167 | content-hash = "31cb32d5165d1cc95e45e9d3e839af556f548df74dda74e25a02b79ba5aa5948" 168 | 169 | # [metadata.files] not shown for brevity 170 | ``` 171 | 172 | We will produce the following dependency graph, from our analyses if both `poetry.lock` and `pyproject.toml` are discovered. 173 | 174 | ![With poetry.lock file](poetry-with-lock.svg) 175 | _Dependencies highlighted in yellow boxes are direct dependencies, rest are deep dependencies._ 176 | 177 | If only, `pyproject.toml` is discovered, following dependency graph will be produced. 178 | 179 | ![Without poetry.lock file](poetry-without-lock.svg) 180 | _Dependencies highlighted in yellow boxes are direct dependencies, rest are deep dependencies._ 181 | 182 | Without `poetry.lock` we are not able to identify any deep dependencies. We are also unable to locally resolve dependency when version ranges are provided, like `loguru = "^0.5"`. 183 | 184 | ### References 185 | 186 | - [Poetry Source Code](https://github.com/python-poetry/poetry) 187 | - [Poetry Documentation](https://python-poetry.org/docs/) 188 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/python.md: -------------------------------------------------------------------------------- 1 | # Python Analysis 2 | 3 | The python buildtool ecosystem consists of three major toolchains: setuptools 4 | (requirements.txt, setup.py), pipenv, and conda. 5 | 6 | | Strategy | Direct Deps | Deep Deps | Edges | 7 | | ------------------------------------------- | ------------------ | ------------------ | ------------------ | 8 | | [pipenv][pipenv] (pipenv) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | 9 | | [pipfile][pipenv] (pipenv) | :heavy_check_mark: | :heavy_check_mark: | :x: | 10 | | [requirements.txt][setuptools] (setuptools) | :heavy_check_mark: | :x: | :x: | 11 | | [setup.py][setuptools] (setuptools) | :heavy_check_mark: | :x: | :x: | 12 | | [piplist][piplist] | :white_check_mark: | :white_check_mark: | :x: | 13 | | [conda][conda] (conda) | :heavy_check_mark: | :heavy_check_mark: | :x: | 14 | | [poetry][poetry] (poetry) | :heavy_check_mark: | :white_check_mark: | :white_check_mark: | 15 | 16 | * :heavy_check_mark: - Supported in all projects 17 | * :white_check_mark: - Supported only when relevant data is available (e.g. lockfiles are present) 18 | * :x: - Not Supported 19 | 20 | [pipenv](pipenv.md) 21 | [setuptools](setuptools.md) 22 | [piplist](piplist.md) 23 | [conda](conda.md) 24 | [poetry](poetry.md) 25 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/setuptools-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: setuptools 2 | 3 | ## Requirements 4 | 5 | **Ideal** 6 | 7 | - `requirements.txt` files present in your project 8 | 9 | **Minimum** 10 | 11 | - `setup.py` files present in your project. 12 | 13 | Unfortunately, we fail to parse many valid `setup.py` files. In general, we recommend the use of `requirements.txt` files for better analysis. 14 | 15 | ## Project discovery 16 | 17 | Directories containing `setup.py` files or `requirements.txt`-like files (e.g., `req-dev.txt`, `test-requires.txt` are valid -- or any filename matching the regex `.*req.*\.txt`) are treated as setuptools projects. 18 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/python/setuptools.md: -------------------------------------------------------------------------------- 1 | # Setuptools (requirements.txt/setup.py) 2 | 3 | requirements.txt, alongside setup.py, is the most common -- yet imprecise -- 4 | approach to dependency management in python projects. 5 | 6 | ## Project Discovery 7 | 8 | `requirements.txt`: Find all files matching the glob: `req*.txt` 9 | 10 | `setup.py`: Find all files named `setup.py` 11 | 12 | ## Analysis: requirements.txt 13 | 14 | requirements.txt contains direct dependencies, and is parsed compliant to its 15 | [file format spec][requirements-file-format]. 16 | 17 | pip-cli options, URLs, absolute paths, and relative paths are ignored -- though 18 | this may be revisited in the future. 19 | 20 | Dependencies found in requirements.txt have a spec defined by 21 | [PEP-508][pep-508]. Dependencies often have version ranges and environment 22 | markers (e.g. python version, OS, ...). The resulting graph contains packages 23 | tagged with environment markers. 24 | 25 | ## Analysis: setup.py 26 | 27 | setup.py is naively scanned for its `install_requires=[...]` field, which often 28 | fails on projects encountered in the wild. Short of implementing a robust python 29 | parser, or running a python script in their environment (which may have 30 | unintended consequences!), reliable output from setup.py is difficult to obtain. 31 | 32 | Entries in the `install_requires` array are parsed compliant to the 33 | [PEP-508][pep-508] spec, similar to requirements.txt 34 | 35 | [requirements-file-format]: https://pip.pypa.io/en/stable/cli/pip_install/#requirements-file-format 36 | [pep-508]: https://www.python.org/dev/peps/pep-0508/ 37 | 38 | ## Limitations 39 | 40 | * Python requirements files and setup.py files do not provide any data about edges between dependencies. 41 | * Requirements files can be completely different than an existing setup.py specification, as there is no built-in 42 | synchronization between them. 43 | * Since we don't completely parse the python files, any programmability done in the `setup.py` file will hide the 44 | true `install_requires` list from our view. However, we do catch *variables* named `install_requires` as well, as 45 | long as they are declared earlier in the file than the `install_requires` keyword argument to `setup`. 46 | * Often, the `requirements.txt` file entirely overlaps the `setup.py` file. This is almost always by design. 47 | 48 | ## Examples 49 | 50 | Given the following files: 51 | 52 | `setup.py` (manually created): 53 | 54 | ```python 55 | setup( 56 | name='Foo-project', 57 | version='1.0', 58 | description='Python example project', 59 | author='Jeff Jefferson', 60 | author_email='bug-catcher@butterfly.net', 61 | url='https://this.url/means#nothing', 62 | packages=['foo'], 63 | # And now the important part... 64 | install_requires=[ 65 | "requests", 66 | ], 67 | ) 68 | ``` 69 | 70 | `requirements.txt` (obtained by running `pip install requests && pip freeze > requirements.txt`): 71 | *Note: your requirements file may have different versions. This file is just a reference example.* 72 | 73 | ```txt 74 | certifi==2021.5.30 75 | chardet==4.0.0 76 | idna==2.10 77 | requests==2.25.1 78 | urllib3==1.26.6 79 | ``` 80 | 81 | We will produce a list of these direct dependencies with no edges between them (see [#limitations](#limitations)): 82 | 83 | ```txt 84 | certifi==2021.5.30 85 | chardet==4.0.0 86 | idna==2.10 87 | requests==2.25.1 88 | urllib3==1.26.6 89 | ``` 90 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/ruby/bundler.md: -------------------------------------------------------------------------------- 1 | # Quick reference: bundler 2 | 3 | ## Requirements 4 | 5 | **Ideal** 6 | 7 | - `bundler` installed locally 8 | - `Gemfile` or `Gemfile.lock` file present in your project 9 | 10 | **Minimum** 11 | 12 | - `Gemfile.lock` file present in your project 13 | 14 | ## Project discovery 15 | 16 | Directories containing `Gemfile` or `Gemfile.lock` files are considered 17 | Ruby projects. 18 | 19 | Subdirectory scans are not affected by the discovery of a Ruby project. 20 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/ruby/ruby.md: -------------------------------------------------------------------------------- 1 | # Ruby Analysis 2 | 3 | Ruby projects use a buildtool called `bundler` to manage their dependencies. We 4 | parse a lockfile or run the `bundle` cli to determine dependencies. 5 | 6 | | Strategy | Direct Deps | Deep Deps | Edges | Tags | 7 | | --- | --- | --- | --- | --- | 8 | | gemfilelock | ✅ | ✅ | ✅ | | 9 | | bundleshow | ✅ unlabeled | ✅ unlabeled | ❌ | | 10 | 11 | ## Project Discovery 12 | 13 | `gemfilelock`: Find all files named `Gemfile.lock` 14 | 15 | `bundleshow`: Find directories containing a `Gemfile` or `Gemfile.lock` 16 | 17 | ## Analysis: gemfilelock 18 | 19 | > TLDR: A perfect dependency graph will be found and dependencies location will also be known. 20 | 21 | The lockfile strategy attempts to parse Bundler's `Gemfile.lock` lockfile. This file is created by bundler itself after a build is completed and can be distributed in order to maintain reproducible builds. It contains the following information about a Ruby project: 22 | - The location for each dependency. These locations are each separate sections and the ones of note are `GIT`, `PATH`, and `GEM` which provide their remote in the `remote: ` line. 23 | - Each dependencies required dependencies. These required dependencies are listed in the remote sections directly following each dependency from that remote. 24 | - All direct dependencies, listed in the `DEPENDENCIES` section. 25 | - Platforms that this ruby project is compatible with, listed in the `PLATFORMS` sections. 26 | - Version of `bundler` that was used to create the lockfile. 27 | 28 | The Lockfile strategy relies on parsing this `Gemfile.lock` file and extracting 29 | information from each of these sections. This strategy takes the following steps 30 | to create an accurate dependency graph. Example `Gemfile.lock`: 31 | 32 | ``` 33 | GIT 34 | remote: https://github.com/matthewd/rb-inotify.git 35 | revision: 856730aad4b285969e8dd621e44808a7c5af4242 36 | branch: close-handling 37 | specs: 38 | rb-inotify (0.9.9) 39 | ffi (~> 1.0) 40 | PATH 41 | remote: . 42 | specs: 43 | activesupport (6.0.0.alpha) 44 | concurrent-ruby (~> 1.0, >= 1.0.2) 45 | i18n (>= 0.7, < 2) 46 | minitest (~> 5.1) 47 | rails (6.0.0.alpha) 48 | sprockets-rails (>= 2.0.0) 49 | GEM 50 | remote: https://rubygems.org/ 51 | specs: 52 | concurrent-ruby (1.0.5) 53 | ffi (1.9.21) 54 | i18n (1.0.1) 55 | concurrent-ruby (~> 1.0) 56 | minitest (5.11.3) 57 | rack (2.0.5) 58 | sprockets-rails (3.2.1) 59 | actionpack (>= 4.0) 60 | activesupport (>= 4.0) 61 | sprockets (>= 3.0.0) 62 | PLATFORMS 63 | java 64 | ruby 65 | x64-mingw32 66 | x86-mingw32 67 | DEPENDENCIES 68 | rails! 69 | rake (>= 11.1) 70 | rb-inotify! 71 | BUNDLED WITH 72 | 1.16.2 73 | ``` 74 | 75 | ## Analysis: bundleshow 76 | 77 | Running `bundle show` displays information about all dependencies used by a 78 | project, and their pinned versions. It doesn't label which dependencies are 79 | direct or deep, and doesn't tell us edges between dependencies 80 | 81 | Example output: 82 | 83 | ``` 84 | Gems included by the bundle: 85 | * CFPropertyList (3.0.1) 86 | * addressable (2.7.0) 87 | * ast (2.4.0) 88 | * atomos (0.1.3) 89 | * babosa (1.0.2) 90 | * binding_of_caller (0.8.0) 91 | * builder (3.2.3) 92 | * bundler (1.17.2) 93 | * byebug (11.0.1) 94 | * claide (1.0.3) 95 | * claide-plugins (0.9.2) 96 | * coderay (1.1.2) 97 | ``` 98 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/rust/cargo.md: -------------------------------------------------------------------------------- 1 | # Quick reference: cargo 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | 7 | - `cargo` buildtool installed on your machine 8 | - `Cargo.toml` file present in your project 9 | 10 | ## Project discovery 11 | 12 | Directories containing `Cargo.toml` files are considered cargo projects. 13 | 14 | Subdirectories of cargo projects are not re-scanned for nested cargo projects, because the dependency tree of the parent project already includes the dependency tree of those subprojects. To scan only the subprojects, run the `fossa` tool against the subproject directories 15 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/rust/rust.md: -------------------------------------------------------------------------------- 1 | # Rust Analysis 2 | 3 | The rust buildtool ecosystem is nearly exclusive to `cargo`, the package manager 4 | that ships with rust distributions. There are rare, but known cases of generic 5 | buildtools being used, like `make`, `cmake`, and `ninja`. These cases are not 6 | handled here. 7 | 8 | | Strategy | Direct Deps | Deep Deps | Edges | Tags | 9 | | --- | --- | --- | --- | --- | 10 | | cargo | ✅ | ✅ | ✅ | Environment | 11 | 12 | ## Project Discovery 13 | 14 | Find all files with a `Cargo.toml` file, where no direct or indirect parent also 15 | contains a `Cargo.toml` file. 16 | 17 | For example, given the following tree, we would only examine `root/Cargo.toml`. 18 | 19 | ``` 20 | root 21 | ├── src1 22 | │ ├── subpackage 23 | │ │ ├── Cargo.toml 24 | │ │ └── ... 25 | │ └── main.rs 26 | ├── src2 27 | │ ├── subpackage 28 | │ │ ├── Cargo.toml 29 | │ │ └── ... 30 | │ └── main.rs 31 | └── Cargo.toml 32 | ``` 33 | 34 | However, in the following tree, we examine `root/pkg1/Cargo.toml` and 35 | `root/pkg2/Cargo.toml`, since neither has a parent directory with a `Cargo.toml` 36 | file. 37 | 38 | ``` 39 | root 40 | ├── pkg1 41 | │ ├── Cargo.toml 42 | │ └── main.rs 43 | └── pkg2 44 | ├── Cargo.toml 45 | └── main.rs 46 | ``` 47 | 48 | ## Analysis 49 | 50 | First, we invoke `cargo generate-lockfile` to trigger the lockfile build. This 51 | downloads the dependency graph info and almost nothing else. Then, we read the 52 | output of the `cargo metadata --format-version 1` command (format version 1 is JSON, 53 | and is currently the only allowed formatting scheme). This will arrange the data 54 | into a slightly simpler scheme. 55 | 56 | **NOTE**: If we do not attempt to regenerate the lockfile, we may try to download 57 | every dependency in the tree. This can take upwards of 10 minutes even for small 58 | projects, which is wasteful and unnecessary. However, if the lockfile has recently 59 | been generated, it will try to update the package index. This usually takes about 60 | 2-10 seconds, which is potentially wasteful, but far less so than the 10 minutes 61 | that it would take to download entire crates. 62 | 63 | We can interrogate the JSON output for direct and deep dependency info, but it is 64 | non-trivial to do so. For more info, see the metadata schema found 65 | [here](https://doc.rust-lang.org/cargo/commands/cargo-metadata.html) 66 | 67 | The analysis of the JSON is slightly complex, but is roughly as follows: 68 | 69 | * Check `.workspace_members` for a list of packages which represent the current 70 | package and any sub packages. For now we'll call these *local crates*. 71 | * Examine `.resolve` (a flattened dependency graph), for each of the local crates to 72 | fetch the list of direct dependencies of that crate. Call this a *dependency node*. 73 | * For each dependency node, we are able to retreive some info directly, like its 74 | version, whether it is platform-specific, what build category it's included in 75 | (build, dev, or standard), and what features it compiles with. For any further 76 | information, we have to compare this package and version with the corresponding 77 | entry in `.packages`. 78 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/scala/sbt-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: sbt 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | 7 | - `sbt` buildtool installed 8 | - `build.sbt` file present in your project 9 | 10 | ## Project discovery 11 | 12 | Directories containing `build.sbt` files are treated as sbt projects 13 | -------------------------------------------------------------------------------- /docs/references/strategies/languages/scala/sbt.md: -------------------------------------------------------------------------------- 1 | # sbt Analysis 2 | 3 | While the other analysis strategies for `gradle` and `maven` offer some scala project coverage, scala projects overwhelmingly use the build tool `sbt`. 4 | 5 | | Strategy | Direct Deps | Deep Deps | Edges | Tags | 6 | | --- | --- | --- | --- | --- | 7 | | sbt | ✅ | ✅ | ✅ | | 8 | 9 | ## Requirements 10 | 11 | - A locally-installed `sbt` 12 | 13 | ## Project Discovery 14 | 15 | Directories that contain `build.sbt` files are treated as sbt projects 16 | 17 | ## Analysis 18 | 19 | 1. Run `sbt makePom` to generate pom files 20 | 2. Use the pom.xml maven strategy to "link together" related poms into projects, and extract a dependency graph 21 | -------------------------------------------------------------------------------- /docs/references/strategies/platforms/conda/conda.md: -------------------------------------------------------------------------------- 1 | # Quick reference: conda 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | 7 | - `environment.yml` file present in your project 8 | 9 | ## Project discovery 10 | 11 | Directories containing an `environment.yml` file are considered conda projects. 12 | -------------------------------------------------------------------------------- /docs/references/strategies/platforms/ios/carthage-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: carthage 2 | 3 | ## Requirements 4 | 5 | **Ideal/Minimum** 6 | - `Cartfile.resolved` file present in your project 7 | 8 | ## Project discovery 9 | Directories containing `Cartfile.resolved` files are considered carthage projects. Subdirectories of carthage project root directories are not scanned for nested carthage projects. 10 | -------------------------------------------------------------------------------- /docs/references/strategies/platforms/ios/carthage.md: -------------------------------------------------------------------------------- 1 | # Carthage Analysis 2 | 3 | ## Project Discovery 4 | 5 | Find any folder which contains a file named `Cartfile.resolved`. Skip all 6 | subdirectories if one is found. 7 | 8 | ## Analysis 9 | 10 | The `Cartfile.resolved` file contains a list of direct dependencies, which 11 | should each represent subfolders in the `Carthage/Checkouts` directory. This 12 | structure is recursively scanned and combined into a single analysis. See 13 | below for an example: 14 | 15 | ``` 16 | myproject 17 | ├─ Cartfile.resolved # ref to "Quick/Nimble" 18 | └─ Carthage/ 19 | └─ Checkouts/ 20 | └─ Nimble/ 21 | ├─ Cartfile.resolved # ref to "mattgallagher/CwlPreconditionTesting" 22 | └─ Carthage/ 23 | └─ Checkouts/ 24 | └─ CwlPreconditionTesting/ # and so on... 25 | ``` -------------------------------------------------------------------------------- /docs/references/strategies/platforms/ios/cocoapods-qr.md: -------------------------------------------------------------------------------- 1 | # Quick reference: cocoapods 2 | 3 | ## Requirements 4 | 5 | **Ideal** 6 | 7 | - `Podfile.lock` file present in your project 8 | 9 | **Minimum** 10 | 11 | - `Podfile` file present in your project 12 | 13 | ## Project discovery 14 | 15 | Directories containing `Podfile` or `Podfile.lock` files are considered 16 | cocoapods projects. 17 | -------------------------------------------------------------------------------- /docs/references/strategies/platforms/ios/cocoapods.md: -------------------------------------------------------------------------------- 1 | # Cocoapods Analysis 2 | 3 | ## Project Discovery 4 | 5 | `podfile`: Find all directories containing a `Podfile` file. 6 | 7 | `podfilelock`: Find all directories containing a `Podfile.lock` file. 8 | 9 | ## Analysis: podfile 10 | 11 | We scan the `Podfile` text for `pod` declarations, which indicate a direct 12 | dependency of the current project. We also scan for a `source` declaration, 13 | which gives us a default source to assign to all `pod` declarations without an 14 | explicit source. 15 | 16 | ## Analysis: podfilelock 17 | 18 | We scan the `Podfile.lock` for two particular sections: `PODS` and 19 | `DEPENDENCIES`. The `PODS` section describes the relationships between the 20 | dependencies, and `DEPENDENCIES` tells us which of the dependencies the project 21 | depends on directly. 22 | 23 | In the following example, we have five dependencies, `one`, `two`, `three`, 24 | `four` and `five/+zlib`. `one`, `three` and `five/+zlib` are direct dependencies, `one` depends on both 25 | `two` and `three`, and `three` depends on `four`. 26 | 27 | ``` 28 | PODS: 29 | - one (1.0.0): 30 | - two (= 3.2.1) 31 | - three (= 3.2.1) 32 | - two (2.0.0) 33 | - three (3.0.0) 34 | - four (= 2.3.3) 35 | - four (4.0.0): 36 | - "five/+zlib (7.0.0)" 37 | 38 | DEPENDENCIES: 39 | - one (> 4.4) 40 | - three (from `Submodules/subproject/.podspec`) 41 | - "five/+zlib (7.0.0)" 42 | ``` 43 | 44 | ## Limitations 45 | 46 | - Pods sourced from local path are not supported (e.g. `pod 'AFNetworking', :path => '~/Documents/AFNetworking'`). 47 | - Pods sourced from http path are not supported (e.g `pod 'JSONKit', :podspec => 'https://example.com/JSONKit.podspec'`). 48 | - Pods sourced from subversion, mercurial, and bazaar are not supported. 49 | - Plugins in Podfiles are ignored. -------------------------------------------------------------------------------- /docs/references/strategies/platforms/ios/ios.md: -------------------------------------------------------------------------------- 1 | # Swift/Objective-C Analysis 2 | 3 | The iOS buildtool ecosystem consists of two major toolchains: `Carthage` and `Cocoapods` 4 | 5 | | Strategy | Direct Deps | Deep Deps | Edges | 6 | | --- | --- | --- | --- | 7 | | [Carthage][cart] | ✅ | ✅ | ✅ | 8 | | [Podfile.lock][coco] | ✅ | ✅ | ✅ | 9 | | [Podfile][coco] | ✅ | ❌ | ❌ | 10 | 11 | [cart](carthage.md) 12 | [coco](cocoapods.md) 13 | -------------------------------------------------------------------------------- /docs/references/strategies/platforms/ios/swift.md: -------------------------------------------------------------------------------- 1 | # Swift Package Manager 2 | 3 | ## Project Discovery 4 | 5 | Find all files named: `Package.swift` or find Xcode's project file named: `project.pbxproj`. 6 | We will not scan `.build` directory if the `Package.swift` or Xcode project file is discovered. 7 | 8 | # Swift Analysis 9 | 10 | | Strategy | Direct Deps | Deep Deps | Edges | Classifies Test Dependencies | 11 | | ------------------------------------------------------------------------ | ------------------ | ------------------ | ----- | ---------------------------- | 12 | | Parse dependencies from `Package.swift` | :white_check_mark: | :x: | :x: | :x: | 13 | | Parse dependencies from `Package.swift` and `Package.resolved` | :white_check_mark: | :white_check_mark: | :x: | :x: | 14 | | Parse dependencies from Xcode's `project.pbxproj` | :white_check_mark: | :x: | :x: | :x: | 15 | | Parse dependencies from Xcode's `project.pbxproj` and `Package.resolved` | :white_check_mark: | :white_check_mark: | :x: | :x: | 16 | 17 | - Manifest file: `Package.swift`, must begin with `// swift-tools-version:` string, followed by version number specifier. 18 | - We follow swift package manager's convention and presume properties of the package are defined in a single nested initializer statement and are not modified after initialization. 19 | - Valid Xcode project for swift, is defined by the discovery of `project.pbxproj` file in ASCII plist format with at least one `XCRemoteSwiftPackageReference` object in its content. 20 | 21 | ## Limitations 22 | 23 | - Path dependencies are ignored in the analysis (e.g. `package(path: "./../local-pkg")`) 24 | - If the Xcode project dependencies are sourced via a local path, they will be ignored in the analysis. 25 | - Only Xcode project files in ASCII plist format with UTF-8 encoding are supported. 26 | 27 | ## Example 28 | 29 | Create Package.swift file in the directory. Add dependencies, targets, products, and source code. Example Package.swift file is shown below. By convention, the properties of a Package are defined in a single nested initializer statement, and not modified after initialization. 30 | 31 | ```swift 32 | // swift-tools-version:5.4.0 33 | import PackageDescription 34 | 35 | let package = Package( 36 | name: "Example", 37 | defaultLocalization: "en", 38 | products: [], 39 | dependencies: [ 40 | .package(name: "grpc-swift", url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0"), 41 | ] 42 | ) 43 | ``` 44 | 45 | We can update and resolve dependencies by performing `swift package update`. Executing this will create Package.resolved in the directory. An example file is shown below: 46 | 47 | ```json 48 | { 49 | "object": { 50 | "pins": [ 51 | { 52 | "package": "grpc-swift", 53 | "repositoryURL": "https://github.com/grpc/grpc-swift.git", 54 | "state": { 55 | "branch": null, 56 | "revision": "14e1ea3350892a864386517c037e11fb68baf818", 57 | "version": "1.3.0" 58 | } 59 | }, 60 | { 61 | "package": "swift-log", 62 | "repositoryURL": "https://github.com/apple/swift-log.git", 63 | "state": { 64 | "branch": null, 65 | "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7", 66 | "version": "1.4.2" 67 | } 68 | } 69 | ] 70 | }, 71 | "version": 1 72 | } 73 | 74 | ``` 75 | Note: Only a few pins are shown above for brevity. 76 | 77 | ### `Package.swift` and `Package.resolved` 78 | 79 | When the analysis is performed (e.g. `fossa analyze -o`), we will identify the following as direct dependencies: 80 | 81 | - https://github.com/grpc/grpc-swift.git with version 1.3.0 82 | 83 | If `Package.resolved` is discovered, the following deep dependencies will be identified, however, we will not identify the edges in the dependency graph: 84 | 85 | - https://github.com/apple/swift-log.git with version 1.4.2 86 | 87 | If `Package.resolved` is not discovered, only direct dependencies will be reported. 88 | 89 | ### Xcode Project and `Package.resolved` 90 | 91 | For Xcode project using swift package manager to manage swift package dependencies, Xcode project file named `project.pbxproj` will be analyzed. In the Xcode project file, `XCRemoteSwiftPackageReference` objects will be used to identify swift packages that are direct dependencies. For the analysis, at least one such reference must exist in the file. If no such references are found, we will not consider the Xcode project in the swift analysis. 92 | 93 | Excerpt from example `project.pbxproj`: 94 | 95 | ``` 96 | // !$*UTF8*$! 97 | { 98 | archiveVersion = 1; 99 | classes = { 100 | }; 101 | objectVersion = 52; 102 | objects = { 103 | 104 | ... 105 | 106 | 170A463726ECEDEF002DDFB8 /* XCRemoteSwiftPackageReference "example-package-deckofplayingcards" */ = { 107 | isa = XCRemoteSwiftPackageReference; 108 | repositoryURL = "https://github.com/apple/example-package-deckofplayingcards"; 109 | requirement = { 110 | branch = main; 111 | kind = branch; 112 | }; 113 | }; 114 | 115 | ... 116 | }; 117 | rootObject = 17874CD926C46B8500D16CA8 /* Project object */; 118 | } 119 | ``` 120 | 121 | If the `Package.resolved` is discovered, deep dependencies will be identified. If not, only direct dependencies listed in xcode project file will be identified. In either case, no edges among dependencies will be reported. 122 | 123 | ## F.A.Q 124 | 125 | ### How do I *only perform analysis* for swift package dependencies? 126 | 127 | You can explicitly specify the analysis target in `.fossa.yml` file. 128 | 129 | The example below will exclude all analysis targets except swift. 130 | 131 | ```yaml 132 | # .fossa.yml 133 | 134 | version: 3 135 | targets: 136 | only: 137 | - type: swift 138 | ``` 139 | 140 | ### Swift packages sourced from local directories are not discovered in the analysis. Is there a workaround? 141 | 142 | This is a current limitation. For swift package manager analysis, we only support non-path dependencies at the moment. 143 | To include local dependencies, you can use `fossa-deps.yml` file to upload the local package for license scanning and analysis. 144 | 145 | ```yaml 146 | # in fossa-deps.yml 147 | 148 | vendored-dependencies: 149 | - name: MyLocalPackage 150 | path: /Jenkins/App/Resources/MyLocalPackage # path can be either a file or a folder. 151 | version: 3.4.16 # revision will be set to the MD5 hash of the file path if left unspecified. 152 | ``` 153 | 154 | Note: License scanning currently operates by uploading the files at the specified path to a secure S3 bucket. All files that do not contain licenses are then removed after 2 weeks. 155 | Refer to [vendored dependencies](../../../../features/vendored-dependencies.md) for more details. 156 | 157 | ### When performing `fossa list-targets`, Xcode project using swift packages are not getting discovered. 158 | 159 | For swift, we consider the Xcode project to be a valid Xcode project, if and only if it meets the following requirements: 160 | - Xcode project file named: `project.pbxproj` exists in the directory. 161 | - Xcode project file must be in ASCII plist format with UTF-8 encoding. 162 | - Xcode project file has at least one object, with isa of `XCRemoteSwiftPackageReference`. 163 | 164 | ## References 165 | 166 | - [Swift Package Manager](https://github.com/apple/swift-package-manager) 167 | - [Package.swift, must begin with version specifier](https://github.com/apple/swift-package-manager/blob/main/Documentation/PackageDescription.md#about-the-swift-tools-version) 168 | - [Package.swift, must be defined in a single nested statement, and should not be modified after initialization](https://github.com/apple/swift-package-manager/blob/main/Documentation/PackageDescription.md#package) -------------------------------------------------------------------------------- /docs/references/strategies/system/rpm/rpm.md: -------------------------------------------------------------------------------- 1 | # RPM analysis 2 | 3 | RPM packages managed by system package managers like `dnf` and `yum` are built 4 | using SPEC files. We are able to analyze these files to determine runtime 5 | dependencies. 6 | 7 | | Strategy | Direct Deps | Deep Deps | Edges | Tags | 8 | | --- | --- | --- | --- | --- | 9 | | rpm-spec | ✅ | ❌ | ❌ | Environment | 10 | 11 | ## Project Discovery 12 | 13 | RPM SPEC files have strict naming conventions. They must be in the form of 14 | `.spec`, e.g.: `binutils.spec`. We scan any file with a `.spec` 15 | file extension. 16 | 17 | ## Analysis 18 | 19 | Currently, we scan for lines which start with `Requires:`, followed by at 20 | least one space. On this line we extract EXACTLY ONE package, which may 21 | optionally specify a single version constraint. This package and its 22 | constraint are considered a single, direct, runtime dependency. 23 | 24 | ## Limitations 25 | 26 | The SPEC file format is simple, yet robust. We currently do not support all of 27 | its features yet. Notably, we do not support the following: 28 | 29 | * Combinatoric version constraints, such as `(>= 1.2 and != 1.4) or = 0.9` 30 | * Parentheses, as well as the `and` and `or` constructs are not supported yet. 31 | * Build-time requirements 32 | * We currently parse these, since the form is identical to runtime dependencies 33 | (`BuildRequires:` vs. `Requires:`), but we do not know if this is valuable 34 | for users, since some of these dependencies are tools like compilers (`gcc` 35 | is a common build-time dependency). 36 | * Macros, such as `xxxxxx-%{?_isa}`, or `xxxxx = %{version}-%{release}` 37 | * SPEC files allow for a few macros to dynamically determine package names/versions. 38 | We do not yet support this, although we may support it in the future. 39 | -------------------------------------------------------------------------------- /docs/references/subcommands/analyze.md: -------------------------------------------------------------------------------- 1 | ## `fossa analyze` 2 | 3 | By default, the analyze command: 4 | 5 | - looks for projects in the current directory (and recursively in subdirectories) 6 | - extracts dependency graphs from those projects 7 | - infers a project name, branch, and revision for the project (from git or svn) 8 | - uploads the dependency graphs to FOSSA 9 | 10 | For supported command-line flags, use `fossa analyze --help` 11 | 12 | ### Specifying FOSSA project details 13 | 14 | In addition to the [usual FOSSA project flags](#common-fossa-project-flags) supported by all commands, the analyze command supports the following FOSSA-project-related flags: 15 | 16 | | Name | Short | Description | 17 | | ------------------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 18 | | `--title 'some title'` | `-t` | Set the title of the FOSSA project | 19 | | `--branch 'some branch'` | `-b` | Override the detected FOSSA project branch | 20 | | `--project-url 'https://example.com'` | `-P` | Add a URL to the FOSSA project | 21 | | `--jira-project-key 'some-key'` | `-j` | Add a Jira project key to the FOSSA project | 22 | | `--link 'https://example.com'` | `-L` | Attach a link to the current FOSSA build | 23 | | `--team 'some team'` | `-T` | Specify a team within your FOSSA organization | 24 | | `--policy 'some policy'` | | Assign a specific FOSSA policy to this project | 25 | | `--config /path/to/file` | `-c` | Path to a [configuration file](../files/fossa-yml.md) including filename. By default we look for `.fossa.yml` in target directory of analyze command. | 26 | 27 | ### Printing results without uploading to FOSSA 28 | 29 | The `--output` flag can be used to print projects and dependency graph information to stdout, rather than uploading to FOSSA 30 | 31 | ```sh 32 | fossa analyze --output 33 | ``` 34 | 35 | ### Printing project metadata 36 | 37 | The `--json` flag can be used to print project metadata after running `fossa analyze` successfully. This metadata can be used to reference your project when integrating with the FOSSA API. 38 | 39 | ```sh 40 | fossa analyze --json 41 | ``` 42 | ```json 43 | {"project":{"name":"custom@new-project","branch":"master","revision":"123","url":"https://app.fossa.com/projects/custom+/new-project/refs/branch/master/123","id":"custom+/new-project$123"}} 44 | ``` 45 | 46 | ### Running in a specific directory 47 | 48 | ```sh 49 | fossa analyze path/to/directory 50 | ``` 51 | 52 | ### Scanning archive contents 53 | 54 | With the `--unpack-archives` flag present, we unpack discovered archives to a temporary directory for dependency analysis. We recursively unpack archives-in-archives. 55 | 56 | ```sh 57 | fossa analyze --unpack-archives 58 | ``` 59 | 60 | We support the following archive formats: 61 | 62 | - `.zip` 63 | - `.tar` 64 | - `.tar.gz` 65 | - `.jar` 66 | - `.rpm` 67 | -------------------------------------------------------------------------------- /docs/references/subcommands/list-targets.md: -------------------------------------------------------------------------------- 1 | ## `fossa list targets` 2 | 3 | The list targets command lists all valid analysis targets in a directory. This output can be useful to understand what is going to be analyzed when `fossa analyze` is run. `list-targets` can be also be used with [analysis target configuration](../files/fossa-yml.md#analysis-target-configuration) to limit what is ultimately analyzed. 4 | 5 | 6 | ### Command output 7 | 8 | Example output 9 | ```bash 10 | $ fossa list-targets 11 | [ INFO] Found target: cabal@./ 12 | [ INFO] Found target: cocoapods@project/mobile/ 13 | [ INFO] Found target: setuptools@scripts/python/ 14 | [ INFO] Found target: yarn@./ 15 | ``` 16 | 17 | This output tells us that when `fossa analyze` is run, we will be analyzing `cabal`, `cocoapods`, `pipenv`, and `yarn` projects. This can be useful to determine if there are targets you expect or don't expect to see. 18 | 19 | ### Utilizing [analysis target configuration](../files/fossa-yml.md#analysis-target-configuration) 20 | 21 | Analysis target configuration through the fossa configuration file allows users to manually determine what they would like to analyze. Looking at the example above, if we know that the dependencies for the `setuptools@scripts/python/` target are not part of the production release, we can exclude it from the analysis. Example exclusion format: 22 | 23 | ```yaml 24 | exclude: 25 | - type: setuptools 26 | path: scripts/python 27 | ``` 28 | 29 | Adding this section to your configuration file at the root of your project will ensure that when `fossa analyze` is run, the `setuptools` target is skipped. 30 | -------------------------------------------------------------------------------- /docs/references/subcommands/report.md: -------------------------------------------------------------------------------- 1 | ## `fossa report` 2 | 3 | The report command downloads a report of the most-recent scan of your FOSSA project. This command is usually run immedately after `fossa analyze` or `fossa test` 4 | 5 | The report type **must** be specified to successfully run, for example: 6 | 7 | ```sh 8 | fossa report attribution 9 | ``` 10 | 11 | `fossa report` supports the [Common FOSSA Project Flags](#common-fossa-project-flags) supported by all commands. 12 | 13 | ### Report types 14 | 15 | - `fossa report attribution` - A report that contains information about your dependencies and their authors. For more info about attributions, check the [FOSSA docs page illustrating the topic](https://docs.fossa.com/docs/generating-reports). 16 | 17 | ### Specifying a report timeout 18 | 19 | By default, `fossa report` waits a maximum of 10 minutes for report contents. To override the default timeout, use, e.g.: 20 | 21 | ```sh 22 | fossa report attribution --timeout 60 23 | ``` 24 | 25 | Where `60` is the maximum number of seconds to wait for the report to be downloaded. 26 | 27 | ### Print report as JSON 28 | 29 | By default, `fossa report` displays issues in a human-readable format. To instead print issues as JSON, use: 30 | 31 | ```sh 32 | fossa report attribution --json 33 | ``` 34 | 35 | *NOTE: Currently, text reports are not supported, and the report will be* 36 | *printed as JSON. It is recommended to use the `--json` flag anyway, since* 37 | *the behavior of the command without the flag will change in the future.* 38 | ### FOSSAv1 report compatibility 39 | 40 | FOSSA supports a compatibility script that converts FOSSAv2 attribution report output to the same format as that in FOSSAv1. 41 | 42 | This script will be supported until the end of April 2022 and is included in the release assets, under the name `compat-attribution`. 43 | 44 | To use this compatibility script: 45 | 46 | 1. Download and extract `compat-attribution` for your platform to the same place as the `fossa` binary. 47 | 2. Run `fossa report attribution --json`, piping its output to `compat-attribution`. 48 | For example, `fossa report attribution --json | compat-attribution` 49 | 3. Parse the resulting output as you would have from FOSSAv1. 50 | 51 | ## Common FOSSA Project Flags 52 | 53 | All `fossa` commands support the following FOSSA-project-related flags: 54 | 55 | | Name | Short | Description | 56 | | ---------------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | 57 | | `--project 'some project'` | `-p` | Override the detected project name | 58 | | `--revision 'some revision'` | `-r` | -Override the detected project revision | 59 | | `--fossa-api-key 'my-api-key'` | | An alternative to using the `FOSSA_API_KEY` environment variable to specify a FOSSA API key | 60 | | `--endpoint 'https://example.com'` | `-e` | Override the FOSSA API server base URL | 61 | | `--config /path/to/file` | `-c` | Path to a [configuration file](../files/fossa-yml.md) including filename. By default we look for `.fossa.yml` in base working directory. | 62 | -------------------------------------------------------------------------------- /docs/references/subcommands/test.md: -------------------------------------------------------------------------------- 1 | 2 | ## `fossa test` 3 | 4 | The test command checks whether the most-recent scan of your FOSSA project raised license-policy or vulnerability issues. This command is usually run immediately after `fossa analyze` 5 | 6 | - If there are issues, it prints them to stdout and fails with an exit code of 1 7 | - If there are no issues, it prints nothing and succeeds with an exit code of 0 8 | 9 | `fossa test` supports the [Common FOSSA Project Flags](#common-fossa-project-flags) supported by all commands 10 | 11 | ### Specifying a timeout 12 | 13 | By default, `fossa test` waits a maximum of 10 minutes for issue scan results. To override the default timeout, use, e.g.: 14 | 15 | ```sh 16 | fossa test --timeout 60 17 | ``` 18 | 19 | Where `60` is the maximum number of seconds to wait for issue scan results. 20 | 21 | ### Print issues as JSON 22 | 23 | By default, `fossa test` displays issues in a human-readable format. To instead print issues as JSON, use: 24 | 25 | ```sh 26 | fossa test --json 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/walkthroughs/analysis-target-configuration.md: -------------------------------------------------------------------------------- 1 | # Analyze only set of targets 2 | 3 | FOSSA CLI can be configured to discover and analyze, based on the target type (e.g. gradle, rebar3, etc.) and by its path. This can be useful when multiple targets exist in the directory, but we are only interested in a select few. 4 | 5 | To do so, we will use the following: 6 | 7 | - [fossa list-target](./../references/subcommands/list-targets.md) command 8 | - [.fossa.yml](./../references/files/fossa-yml.md) configuration file 9 | 10 | ## Example 11 | 12 | For an example scenario, presume our source code is structured in the following manner (simplified for brevity): 13 | 14 | ```bash 15 | . 16 | ├── src 17 | │ ├── back-end 18 | │ │ └── pyproject.toml 19 | │ └── front-end 20 | │ ├── v1 21 | │ │ └── package.json 22 | │ └── v2 23 | │ └── package.json 24 | ├── test-suite 25 | │ ├── browser 26 | │ │ ├── package.json 27 | │ │ └── yarn.lock 28 | │ └── integration 29 | │ └── build.gradle 30 | └── utils 31 | ├── helpers 32 | │ └── requirements.txt 33 | ├── migration-tests 34 | │ └── build.gradle 35 | ├── requirements.txt 36 | └── scripts 37 | └── requirements.txt 38 | ``` 39 | 40 | And we are only interested in analyzing: 41 | 42 | - Any targets under `src/back-end/` and `src/front-end/v2/` directory 43 | - Any targets under `utils/` directory, 44 | - But excluding only setuptools targets found in `utils/scripts` directory. 45 | - But excluding any targets under `utils/migration-tests` directory 46 | 47 | To identify, target and its path discovered by fossa CLI, we can use: `fossa list-targets` command. 48 | 49 | When command is executed, it would produce a list of target and their path: 50 | 51 | ```bash 52 | [ INFO] Found project: yarn@test-suite/browser/ 53 | [ INFO] Found target: yarn@test-suite/browser/ 54 | [ INFO] Found project: setuptools@utils/helpers/ 55 | [ INFO] Found target: setuptools@utils/helpers/ 56 | [ INFO] Found project: setuptools@utils/scripts/ 57 | [ INFO] Found target: setuptools@utils/scripts/ 58 | [ INFO] Found project: setuptools@utils/ 59 | [ INFO] Found target: setuptools@utils/ 60 | [ INFO] Found project: poetry@src/back-end/ 61 | [ INFO] Found target: poetry@src/back-end/ 62 | [ INFO] Found project: npm@src/front-end/v1/ 63 | [ INFO] Found target: npm@src/front-end/v1/ 64 | [ INFO] Found project: npm@src/front-end/v2/ 65 | [ INFO] Found target: npm@src/front-end/v2/ 66 | [ INFO] Found project: gradle@utils/migration-tests/ 67 | [ INFO] Found target: gradle@utils/migration-tests/: 68 | [ INFO] Found project: gradle@test-suite/integration/ 69 | [ INFO] Found target: gradle@test-suite/integration/: 70 | ``` 71 | 72 | So, 73 | 74 | 1. Let's select any targets under `src/back-end` and `src/front-end/v2/` directory using [`paths.only`](./../references/files/fossa-yml.md#`paths.only:`) directive: 75 | 76 | ```yaml 77 | version: 3 78 | 79 | paths: 80 | only: 81 | - src/back-end/ 82 | - src/front-end/v2/ 83 | ``` 84 | 85 | 2. We want to scan for targets in the `utils` directory. Let's add that to the paths to scan for targets. 86 | 87 | ```yaml 88 | version: 3 89 | 90 | paths: 91 | only: 92 | - src/back-end/ 93 | - src/front-end/v2/ 94 | - utils/ 95 | ``` 96 | 97 | 98 | 3. We want to exclude any targets in `utils/migration-tests/` directory, to do so, use [`paths.exclude`](./../references/files/fossa-yml.md#`paths.exclude:`) directive. This will ensure cli does not scan `utils/migrations/` directory for analysis. 99 | 100 | ```yaml 101 | version: 3 102 | 103 | paths: 104 | exclude: 105 | - utils/migration-tests/ 106 | only: 107 | - src/back-end/ 108 | - src/front-end/v2/ 109 | - utils/ 110 | 111 | targets: 112 | exclude: 113 | - type: setuptools 114 | path: utils/scripts/ 115 | ``` 116 | 117 | 4. We want to exclude only `setuptools` targets in `utils/scripts-tests/` directory. Since there may be other type of targets in `utils/scripts-tests/` directory, use [`targets.exclude`](./../references/files/fossa-yml.md#`targets.exclude`) directive to explicitly ignore analysis of `setuptools` type in `utils/scripts/` directory. 118 | 119 | ```yaml 120 | version: 3 121 | 122 | paths: 123 | exclude: 124 | - utils/migration-tests/ 125 | only: 126 | - src/back-end/ 127 | - src/front-end/v2/ 128 | - utils/ 129 | 130 | targets: 131 | exclude: 132 | - type: setuptools 133 | path: utils/scripts/ 134 | ``` 135 | 136 | Likewise, we can also use [`targets.only`](./../references/files/fossa-yml.md#`targets.only`) directive to explicitly indicate which targets we are interested. This will achieve the same the behavior. 137 | 138 | ```yaml 139 | version: 3 140 | 141 | targets: 142 | only: 143 | - type: npm 144 | path: src/front-end/v2/ 145 | - type: poetry 146 | path: src/back-end/ 147 | - type: setuptools 148 | path: utils/ 149 | - type: setuptools 150 | path: utils/helpers/ 151 | - type: setuptools 152 | path: utils/helpers/ 153 | ``` -------------------------------------------------------------------------------- /docs/walkthroughs/custom-integrating-with-bower-example.md: -------------------------------------------------------------------------------- 1 | # Custom Integration using `fossa-deps` 2 | 3 | With `fossa-deps.{yml, json, yaml}` file, FOSSA CLI can be integrated to support any package manager or custom and non-standard management solution, that is yet to be supported natively by FOSSA CLI. With the fossa-deps file, we can: 4 | 5 | - [Include manual dependencies](./../features/manual-dependencies.md) 6 | - [Include vendored dependencies](./../features/vendored-dependencies.md) 7 | 8 | ## Example with Bower 9 | 10 | For an example, we will look at [Bower](https://bower.io/). 11 | 12 | We can usually identify a list of dependencies from our custom tool by looking at configuration files or executing a command. Bower provides both of these options, we can inspect (1) `bower.json` or (2) parse the output from the `bower list` command. 13 | 14 | From an example `bower.json` file, lists direct dependencies: 15 | 16 | ```json 17 | { 18 | "name": "example-project", 19 | "authors": [ 20 | "user " 21 | ], 22 | "description": "Example project", 23 | "main": "main.js", 24 | "license": "MIT", 25 | "homepage": "", 26 | "ignore": [ 27 | "**/.*", 28 | "node_modules", 29 | "bower_components", 30 | "test", 31 | "tests" 32 | ], 33 | "dependencies": { 34 | "font-awsome": "^5.0.0", 35 | "jquery": "^3.6.0" 36 | } 37 | } 38 | ``` 39 | 40 | We can execute `bower list` command to list all of the resolved bower dependencies: 41 | 42 | ``` 43 | example-project /Users/example-user/path 44 | ├── font-awsome#5.15.4 45 | └── jquery#3.6.0 46 | ``` 47 | 48 | We have two dependencies (1) jquery and (2) font-awsome. 49 | 50 | From [manual dependencies](./../features/manual-dependencies.md) documentation, we know that `bower` type dependencies are supported type as reference dependency. 51 | 52 | We can include all listed dependencies in fossa-deps.json. 53 | 54 | ```json 55 | { 56 | "referenced-dependencies": [ 57 | { 58 | "type": "bower", 59 | "name": "jquery", 60 | "version": "3.6.0" 61 | }, 62 | { 63 | "type": "bower", 64 | "name": "font-awsome", 65 | "version": "5.15.4" 66 | } 67 | ] 68 | } 69 | ``` 70 | 71 | To programmatically add these dependencies, you can write a script in your language of choice to translate the dependency graph produced by bower to a fossa-deps file. Provided below is an example python script, which parses a dependency graph and produces a fossa-deps file. 72 | 73 | [Here](./../../experimental-scripts/bower.py) is an example python script that parses bower list command, and prints fossa-deps file. 74 | 75 | ## Limitation 76 | 77 | Please note that with the fossa-deps file, we can report dependencies, but we cannot: 78 | 79 | - differentiate between direct and deep dependencies 80 | - report edge information between dependencies 81 | -------------------------------------------------------------------------------- /docs/walkthroughs/debugging-your-integration.md: -------------------------------------------------------------------------------- 1 | ### `fossa analyze`: Why wasn't my project found? 2 | 3 | If your project wasn't found, make sure you meet the requirements in the [relevant language/build-tool's quick reference](../references/strategies/README.md) 4 | 5 | If your project meets the requirements, it's very likely `fossa analyze` found your project, but dependency analysis failed. To show the failure reason, use the `--debug` flag: 6 | 7 | ```sh 8 | fossa analyze --debug 9 | ``` 10 | 11 | Note that the output is likely to be very noisy: our project discovery process is very lenient, and can produce many false-positives. False-positive projects almost always fail during the dependency analysis step, so we don't show analysis failures by default. 12 | 13 | If your project wasn't in the `--debug` output, or you believe you've encountered a bug, please [file a bug](https://github.com/fossas/spectrometer/issues/new). 14 | 15 | In your bug report, please include: 16 | 17 | - relevant package manifest files (e.g., `pom.xml` or `package.json`) 18 | - the output of `fossa analyze --debug` 19 | 20 | ### When are you adding support for (some buildtool/language)? 21 | 22 | If we don't support your choice of language/buildtool, please [open an issue](https://github.com/fossas/spectrometer/issues/new) to express interest 23 | -------------------------------------------------------------------------------- /docs/walkthroughs/integrating.md: -------------------------------------------------------------------------------- 1 | ## Quick Start 2 | 3 | Spectrometer is a tool that requires minimal configuration: usually, only a FOSSA API key is required. 4 | 5 | If you do not have an API key, please check the [FOSSA documentation](https://docs.fossa.com/docs/api-reference) for instructions on generating an API key. 6 | 7 | ### Configure your API key 8 | 9 | ```sh 10 | export FOSSA_API_KEY=abcdef123456 11 | ``` 12 | 13 | ### Run Analysis 14 | 15 | This runs dependency analysis in the current directory, uploading results to FOSSA 16 | 17 | ```sh 18 | fossa analyze 19 | ``` 20 | 21 | ### Check for FOSSA scan results 22 | 23 | ```sh 24 | fossa test 25 | ``` 26 | 27 | For additional commands and command flags, use `--help`: 28 | 29 | ```sh 30 | fossa --help 31 | fossa analyze --help 32 | # etc 33 | ``` 34 | -------------------------------------------------------------------------------- /install.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5 2 | 3 | <# 4 | .SYNOPSIS 5 | Download and install the latest available FOSSA release from GitHub. 6 | #> 7 | 8 | [CmdletBinding()] 9 | Param() 10 | 11 | Write-Host "" 12 | Write-Host "Notice:" 13 | Write-Host "" 14 | Write-Host " Spectrometer has been migrated to the fossa-cli repository at:" 15 | Write-Host " https://github.com/fossas/fossa-cli" 16 | Write-Host "" 17 | Write-Host " Please migrate to using latest installation script provided at:" 18 | Write-Host " https://github.com/fossas/fossa-cli" 19 | Write-Host "" 20 | Write-Host "" 21 | 22 | 23 | $OldEAP = $ErrorActionPreference #Preserve the original value 24 | $ErrorActionPreference = "Stop" 25 | 26 | $app = "fossa" 27 | 28 | # Set to default if null 29 | if ($env:FOSSA_RELEASE) 30 | { 31 | if ($env:FOSSA_RELEASE -inotmatch '^v\d.\d+.\d+$') 32 | { 33 | throw "FOSSA_RELEASE must be in the format of v2.x.x (e.g.: 'v2.0.1')" 34 | } 35 | $releaseTag = "$env:FOSSA_RELEASE" 36 | } 37 | else 38 | { 39 | $releaseTag = "latest" 40 | } 41 | 42 | $github = "https://github.com" 43 | $latestUri = "$github/fossas/fossa-cli/releases/$releaseTag" 44 | $userExtractDir = "$env:LOCALAPPDATA\fossa-cli" 45 | $allUsersExtractDir = "$env:PROGRAMFILES\fossa-cli" 46 | 47 | if ($env:FOSSA_ALL_USERS) 48 | { 49 | $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) 50 | if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) 51 | { 52 | throw "Cannot install for all users without admin privleges. Please run powershell as administrator to install for all users." 53 | } 54 | $extractDir = "$allUsersExtractDir" 55 | } 56 | else 57 | { 58 | $extractDir = "$userExtractDir" 59 | } 60 | 61 | Write-Verbose "Looking up release ($releaseTag)..." 62 | 63 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12 64 | 65 | $headers = @{ 66 | 'Accept' = 'application/json' 67 | } 68 | 69 | $release = Invoke-RestMethod -Uri $latestUri -Method Get -Headers $headers 70 | $releaseVersion = $release.tag_name; 71 | $releaseVersionSemver = $releaseVersion.TrimStart("v"); 72 | $downloadUri = "$github/fossas/fossa-cli/releases/download/$releaseVersion/$($app)_$($releaseVersionSemver)_windows_amd64.zip" 73 | 74 | Write-Output "Downloading from: $downloadUri" 75 | 76 | $TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "fossa" 77 | if (![System.IO.Directory]::Exists($TempDir)) {[void][System.IO.Directory]::CreateDirectory($TempDir)} 78 | 79 | $zipFile = "$TempDir\fossa.zip" 80 | 81 | (New-Object System.Net.WebClient).DownloadFile($downloadUri, $zipFile) 82 | 83 | Expand-Archive -Path $zipFile -DestinationPath $extractDir -Force 84 | 85 | $ErrorActionPreference = $OldEAP 86 | 87 | $fossa = "$extractDir\fossa.exe" 88 | $env:Path += ";$extractDir" 89 | Write-Host "The fossa-cli installation directory has been added to the PATH for this session." 90 | 91 | Write-Host "Installed fossa at: $fossa" 92 | Write-Host "Get started by running: fossa.exe --help" 93 | 94 | Write-Host "Running fossa.exe --version" 95 | # Doesn't run without '&', seems to tell PS to treat the output as a command 96 | & $fossa --version --------------------------------------------------------------------------------