From 3d5eb4cfdc9b68aab1a35913bcad569f5f79fa11 Mon Sep 17 00:00:00 2001
From: Lukas 'Eipi' Eipert <leipert@gitlab.com>
Date: Wed, 10 Mar 2021 12:42:16 +0000
Subject: [PATCH] Run eslint on node scripts and configs

This re-adds our config/, scripts/ and *.config.js files to eslint,
together with some rules to make it a little easier for those
node-scripts, e.g. console logging or importing node or dev dependencies
should be fine.
---
 .eslintignore                                 |  6 --
 .eslintrc.yml                                 | 12 ++++
 babel.config.js                               |  2 -
 .../helpers/incremental_webpack_compiler.js   |  3 +
 config/helpers/is_eslint.js                   |  2 +-
 config/helpers/vendor_dll_hash.js             |  2 +-
 config/karma.config.js                        | 19 +++---
 config/webpack.config.js                      | 62 +++++++++++--------
 config/webpack.vendor.config.js               |  2 +-
 jest.config.base.js                           |  2 +-
 scripts/frontend/block_dependencies.js        |  8 +--
 ..._page_bundle_mixins_css_for_sideeffects.js |  2 +-
 scripts/frontend/extract_gettext_all.js       | 39 +++++++-----
 scripts/frontend/file_test_coverage.js        | 44 ++++++-------
 scripts/frontend/merge_coverage_frontend.js   | 13 ++--
 scripts/frontend/parallel_ci_sequencer.js     | 24 ++++---
 .../stylelint-duplicate-selectors.js          |  6 +-
 .../stylelint/stylelint-utility-classes.js    |  5 +-
 .../stylelint/stylelint-utility-map.js        | 30 ++++++---
 scripts/frontend/stylelint/stylelint-utils.js | 11 ++--
 scripts/frontend/webpack_dev_server.js        | 12 ++--
 21 files changed, 174 insertions(+), 132 deletions(-)

diff --git a/.eslintignore b/.eslintignore
index c41556f6aae10..73e11dfd9744a 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,15 +1,9 @@
 /app/assets/javascripts/locale/**/app.js
-/config/
 /builds/
 /coverage/
 /coverage-frontend/
 /coverage-javascript/
 /node_modules/
 /public/
-/scripts/
 /tmp/
 /vendor/
-jest.config.js
-jest.config.*.js
-karma.config.js
-webpack.config.js
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 75c52ac1319a3..678750c085b29 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -89,3 +89,15 @@ overrides:
     rules:
       '@gitlab/require-i18n-strings': off
       '@gitlab/no-runtime-template-compiler': off
