Commit 6d5b9fd5 authored by Lukas Eipert's avatar Lukas Eipert

Move prettier related yarn scripts to the lint scope

Similar to `eslint`, this moves our `prettier` related scripts to the
`lint` scope. We keep the old scripts in place and error out
immediately, hinting the user to the new scripts.

Thanks to the introduced `scripts/frontend/execute-on-staged-files.sh`
and the fact that `prettier` itself has implemented better command line
interfaces (`--check` and `--write`) since we introduced it, we are able
to remove our home made node script in favor of those.

Now the scripts carry the following names:

 - `prettier-all` => `lint:prettier`
 - `prettier-all-save` => `lint:prettier:fix`
 - `prettier-staged` => `lint:prettier:staged`
 - `prettier-staged-save`: `lint:prettier:staged:fixed`
parent 61e992af
/app/assets/javascripts/locale/**/app.js
/fixtures/lib/gitlab/graphql/
/node_modules/
/public/
/vendor/
......
......@@ -125,44 +125,28 @@ Please take care that you only let Prettier format the same file types as the gl
The following yarn scripts are available to do global formatting:
```shell
yarn prettier-staged-save
yarn run lint:prettier:staged:fix
```
Updates all staged files (based on `git diff`) with Prettier and saves the needed changes.
```shell
yarn prettier-staged
yarn run lint:prettier:staged
```
Checks all staged files (based on `git diff`) with Prettier and log which files would need manual updating to the console.
```shell
yarn prettier-all
yarn run lint:prettier
```
Checks all files with Prettier and logs which files need manual updating to the console.
```shell
yarn prettier-all-save
yarn run lint:prettier:fix
```
Formats all files in the repository with Prettier. (This should only be used to test global rule updates otherwise you would end up with huge MR's).
The source of these Yarn scripts can be found in `/scripts/frontend/prettier.js`.
#### Scripts during Conversion period
```shell
node ./scripts/frontend/prettier.js check-all ./vendor/
```
This iterates over all files in a specific folder, and checks them.
```shell
node ./scripts/frontend/prettier.js save-all ./vendor/
```
This iterates over all files in a specific folder and saves them.
Formats all files in the repository with Prettier.
### VSCode Settings
......
......@@ -26,12 +26,16 @@
"lint:eslint:report": "yarn run internal:eslint --format html --output-file ./eslint-report.html --no-inline-config .",
"lint:eslint:staged": "scripts/frontend/execute-on-staged-files.sh internal:eslint '(js|vue)'",
"lint:eslint:staged:fix": "yarn run lint:eslint:staged --fix",
"lint:prettier": "yarn run prettier --check '**/*.{graphql,js,vue}'",
"lint:prettier:fix": "yarn run prettier --write '**/*.{graphql,js,vue}'",
"lint:prettier:staged": "scripts/frontend/execute-on-staged-files.sh prettier '(graphql|js|vue)' --check",
"lint:prettier:staged:fix": "scripts/frontend/execute-on-staged-files.sh prettier '(graphql|js|vue)' --write",
"markdownlint": "markdownlint --config .markdownlint.json",
"postinstall": "node ./scripts/frontend/postinstall.js",
"prettier-staged": "node ./scripts/frontend/prettier.js check",
"prettier-staged-save": "node ./scripts/frontend/prettier.js save",
"prettier-all": "node ./scripts/frontend/prettier.js check-all",
"prettier-all-save": "node ./scripts/frontend/prettier.js save-all",
"prettier-all": "echo 'Please use lint:prettier instead' && exit 1",
"prettier-all-save": "echo 'Please use lint:prettier:fix instead' && exit 1",
"prettier-staged": "echo 'Please use lint:prettier:staged instead' && exit 1",
"prettier-staged-save": "echo 'Please use lint:prettier:staged:fixed instead' && exit 1",
"stylelint": "yarn stylelint-file 'app/assets/stylesheets/**/*.*' 'ee/app/assets/stylesheets/**/*.*' '!app/assets/stylesheets/startup/startup-*.scss' '!**/vendors/**'",
"stylelint-file": "BROWSERSLIST_IGNORE_OLD_DATA=true node node_modules/stylelint/bin/stylelint.js",
"stylelint-create-utility-map": "node scripts/frontend/stylelint/stylelint-utility-map.js",
......
const execFileSync = require('child_process').execFileSync;
const exec = (command, args) => {
const options = {
cwd: process.cwd(),
env: process.env,
encoding: 'utf-8',
};
return execFileSync(command, args, options);
};
const execGitCmd = (args) => exec('git', args).trim().toString().split('\n').filter(Boolean);
module.exports = {
getStagedFiles: (fileExtensionFilter) => {
const gitOptions = ['diff', '--name-only', '--cached', '--diff-filter=ACMRTUB'];
if (fileExtensionFilter) gitOptions.push(...fileExtensionFilter);
return execGitCmd(gitOptions);
},
};
const glob = require('glob');
const prettier = require('prettier');
const fs = require('fs');
const { getStagedFiles } = require('./frontend_script_utils');
const matchExtensions = ['js', 'vue', 'graphql'];
// This will improve glob performance by excluding certain directories.
// The .prettierignore file will also be respected, but after the glob has executed.
const globIgnore = ['**/node_modules/**', 'vendor/**', 'public/**', 'fixtures/**'];
const readFileAsync = (file, options) =>
new Promise((resolve, reject) => {
fs.readFile(file, options, function (err, data) {
if (err) reject(err);
else resolve(data);
});
});
const writeFileAsync = (file, data, options) =>
new Promise((resolve, reject) => {
fs.writeFile(file, data, options, function (err) {
if (err) reject(err);
else resolve();
});
});
const mode = process.argv[2] || 'check';
const shouldSave = mode === 'save' || mode === 'save-all';
const allFiles = mode === 'check-all' || mode === 'save-all';
let globDir = process.argv[3] || '';
if (globDir && globDir.charAt(globDir.length - 1) !== '/') globDir += '/';
console.log(
`Loading all ${allFiles ? '' : 'staged '}files ${globDir ? `within ${globDir} ` : ''}...`,
);
const globPatterns = matchExtensions.map((ext) => `${globDir}**/*.${ext}`);
const matchedFiles = allFiles
? glob.sync(`{${globPatterns.join(',')}}`, { ignore: globIgnore })
: getStagedFiles(globPatterns);
const matchedCount = matchedFiles.length;
if (!matchedCount) {
console.log('No files found to process with prettier');
process.exit(0);
}
let didWarn = false;
let passedCount = 0;
let failedCount = 0;
let ignoredCount = 0;
console.log(`${shouldSave ? 'Updating' : 'Checking'} ${matchedCount} file(s)`);
const fixCommand = `yarn prettier-${allFiles ? 'all' : 'staged'}-save`;
const warningMessage = `
===============================
GitLab uses Prettier to format all JavaScript code.
Please format each file listed below or run "${fixCommand}"
===============================
`;
const checkFileWithOptions = (filePath, options) =>
readFileAsync(filePath, 'utf8').then((input) => {
if (shouldSave) {
const output = prettier.format(input, options);
if (input === output) {
passedCount += 1;
} else {
return writeFileAsync(filePath, output, 'utf8').then(() => {
console.log(`Prettified : ${filePath}`);
failedCount += 1;
});
}
} else {
if (prettier.check(input, options)) {
passedCount += 1;
} else {
if (!didWarn) {
// \x1b[31m make text red
// \x1b[1m make text bold
// %s warningMessage
// \x1b[0m reset text color (so logs after aren't red)
const redBoldText = '\x1b[1m\x1b[31;1m%s\x1b[0m';
console.log(redBoldText, warningMessage);
didWarn = true;
}
console.log(`yarn prettier --write ${filePath}`);
failedCount += 1;
}
}
});
const checkFileWithPrettierConfig = (filePath) =>
prettier
.getFileInfo(filePath, { ignorePath: '.prettierignore' })
.then(({ ignored, inferredParser }) => {
if (ignored || !inferredParser) {
ignoredCount += 1;
return;
}
return prettier.resolveConfig(filePath).then((fileOptions) => {
const options = { ...fileOptions, parser: inferredParser };
return checkFileWithOptions(filePath, options);
});
});
Promise.all(matchedFiles.map(checkFileWithPrettierConfig))
.then(() => {
const failAction = shouldSave ? 'fixed' : 'failed';
console.log(
`\nSummary:\n ${matchedCount} files processed (${passedCount} passed, ${failedCount} ${failAction}, ${ignoredCount} ignored)\n`,
);
if (didWarn) process.exit(1);
})
.catch((e) => {
console.log(`\nAn error occurred while processing files with prettier: ${e.message}\n`);
process.exit(1);
});
......@@ -26,7 +26,7 @@ class StaticAnalysis
# duration of 300 to lower the likelihood that it will run in the same job as another long task...
%w[bundle exec rubocop --parallel] => 300,
%w[yarn run lint:eslint] => 197,
%w[yarn run prettier-all] => 124,
%w[yarn run lint:prettier] => 124,
%w[bin/rake gettext:lint] => 96,
%w[bundle exec license_finder] => 49,
%w[bin/rake scss_lint] => 38,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment