aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Cho-Lerat <david.cho-lerat@sonarsource.com>2024-10-16 11:56:00 +0200
committersonartech <sonartech@sonarsource.com>2024-10-22 20:03:10 +0000
commitc33a6b9956802dfa00133e304326887b901af901 (patch)
tree1e18cddecf6e82106c12389eba936a6967f17274
parent277983982024a703888152be3a7b4d6e5bc2fc14 (diff)
downloadsonarqube-c33a6b9956802dfa00133e304326887b901af901.tar.gz
sonarqube-c33a6b9956802dfa00133e304326887b901af901.zip
SONAR-23205 Add rollup-plugin-license like in SC (serve 3rd-party licenses at /vendor.LICENSE.txt)
-rw-r--r--server/sonar-web/config/license.ts70
-rw-r--r--server/sonar-web/package.json1
-rw-r--r--server/sonar-web/vite.config.mjs28
-rw-r--r--server/sonar-web/yarn.lock132
-rw-r--r--sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/StaticResources.java2
5 files changed, 229 insertions, 4 deletions
diff --git a/server/sonar-web/config/license.ts b/server/sonar-web/config/license.ts
new file mode 100644
index 00000000000..066d4e4cad0
--- /dev/null
+++ b/server/sonar-web/config/license.ts
@@ -0,0 +1,70 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { Dependency } from 'rollup-plugin-license';
+
+// To be always synced with https://saas-eu.whitesourcesoftware.com/Wss/WSS.html#!policyDetails;policy=3131;org=318388
+// Below is the list of approved front-end licenses extracted from Mend
+export const ALLOWED_LICENSES = [
+ '(MPL-2.0 OR Apache-2.0)', // Multiple licenses. Added specifically for dompurify as we have ignored this in Mend
+ '0BSD',
+ 'Apache-2.0',
+ 'BSD-2-Clause',
+ 'BSD-3-Clause',
+ 'ISC',
+ 'LGPL-3.0',
+ 'MIT',
+];
+
+// Just for Sprig currently, it has an Apache-2 license that isn't correctly parsed by the plugin
+export const ALLOWED_LICENSE_TEXT = ['http://www.apache.org/licenses/LICENSE-2.0'];
+
+// Generates license information with necessary details.
+// A package which has a valid license that the plugin is unable read will default to MIT
+export const generateLicenseText = (dependency: Dependency) => {
+ const { author, homepage, license, licenseText, name, repository, version } = dependency;
+ const lines: string[] = [];
+
+ lines.push(`Name: ${name}`);
+ lines.push(`Version: ${version}`);
+
+ if (license) {
+ lines.push(`License: ${license}`);
+ }
+
+ if (typeof repository === 'string') {
+ lines.push(`Repository: ${repository}`);
+ } else if (repository?.url) {
+ lines.push(`Repository: ${repository.url}`);
+ } else if (homepage) {
+ lines.push(`Homepage: ${homepage}`);
+ }
+
+ if (author) {
+ lines.push(`Author: ${author.text()}`);
+ }
+
+ if (licenseText) {
+ lines.push(`License Copyright:`);
+ lines.push(`${licenseText}`);
+ }
+
+ return lines.join('\n');
+};
diff --git a/server/sonar-web/package.json b/server/sonar-web/package.json
index b8ccadcbde1..ca3163a31b7 100644
--- a/server/sonar-web/package.json
+++ b/server/sonar-web/package.json
@@ -121,6 +121,7 @@
"postcss-calc": "10.0.2",
"prettier": "3.3.3",
"prettier-plugin-organize-imports": "4.1.0",
+ "rollup-plugin-license": "3.5.3",
"rollup-plugin-visualizer": "5.12.0",
"tailwindcss": "3.4.13",
"turbo": "2.1.3",
diff --git a/server/sonar-web/vite.config.mjs b/server/sonar-web/vite.config.mjs
index b0759c5f7f1..f5c3d1fcb2c 100644
--- a/server/sonar-web/vite.config.mjs
+++ b/server/sonar-web/vite.config.mjs
@@ -23,12 +23,14 @@ import autoprefixer from 'autoprefixer';
import browserslistToEsbuild from 'browserslist-to-esbuild';
import path, { resolve } from 'path';
import postCssCalc from 'postcss-calc';
+import license from 'rollup-plugin-license';
import { visualizer } from 'rollup-plugin-visualizer';
import tailwind from 'tailwindcss';
import { defineConfig, loadEnv } from 'vite';
import macrosPlugin from 'vite-plugin-babel-macros';
import requireTransform from 'vite-plugin-require-transform';
import babelConfig from './babel.config';
+import { ALLOWED_LICENSES, ALLOWED_LICENSE_TEXT, generateLicenseText } from './config/license';
import { viteDevServerHtmlPlugin } from './config/vite-dev-server-html-plugin.mjs';
const DEFAULT_DEV_SERVER_PORT = 3000;
@@ -58,7 +60,7 @@ export default ({ mode }) => {
return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` };
} else {
// Other files (css, images, etc.) are loaded relatively to the current url,
- // automatically taking into accound the WEB_CONTEXT
+ // automatically taking into account the WEB_CONTEXT
return { relative: filename };
}
},
@@ -90,7 +92,29 @@ export default ({ mode }) => {
lodash: ['lodash/lodash.js'],
},
},
- plugins: [],
+ plugins: [
+ // a tool used to concatenate all of our 3rd party licenses together for legal reasons
+ license({
+ thirdParty: {
+ allow: {
+ test: ({ license, licenseText }) =>
+ ALLOWED_LICENSES.includes(license) ||
+ ALLOWED_LICENSE_TEXT.some((text) => (licenseText ?? '').includes(text)),
+ failOnUnlicensed: false, // default is false. valid-url package has missing license
+ failOnViolation: true, // Fail if a dependency specifies a license that does not match requirements
+ },
+ output: {
+ // Output file into build/webapp directory which is included in the build output
+ file: path.join(__dirname, 'build/webapp', 'vendor.LICENSE.txt'),
+ template(dependencies) {
+ return dependencies
+ .map((dependency) => generateLicenseText(dependency))
+ .join('\n');
+ },
+ },
+ },
+ }),
+ ],
},
sourcemap: isProduction, // enable source maps for production
},
diff --git a/server/sonar-web/yarn.lock b/server/sonar-web/yarn.lock
index d62c34d11e1..f1fe0bcdf7d 100644
--- a/server/sonar-web/yarn.lock
+++ b/server/sonar-web/yarn.lock
@@ -7613,6 +7613,7 @@ __metadata:
react-select: "npm:5.7.7"
react-virtualized: "npm:9.22.5"
regenerator-runtime: "npm:0.14.1"
+ rollup-plugin-license: "npm:3.5.3"
rollup-plugin-visualizer: "npm:5.12.0"
shared-store-hook: "npm:0.0.4"
tailwindcss: "npm:3.4.13"
@@ -8009,6 +8010,13 @@ __metadata:
languageName: node
linkType: hard
+"array-find-index@npm:^1.0.2":
+ version: 1.0.2
+ resolution: "array-find-index@npm:1.0.2"
+ checksum: 10/aac128bf369e1ac6c06ff0bb330788371c0e256f71279fb92d745e26fb4b9db8920e485b4ec25e841c93146bf71a34dcdbcefa115e7e0f96927a214d237b7081
+ languageName: node
+ linkType: hard
+
"array-includes@npm:^3.1.2":
version: 3.1.2
resolution: "array-includes@npm:3.1.2"
@@ -8951,6 +8959,13 @@ __metadata:
languageName: node
linkType: hard
+"commenting@npm:~1.1.0":
+ version: 1.1.0
+ resolution: "commenting@npm:1.1.0"
+ checksum: 10/e172a2b6234c089ae826a1ff7c42811b88e8cf7166ebde461ad0b6cddd3822c16996b8175ce1d3c1a49d1475b1c1d8acdc906c18d3126cb4b0432df29529f232
+ languageName: node
+ linkType: hard
+
"compare-versions@npm:^6.1.1":
version: 6.1.1
resolution: "compare-versions@npm:6.1.1"
@@ -11082,6 +11097,18 @@ __metadata:
languageName: node
linkType: hard
+"fdir@npm:6.3.0":
+ version: 6.3.0
+ resolution: "fdir@npm:6.3.0"
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+ checksum: 10/baa3a476a8407cc77bc77e3c946aea5ca0aa48f080f2c434b70196a37ddcd57bbc4c12d75164f9e6d947f6e148c297c9fa65f507178d0e9204d98ef83d776dcc
+ languageName: node
+ linkType: hard
+
"file-entry-cache@npm:^6.0.1":
version: 6.0.1
resolution: "file-entry-cache@npm:6.0.1"
@@ -13881,7 +13908,7 @@ __metadata:
languageName: node
linkType: hard
-"lodash@npm:4.17.21, lodash@npm:^4.17.11, lodash@npm:^4.17.13, lodash@npm:^4.17.21, lodash@npm:~4.17.15":
+"lodash@npm:4.17.21, lodash@npm:^4.17.11, lodash@npm:^4.17.13, lodash@npm:^4.17.21, lodash@npm:~4.17.15, lodash@npm:~4.17.21":
version: 4.17.21
resolution: "lodash@npm:4.17.21"
checksum: 10/c08619c038846ea6ac754abd6dd29d2568aa705feb69339e836dfa8d8b09abbb2f859371e86863eda41848221f9af43714491467b5b0299122431e202bb0c532
@@ -13963,6 +13990,15 @@ __metadata:
languageName: node
linkType: hard
+"magic-string@npm:~0.30.0":
+ version: 0.30.12
+ resolution: "magic-string@npm:0.30.12"
+ dependencies:
+ "@jridgewell/sourcemap-codec": "npm:^1.5.0"
+ checksum: 10/98016180a52b28efc1362152b45671067facccdaead6b70c1c14c566cba98491bc2e1336474b0996397730dca24400e85649da84d3da62b2560ed03c067573e6
+ languageName: node
+ linkType: hard
+
"make-dir@npm:^3.0.0":
version: 3.0.2
resolution: "make-dir@npm:3.0.2"
@@ -14610,6 +14646,13 @@ __metadata:
languageName: node
linkType: hard
+"moment@npm:~2.30.1":
+ version: 2.30.1
+ resolution: "moment@npm:2.30.1"
+ checksum: 10/ae42d876d4ec831ef66110bdc302c0657c664991e45cf2afffc4b0f6cd6d251dde11375c982a5c0564ccc0fa593fc564576ddceb8c8845e87c15f58aa6baca69
+ languageName: node
+ linkType: hard
+
"ms@npm:2.1.2, ms@npm:^2.1.1":
version: 2.1.2
resolution: "ms@npm:2.1.2"
@@ -15129,6 +15172,13 @@ __metadata:
languageName: node
linkType: hard
+"package-name-regex@npm:~2.0.6":
+ version: 2.0.6
+ resolution: "package-name-regex@npm:2.0.6"
+ checksum: 10/a889d52cdd860dd4feafebb3b9a2fed47d36408fd62bfab07f6386a80395d66e89f9c913bc8ea8ff62108f23d6e6470e5342e20e660a2743465cd4c45f676d4e
+ languageName: node
+ linkType: hard
+
"parent-module@npm:^1.0.0":
version: 1.0.1
resolution: "parent-module@npm:1.0.1"
@@ -16549,6 +16599,24 @@ __metadata:
languageName: node
linkType: hard
+"rollup-plugin-license@npm:3.5.3":
+ version: 3.5.3
+ resolution: "rollup-plugin-license@npm:3.5.3"
+ dependencies:
+ commenting: "npm:~1.1.0"
+ fdir: "npm:6.3.0"
+ lodash: "npm:~4.17.21"
+ magic-string: "npm:~0.30.0"
+ moment: "npm:~2.30.1"
+ package-name-regex: "npm:~2.0.6"
+ spdx-expression-validate: "npm:~2.0.0"
+ spdx-satisfies: "npm:~5.0.1"
+ peerDependencies:
+ rollup: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0
+ checksum: 10/53444d334b21e69ff38f6b223f53f6459ea70cb4d0ba674a9573b967d7bdd1cadc042e97bfe92e9cd5fe8a396fa7857de94e5aeb877cc0a0b8641c4d1d58e195
+ languageName: node
+ linkType: hard
+
"rollup-plugin-visualizer@npm:5.12.0":
version: 5.12.0
resolution: "rollup-plugin-visualizer@npm:5.12.0"
@@ -17067,6 +17135,68 @@ __metadata:
languageName: node
linkType: hard
+"spdx-compare@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "spdx-compare@npm:1.0.0"
+ dependencies:
+ array-find-index: "npm:^1.0.2"
+ spdx-expression-parse: "npm:^3.0.0"
+ spdx-ranges: "npm:^2.0.0"
+ checksum: 10/7d8b55b31163ba8e7abeaf69d8d7accba5aee324dd55e22a796a685ec4d5e3c3cbc2683b9a2edff5543ee6f6242f4ec22c15dc2e493eb807690fb65e1051e5eb
+ languageName: node
+ linkType: hard
+
+"spdx-exceptions@npm:^2.1.0":
+ version: 2.5.0
+ resolution: "spdx-exceptions@npm:2.5.0"
+ checksum: 10/bb127d6e2532de65b912f7c99fc66097cdea7d64c10d3ec9b5e96524dbbd7d20e01cba818a6ddb2ae75e62bb0c63d5e277a7e555a85cbc8ab40044984fa4ae15
+ languageName: node
+ linkType: hard
+
+"spdx-expression-parse@npm:^3.0.0":
+ version: 3.0.1
+ resolution: "spdx-expression-parse@npm:3.0.1"
+ dependencies:
+ spdx-exceptions: "npm:^2.1.0"
+ spdx-license-ids: "npm:^3.0.0"
+ checksum: 10/a1c6e104a2cbada7a593eaa9f430bd5e148ef5290d4c0409899855ce8b1c39652bcc88a725259491a82601159d6dc790bedefc9016c7472f7de8de7361f8ccde
+ languageName: node
+ linkType: hard
+
+"spdx-expression-validate@npm:~2.0.0":
+ version: 2.0.0
+ resolution: "spdx-expression-validate@npm:2.0.0"
+ dependencies:
+ spdx-expression-parse: "npm:^3.0.0"
+ checksum: 10/c100f949afeb529b3b519a70b86d64c3c35be8bf1ef30db32e48936f0c52a0339b3c88c283c97c55f372ea3c347165c9360aae7905cd8f303b817cfef49032c1
+ languageName: node
+ linkType: hard
+
+"spdx-license-ids@npm:^3.0.0":
+ version: 3.0.20
+ resolution: "spdx-license-ids@npm:3.0.20"
+ checksum: 10/30e566ea74b04232c64819d1f5313c00d92e9c73d054541650331fc794499b3bcc4991bcd90fa3c2fc4d040006f58f63104706255266e87a9d452e6574afc60c
+ languageName: node
+ linkType: hard
+
+"spdx-ranges@npm:^2.0.0":
+ version: 2.1.1
+ resolution: "spdx-ranges@npm:2.1.1"
+ checksum: 10/f807bd915aa2975bcebd9c4b4805661f248efcd4953ee62557626452fcd2933183f5b1a307d65507d8be6b9519b4e46dce05b61db0fbd5fce253b8f6d69bbbad
+ languageName: node
+ linkType: hard
+
+"spdx-satisfies@npm:~5.0.1":
+ version: 5.0.1
+ resolution: "spdx-satisfies@npm:5.0.1"
+ dependencies:
+ spdx-compare: "npm:^1.0.0"
+ spdx-expression-parse: "npm:^3.0.0"
+ spdx-ranges: "npm:^2.0.0"
+ checksum: 10/7f28a6ac492afbfc4794602b5d43957451b7afdd42506dc52dbeeed875d9b5f5b94f8f3deab1da4e2815111f57f916d135c7bd24f40245be6dab5dda09d41e91
+ languageName: node
+ linkType: hard
+
"specificity@npm:^0.4.1":
version: 0.4.1
resolution: "specificity@npm:0.4.1"
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/StaticResources.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/StaticResources.java
index 193d44b4a01..967e635bf01 100644
--- a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/StaticResources.java
+++ b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/StaticResources.java
@@ -25,7 +25,7 @@ import java.util.List;
public class StaticResources {
private static final Collection<String> STATIC_RESOURCES = List.of("*.css", "*.css.map", "*.ico", "*.png",
"*.jpg", "*.jpeg", "*.gif", "*.svg", "*.js", "*.js.map", "*.pdf", "/json/*", "*.woff2", "/static/*",
- "/robots.txt", "/favicon.ico", "/apple-touch-icon*", "/mstile*");
+ "/robots.txt", "/favicon.ico", "/apple-touch-icon*", "/mstile*", "/vendor.LICENSE.txt");
private StaticResources() {
// only static