+  - files:
+      - 'config/**/*'
+      - 'scripts/**/*'
+      - '*.config.js'
+      - 'jest.*.js'
+    rules:
+      '@gitlab/require-i18n-strings': off
+      import/no-extraneous-dependencies: off
+      import/no-commonjs: off
+      import/no-nodejs-modules: off
+      filenames/match-regex: off
+      no-console: off
diff --git a/babel.config.js b/babel.config.js
index 6c9d464053558..4dfca8f61448c 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -1,5 +1,3 @@
-/* eslint-disable import/no-commonjs, filenames/match-regex */
-
 const BABEL_ENV = process.env.BABEL_ENV || process.env.NODE_ENV || null;
 
 let presets = [
diff --git a/config/helpers/incremental_webpack_compiler.js b/config/helpers/incremental_webpack_compiler.js
index 786bb6071fa3b..5d4f9bd040d16 100644
--- a/config/helpers/incremental_webpack_compiler.js
+++ b/config/helpers/incremental_webpack_compiler.js
@@ -1,3 +1,4 @@
+/* eslint-disable max-classes-per-file, no-underscore-dangle */
 const fs = require('fs');
 const path = require('path');
 
@@ -7,6 +8,7 @@ const log = (msg, ...rest) => console.log(`IncrementalWebpackCompiler: ${msg}`,
 // Five seconds seem to work fine and the user can read the message
 const TIMEOUT = 5000;
 
+/* eslint-disable class-methods-use-this */
 class NoopCompiler {
   constructor() {
     this.enabled = false;
@@ -20,6 +22,7 @@ class NoopCompiler {
 
   setupMiddleware() {}
 }
+/* eslint-enable class-methods-use-this */
 
 class IncrementalWebpackCompiler {
   constructor(historyFilePath) {
diff --git a/config/helpers/is_eslint.js b/config/helpers/is_eslint.js
index 60528796962ec..9a3a9bfca12fc 100644
--- a/config/helpers/is_eslint.js
+++ b/config/helpers/is_eslint.js
@@ -2,7 +2,7 @@
  * Returns true if the given module is required from eslint
  */
 const isESLint = (mod) => {
-  let parent = mod.parent;
+  let { parent } = mod;
 
   while (parent) {
     if (parent.filename && parent.filename.includes('/eslint')) {
diff --git a/config/helpers/vendor_dll_hash.js b/config/helpers/vendor_dll_hash.js
index 2df97e7b95d60..cdbaebc9789b4 100644
--- a/config/helpers/vendor_dll_hash.js
+++ b/config/helpers/vendor_dll_hash.js
@@ -1,6 +1,6 @@
 const fs = require('fs');
-const path = require('path');
 const crypto = require('crypto');
+const path = require('path');
 
 const CACHE_PATHS = [
   './config/webpack.config.js',
diff --git a/config/karma.config.js b/config/karma.config.js
index 1d65e65ce2ac6..1c2dd21c1890c 100644
--- a/config/karma.config.js
+++ b/config/karma.config.js
@@ -1,13 +1,14 @@
-const path = require('path');
-const glob = require('glob');
+/* eslint-disable no-inner-declarations, no-param-reassign */
 const chalk = require('chalk');
-const webpack = require('webpack');
 const argumentsParser = require('commander');
-const webpackConfig = require('./webpack.config.js');
+const glob = require('glob');
+const path = require('path');
+const webpack = require('webpack');
 const IS_EE = require('./helpers/is_ee_env');
+const webpackConfig = require('./webpack.config.js');
 
 const ROOT_PATH = path.resolve(__dirname, '..');
-const SPECS_PATH = /^(?:\.[\\\/])?(ee[\\\/])?spec[\\\/]javascripts[\\\/]/;
+const SPECS_PATH = /^(?:\.[\\/])?(ee[\\/])?spec[\\/]javascripts[\\/]/;
 
 function exitError(message) {
   console.error(chalk.red(`\nError: ${message}\n`));
@@ -77,7 +78,7 @@ if (specFilters.length) {
         root: ROOT_PATH,
         matchBase: true,
       })
-      .filter((path) => path.endsWith('spec.js')),
+      .filter((filePath) => filePath.endsWith('spec.js')),
   );
 
   // flatten
@@ -97,14 +98,14 @@ if (specFilters.length) {
   }
 
   const CE_FILES = filteredSpecFiles.filter((file) => !file.startsWith('ee'));
-  createContext(CE_FILES, /[^e]{2}[\\\/]spec[\\\/]javascripts$/, 'spec/javascripts');
+  createContext(CE_FILES, /[^e]{2}[\\/]spec[\\/]javascripts$/, 'spec/javascripts');
 
   const EE_FILES = filteredSpecFiles.filter((file) => file.startsWith('ee'));
-  createContext(EE_FILES, /ee[\\\/]spec[\\\/]javascripts$/, 'ee/spec/javascripts');
+  createContext(EE_FILES, /ee[\\/]spec[\\/]javascripts$/, 'ee/spec/javascripts');
 }
 
 // Karma configuration
-module.exports = function (config) {
+module.exports = (config) => {
   process.env.TZ = 'Etc/UTC';
 
   const fixturesPath = `tmp/tests/frontend/fixtures${IS_EE ? '-ee' : ''}`;
diff --git a/config/webpack.config.js b/config/webpack.config.js
index e43fc3ed21c33..e02141acc5909 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -1,25 +1,34 @@
 const fs = require('fs');
-const path = require('path');
-const glob = require('glob');
-const webpack = require('webpack');
-const VueLoaderPlugin = require('vue-loader/lib/plugin');
-const StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;
+
+const SOURCEGRAPH_VERSION = require('@sourcegraph/code-host-integration/package.json').version;
+
 const CompressionPlugin = require('compression-webpack-plugin');
-const MonacoWebpackPlugin = require('./plugins/monaco_webpack');
-const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 const CopyWebpackPlugin = require('copy-webpack-plugin');
-const vendorDllHash = require('./helpers/vendor_dll_hash');
+const glob = require('glob');
+const path = require('path');
+const VueLoaderPlugin = require('vue-loader/lib/plugin');
+const VUE_LOADER_VERSION = require('vue-loader/package.json').version;
+const VUE_VERSION = require('vue/package.json').version;
+const webpack = require('webpack');
+const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
+const { StatsWriterPlugin } = require('webpack-stats-plugin');
+const WEBPACK_VERSION = require('webpack/package.json').version;
+
 const createIncrementalWebpackCompiler = require('./helpers/incremental_webpack_compiler');
+const IS_EE = require('./helpers/is_ee_env');
+const vendorDllHash = require('./helpers/vendor_dll_hash');
+
+const MonacoWebpackPlugin = require('./plugins/monaco_webpack');
 
 const ROOT_PATH = path.resolve(__dirname, '..');
 const VENDOR_DLL = process.env.WEBPACK_VENDOR_DLL && process.env.WEBPACK_VENDOR_DLL !== 'false';
 const CACHE_PATH = process.env.WEBPACK_CACHE_PATH || path.join(ROOT_PATH, 'tmp/cache');
 const IS_PRODUCTION = process.env.NODE_ENV === 'production';
 const IS_DEV_SERVER = process.env.WEBPACK_DEV_SERVER === 'true';
-const IS_EE = require('./helpers/is_ee_env');
+
 const DEV_SERVER_HOST = process.env.DEV_SERVER_HOST || 'localhost';
 const DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10) || 3808;
-const DEV_SERVER_PUBLIC_ADDR = process.env.DEV_SERVER_PUBLIC_ADDR;
+const { DEV_SERVER_PUBLIC_ADDR } = process.env;
 const DEV_SERVER_ALLOWED_HOSTS =
   process.env.DEV_SERVER_ALLOWED_HOSTS && process.env.DEV_SERVER_ALLOWED_HOSTS.split(',');
 const DEV_SERVER_HTTPS = process.env.DEV_SERVER_HTTPS && process.env.DEV_SERVER_HTTPS !== 'false';
@@ -38,11 +47,6 @@ const WEBPACK_OUTPUT_PATH = path.join(ROOT_PATH, 'public/assets/webpack');
 const WEBPACK_PUBLIC_PATH = '/assets/webpack/';
 const SOURCEGRAPH_PACKAGE = '@sourcegraph/code-host-integration';
 
-const VUE_VERSION = require('vue/package.json').version;
-const VUE_LOADER_VERSION = require('vue-loader/package.json').version;
-const WEBPACK_VERSION = require('webpack/package.json').version;
-const SOURCEGRAPH_VERSION = require(path.join(SOURCEGRAPH_PACKAGE, 'package.json')).version;
-
 const SOURCEGRAPH_PATH = path.join('sourcegraph', SOURCEGRAPH_VERSION, '/');
 const SOURCEGRAPH_OUTPUT_PATH = path.join(WEBPACK_OUTPUT_PATH, SOURCEGRAPH_PATH);
 const SOURCEGRAPH_PUBLIC_PATH = path.join(WEBPACK_PUBLIC_PATH, SOURCEGRAPH_PATH);
@@ -67,19 +71,19 @@ function generateEntries() {
   });
   watchAutoEntries = [path.join(ROOT_PATH, 'app/assets/javascripts/pages/')];
 
-  function generateAutoEntries(path, prefix = '.') {
-    const chunkPath = path.replace(/\/index\.js$/, '');
+  function generateAutoEntries(entryPath, prefix = '.') {
+    const chunkPath = entryPath.replace(/\/index\.js$/, '');
     const chunkName = chunkPath.replace(/\//g, '.');
-    autoEntriesMap[chunkName] = `${prefix}/${path}`;
+    autoEntriesMap[chunkName] = `${prefix}/${entryPath}`;
   }
 
-  pageEntries.forEach((path) => generateAutoEntries(path));
+  pageEntries.forEach((entryPath) => generateAutoEntries(entryPath));
 
   if (IS_EE) {
     const eePageEntries = glob.sync('pages/**/index.js', {
       cwd: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
     });
-    eePageEntries.forEach((path) => generateAutoEntries(path, 'ee'));
+    eePageEntries.forEach((entryPath) => generateAutoEntries(entryPath, 'ee'));
     watchAutoEntries.push(path.join(ROOT_PATH, 'ee/app/assets/javascripts/pages/'));
   }
 
@@ -198,9 +202,9 @@ module.exports = {
       },
       {
         test: /\.js$/,
-        exclude: (path) =>
-          /node_modules\/(?!tributejs)|node_modules|vendor[\\/]assets/.test(path) &&
-          !/\.vue\.js/.test(path),
+        exclude: (modulePath) =>
+          /node_modules\/(?!tributejs)|node_modules|vendor[\\/]assets/.test(modulePath) &&
+          !/\.vue\.js/.test(modulePath),
         loader: 'babel-loader',
         options: {
           cacheDirectory: path.join(CACHE_PATH, 'babel-loader'),
@@ -354,7 +358,7 @@ module.exports = {
     // webpack-rails only needs assetsByChunkName to function properly
     new StatsWriterPlugin({
       filename: 'manifest.json',
-      transform: function (data, opts) {
+      transform(data, opts) {
         const stats = opts.compiler.getStats().toJson({
           chunkModules: false,
           source: false,
@@ -412,6 +416,7 @@ module.exports = {
               `Warning: No vendor DLL found at: ${dll.cacheFrom}. Compiling DLL automatically.`,
             );
 
+            // eslint-disable-next-line global-require
             const dllConfig = require('./webpack.vendor.config.js');
             const dllCompiler = webpack(dllConfig);
 
@@ -435,7 +440,7 @@ module.exports = {
               }
 
               dll.exists = true;
-              callback();
+              return callback();
             });
           }
         });
@@ -459,6 +464,7 @@ module.exports = {
 
     !IS_EE &&
       new webpack.NormalModuleReplacementPlugin(/^ee_component\/(.*)\.vue/, (resource) => {
+        // eslint-disable-next-line no-param-reassign
         resource.request = path.join(
           ROOT_PATH,
           'app/assets/javascripts/vue_shared/components/empty_component.js',
@@ -521,7 +527,7 @@ module.exports = {
     // output the in-memory heap size upon compilation and exit
     WEBPACK_MEMORY_TEST && {
       apply(compiler) {
-        compiler.hooks.emit.tapAsync('ReportMemoryConsumptionPlugin', (compilation, callback) => {
+        compiler.hooks.emit.tapAsync('ReportMemoryConsumptionPlugin', () => {
           console.log('Assets compiled...');
           if (global.gc) {
             console.log('Running garbage collection...');
@@ -552,7 +558,9 @@ module.exports = {
           );
 
           // exit in case we're running webpack-dev-server
-          IS_DEV_SERVER && process.exit();
+          if (IS_DEV_SERVER) {
+            process.exit();
+          }
         });
       },
     },
diff --git a/config/webpack.vendor.config.js b/config/webpack.vendor.config.js
index 29c4c33314e74..7e5365987eeca 100644
--- a/config/webpack.vendor.config.js
+++ b/config/webpack.vendor.config.js
@@ -1,7 +1,7 @@
 const path = require('path');
 const webpack = require('webpack');
-const vendorDllHash = require('./helpers/vendor_dll_hash');
 const { YarnCheck } = require('yarn-check-webpack-plugin');
+const vendorDllHash = require('./helpers/vendor_dll_hash');
 
 const ROOT_PATH = path.resolve(__dirname, '..');
 
diff --git a/jest.config.base.js b/jest.config.base.js
index 98c70735d92f4..4e9b84d1d34f8 100644
--- a/jest.config.base.js
+++ b/jest.config.base.js
@@ -27,7 +27,7 @@ module.exports = (path) => {
   // workaround for eslint-import-resolver-jest only resolving in test files
   // see https://github.com/JoinColony/eslint-import-resolver-jest#note
   if (isESLint(module)) {
-    testMatch = testMatch.map((path) => path.replace('_spec.js', ''));
+    testMatch = testMatch.map((modulePath) => modulePath.replace('_spec.js', ''));
   }
 
   const TEST_FIXTURES_PATTERN = 'test_fixtures(/.*)$';
diff --git a/scripts/frontend/block_dependencies.js b/scripts/frontend/block_dependencies.js
index a1ff8d5ee3612..f229f317cbb6d 100644
--- a/scripts/frontend/block_dependencies.js
+++ b/scripts/frontend/block_dependencies.js
@@ -1,8 +1,8 @@
-const path = require('path');
-const packageJson = require(path.join(process.cwd(), 'package.json'));
+const packageJson = require('../../package.json');
+
 const blockedDependencies = packageJson.blockedDependencies || {};
-const dependencies = packageJson.dependencies;
-const devDependencies = packageJson.devDependencies;
+const { dependencies } = packageJson;
+const { devDependencies } = packageJson;
 const blockedDependenciesNames = Object.keys(blockedDependencies);
 const blockedDependenciesFound = blockedDependenciesNames.filter(
   (blockedDependency) => dependencies[blockedDependency] || devDependencies[blockedDependency],
diff --git a/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js b/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
index 34e939e3cebe8..22a4aac762b53 100755
--- a/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
+++ b/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
@@ -7,9 +7,9 @@ if (process.env.RAILS_ENV !== 'production') {
   process.exit(0);
 }
 
-const path = require('path');
 const fs = require('fs');
 const glob = require('glob');
+const path = require('path');
 const pjs = require('postcss');
 
 const paths = glob.sync('public/assets/page_bundles/_mixins_and_variables_and_functions*.css', {
diff --git a/scripts/frontend/extract_gettext_all.js b/scripts/frontend/extract_gettext_all.js
index 67163a601bcac..896790a73bb9a 100644
--- a/scripts/frontend/extract_gettext_all.js
+++ b/scripts/frontend/extract_gettext_all.js
@@ -5,6 +5,7 @@ const {
   decorateJSParserWithVueSupport,
   decorateExtractorWithHelpers,
 } = require('gettext-extractor-vue');
+const vue2TemplateCompiler = require('vue-template-compiler');
 const ensureSingleLine = require('../../app/assets/javascripts/locale/ensure_single_line.js');
 
 const args = argumentsParser
@@ -37,12 +38,12 @@ const jsParser = extractor.createJsParser([
 ]);
 
 const vueParser = decorateJSParserWithVueSupport(jsParser, {
-  vue2TemplateCompiler: require('vue-template-compiler'),
+  vue2TemplateCompiler,
 });
 
 function printJson() {
-  const messages = extractor.getMessages().reduce((result, message) => {
-    let text = message.text;
+  const messages = extractor.getMessages().reduce((acc, message) => {
+    let { text } = message;
     if (message.textPlural) {
       text += `\u0000${message.textPlural}`;
     }
@@ -50,25 +51,35 @@ function printJson() {
     message.references.forEach((reference) => {
       const filename = reference.replace(/:\d+$/, '');
 
-      if (!Array.isArray(result[filename])) {
-        result[filename] = [];
+      if (!Array.isArray(acc[filename])) {
+        acc[filename] = [];
       }
 
-      result[filename].push([text, reference]);
+      acc[filename].push([text, reference]);
     });
 
-    return result;
+    return acc;
   }, {});
 
   console.log(JSON.stringify(messages));
 }
 
-if (args.file) {
-  vueParser.parseFile(args.file).then(() => printJson());
-} else if (args.all) {
-  vueParser.parseFilesGlob('{ee/app,app}/assets/javascripts/**/*.{js,vue}').then(() => printJson());
-} else {
-  console.warn('ERROR: Please use the script correctly:');
+async function main() {
+  if (args.file) {
+    return vueParser.parseFile(args.file).then(() => printJson());
+  }
+
+  if (args.all) {
+    return vueParser
+      .parseFilesGlob('{ee/app,app}/assets/javascripts/**/*.{js,vue}')
+      .then(() => printJson());
+  }
+
+  throw new Error('ERROR: Please use the script correctly:');
+}
+
+main().catch((error) => {
+  console.warn(error.message);
   args.outputHelp();
   process.exit(1);
-}
+});
diff --git a/scripts/frontend/file_test_coverage.js b/scripts/frontend/file_test_coverage.js
index ec6ec4a1e9d07..04a9035fce269 100755
--- a/scripts/frontend/file_test_coverage.js
+++ b/scripts/frontend/file_test_coverage.js
@@ -31,28 +31,6 @@ let numTestFiles = 0;
 
 const isVerbose = process.argv.some((arg) => arg === '-v');
 
-const countSourceFiles = (path) =>
-  forEachFileIn(path, (fileName) => {
-    if (fileName.endsWith('.vue') || fileName.endsWith('.js')) {
-      if (isVerbose) {
-        console.log(`source file: ${fileName}`);
-      }
-
-      numSourceFiles += 1;
-    }
-  });
-
-const countTestFiles = (path) =>
-  forEachFileIn(path, (fileName) => {
-    if (fileName.endsWith('_spec.js')) {
-      if (isVerbose) {
-        console.log(`test file: ${fileName}`);
-      }
-
-      numTestFiles += 1;
-    }
-  });
-
 function forEachFileIn(dirPath, callback) {
   fs.readdir(dirPath, (err, files) => {
     if (err) {
@@ -75,6 +53,28 @@ function forEachFileIn(dirPath, callback) {
   });
 }
 
+const countSourceFiles = (currentPath) =>
+  forEachFileIn(currentPath, (fileName) => {
+    if (fileName.endsWith('.vue') || fileName.endsWith('.js')) {
+      if (isVerbose) {
+        console.log(`source file: ${fileName}`);
+      }
+
+      numSourceFiles += 1;
+    }
+  });
+
+const countTestFiles = (currentPath) =>
+  forEachFileIn(currentPath, (fileName) => {
+    if (fileName.endsWith('_spec.js')) {
+      if (isVerbose) {
+        console.log(`test file: ${fileName}`);
+      }
+
+      numTestFiles += 1;
+    }
+  });
+
 console.log(`Source directories: ${sourceDirectories.join(', ')}`);
 console.log(`Test directories: ${testDirectories.join(', ')}`);
 
diff --git a/scripts/frontend/merge_coverage_frontend.js b/scripts/frontend/merge_coverage_frontend.js
index 0c45a38b9b51b..6b3826ddac75f 100644
--- a/scripts/frontend/merge_coverage_frontend.js
+++ b/scripts/frontend/merge_coverage_frontend.js
@@ -1,8 +1,8 @@
-const { create } = require('istanbul-reports');
+const { sync } = require('glob');
 const { createCoverageMap } = require('istanbul-lib-coverage');
 const { createContext } = require('istanbul-lib-report');
+const { create } = require('istanbul-reports');
 const { resolve } = require('path');
-const { sync } = require('glob');
 
 const coverageMap = createCoverageMap();
 
@@ -12,7 +12,7 @@ const reportFiles = sync(`${coverageDir}/*/coverage-final.json`);
 // Normalize coverage report generated by jest that has additional "data" key
 // https://github.com/facebook/jest/issues/2418#issuecomment-423806659
 const normalizeReport = (report) => {
-  const normalizedReport = Object.assign({}, report);
+  const normalizedReport = { ...report };
   Object.entries(normalizedReport).forEach(([k, v]) => {
     if (v.data) normalizedReport[k] = v.data;
   });
@@ -20,11 +20,14 @@ const normalizeReport = (report) => {
 };
 
 reportFiles
-  .map((reportFile) => require(reportFile))
+  .map((reportFile) => {
+    // eslint-disable-next-line global-require, import/no-dynamic-require
+    return require(reportFile);
+  })
   .map(normalizeReport)
   .forEach((report) => coverageMap.merge(report));
 
-const context = createContext({ coverageMap: coverageMap, dir: 'coverage-frontend' });
+const context = createContext({ coverageMap, dir: 'coverage-frontend' });
 
 ['json', 'lcov', 'text-summary', 'clover', 'cobertura'].forEach((reporter) => {
   create(reporter, {}).execute(context);
diff --git a/scripts/frontend/parallel_ci_sequencer.js b/scripts/frontend/parallel_ci_sequencer.js
index d7a674535a68d..262e9e2256ecc 100644
--- a/scripts/frontend/parallel_ci_sequencer.js
+++ b/scripts/frontend/parallel_ci_sequencer.js
@@ -1,5 +1,15 @@
 const Sequencer = require('@jest/test-sequencer').default;
 
+const sortByPath = (test1, test2) => {
+  if (test1.path < test2.path) {
+    return -1;
+  }
+  if (test1.path > test2.path) {
+    return 1;
+  }
+  return 0;
+};
+
 class ParallelCISequencer extends Sequencer {
   constructor() {
     super();
@@ -8,7 +18,7 @@ class ParallelCISequencer extends Sequencer {
   }
 
   sort(tests) {
-    const sortedTests = this.sortByPath(tests);
+    const sortedTests = [...tests].sort(sortByPath);
     const testsForThisRunner = this.distributeAcrossCINodes(sortedTests);
 
     console.log(`CI_NODE_INDEX: ${this.ciNodeIndex}`);
@@ -19,18 +29,6 @@ class ParallelCISequencer extends Sequencer {
     return testsForThisRunner;
   }
 
-  sortByPath(tests) {
-    return tests.sort((test1, test2) => {
-      if (test1.path < test2.path) {
-        return -1;
-      }
-      if (test1.path > test2.path) {
-        return 1;
-      }
-      return 0;
-    });
-  }
-
   distributeAcrossCINodes(tests) {
     return tests.filter((test, index) => {
       return index % this.ciNodeTotal === this.ciNodeIndex - 1;
diff --git a/scripts/frontend/stylelint/stylelint-duplicate-selectors.js b/scripts/frontend/stylelint/stylelint-duplicate-selectors.js
index 89242158157a4..982ddf524a315 100644
--- a/scripts/frontend/stylelint/stylelint-duplicate-selectors.js
+++ b/scripts/frontend/stylelint/stylelint-duplicate-selectors.js
@@ -1,5 +1,6 @@
 const stylelint = require('stylelint');
 const utils = require('./stylelint-utils');
+
 const ruleName = 'stylelint-gitlab/duplicate-selectors';
 
 const messages = stylelint.utils.ruleMessages(ruleName, {
@@ -8,12 +9,13 @@ const messages = stylelint.utils.ruleMessages(ruleName, {
   },
 });
 
-module.exports = stylelint.createPlugin(ruleName, function (enabled) {
+module.exports = stylelint.createPlugin(ruleName, (enabled) => {
   if (!enabled) {
     return;
   }
 
-  return function (root, result) {
+  // eslint-disable-next-line consistent-return
+  return (root, result) => {
     const selectorGroups = {};
     utils.createPropertiesHashmap(root, result, ruleName, messages, selectorGroups, true);
   };
diff --git a/scripts/frontend/stylelint/stylelint-utility-classes.js b/scripts/frontend/stylelint/stylelint-utility-classes.js
index 1b266fc31c9cf..420fe82d826f1 100644
--- a/scripts/frontend/stylelint/stylelint-utility-classes.js
+++ b/scripts/frontend/stylelint/stylelint-utility-classes.js
@@ -10,12 +10,13 @@ const messages = stylelint.utils.ruleMessages(ruleName, {
   },
 });
 
-module.exports = stylelint.createPlugin(ruleName, function (enabled) {
+module.exports = stylelint.createPlugin(ruleName, (enabled) => {
   if (!enabled) {
     return;
   }
 
-  return function (root, result) {
+  // eslint-disable-next-line consistent-return
+  return (root, result) => {
     utils.createPropertiesHashmap(root, result, ruleName, messages, utilityClasses, false);
   };
 });
diff --git a/scripts/frontend/stylelint/stylelint-utility-map.js b/scripts/frontend/stylelint/stylelint-utility-map.js
index bf8ee362740eb..545aade9ccc00 100644
--- a/scripts/frontend/stylelint/stylelint-utility-map.js
+++ b/scripts/frontend/stylelint/stylelint-utility-map.js
@@ -1,10 +1,11 @@
-const sass = require('node-sass');
-const postcss = require('postcss');
 const fs = require('fs');
+const sass = require('node-sass');
 const path = require('path');
+const postcss = require('postcss');
 const prettier = require('prettier');
 
 const utils = require('./stylelint-utils');
+
 const ROOT_PATH = path.resolve(__dirname, '../../..');
 const hashMapPath = path.resolve(__dirname, './utility-classes-map.js');
 
@@ -22,19 +23,28 @@ sass.render(
     includePaths: [path.resolve(ROOT_PATH, 'node_modules/bootstrap/scss')],
   },
   (err, result) => {
-    if (err) console.error('Error ', err);
+    if (err) {
+      return console.error('Error ', err);
+    }
 
     const cssResult = result.css.toString();
 
     // We just use postcss to create a CSS tree
-    postcss([])
+    return postcss([])
       .process(cssResult, {
         // This suppresses a postcss warning
         from: undefined,
       })
-      .then((result) => {
+      .then((processedResult) => {
         const selectorGroups = {};
-        utils.createPropertiesHashmap(result.root, result, null, null, selectorGroups, true);
+        utils.createPropertiesHashmap(
+          processedResult.root,
+          processedResult,
+          null,
+          null,
+          selectorGroups,
+          true,
+        );
 
         const prettierOptions = prettier.resolveConfig.sync(hashMapPath);
         const prettyHashmap = prettier.format(
@@ -42,12 +52,12 @@ sass.render(
           prettierOptions,
         );
 
-        fs.writeFile(hashMapPath, prettyHashmap, function (err) {
-          if (err) {
-            return console.log(err);
+        fs.writeFile(hashMapPath, prettyHashmap, (e) => {
+          if (e) {
+            return console.log(e);
           }
 
-          console.log('The file was saved!');
+          return console.log('The file was saved!');
         });
       });
   },
diff --git a/scripts/frontend/stylelint/stylelint-utils.js b/scripts/frontend/stylelint/stylelint-utils.js
index e7452b0cdb28c..c9d9c7d9aad57 100644
--- a/scripts/frontend/stylelint/stylelint-utils.js
+++ b/scripts/frontend/stylelint/stylelint-utils.js
@@ -1,5 +1,5 @@
-const stylelint = require('stylelint');
 const md5 = require('md5');
+const stylelint = require('stylelint');
 
 module.exports.createPropertiesHashmap = (
   ruleRoot,
@@ -15,7 +15,7 @@ module.exports.createPropertiesHashmap = (
     if (
       rule &&
       rule.parent &&
-      rule.parent.type != 'atrule' &&
+      rule.parent.type !== 'atrule' &&
       !(
         selector.includes('-webkit-') ||
         selector.includes('-moz-') ||
@@ -25,7 +25,7 @@ module.exports.createPropertiesHashmap = (
       )
     ) {
       let cssArray = [];
-      rule.nodes.forEach(function (property) {
+      rule.nodes.forEach((property) => {
         const { prop, value } = property;
         if (property && value) {
           const propval = `${prop}${value}${property.important ? '!important' : ''}`;
@@ -41,11 +41,11 @@ module.exports.createPropertiesHashmap = (
         const selObj = selectorGroups[hashValue];
 
         const selectorLine = `${selector} (${
-          rule.source.input.file ? rule.source.input.file + ' -' : ''
+          rule.source.input.file ? `${rule.source.input.file} -` : ''
         }${rule.source.start.line}:${rule.source.start.column})`;
 
         if (selObj) {
-          if (selectorGroups[hashValue].selectors.indexOf(selector) == -1) {
+          if (selectorGroups[hashValue].selectors.indexOf(selector) === -1) {
             let lastSelector =
               selectorGroups[hashValue].selectors[selectorGroups[hashValue].selectors.length - 1];
 
@@ -67,6 +67,7 @@ module.exports.createPropertiesHashmap = (
             }
           }
         } else if (addSelectors) {
+          // eslint-disable-next-line no-param-reassign
           selectorGroups[hashValue] = {
             selectors: [selectorLine],
           };
diff --git a/scripts/frontend/webpack_dev_server.js b/scripts/frontend/webpack_dev_server.js
index fbb80c9617d09..a76e6dc024ac9 100755
--- a/scripts/frontend/webpack_dev_server.js
+++ b/scripts/frontend/webpack_dev_server.js
@@ -2,8 +2,8 @@ const nodemon = require('nodemon');
 
 const DEV_SERVER_HOST = process.env.DEV_SERVER_HOST || 'localhost';
 const DEV_SERVER_PORT = process.env.DEV_SERVER_PORT || '3808';
-const STATIC_MODE = process.env.DEV_SERVER_STATIC && process.env.DEV_SERVER_STATIC != 'false';
-const DLL_MODE = process.env.WEBPACK_VENDOR_DLL && process.env.WEBPACK_VENDOR_DLL != 'false';
+const STATIC_MODE = process.env.DEV_SERVER_STATIC && process.env.DEV_SERVER_STATIC !== 'false';
+const DLL_MODE = process.env.WEBPACK_VENDOR_DLL && process.env.WEBPACK_VENDOR_DLL !== 'false';
 
 const baseConfig = {
   ignoreRoot: ['.git', 'node_modules/*/'],
@@ -30,7 +30,7 @@ if (STATIC_MODE) {
 
 // run webpack through webpack-dev-server, optionally compiling a DLL to reduce memory
 else {
-  let watch = ['config/webpack.config.js'];
+  const watch = ['config/webpack.config.js'];
 
   // if utilizing the vendor DLL, we need to restart the process when dependency changes occur
   if (DLL_MODE) {
@@ -51,7 +51,7 @@ else {
 
 // print useful messages for nodemon events
 nodemon
-  .on('start', function () {
+  .on('start', () => {
     console.log(`Starting webpack webserver on http://${DEV_SERVER_HOST}:${DEV_SERVER_PORT}`);
     if (STATIC_MODE) {
       console.log('You are starting webpack in compile-once mode');
@@ -59,10 +59,10 @@ nodemon
       console.log('If you change them often, you might want to unset DEV_SERVER_STATIC');
     }
   })
-  .on('quit', function () {
+  .on('quit', () => {
     console.log('Shutting down webpack process');
     process.exit();
   })
-  .on('restart', function (files) {
+  .on('restart', (files) => {
     console.log('Restarting webpack process due to: ', files);
   });
-- 
GitLab