-
Notifications
You must be signed in to change notification settings - Fork 900
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(pluginsdk): Add support for checking if an existing plugin is us…
…ing the latest opinions. This adds a new script `check-plugin`. A plugin should run `check-plugin` in its postinstall script in package.json.
- Loading branch information
1 parent
12c60d8
commit b728b15
Showing
15 changed files
with
313 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#!/usr/bin/env node | ||
const yargs = require('yargs'); | ||
const { linters } = require('./check-plugin/linters'); | ||
|
||
yargs | ||
.scriptName('check-plugin') | ||
.option('verbose', { | ||
alias: 'v', | ||
type: 'boolean', | ||
default: false, | ||
}) | ||
.option('fix', { | ||
type: 'boolean', | ||
alias: 'f', | ||
describe: 'When enabled, fixes are automatically applied', | ||
default: false, | ||
}) | ||
.option('fix-warnings', { | ||
type: 'boolean', | ||
alias: 'w', | ||
describe: 'When enabled, fixes are automatically applied even for warnings', | ||
default: false, | ||
}); | ||
|
||
const { verbose, fix, fixWarnings } = yargs.argv; | ||
checkPlugin({ verbose, fixWarnings, fix: fix || fixWarnings }); | ||
|
||
function checkPlugin(options) { | ||
const { verbose, fix, fixWarnings } = options; | ||
|
||
const errorFixers = []; | ||
const warningFixers = []; | ||
|
||
function reporter(message, ok, resolution, fixer) { | ||
if (ok === true) { | ||
if (verbose) { | ||
console.log(` ✅ ${message}`); | ||
} | ||
} else if (ok === false) { | ||
console.log(` ❌ ${message}`); | ||
if (fixer) { | ||
errorFixers.push(fixer); | ||
if (resolution) { | ||
console.log(); | ||
console.log(' ' + resolution); | ||
console.log(); | ||
} | ||
} | ||
} else { | ||
console.log(` ☑️ ${message}`); | ||
|
||
if (fixer) { | ||
warningFixers.push(fixer); | ||
if (resolution) { | ||
console.log(); | ||
console.log(' ' + resolution); | ||
console.log(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
linters.forEach(linter => linter(reporter)); | ||
|
||
const fixingErrors = fix && errorFixers.length; | ||
const fixingWarnings = fixWarnings && warningFixers.length; | ||
|
||
console.log(); | ||
console.log(); | ||
if (fixingErrors || fixingWarnings) { | ||
if (fixingWarnings) { | ||
console.log('Fixing errors and warnings...'); | ||
} else { | ||
console.log('Fixing errors...'); | ||
} | ||
} else if (warningFixers.length) { | ||
console.log(`Run this command to fix the errors and warnings:`); | ||
console.log(); | ||
console.log(`npx check-plugin --fix-warnings`); | ||
} else if (errorFixers.length) { | ||
console.log(`Run this command to fix the errors:`); | ||
console.log(); | ||
console.log(`npx check-plugin --fix`); | ||
} | ||
|
||
console.log(); | ||
console.log(); | ||
|
||
if (fix) { | ||
const commits = errorFixers.map(fixer => fixer()); | ||
commits.filter(x => typeof x === 'function').forEach(commit => commit()); | ||
} | ||
|
||
if (fixWarnings) { | ||
const commits = warningFixers.map(fixer => fixer()); | ||
commits.filter(x => typeof x === 'function').forEach(commit => commit()); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
packages/pluginsdk/scripts/check-plugin/asserters/assertFileExists.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
const fs = require('fs'); | ||
const { restoreFile } = require('../util/restoreFile'); | ||
|
||
const assertFileExists = (report, filename, pristineFilename = filename) => { | ||
const exists = fs.existsSync(filename); | ||
const resolution = `restore ${filename} from scaffold defaults`; | ||
const restore = () => restoreFile(filename, pristineFilename); | ||
report(`${filename} exists`, exists, resolution, restore); | ||
return exists; | ||
}; | ||
|
||
module.exports = { assertFileExists }; |
27 changes: 27 additions & 0 deletions
27
packages/pluginsdk/scripts/check-plugin/asserters/assertJavascriptFile.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const { assertFileExists } = require('./assertFileExists'); | ||
const { restoreFile } = require('../util/restoreFile'); | ||
|
||
function assertJavascriptFile(report, filename, pristineFilename, name, requireString) { | ||
const exists = assertFileExists(report, filename, pristineFilename); | ||
|
||
if (exists) { | ||
// packages/pluginsdk/scaffold/${pristineFilename} | ||
const pristinePath = path.resolve(__dirname, '..', '..', '..', 'scaffold', pristineFilename); | ||
const pristineFile = fs.readFileSync(pristinePath).toString(); | ||
const pluginFile = fs.readFileSync(filename).toString(); | ||
const hasRequire = pluginFile.includes(`require('${requireString}')`); | ||
const resolution = `restore ${filename} from scaffold defaults`; | ||
const restore = () => restoreFile(filename, pristineFilename); | ||
report(`${name} extends @spinnaker/pluginsdk`, hasRequire, `--fix: ${resolution}`, restore); | ||
report( | ||
filename, | ||
pristineFile.trim() === pluginFile.trim() || null, | ||
`--fix-warnings: ${resolution} (${filename} has been customized)`, | ||
restore, | ||
); | ||
} | ||
} | ||
|
||
module.exports = { assertJavascriptFile }; |
28 changes: 28 additions & 0 deletions
28
packages/pluginsdk/scripts/check-plugin/asserters/assertJsonFile.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
const { readJson, writeJson } = require('../util/readWriteJson'); | ||
|
||
const get = (path, obj) => { | ||
return path.split('.').reduce((acc, key) => (acc !== undefined ? acc[key] : undefined), obj); | ||
}; | ||
|
||
const writeJsonField = (filename, field, val) => { | ||
const json = readJson(filename); | ||
const segments = field.split('.'); | ||
const tail = segments.pop(); | ||
const parent = get(segments.join('.'), json); | ||
parent[tail] = val; | ||
writeJson(filename, json); | ||
}; | ||
|
||
const assertJsonFile = (report, filename, json) => { | ||
return function assertJsonFile(field, expectedValue) { | ||
const currentValue = get(field, json); | ||
const resolution = `--fix: change ${field} in ${filename} from "${currentValue}" to "${expectedValue}"`; | ||
const fixer = () => { | ||
writeJsonField(filename, field, expectedValue); | ||
console.log(`fixed: changed ${field} in ${filename} from "${currentValue}" to "${expectedValue}"`); | ||
}; | ||
report(`${filename}: ${field} field`, currentValue === expectedValue, resolution, fixer); | ||
}; | ||
}; | ||
|
||
module.exports = { assertJsonFile }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const { checkPackageJson } = require('./lint.package.json'); | ||
const { checkTsconfig } = require('./lint.tsconfig.json'); | ||
const { checkRollupConfig } = require('./lint.rollup.config'); | ||
const { checkPrettierRc } = require('./lint.prettierrc'); | ||
const { checkEslintRc } = require('./lint.eslintrc'); | ||
|
||
const linters = [checkPackageJson, checkTsconfig, checkRollupConfig, checkPrettierRc, checkEslintRc]; | ||
module.exports = { linters }; |
13 changes: 13 additions & 0 deletions
13
packages/pluginsdk/scripts/check-plugin/linters/lint.eslintrc.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const { assertJavascriptFile } = require('../asserters/assertJavascriptFile'); | ||
|
||
function checkEslintRc(report) { | ||
assertJavascriptFile( | ||
report, | ||
'.eslintrc.js', | ||
'.eslintrc.js', | ||
'Eslint config', | ||
'@spinnaker/pluginsdk/pluginconfig/eslintrc', | ||
); | ||
} | ||
|
||
module.exports = { checkEslintRc }; |
46 changes: 46 additions & 0 deletions
46
packages/pluginsdk/scripts/check-plugin/linters/lint.package.json.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
const { execSync } = require('child_process'); | ||
const { assertJsonFile } = require('../asserters/assertJsonFile'); | ||
const { readJson, writeJson } = require('../util/readWriteJson'); | ||
|
||
function getLatestSdkVersion() { | ||
const versionsString = execSync('npm info @spinnaker/pluginsdk versions').toString(); | ||
return JSON.parse(versionsString.replace(/'/g, '"')).pop(); | ||
} | ||
|
||
function checkPackageJson(report) { | ||
const pkgJson = readJson('package.json'); | ||
const deps = pkgJson.dependencies || {}; | ||
const sdk = deps['@spinnaker/pluginsdk']; | ||
const latest = getLatestSdkVersion(); | ||
|
||
const latestVersionFixer = () => { | ||
execSync(`yarn add @spinnaker/pluginsdk@${latest}`, { stdio: 'inherit' }); | ||
console.log(`fixed: installed @spinnaker/pluginsdk@${latest}`); | ||
}; | ||
const latestVersionResolution = '--fix: install latest @spinnaker/pluginsdk'; | ||
report('Uses latest @spinnaker/pluginsdk', sdk === latest, latestVersionResolution, latestVersionFixer); | ||
|
||
const checkPackageJsonField = assertJsonFile(report, 'package.json', pkgJson); | ||
|
||
checkPackageJsonField('module', 'build/dist/index.js'); | ||
checkPackageJsonField('scripts.clean', 'npx shx rm -rf build'); | ||
checkPackageJsonField('scripts.build', 'rollup -c'); | ||
checkPackageJsonField('scripts.watch', 'rollup -c -w'); | ||
checkPackageJsonField('scripts.postinstall', 'lint-plugin && check-peer-dependencies'); | ||
|
||
const bundlesFiles = pkgJson.files && pkgJson.files.includes('build/dist'); | ||
const bundlesFilesFixer = () => { | ||
const json = readJson('package.json'); | ||
if (!json.files) { | ||
json.files = []; | ||
} | ||
json.files.push('build/dist'); | ||
writeJson('package.json', json); | ||
|
||
console.log(`fixed: added "build/dist" to "files" in package.json`); | ||
}; | ||
const resolution = `--fix: Add "build/dist" to files array in package.json`; | ||
report('package.json: files includes "build/dist"', bundlesFiles, resolution, bundlesFilesFixer); | ||
} | ||
|
||
module.exports = { checkPackageJson }; |
13 changes: 13 additions & 0 deletions
13
packages/pluginsdk/scripts/check-plugin/linters/lint.prettierrc.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const { assertJavascriptFile } = require('../asserters/assertJavascriptFile'); | ||
|
||
function checkPrettierRc(report) { | ||
assertJavascriptFile( | ||
report, | ||
'.prettierrc.js', | ||
'scaffold.prettierrc.js', | ||
'Prettier config', | ||
'@spinnaker/pluginsdk/pluginconfig/prettierrc.js', | ||
); | ||
} | ||
|
||
module.exports = { checkPrettierRc }; |
13 changes: 13 additions & 0 deletions
13
packages/pluginsdk/scripts/check-plugin/linters/lint.rollup.config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const { assertJavascriptFile } = require('../asserters/assertJavascriptFile'); | ||
|
||
function checkRollupConfig(report) { | ||
assertJavascriptFile( | ||
report, | ||
'rollup.config.js', | ||
'rollup.config.js', | ||
'Rollup config', | ||
'@spinnaker/pluginsdk/pluginconfig/rollup.config', | ||
); | ||
} | ||
|
||
module.exports = { checkRollupConfig }; |
19 changes: 19 additions & 0 deletions
19
packages/pluginsdk/scripts/check-plugin/linters/lint.tsconfig.json.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
const { assertJsonFile } = require('../asserters/assertJsonFile'); | ||
const { assertFileExists } = require('../asserters/assertFileExists'); | ||
const { readJson } = require('../util/readWriteJson'); | ||
|
||
function checkTsconfig(report) { | ||
const exists = assertFileExists(report, 'tsconfig.json'); | ||
|
||
if (exists) { | ||
const tsConfigJson = readJson('tsconfig.json'); | ||
|
||
const checkTsconfigField = assertJsonFile(report, 'tsconfig.json', tsConfigJson); | ||
|
||
checkTsconfigField('extends', '@spinnaker/pluginsdk/pluginconfig/tsconfig.json'); | ||
checkTsconfigField('compilerOptions.outDir', 'build/dist'); | ||
checkTsconfigField('compilerOptions.rootDir', 'src'); | ||
} | ||
} | ||
|
||
module.exports = { checkTsconfig }; |
13 changes: 13 additions & 0 deletions
13
packages/pluginsdk/scripts/check-plugin/util/readWriteJson.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const fs = require('fs'); | ||
const stripJsonComments = require('strip-json-comments'); | ||
|
||
function readJson(pathname) { | ||
const string = fs.readFileSync(pathname).toString(); | ||
return JSON.parse(stripJsonComments(string)); | ||
} | ||
|
||
function writeJson(pathname, json) { | ||
fs.writeFileSync(pathname, JSON.stringify(json, null, 2)); | ||
} | ||
|
||
module.exports = { readJson, writeJson }; |
10 changes: 10 additions & 0 deletions
10
packages/pluginsdk/scripts/check-plugin/util/restoreFile.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
function restoreFile(file, pristineFilename = file) { | ||
const srcFile = path.resolve(__dirname, '..', '..', '..', 'scaffold', pristineFilename); | ||
fs.writeFileSync(file, fs.readFileSync(srcFile)); | ||
console.log(`fixed: restored ${file} to default from scaffold`); | ||
} | ||
|
||
module.exports = { restoreFile }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters