UNPKG

@interaktiv/dia-scripts

Version:

CLI toolbox with common scripts for most sort of projects at DIA

204 lines (164 loc) 6.5 kB
"use strict"; const path = require('path'); const { ensureString, isArray } = require('@interaktiv/types'); const spawn = require('cross-spawn'); const exit = require('exit'); const fs = require('fs-extra'); const mkdirp = require('mkdirp'); const yargsParser = require('yargs-parser'); const { PMD_CACHE_FILE, PMD_DIR, PMD_IGNORE_FILE, PMD_LOGFILE, PMD_META_DATA_BUNDLE, createFileIfNeeded, createPmdMetaDataBundleFromDir, createPmdMetaDataBundleFromFiles, fromRoot, hasFile, isApexFile, parseEnv, resolveBin, resolvePmdBin } = require('../../utils'); const CMD_EXIT_CODE_SUCCESS = 0; const PMD_EXIT_CODE_RULE_VIOLATION = 4; const PMD_EXIT_CODE_SUCCESS = CMD_EXIT_CODE_SUCCESS; const ON_PRE_COMMIT = parseEnv('SCRIPTS_PRE-COMMIT', false); const here = p => path.join(__dirname, p); const hereRelative = p => here(p).replace(process.cwd(), '.'); const getPmdPath = () => { try { return resolveBin('pmd'); } catch (_err) { return `bash ${resolvePmdBin()}`; } }; const convertCmdToSpawnArgs = cmd => { ensureString(cmd); return cmd.split(' '); }; const validatePmdInstallation = cmd => { const [command, ...args] = convertCmdToSpawnArgs(cmd); const result = spawn.sync(command, [...args, '-help']); if (result.status === PMD_EXIT_CODE_SUCCESS) return; process.exitCode = result.status; throw new Error(result.stderr || result.error); }; const printReport = reportFile => { if (fs.existsSync(reportFile) === false) return; const contents = fs.readFileSync(reportFile); console.log(''); console.log('[***] PMD Logs'); console.log(''); console.log(contents.toString()); console.log(''); }; const printMetaDataConvertMessage = () => { console.log(''); console.log('[***] Converting Metadata for PMD'); console.log(''); }; const createPmdMetaDataBundleInternal = args => { const filesGiven = args._.length > 0; let status = -1; if (filesGiven) { // We need to take all the flag-less arguments (the files that should be // linted) and filter out the ones that aren't Apex files. Otherwise json // or css files may be passed through, cause of pre-commit hook for example const filesToConvert = args._.filter(isApexFile); printMetaDataConvertMessage(); if (isArray(filesToConvert)) { status = createPmdMetaDataBundleFromFiles(filesToConvert); } } else if (args.refreshMetaData || hasFile(PMD_META_DATA_BUNDLE) === false) { printMetaDataConvertMessage(); status = createPmdMetaDataBundleFromDir(fromRoot('force-app')); } if (status !== CMD_EXIT_CODE_SUCCESS) exit(status); }; const resolveConfig = argv => { if (argv.includes('-rulesets')) return []; const projectRulesetPath = path.join(PMD_DIR, 'ruleset.xml'); if (hasFile(projectRulesetPath)) { return ['-rulesets', projectRulesetPath]; } return ['-rulesets', hereRelative('../../config/pmd-ruleset.xml')]; }; /** * Checks if JRE is there and has the needed version. * * @private * @throws */ function validateJRE() { // Check if JRE is 1.7 or higher const javaResult = spawn.sync('java', ['-version']); if (javaResult.status > 0) { throw new Error('JRE is missing, you must use JRE 1.7 or higher'); } const versionMatch = javaResult.output.toString('utf-8').match(/"([0-9._]*)"/); if (versionMatch == null || versionMatch.length === 0 || versionMatch.length < 2) { console.log('[***] Could not determine Java version, skipping JRE validation'); console.log(''); } const version = versionMatch[1]; const versionParts = version.split('.'); const majorVersion = versionParts[0]; const minorVersion = versionParts[1]; if (majorVersion < 1 || minorVersion < 7) { throw new Error('You must use JRE 1.7 or higher'); } } // eslint-disable-next-line complexity (function () { let argv = process.argv.slice(2); const args = yargsParser(argv); const filesGiven = args._.length > 0; // We are running on `pre-commit` hook but no files passed from `lint-staged`, // skip if (ON_PRE_COMMIT && filesGiven === false) { exit(0); return; } if (argv.includes('--validate-jre')) validateJRE(); const config = resolveConfig(argv); const printReportAfterRun = argv.includes('--no-print-report') === false; const cache = argv.includes('-cache') ? [] : ['-cache', PMD_CACHE_FILE]; const useBuiltinLogFile = argv.includes('-reportfile') === false; const logFile = useBuiltinLogFile ? ['-reportfile', PMD_LOGFILE] : []; createFileIfNeeded(useBuiltinLogFile ? PMD_LOGFILE : args.reportFile); const logFormat = argv.includes('-format') ? [] : ['-format', 'textcolor']; const suppressMarker = argv.includes('-suppressmarker') ? [] : ['-suppressmarker', 'pmd-disable-line']; const useBuiltinSourceDir = argv.includes('-dir') === false; const sourceDir = useBuiltinSourceDir ? ['-dir', PMD_META_DATA_BUNDLE] : []; mkdirp.sync(useBuiltinSourceDir ? path.dirname(PMD_META_DATA_BUNDLE) : args.dir); const showSuppressed = argv.includes('--do-not-showsuppressed') ? [] : ['-showsuppressed']; const ignoreFile = args.ignorelist || PMD_IGNORE_FILE; let ignoreList = []; // Check if ignore file exists otherwise PMD raises an error. // Please make sure the file is not empty, otherwise PMD also raises an error if (hasFile(ignoreFile)) ignoreList = ['-ignorelist', ignoreFile]; const DEBUG_ENV = parseEnv('DEBUG'); const debugFlag = DEBUG_ENV === true || DEBUG_ENV === 1 ? ['-debug'] : []; createPmdMetaDataBundleInternal(args); argv = argv.filter(a => ['--no-print-report', '--refresh-meta-data', '--do-not-showsuppressed', '--validate-jre'].includes(a) === false).filter(a => args._.includes(a) === false); const cmd = getPmdPath(); validatePmdInstallation(cmd); const [command, ...cmdArgs] = convertCmdToSpawnArgs(cmd); console.log(''); console.log('[***] Running PMD'); console.log(''); const result = spawn.sync(command, [...cmdArgs, ...config, ...cache, ...logFormat, ...logFile, ...suppressMarker, ...sourceDir, ...ignoreList, ...showSuppressed, ...debugFlag, ...argv].filter(Boolean), { stdio: 'inherit' }); if (printReportAfterRun) { printReport(useBuiltinLogFile ? PMD_LOGFILE : args.reportFile); } // If not success or rule violation, output error if ([PMD_EXIT_CODE_SUCCESS, PMD_EXIT_CODE_RULE_VIOLATION].includes(result.status) === false) { const err = result.stderr || result.error; if (err) console.error(err); } exit(result.status); })();