diff options
| author | Can Eldem <celdem@gitlab.com> | 2020-03-20 10:31:37 +0000 |
|---|---|---|
| committer | Can Eldem <celdem@gitlab.com> | 2020-03-20 10:31:37 +0000 |
| commit | d9ddfb4662dc3d9ba283e7832f6d1ec0e1451d25 (patch) | |
| tree | 417c4a313b1d6428c1a43f38278d2c828a36b293 | |
| parent | df97efaccfc0a5d4e3ef564e74c60987f65ff6fa (diff) | |
| parent | 43fec0e1e3151371929139c4f67c43e7f81f1a80 (diff) | |
Merge branch 'java-maven-multimodules' into 'master'v3.1.2
Detect all licenses for maven multi-module projects.
See merge request gitlab-org/security-products/license-management!123
26 files changed, 530 insertions, 37 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ee7c130..dc514dd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,7 +27,8 @@ build commit: script: - docker info - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY - - docker build -t $TMP_IMAGE . + - docker pull $CI_REGISTRY_IMAGE:latest || true + - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $TMP_IMAGE . - docker image inspect $TMP_IMAGE --format='{{.Size}}' - docker push $TMP_IMAGE diff --git a/CHANGELOG.md b/CHANGELOG.md index bbaee95..dc28b9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # GitLab License management changelog +## v3.1.2 + +- Use `license-maven-plugin:aggreate-download-licenses` for multi-module projects. (!123) + ## v3.1.1 - Fix invocation of `SETUP_CMD`. (!122) @@ -11,11 +11,11 @@ RUN apt-get update -q \ && apt-get install -y --no-install-recommends ruby \ && gem build *.gemspec -# Install org.codehaus.mojo:license-maven-plugin:download-licenses to $HOME/.m2/repository +# Install org.codehaus.mojo:license-maven-plugin to $HOME/.m2/repository FROM debian:stable AS license-maven-plugin-builder RUN apt-get update -q \ && apt-get install -y --no-install-recommends maven \ - && mvn license:help + && mvn license:license-list FROM debian:stable-slim as tools-builder ENV ASDF_DATA_DIR="/opt/asdf" diff --git a/Gemfile.lock b/Gemfile.lock index 68c0773..f0b6004 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - license-management (3.1.1) + license-management (3.1.2) license_finder (~> 6.0.0) GEM @@ -38,16 +38,16 @@ You can then run License Management on some target directory: docker run --rm --volume "/path/to/my/project":/code license-management analyze /code ``` -You can run the tests using the following command: +You can run the tests from your host machine using the following command: ```sh ./bin/test ``` -It is much more efficient to run the tests from inside the docker container. This can be -accomplished by following these steps: +It is much more efficient to run the tests from inside the docker container: ```sh +./bin/docker-build ./bin/docker-shell cd /opt/license-management/ ./bin/test diff --git a/bin/docker-test b/bin/docker-test index daf2b68..5a4436d 100755 --- a/bin/docker-test +++ b/bin/docker-test @@ -8,9 +8,7 @@ export CI_PROJECT_DIR="$1" echo "Scanning $CI_PROJECT_DIR" if [ -n "${LM_HOME:-}" ]; then - gem build ./*.gemspec - mkdir -p pkg/ - mv ./*.gem pkg/ + mkdir -p pkg/ && gem build --silent -o pkg/license-management-test.gem ./*.gemspec ./run.sh analyze "$CI_PROJECT_DIR" else export IMAGE_NAME=${IMAGE_NAME:-$(basename "$PWD"):latest} diff --git a/config/.bashrc b/config/.bashrc index ea68a94..e85ae56 100644 --- a/config/.bashrc +++ b/config/.bashrc @@ -25,7 +25,7 @@ function enable_dev_mode() { export EDITOR=vim set -o vi apt-get update -y - apt-get install -y --no-install-recommends vim less + apt-get install -y --no-install-recommends vim less shellcheck } inflate /opt/asdf.tar.zst /opt diff --git a/config/.m2/settings.xml b/config/.m2/settings.xml index c36a363..9a89d90 100644 --- a/config/.m2/settings.xml +++ b/config/.m2/settings.xml @@ -11,7 +11,7 @@ <repositories> <repository> <id>gitlab-maven</id> - <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url> + <url>${env.CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url> </repository> </repositories> </profile> diff --git a/lib/license/finder/ext.rb b/lib/license/finder/ext.rb index 9788abb..c17ffea 100644 --- a/lib/license/finder/ext.rb +++ b/lib/license/finder/ext.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'license/finder/ext/license' +require 'license/finder/ext/maven' require 'license/finder/ext/nuget' require 'license/finder/ext/shared_helpers' diff --git a/lib/license/finder/ext/maven.rb b/lib/license/finder/ext/maven.rb new file mode 100644 index 0000000..954d18d --- /dev/null +++ b/lib/license/finder/ext/maven.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module LicenseFinder + Maven.class_eval do + XML_PARSE_OPTIONS = { + 'ForceArray' => %w[license dependency], + 'GroupTags' => { + 'licenses' => 'license', + 'dependencies' => 'dependency' + } + }.freeze + + def current_packages + Dir.chdir(project_path) do + LicenseFinder::SharedHelpers::Cmd.run(detect_licenses_command) + resource_files.flat_map { |file| map_from(file.read) }.uniq + end + end + + private + + def detect_licenses_command + [ + package_management_command, + "-e", + "org.codehaus.mojo:license-maven-plugin:aggregate-download-licenses", + "-Dlicense.excludedScopes=#{@ignored_groups.to_a.join(',')}", + ENV.fetch('MAVEN_CLI_OPTS', '-DskipTests') + ].join(' ') + end + + def resource_files + Pathname.glob(project_path.join('**', 'target', 'generated-resources', 'licenses.xml')) + end + + def map_from(xml) + ::License::Management.logger.debug(xml) + XmlSimple + .xml_in(xml, XML_PARSE_OPTIONS)['dependencies'] + .map { |dependency| MavenPackage.new(dependency) } + end + end +end diff --git a/lib/license/finder/ext/shared_helpers.rb b/lib/license/finder/ext/shared_helpers.rb index 4e61261..bc37b9c 100644 --- a/lib/license/finder/ext/shared_helpers.rb +++ b/lib/license/finder/ext/shared_helpers.rb @@ -5,15 +5,9 @@ module LicenseFinder class Cmd def self.run(command) stdout, stderr, status = Open3.capture3(command) - debug([command, stdout].join('\n')) + ::License::Management.logger.debug([command, stdout].join('\n')) [stdout, stderr, status] end - - def self.debug(message) - return unless ENV['CI_DEBUG_TRACE'] == 'true' - - ::LicenseFinder::Core.default_logger.info(self.class, message) - end end end end diff --git a/lib/license/management.rb b/lib/license/management.rb index bfcf54c..a39c841 100644 --- a/lib/license/management.rb +++ b/lib/license/management.rb @@ -1,8 +1,10 @@ # frozen_string_literal: true +require 'json' +require 'logger' require 'pathname' require 'yaml' -require 'json' + require 'license_finder' require 'license/management/loggable' require 'license/management/verifiable' @@ -18,11 +20,8 @@ module License Pathname.new(File.dirname(__FILE__)).join('../..') end - def self.http - @http ||= Net::Hippie::Client.new.tap do |client| - client.logger = ::Logger.new('http.log') - client.follow_redirects = 3 - end + def self.logger + @logger ||= Logger.new(STDOUT) end end end diff --git a/lib/license/management/loggable.rb b/lib/license/management/loggable.rb index 165d8ca..0122018 100644 --- a/lib/license/management/loggable.rb +++ b/lib/license/management/loggable.rb @@ -4,15 +4,15 @@ module License module Management module Loggable def logger - ::LicenseFinder::Core.default_logger + License::Management.logger end def log_info(message) - logger.info(self.class, message) + logger.info(message) end def log_error(message) - logger.info(self.class, message, color: :red) + logger.error(message) end end end diff --git a/lib/license/management/report/base.rb b/lib/license/management/report/base.rb index 2d49341..0155c15 100644 --- a/lib/license/management/report/base.rb +++ b/lib/license/management/report/base.rb @@ -26,7 +26,7 @@ module License paths = dependency.aggregate_paths return [] if blank?(paths) - paths.map { |x| x.gsub(Dir.pwd, '.') } + paths.map { |x| x.gsub(Dir.pwd, '.') }.sort end def description_for(dependency) diff --git a/lib/license/management/version.rb b/lib/license/management/version.rb index 308a738..9b8fdc3 100644 --- a/lib/license/management/version.rb +++ b/lib/license/management/version.rb @@ -2,6 +2,6 @@ module License module Management - VERSION = '3.1.1' + VERSION = '3.1.2' end end @@ -6,14 +6,15 @@ set -e BUNDLE_JOBS="$(nproc)" export BUNDLE_JOBS export BUNDLE_WITHOUT="development:test" +export CI_API_V4_URL="${CI_API_V4_URL:-https://gitlab.com/api/v4}" export CI_DEBUG_TRACE=${CI_DEBUG_TRACE:='false'} export DOTNET_CLI_TELEMETRY_OPTOUT=1 export HISTFILESIZE=0 export HISTSIZE=0 export LICENSE_FINDER_CLI_OPTS=${LICENSE_FINDER_CLI_OPTS:='--no-debug'} export LM_REPORT_FILE=${LM_REPORT_FILE:-'gl-license-management-report.json'} -export MAVEN_CLI_OPTS="${MAVEN_CLI_OPTS:='-DskipTests'}" -export PREPARE="--prepare-no-fail" +export MAVEN_CLI_OPTS="${MAVEN_CLI_OPTS:--DskipTests}" +export PREPARE="${PREPARE:---prepare-no-fail}" export RECURSIVE='--no-recursive' export RUBY_GC_HEAP_INIT_SLOTS=800000 export RUBY_GC_MALLOC_LIMIT=79000000 @@ -42,7 +43,7 @@ function debug_env() { } function scan_project() { - gem install --quiet --silent "$LM_HOME/pkg/*.gem" + gem install -f --silent "$LM_HOME/pkg/*.gem" license_management ignored_groups add development license_management ignored_groups add test echo license_management report "$@" @@ -112,5 +113,4 @@ scan_project "$PREPARE" \ --save="${LM_REPORT_FILE}" \ --python-version="${python_version}" \ "$RECURSIVE" \ - --maven-options="$MAVEN_CLI_OPTS" \ "$LICENSE_FINDER_CLI_OPTS" diff --git a/spec/fixtures/expected/java/maven-multimodules/v1.0.json b/spec/fixtures/expected/java/maven-multimodules/v1.0.json new file mode 100644 index 0000000..ac9f480 --- /dev/null +++ b/spec/fixtures/expected/java/maven-multimodules/v1.0.json @@ -0,0 +1,94 @@ +{ + "licenses": [ + { "count": 15, "name": "Apache 2.0" }, + { "count": 4, "name": "BSD" }, + { "count": 1, "name": "MPL 1.1, GNU Lesser General Public License version 2.1, Apache 2.0" }, + { "count": 1, "name": "unknown" } + ], + "dependencies": [ + { + "license": { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" }, + "dependency": { "name": "asm", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" }, + "dependency": { "name": "asm-commons", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" }, + "dependency": { "name": "asm-tree", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "commons-fileupload", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "commons-io", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "commons-lang3", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "freemarker", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-annotations", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-core", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-databind", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-dataformat-xml", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-module-jaxb-annotations", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "MPL 1.1, GNU Lesser General Public License version 2.1, Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "javassist", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "log4j-api", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "log4j-api", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "log4j-core", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "unknown" }, + "dependency": { "name": "model", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "netty-all", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "ognl", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" }, + "dependency": { "name": "stax2-api", "description": "", "pathes": [ "." ] } + }, + { + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "struts2-core", "description": "", "pathes": [ "." ] } + } + ] +} diff --git a/spec/fixtures/expected/java/maven-multimodules/v1.1.json b/spec/fixtures/expected/java/maven-multimodules/v1.1.json new file mode 100644 index 0000000..a8e2841 --- /dev/null +++ b/spec/fixtures/expected/java/maven-multimodules/v1.1.json @@ -0,0 +1,157 @@ +{ + "version": "1.1", + "licenses": [ + { "count": 15, "name": "Apache 2.0" }, + { "count": 4, "name": "BSD" }, + { "count": 1, "name": "MPL 1.1, GNU Lesser General Public License version 2.1, Apache 2.0" }, + { "count": 1, "name": "unknown" } + ], + "dependencies": [ + { + "licenses": [ + { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" } + ], + "license": { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" }, + "dependency": { "name": "asm", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" } ], + "license": { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" }, + "dependency": { "name": "asm-commons", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" } ], + "license": { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" }, + "dependency": { "name": "asm-tree", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "commons-fileupload", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "commons-io", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "commons-lang3", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "freemarker", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-annotations", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-core", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-databind", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-dataformat-xml", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "jackson-module-jaxb-annotations", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + { "name": "GNU Lesser General Public License version 2.1", "url": "https://opensource.org/licenses/LGPL-2.1" }, + { "name": "MPL 1.1", "url": "" } + ], + "license": { "name": "MPL 1.1, GNU Lesser General Public License version 2.1, Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "javassist", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "log4j-api", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "log4j-api", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "log4j-core", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "unknown", "url": "" } + ], + "license": { "name": "unknown" }, + "dependency": { "name": "model", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" + } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "netty-all", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "ognl", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" } + ], + "license": { "name": "BSD", "url": "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29" }, + "dependency": { "name": "stax2-api", "description": "", "pathes": [ "." ] } + }, + { + "licenses": [ + { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" } + ], + "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" }, + "dependency": { "name": "struts2-core", "description": "", "pathes": [ "." ] } + } + ] +} diff --git a/spec/fixtures/expected/java/maven-multimodules/v2.0.json b/spec/fixtures/expected/java/maven-multimodules/v2.0.json new file mode 100644 index 0000000..aa08ef9 --- /dev/null +++ b/spec/fixtures/expected/java/maven-multimodules/v2.0.json @@ -0,0 +1,58 @@ +{ + "version": "2.0", + "licenses": [ + { + "id": "Apache-2.0", + "name": "Apache License 2.0", + "url": "https://opensource.org/licenses/Apache-2.0", + "count": 16 + }, + { + "id": "BSD-4-Clause", + "name": "BSD 4-Clause \"Original\" or \"Old\" License", + "url": "http://directory.fsf.org/wiki/License:BSD_4Clause", + "count": 4 + }, + { + "id": "LGPL-2.1", + "name": "GNU Lesser General Public License v2.1 only", + "url": "https://opensource.org/licenses/LGPL-2.1", + "count": 1 + }, + { + "id": "MPL-1.1", + "name": "Mozilla Public License 1.1", + "url": "https://opensource.org/licenses/MPL-1.1", + "count": 1 + }, + { + "id": "unknown", + "name": "unknown", + "url": "", + "count": 1 + } + ], + "dependencies": [ + { "name": "asm", "url": "", "description": "", "paths": [ "." ], "licenses": [ "BSD-4-Clause" ] }, + { "name": "asm-commons", "url": "", "description": "", "paths": [ "." ], "licenses": [ "BSD-4-Clause" ] }, + { "name": "asm-tree", "url": "", "description": "", "paths": [ "." ], "licenses": [ "BSD-4-Clause" ] }, + { "name": "commons-fileupload", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "commons-io", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "commons-lang3", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "freemarker", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "jackson-annotations", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "jackson-core", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "jackson-databind", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "jackson-dataformat-xml", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "jackson-module-jaxb-annotations", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "javassist", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0", "LGPL-2.1", "MPL-1.1" ] }, + { "name": "log4j-api", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "log4j-api", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "log4j-core", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "model", "url": "", "description": "", "paths": [ "." ], "licenses": [ "unknown" ] }, + { "name": "netty-all", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "ognl", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] }, + { "name": "stax2-api", "url": "", "description": "", "paths": [ "." ], "licenses": [ "BSD-4-Clause" ] }, + { "name": "struts2-core", "url": "", "description": "", "paths": [ "." ], "licenses": [ "Apache-2.0" ] } + ] +} diff --git a/spec/fixtures/maven-multimodule/api/pom.xml b/spec/fixtures/maven-multimodule/api/pom.xml new file mode 100644 index 0000000..c621c1a --- /dev/null +++ b/spec/fixtures/maven-multimodule/api/pom.xml @@ -0,0 +1,26 @@ +<?xml version="1.0"?> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.gitlab.security_products.tests</groupId> + <artifactId>java-maven-multi-modules</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + <groupId>com.gitlab.security_products.tests</groupId> + <artifactId>api</artifactId> + <version>1.0-SNAPSHOT</version> + <name>api</name> + <url>http://maven.apache.org</url> + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>model</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.struts</groupId> + <artifactId>struts2-core</artifactId> + <version>2.5.1</version> + </dependency> + </dependencies> +</project> diff --git a/spec/fixtures/maven-multimodule/model/pom.xml b/spec/fixtures/maven-multimodule/model/pom.xml new file mode 100644 index 0000000..91b366b --- /dev/null +++ b/spec/fixtures/maven-multimodule/model/pom.xml @@ -0,0 +1,27 @@ +<?xml version="1.0"?> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.gitlab.security_products.tests</groupId> + <artifactId>java-maven-multi-modules</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + <groupId>com.gitlab.security_products.tests</groupId> + <artifactId>model</artifactId> + <version>1.0-SNAPSHOT</version> + <name>model</name> + <url>http://maven.apache.org</url> + <properties> + <maven.compiler.source>1.6</maven.compiler.source> + <maven.compiler.target>1.6</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <dependencies> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>2.8.2</version> + </dependency> + </dependencies> +</project> diff --git a/spec/fixtures/maven-multimodule/pom.xml b/spec/fixtures/maven-multimodule/pom.xml new file mode 100644 index 0000000..e84ad4a --- /dev/null +++ b/spec/fixtures/maven-multimodule/pom.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>com.gitlab.security_products.tests</groupId> + <artifactId>java-maven-multi-modules</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>pom</packaging> + <name>java-maven-multi-modules</name> + <modules> + <module>api</module> + <module>model</module> + <module>web</module> + </modules> + <dependencies> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + <version>4.1.0.Final</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/spec/fixtures/maven-multimodule/web/pom.xml b/spec/fixtures/maven-multimodule/web/pom.xml new file mode 100644 index 0000000..548e9fb --- /dev/null +++ b/spec/fixtures/maven-multimodule/web/pom.xml @@ -0,0 +1,27 @@ +<?xml version="1.0"?> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.gitlab.security_products.tests</groupId> + <artifactId>java-maven-multi-modules</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + <groupId>com.gitlab.security_products.tests</groupId> + <artifactId>web</artifactId> + <version>1.0-SNAPSHOT</version> + <name>web</name> + <url>http://maven.apache.org</url> + <properties> + <maven.compiler.source>1.6</maven.compiler.source> + <maven.compiler.target>1.6</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <dependencies> + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-xml</artifactId> + <version>2.7.3</version> + </dependency> + </dependencies> +</project> diff --git a/spec/integration/java/maven_spec.rb b/spec/integration/java/maven_spec.rb index dbcfa5e..ad4cf5e 100644 --- a/spec/integration/java/maven_spec.rb +++ b/spec/integration/java/maven_spec.rb @@ -2,12 +2,15 @@ require 'spec_helper' RSpec.describe "maven" do include_examples "each report version", "java", "maven" + include_examples "each report version", "java", "maven-multimodules" describe "When the maven dependencies come from a custom public maven repository" do it 'is able to detect some of the licenses' do runner.add_file('pom.xml', fixture_file_content('pom-public-gitlab-repository.xml')) - report = runner.scan(env: { 'CI_PROJECT_ID' => '17523603' }) + report = runner.scan(env: { + 'CI_PROJECT_ID' => '17523603' + }) expect(report).to match_schema(version: '2.0') expect(report[:dependencies]).to match_array([{ name: 'mvn-spike', url: '', description: '', paths: ['.'], licenses: ['MIT'] }]) @@ -18,7 +21,6 @@ RSpec.describe "maven" do runner.add_file('my_settings.xml', fixture_file_content('custom-maven-settings.xml')) report = runner.scan(env: { - 'CI_DEBUG_TRACE' => 'true', 'CI_PROJECT_ID' => 'invalid', 'MAVEN_CLI_OPTS' => "--settings my_settings.xml" }) @@ -45,4 +47,35 @@ RSpec.describe "maven" do expect(report).to match_schema(version: '2.0') end end + + describe "When scanning a project with multiple modules" do + before do + runner.mount(dir: fixture_file('maven-multimodule')) + end + + it 'detects dependences from each module' do + report = runner.scan + + expect(report).to match_schema(version: '2.0') + expect(report[:dependencies]).not_to be_empty + + [ + { name: "asm", licenses: ["BSD-4-Clause"] }, + { name: "asm-commons", licenses: ["BSD-4-Clause"] }, + { name: "jackson-annotations", licenses: ["Apache-2.0"] }, + { name: "jackson-core", licenses: ["Apache-2.0"] }, + { name: "jackson-databind", licenses: ["Apache-2.0"] }, + { name: "jackson-dataformat-xml", licenses: ["Apache-2.0"] }, + { name: "jackson-module-jaxb-annotations", licenses: ["Apache-2.0"] }, + { name: "log4j-api", licenses: ["Apache-2.0"] }, + { name: "log4j-core", licenses: ["Apache-2.0"] }, + { name: "netty-all", licenses: ["Apache-2.0"] }, + { name: "stax2-api", licenses: ["BSD-4-Clause"] } + ].each do |dependency| + expect(find_in(report, dependency[:name])[:licenses]).to match_array(dependency[:licenses]) + end + + expect(report[:dependencies].map { |x| x[:name] }).not_to include('junit') + end + end end diff --git a/spec/support/integration_test_helper.rb b/spec/support/integration_test_helper.rb index 9ecc8aa..25e670f 100644 --- a/spec/support/integration_test_helper.rb +++ b/spec/support/integration_test_helper.rb @@ -13,6 +13,10 @@ module IntegrationTestHelper IO.write(full_path, block_given? ? yield : content) end + def mount(dir:) + FileUtils.cp_r("#{dir}/.", project_path) + end + def clone(repo, branch: 'master') execute({}, "git", "clone", repo, project_path) Dir.chdir project_path do diff --git a/spec/support/shared.rb b/spec/support/shared.rb index 049191e..ba3d3cc 100644 --- a/spec/support/shared.rb +++ b/spec/support/shared.rb @@ -1,6 +1,6 @@ RSpec.shared_examples "each report version" do |language, package_manager, branch = 'master'| ['1.0', '1.1', '2.0'].each do |version| - context "when generating a `#{version}` report" do + context "when generating a `#{version}` report for #{package_manager}" do let(:url) { "https://gitlab.com/gitlab-org/security-products/tests/#{language}-#{package_manager}.git" } let(:expected_content) { JSON.parse(fixture_file_content("expected/#{language}/#{package_manager}/v#{version}.json")) } |
