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 /app/assets/javascripts/locale/**/app.js
/fixtures/lib/gitlab/graphql/
/node_modules/ /node_modules/
/public/ /public/
/vendor/ /vendor/
......
...@@ -125,44 +125,28 @@ Please take care that you only let Prettier format the same file types as the gl ...@@ -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: The following yarn scripts are available to do global formatting:
```shell ```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. Updates all staged files (based on `git diff`) with Prettier and saves the needed changes.
```shell ```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. Checks all staged files (based on `git diff`) with Prettier and log which files would need manual updating to the console.
```shell ```shell
yarn prettier-all yarn run lint:prettier
``` ```
Checks all files with Prettier and logs which files need manual updating to the console. Checks all files with Prettier and logs which files need manual updating to the console.
```shell ```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). Formats all files in the repository with Prettier.
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.
### VSCode Settings ### VSCode Settings
......
...@@ -26,12 +26,16 @@ ...@@ -26,12 +26,16 @@
"lint:eslint:report": "yarn run internal:eslint --format html --output-file ./eslint-report.html --no-inline-config .", "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": "scripts/frontend/execute-on-staged-files.sh internal:eslint '(js|vue)'",
"lint:eslint:staged:fix": "yarn run lint:eslint:staged --fix", "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", "markdownlint": "markdownlint --config .markdownlint.json",
"postinstall": "node ./scripts/frontend/postinstall.js", "postinstall": "node ./scripts/frontend/postinstall.js",
"prettier-staged": "node ./scripts/frontend/prettier.js check", "prettier-all": "echo 'Please use lint:prettier instead' && exit 1",
"prettier-staged-save": "node ./scripts/frontend/prettier.js save", "prettier-all-save": "echo 'Please use lint:prettier:fix instead' && exit 1",
"prettier-all": "node ./scripts/frontend/prettier.js check-all", "prettier-staged": "echo 'Please use lint:prettier:staged instead' && exit 1",
"prettier-all-save": "node ./scripts/frontend/prettier.js save-all", "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": "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-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", "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 ...@@ -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... # 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[bundle exec rubocop --parallel] => 300,
%w[yarn run lint:eslint] => 197, %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[bin/rake gettext:lint] => 96,
%w[bundle exec license_finder] => 49, %w[bundle exec license_finder] => 49,
%w[bin/rake scss_lint] => 38, %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