2021-01-08 03:52:45 +01:00
|
|
|
'use strict';
|
|
|
|
|
2020-11-02 17:13:24 +01:00
|
|
|
/*
|
2021-01-11 00:35:50 +01:00
|
|
|
* Usage -- see README.md
|
|
|
|
*
|
2021-02-05 00:43:27 +01:00
|
|
|
* Normal usage: node src/bin/plugins/checkPlugin.js ep_whatever
|
|
|
|
* Auto fix the things it can: node src/bin/plugins/checkPlugin.js ep_whatever autofix
|
2021-06-17 00:41:26 +02:00
|
|
|
* Auto fix and commit: node src/bin/plugins/checkPlugin.js ep_whatever autocommit
|
|
|
|
* Auto fix, commit, push and publish to npm (highly dangerous):
|
|
|
|
* node src/bin/plugins/checkPlugin.js ep_whatever autopush
|
2021-01-11 00:35:50 +01:00
|
|
|
*/
|
2020-11-02 17:13:24 +01:00
|
|
|
|
2021-01-18 09:53:15 +01:00
|
|
|
// As of v14, Node.js does not exit when there is an unhandled Promise rejection. Convert an
|
|
|
|
// unhandled rejection into an uncaught exception, which does cause Node.js to exit.
|
|
|
|
process.on('unhandledRejection', (err) => { throw err; });
|
|
|
|
|
2021-06-15 01:23:04 +02:00
|
|
|
const assert = require('assert').strict;
|
2020-11-23 19:21:51 +01:00
|
|
|
const fs = require('fs');
|
2021-06-17 23:19:56 +02:00
|
|
|
const fsp = fs.promises;
|
2021-01-08 03:52:45 +01:00
|
|
|
const childProcess = require('child_process');
|
2021-06-15 01:23:04 +02:00
|
|
|
const path = require('path');
|
2020-11-02 17:13:24 +01:00
|
|
|
|
|
|
|
// get plugin name & path from user input
|
|
|
|
const pluginName = process.argv[2];
|
|
|
|
|
2021-01-18 09:53:15 +01:00
|
|
|
if (!pluginName) throw new Error('no plugin name specified');
|
2020-11-02 17:13:24 +01:00
|
|
|
|
2020-11-23 19:21:51 +01:00
|
|
|
const pluginPath = `node_modules/${pluginName}`;
|
2020-11-02 17:13:24 +01:00
|
|
|
|
2020-11-23 19:21:51 +01:00
|
|
|
console.log(`Checking the plugin: ${pluginName}`);
|
2020-11-02 17:13:24 +01:00
|
|
|
|
2021-01-09 00:07:55 +01:00
|
|
|
const optArgs = process.argv.slice(3);
|
2021-06-17 22:50:23 +02:00
|
|
|
const autoPush = optArgs.includes('autopush');
|
|
|
|
const autoCommit = autoPush || optArgs.includes('autocommit');
|
|
|
|
const autoFix = autoCommit || optArgs.includes('autofix');
|
2020-11-02 17:13:24 +01:00
|
|
|
|
2021-01-09 05:04:11 +01:00
|
|
|
const execSync = (cmd, opts = {}) => (childProcess.execSync(cmd, {
|
|
|
|
cwd: `${pluginPath}/`,
|
|
|
|
...opts,
|
|
|
|
}) || '').toString().replace(/\n+$/, '');
|
|
|
|
|
2021-06-17 23:19:56 +02:00
|
|
|
const writePackageJson = async (obj) => {
|
2021-01-10 00:28:11 +01:00
|
|
|
let s = JSON.stringify(obj, null, 2);
|
|
|
|
if (s.length && s.slice(s.length - 1) !== '\n') s += '\n';
|
2021-06-17 23:19:56 +02:00
|
|
|
return await fsp.writeFile(`${pluginPath}/package.json`, s);
|
2021-01-10 00:28:11 +01:00
|
|
|
};
|
2021-01-10 00:27:37 +01:00
|
|
|
|
2021-06-15 01:31:26 +02:00
|
|
|
const checkEntries = (got, want) => {
|
|
|
|
let changed = false;
|
|
|
|
for (const [key, val] of Object.entries(want)) {
|
|
|
|
try {
|
|
|
|
assert.deepEqual(got[key], val);
|
|
|
|
} catch (err) {
|
|
|
|
console.warn(`${key} possibly outdated.`);
|
|
|
|
console.warn(err.message);
|
|
|
|
if (autoFix) {
|
|
|
|
got[key] = val;
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return changed;
|
|
|
|
};
|
|
|
|
|
2021-06-17 23:19:56 +02:00
|
|
|
const updateDeps = async (parsedPackageJson, key, wantDeps) => {
|
2021-01-10 00:51:31 +01:00
|
|
|
const {[key]: deps = {}} = parsedPackageJson;
|
|
|
|
let changed = false;
|
2021-01-10 22:23:04 +01:00
|
|
|
for (const [pkg, verInfo] of Object.entries(wantDeps)) {
|
|
|
|
const {ver, overwrite = true} = typeof verInfo === 'string' ? {ver: verInfo} : verInfo;
|
2021-01-10 00:51:31 +01:00
|
|
|
if (deps[pkg] === ver) continue;
|
|
|
|
if (deps[pkg] == null) {
|
|
|
|
console.warn(`Missing dependency in ${key}: '${pkg}': '${ver}'`);
|
|
|
|
} else {
|
2021-01-10 22:23:04 +01:00
|
|
|
if (!overwrite) continue;
|
2021-01-10 00:51:31 +01:00
|
|
|
console.warn(`Dependency mismatch in ${key}: '${pkg}': '${ver}' (current: ${deps[pkg]})`);
|
|
|
|
}
|
|
|
|
if (autoFix) {
|
|
|
|
deps[pkg] = ver;
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (changed) {
|
|
|
|
parsedPackageJson[key] = deps;
|
2021-06-17 23:19:56 +02:00
|
|
|
await writePackageJson(parsedPackageJson);
|
2021-01-10 00:51:31 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-01-09 06:08:43 +01:00
|
|
|
const prepareRepo = () => {
|
2021-01-09 23:30:41 +01:00
|
|
|
const modified = execSync('git diff-files --name-status');
|
|
|
|
if (modified !== '') throw new Error(`working directory has modifications:\n${modified}`);
|
|
|
|
const untracked = execSync('git ls-files -o --exclude-standard');
|
|
|
|
if (untracked !== '') throw new Error(`working directory has untracked files:\n${untracked}`);
|
2021-01-09 23:27:51 +01:00
|
|
|
const indexStatus = execSync('git diff-index --cached --name-status HEAD');
|
2021-01-09 06:08:43 +01:00
|
|
|
if (indexStatus !== '') throw new Error(`uncommitted staged changes to files:\n${indexStatus}`);
|
2021-12-10 02:39:40 +01:00
|
|
|
let br;
|
2021-01-09 06:08:43 +01:00
|
|
|
if (autoCommit) {
|
2021-12-10 02:39:40 +01:00
|
|
|
br = execSync('git symbolic-ref HEAD');
|
|
|
|
if (!br.startsWith('refs/heads/')) throw new Error('detached HEAD');
|
|
|
|
br = br.replace(/^refs\/heads\//, '');
|
|
|
|
execSync('git rev-parse --verify -q HEAD^0 || ' +
|
|
|
|
`{ echo "Error: no commits on ${br}" >&2; exit 1; }`);
|
2021-01-09 06:08:43 +01:00
|
|
|
execSync('git config --get user.name');
|
|
|
|
execSync('git config --get user.email');
|
|
|
|
}
|
2021-12-10 02:39:40 +01:00
|
|
|
if (autoPush) {
|
|
|
|
if (!['master', 'main'].includes(br)) throw new Error('master/main not checked out');
|
|
|
|
execSync('git rev-parse --verify @{u}');
|
|
|
|
execSync('git pull --ff-only', {stdio: 'inherit'});
|
|
|
|
if (execSync('git rev-list @{u}...') !== '') throw new Error('repo contains unpushed commits');
|
|
|
|
}
|
2021-01-09 06:08:43 +01:00
|
|
|
};
|
|
|
|
|
2021-06-17 23:19:56 +02:00
|
|
|
const checkFile = async (srcFn, dstFn) => {
|
2021-06-15 01:23:04 +02:00
|
|
|
const outFn = path.join(pluginPath, dstFn);
|
2021-06-17 23:19:56 +02:00
|
|
|
const wantContents = await fsp.readFile(srcFn, {encoding: 'utf8'});
|
2021-06-15 01:23:04 +02:00
|
|
|
let gotContents = null;
|
|
|
|
try {
|
2021-06-17 23:19:56 +02:00
|
|
|
gotContents = await fsp.readFile(outFn, {encoding: 'utf8'});
|
2021-06-15 01:23:04 +02:00
|
|
|
} catch (err) { /* treat as if the file doesn't exist */ }
|
|
|
|
try {
|
2021-06-15 01:54:37 +02:00
|
|
|
assert.equal(gotContents, wantContents);
|
2021-06-15 01:23:04 +02:00
|
|
|
} catch (err) {
|
|
|
|
console.warn(`File ${dstFn} is out of date`);
|
|
|
|
console.warn(err.message);
|
|
|
|
if (autoFix) {
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.mkdir(path.dirname(outFn), {recursive: true});
|
|
|
|
await fsp.writeFile(outFn, wantContents);
|
2021-06-15 01:23:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-06-17 00:41:26 +02:00
|
|
|
if (autoPush) {
|
|
|
|
console.warn('Auto push is enabled, I hope you know what you are doing...');
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
|
2021-06-17 23:19:56 +02:00
|
|
|
(async () => {
|
2021-06-17 23:35:54 +02:00
|
|
|
const files = await fsp.readdir(pluginPath);
|
2020-11-02 17:13:24 +01:00
|
|
|
|
|
|
|
// some files we need to know the actual file name. Not compulsory but might help in the future.
|
2021-06-17 23:35:54 +02:00
|
|
|
const readMeFileName = files.filter((f) => f === 'README' || f === 'README.md')[0];
|
2020-11-02 17:13:24 +01:00
|
|
|
|
2021-06-17 22:50:23 +02:00
|
|
|
if (!files.includes('.git')) throw new Error('No .git folder, aborting');
|
2021-01-09 06:08:43 +01:00
|
|
|
prepareRepo();
|
2020-11-02 17:13:24 +01:00
|
|
|
|
2021-06-17 23:19:56 +02:00
|
|
|
const workflows = ['backend-tests.yml', 'frontend-tests.yml', 'npmpublish.yml'];
|
|
|
|
await Promise.all(workflows.map(async (fn) => {
|
|
|
|
await checkFile(`src/bin/plugins/lib/${fn}`, `.github/workflows/${fn}`);
|
|
|
|
}));
|
2020-11-30 18:22:52 +01:00
|
|
|
|
2021-06-17 22:50:23 +02:00
|
|
|
if (!files.includes('package.json')) {
|
2020-11-23 19:21:51 +01:00
|
|
|
console.warn('no package.json, please create');
|
2021-06-17 22:50:23 +02:00
|
|
|
} else {
|
2021-01-08 03:52:45 +01:00
|
|
|
const packageJSON =
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.readFile(`${pluginPath}/package.json`, {encoding: 'utf8', flag: 'r'});
|
2020-11-23 19:21:51 +01:00
|
|
|
const parsedPackageJSON = JSON.parse(packageJSON);
|
2020-11-02 17:13:24 +01:00
|
|
|
|
2021-06-17 23:19:56 +02:00
|
|
|
await updateDeps(parsedPackageJSON, 'devDependencies', {
|
2021-12-10 02:44:58 +01:00
|
|
|
'eslint': '^7.32.0',
|
|
|
|
'eslint-config-etherpad': '^2.0.2',
|
|
|
|
'eslint-plugin-cypress': '^2.12.1',
|
2021-01-09 00:45:27 +01:00
|
|
|
'eslint-plugin-eslint-comments': '^3.2.0',
|
2021-06-14 20:36:17 +02:00
|
|
|
'eslint-plugin-mocha': '^9.0.0',
|
2021-01-09 00:45:27 +01:00
|
|
|
'eslint-plugin-node': '^11.1.0',
|
2021-01-29 07:00:33 +01:00
|
|
|
'eslint-plugin-prefer-arrow': '^1.2.3',
|
2021-12-10 02:44:58 +01:00
|
|
|
'eslint-plugin-promise': '^5.1.1',
|
2021-06-14 20:36:17 +02:00
|
|
|
'eslint-plugin-you-dont-need-lodash-underscore': '^6.12.0',
|
2021-01-10 00:51:31 +01:00
|
|
|
});
|
2020-11-22 15:58:11 +01:00
|
|
|
|
2021-06-17 23:19:56 +02:00
|
|
|
await updateDeps(parsedPackageJSON, 'peerDependencies', {
|
2021-01-10 22:23:04 +01:00
|
|
|
// Some plugins require a newer version of Etherpad so don't overwrite if already set.
|
|
|
|
'ep_etherpad-lite': {ver: '>=1.8.6', overwrite: false},
|
|
|
|
});
|
2020-11-27 22:43:23 +01:00
|
|
|
|
2021-06-17 23:19:56 +02:00
|
|
|
await updateDeps(parsedPackageJSON, 'engines', {
|
2022-01-27 07:26:41 +01:00
|
|
|
node: '>=12.17.0',
|
2021-06-15 01:27:33 +02:00
|
|
|
});
|
|
|
|
|
2021-06-15 01:31:26 +02:00
|
|
|
if (parsedPackageJSON.eslintConfig == null) parsedPackageJSON.eslintConfig = {};
|
|
|
|
if (checkEntries(parsedPackageJSON.eslintConfig, {
|
|
|
|
root: true,
|
|
|
|
extends: 'etherpad/plugin',
|
|
|
|
})) await writePackageJson(parsedPackageJSON);
|
|
|
|
|
|
|
|
if (checkEntries(parsedPackageJSON, {
|
|
|
|
funding: {
|
|
|
|
type: 'individual',
|
|
|
|
url: 'https://etherpad.org/',
|
|
|
|
},
|
2021-06-17 23:19:56 +02:00
|
|
|
})) await writePackageJson(parsedPackageJSON);
|
2021-06-15 01:31:26 +02:00
|
|
|
|
|
|
|
if (parsedPackageJSON.scripts == null) parsedPackageJSON.scripts = {};
|
|
|
|
if (checkEntries(parsedPackageJSON.scripts, {
|
|
|
|
'lint': 'eslint .',
|
|
|
|
'lint:fix': 'eslint --fix .',
|
2021-06-17 23:19:56 +02:00
|
|
|
})) await writePackageJson(parsedPackageJSON);
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
|
2021-06-17 22:50:23 +02:00
|
|
|
if (!files.includes('package-lock.json')) {
|
2021-01-10 00:50:06 +01:00
|
|
|
console.warn('package-lock.json not found');
|
|
|
|
if (!autoFix) {
|
|
|
|
console.warn('Run npm install in the plugin folder and commit the package-lock.json file.');
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
}
|
2021-12-10 03:48:59 +01:00
|
|
|
|
|
|
|
const fillTemplate = async (templateFilename, outputFilename) => {
|
|
|
|
const contents = (await fsp.readFile(templateFilename, 'utf8'))
|
|
|
|
.replace(/\[name of copyright owner\]/g, execSync('git config user.name'))
|
|
|
|
.replace(/\[plugin_name\]/g, pluginName)
|
|
|
|
.replace(/\[yyyy\]/g, new Date().getFullYear());
|
|
|
|
await fsp.writeFile(outputFilename, contents);
|
|
|
|
};
|
|
|
|
|
2021-06-17 23:30:38 +02:00
|
|
|
if (!readMeFileName) {
|
2020-11-23 19:21:51 +01:00
|
|
|
console.warn('README.md file not found, please create');
|
|
|
|
if (autoFix) {
|
2021-01-08 03:52:45 +01:00
|
|
|
console.log('Autofixing missing README.md file');
|
|
|
|
console.log('please edit the README.md file further to include plugin specific details.');
|
2021-12-10 03:48:59 +01:00
|
|
|
await fillTemplate('src/bin/plugins/lib/README.md', `${pluginPath}/README.md`);
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-17 23:35:54 +02:00
|
|
|
if (!files.includes('CONTRIBUTING') && !files.includes('CONTRIBUTING.md')) {
|
2020-12-05 08:47:13 +01:00
|
|
|
console.warn('CONTRIBUTING.md file not found, please create');
|
|
|
|
if (autoFix) {
|
2021-01-18 09:53:15 +01:00
|
|
|
console.log('Autofixing missing CONTRIBUTING.md file, please edit the CONTRIBUTING.md ' +
|
|
|
|
'file further to include plugin specific details.');
|
2021-12-10 03:48:59 +01:00
|
|
|
await fillTemplate('src/bin/plugins/lib/CONTRIBUTING.md', `${pluginPath}/CONTRIBUTING.md`);
|
2020-12-05 08:47:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-02-09 10:41:41 +01:00
|
|
|
if (readMeFileName) {
|
|
|
|
let readme =
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.readFile(`${pluginPath}/${readMeFileName}`, {encoding: 'utf8', flag: 'r'});
|
2021-06-17 22:50:23 +02:00
|
|
|
if (!readme.toLowerCase().includes('license')) {
|
2020-11-23 19:21:51 +01:00
|
|
|
console.warn('No license section in README');
|
|
|
|
if (autoFix) {
|
|
|
|
console.warn('Please add License section to README manually.');
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
}
|
2021-02-09 10:41:41 +01:00
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
const publishBadge = `![Publish Status](https://github.com/ether/${pluginName}/workflows/Node.js%20Package/badge.svg)`;
|
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
const testBadge = `![Backend Tests Status](https://github.com/ether/${pluginName}/workflows/Backend%20tests/badge.svg)`;
|
2021-06-17 22:50:23 +02:00
|
|
|
if (readme.toLowerCase().includes('travis')) {
|
2021-02-09 10:41:41 +01:00
|
|
|
console.warn('Remove Travis badges');
|
|
|
|
}
|
2021-06-17 22:50:23 +02:00
|
|
|
if (!readme.includes('workflows/Node.js%20Package/badge.svg')) {
|
2021-02-09 10:41:41 +01:00
|
|
|
console.warn('No Github workflow badge detected');
|
|
|
|
if (autoFix) {
|
|
|
|
readme = `${publishBadge} ${testBadge}\n\n${readme}`;
|
|
|
|
// write readme to file system
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.writeFile(`${pluginPath}/${readMeFileName}`, readme);
|
2021-02-09 10:41:41 +01:00
|
|
|
console.log('Wrote Github workflow badges to README');
|
|
|
|
}
|
|
|
|
}
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
|
2021-06-17 23:35:54 +02:00
|
|
|
if (!files.includes('LICENSE') && !files.includes('LICENSE.md')) {
|
2021-12-10 03:48:59 +01:00
|
|
|
console.warn('LICENSE file not found, please create');
|
2020-11-23 19:21:51 +01:00
|
|
|
if (autoFix) {
|
2021-12-10 03:48:59 +01:00
|
|
|
console.log('Autofixing missing LICENSE file (Apache 2.0).');
|
|
|
|
await fsp.copyFile('src/bin/plugins/lib/LICENSE', `${pluginPath}/LICENSE`);
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-17 22:50:23 +02:00
|
|
|
if (!files.includes('.gitignore')) {
|
2021-01-18 09:53:15 +01:00
|
|
|
console.warn('.gitignore file not found, please create. .gitignore files are useful to ' +
|
|
|
|
"ensure files aren't incorrectly commited to a repository.");
|
2020-11-23 19:21:51 +01:00
|
|
|
if (autoFix) {
|
|
|
|
console.log('Autofixing missing .gitignore file');
|
2021-02-05 00:43:27 +01:00
|
|
|
const gitignore =
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.readFile('src/bin/plugins/lib/gitignore', {encoding: 'utf8', flag: 'r'});
|
|
|
|
await fsp.writeFile(`${pluginPath}/.gitignore`, gitignore);
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
2020-12-16 22:51:43 +01:00
|
|
|
} else {
|
2020-11-28 14:13:14 +01:00
|
|
|
let gitignore =
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.readFile(`${pluginPath}/.gitignore`, {encoding: 'utf8', flag: 'r'});
|
2021-06-17 22:50:23 +02:00
|
|
|
if (!gitignore.includes('node_modules/')) {
|
2020-12-16 22:51:43 +01:00
|
|
|
console.warn('node_modules/ missing from .gitignore');
|
|
|
|
if (autoFix) {
|
|
|
|
gitignore += 'node_modules/';
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.writeFile(`${pluginPath}/.gitignore`, gitignore);
|
2020-12-16 22:51:43 +01:00
|
|
|
}
|
|
|
|
}
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// if we include templates but don't have translations...
|
2021-06-17 22:50:23 +02:00
|
|
|
if (files.includes('templates') && !files.includes('locales')) {
|
2021-01-18 09:53:15 +01:00
|
|
|
console.warn('Translations not found, please create. ' +
|
|
|
|
'Translation files help with Etherpad accessibility.');
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-17 22:50:23 +02:00
|
|
|
if (files.includes('.ep_initialized')) {
|
2021-01-18 09:53:15 +01:00
|
|
|
console.warn(
|
|
|
|
'.ep_initialized found, please remove. .ep_initialized should never be commited to git ' +
|
|
|
|
'and should only exist once the plugin has been executed one time.');
|
2020-11-23 19:21:51 +01:00
|
|
|
if (autoFix) {
|
|
|
|
console.log('Autofixing incorrectly existing .ep_initialized file');
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.unlink(`${pluginPath}/.ep_initialized`);
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-17 22:50:23 +02:00
|
|
|
if (files.includes('npm-debug.log')) {
|
2021-01-18 09:53:15 +01:00
|
|
|
console.warn('npm-debug.log found, please remove. npm-debug.log should never be commited to ' +
|
|
|
|
'your repository.');
|
2020-11-23 19:21:51 +01:00
|
|
|
if (autoFix) {
|
|
|
|
console.log('Autofixing incorrectly existing npm-debug.log file');
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.unlink(`${pluginPath}/npm-debug.log`);
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-17 22:50:23 +02:00
|
|
|
if (files.includes('static')) {
|
2021-06-17 23:19:56 +02:00
|
|
|
const staticFiles = await fsp.readdir(`${pluginPath}/static`);
|
|
|
|
if (!staticFiles.includes('tests')) {
|
|
|
|
console.warn('Test files not found, please create tests. https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin#writing-and-running-front-end-tests-for-your-plugin');
|
|
|
|
}
|
2020-11-23 19:21:51 +01:00
|
|
|
} else {
|
|
|
|
console.warn('Test files not found, please create tests. https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin#writing-and-running-front-end-tests-for-your-plugin');
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
|
2021-01-10 00:50:06 +01:00
|
|
|
// Install dependencies so we can run ESLint. This should also create or update package-lock.json
|
|
|
|
// if autoFix is enabled.
|
|
|
|
const npmInstall = `npm install${autoFix ? '' : ' --no-package-lock'}`;
|
|
|
|
execSync(npmInstall, {stdio: 'inherit'});
|
2021-01-10 01:29:30 +01:00
|
|
|
// The ep_etherpad-lite peer dep must be installed last otherwise `npm install` will nuke it. An
|
|
|
|
// absolute path to etherpad-lite/src is used here so that pluginPath can be a symlink.
|
|
|
|
execSync(
|
2021-02-03 13:08:43 +01:00
|
|
|
`${npmInstall} --no-save ep_etherpad-lite@file:${__dirname}/../../`, {stdio: 'inherit'});
|
2020-11-22 15:58:11 +01:00
|
|
|
// linting begins
|
2020-11-23 19:21:51 +01:00
|
|
|
try {
|
2021-01-09 06:59:20 +01:00
|
|
|
console.log('Linting...');
|
2021-01-08 03:52:45 +01:00
|
|
|
const lintCmd = autoFix ? 'npx eslint --fix .' : 'npx eslint';
|
2021-01-09 06:59:56 +01:00
|
|
|
execSync(lintCmd, {stdio: 'inherit'});
|
2020-11-23 19:21:51 +01:00
|
|
|
} catch (e) {
|
2020-11-22 15:58:11 +01:00
|
|
|
// it is gonna throw an error anyway
|
2020-11-23 19:21:51 +01:00
|
|
|
console.log('Manual linting probably required, check with: npm run lint');
|
2020-11-22 15:58:11 +01:00
|
|
|
}
|
|
|
|
// linting ends.
|
|
|
|
|
2021-01-10 01:16:56 +01:00
|
|
|
if (autoFix) {
|
|
|
|
const unchanged = JSON.parse(execSync(
|
|
|
|
'untracked=$(git ls-files -o --exclude-standard) || exit 1; ' +
|
|
|
|
'git diff-files --quiet && [ -z "$untracked" ] && echo true || echo false'));
|
|
|
|
if (!unchanged) {
|
2021-01-11 00:28:32 +01:00
|
|
|
// Display a diff of changes. Git doesn't diff untracked files, so they must be added to the
|
|
|
|
// index. Use a temporary index file to avoid modifying Git's default index file.
|
|
|
|
execSync('git read-tree HEAD; git add -A && git diff-index -p --cached HEAD && echo ""', {
|
|
|
|
env: {...process.env, GIT_INDEX_FILE: '.git/checkPlugin.index'},
|
|
|
|
stdio: 'inherit',
|
|
|
|
});
|
2021-06-17 23:19:56 +02:00
|
|
|
await fsp.unlink(`${pluginPath}/.git/checkPlugin.index`);
|
2021-01-11 00:28:32 +01:00
|
|
|
|
2021-06-17 00:41:26 +02:00
|
|
|
const commitCmd = [
|
2021-01-10 01:16:56 +01:00
|
|
|
'git add -A',
|
|
|
|
'git commit -m "autofixes from Etherpad checkPlugin.js"',
|
|
|
|
].join(' && ');
|
|
|
|
if (autoCommit) {
|
2021-06-17 00:41:26 +02:00
|
|
|
console.log('Committing changes...');
|
|
|
|
execSync(commitCmd, {stdio: 'inherit'});
|
2021-01-10 01:16:56 +01:00
|
|
|
} else {
|
2021-01-11 00:28:32 +01:00
|
|
|
console.log('Fixes applied. Check the above git diff then run the following command:');
|
2021-06-17 00:41:26 +02:00
|
|
|
console.log(`(cd node_modules/${pluginName} && ${commitCmd})`);
|
|
|
|
}
|
|
|
|
const pushCmd = 'git push';
|
|
|
|
if (autoPush) {
|
|
|
|
console.log('Pushing new commit...');
|
|
|
|
execSync(pushCmd, {stdio: 'inherit'});
|
|
|
|
} else {
|
|
|
|
console.log('Changes committed. To push, run the following command:');
|
|
|
|
console.log(`(cd node_modules/${pluginName} && ${pushCmd})`);
|
2021-01-10 01:16:56 +01:00
|
|
|
}
|
2020-11-23 19:21:51 +01:00
|
|
|
} else {
|
2021-01-10 01:16:56 +01:00
|
|
|
console.log('No changes.');
|
2020-11-02 17:13:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-23 19:21:51 +01:00
|
|
|
console.log('Finished');
|
2021-06-17 23:19:56 +02:00
|
|
|
})();
|