]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-23205 Add rollup-plugin-license like in SC (serve 3rd-party licenses at /vendor...
authorDavid Cho-Lerat <david.cho-lerat@sonarsource.com>
Wed, 16 Oct 2024 09:56:00 +0000 (11:56 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 22 Oct 2024 20:03:10 +0000 (20:03 +0000)
server/sonar-web/config/license.ts [new file with mode: 0644]
server/sonar-web/package.json
server/sonar-web/vite.config.mjs
server/sonar-web/yarn.lock
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/StaticResources.java

diff --git a/server/sonar-web/config/license.ts b/server/sonar-web/config/license.ts
new file mode 100644 (file)
index 0000000..066d4e4
--- /dev/null
@@ -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');
+};
index b8ccadcbde1c54c563dceac08c5734804dcffb3d..ca3163a31b7d842d02df186ae9290f1576caf690 100644 (file)
     "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",
index b0759c5f7f1be984ab80be41acd9de3ed8076d03..f5c3d1fcb2c2308fbfa10d859e3400b656fb08ef 100644 (file)
@@ -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
     },
index d62c34d11e1c20c4e26e4c41be457b5645db1a27..f1fe0bcdf7dd9c1a42b6962fbda82e0de0bf0530 100644 (file)
@@ -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"
index 193d44b4a0102a0a73996480e2ea46e19efa6b4b..967e635bf01d177efc9d81080beb58ab8a6966fe 100644 (file)
@@ -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