From e1e8bde0c55e799b21568a69f015646e991e92fa Mon Sep 17 00:00:00 2001 From: Mark Yen Date: Mon, 23 Dec 2024 11:06:36 -0800 Subject: [PATCH] Add spell checking to linter step Note that this is currently only enabled on Linux, because: - check-spelling does not support Windows - on macOS, check-spelling fails to ignore long words listed in expect.txt (https://github.com/check-spelling/check-spelling/issues/84) Signed-off-by: Mark Yen --- package.json | 5 +-- scripts/spelling.ts | 88 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 scripts/spelling.ts diff --git a/package.json b/package.json index 0a61b56543f..c8e2323fcc5 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,13 @@ "scripts": { "dev": "node scripts/ts-wrapper.js scripts/dev.ts", "lint": "yarn lint:fix", - "lint:fix": "yarn lint:typescript:fix && yarn lint:go:fix ", - "lint:nofix": "yarn lint:typescript:nofix && yarn lint:go:nofix", + "lint:fix": "yarn lint:typescript:fix && yarn lint:go:fix && yarn lint:spelling", + "lint:nofix": "yarn lint:typescript:nofix && yarn lint:go:nofix && yarn lint:spelling", "lint:typescript:fix": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=1 NODE_OPTIONS=--max_old_space_size=4096 eslint --ignore-path=.gitignore --ext mjs,js,ts,tsx,vue --fix --report-unused-disable-directives .", "lint:typescript:nofix": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=1 NODE_OPTIONS=--max_old_space_size=4096 eslint --ignore-path=.gitignore --ext mjs,js,ts,tsx,vue --report-unused-disable-directives --max-warnings=0 .", "lint:go:fix": "node scripts/ts-wrapper.js scripts/lint-go.ts --fix", "lint:go:nofix": "node scripts/ts-wrapper.js scripts/lint-go.ts", + "lint:spelling": "node scripts/ts-wrapper.js scripts/spelling.ts", "generate:nerdctl-stub": "powershell scripts/windows/generate-nerdctl-stub.ps1", "build": "cross-env NODE_OPTIONS=--max_old_space_size=4096 node --stack-size=16384 scripts/ts-wrapper.js scripts/build.ts", "package": "node scripts/ts-wrapper.js scripts/package.ts", diff --git a/scripts/spelling.ts b/scripts/spelling.ts new file mode 100644 index 00000000000..acd8598c25f --- /dev/null +++ b/scripts/spelling.ts @@ -0,0 +1,88 @@ +/** + * This script runs github.com/check-spelling/check-spelling locally. It + * requires a working sh interpreter, perl, and possibly other things. + * This is meant to be used as a local check before pushing to make PRs; this is + * a no-op in CI as we still rely on the CI workflow there instead. + */ + +import fs from 'fs/promises'; +import path from 'path'; + +import yaml from 'yaml'; + +import { simpleSpawn } from './simple_process'; + +if (process.env.CI) { + console.log(`Skipping spell checking in CI, please see separate workflow.`); + process.exit(); +} + +if (process.platform === 'win32') { + console.log(`Skipping spell checking, Windows is not supported.`); + process.exit(); +} + +if (process.platform === 'darwin') { + // On macOS, the spell checker fails to skip expected long words. + // Disable spell checking there for now. + // https://github.com/check-spelling/check-spelling/issues/84 + console.log(`Skipping spell checking, macOS has false positives.`); + process.exit(); +} + +/** + * Clone the check-spelling repository if needed, and return the script. + * @param step GitHub Actions check spelling step configuration. + * @returns Path to unknown-words.sh + */ +async function findScript(step: any): Promise { + // Put the check-spelling files in `$PWD/resources/host/check-spelling + const checkout = path.join(process.cwd(), 'resources', 'host', 'check-spelling'); + const script = path.join(checkout, 'unknown-words.sh'); + const [repo, hash] = step.uses?.split('@') ?? []; + + if (!repo) { + throw new Error('Failed to find check-spelling repository from GitHub Actions workflow'); + } + if (!hash) { + throw new Error('Failed to find commit/branch to use for check-spelling'); + } + + try { + await fs.stat(script); + // Update the checkout. + await simpleSpawn('git', ['-C', checkout, 'fetch']); + } catch (ex) { + // Assume file not found. + await simpleSpawn('git', ['clone', '--no-checkout', `https://github.com/${ repo }.git`, checkout]); + } + await simpleSpawn('git', ['-C', checkout, 'checkout', hash]); + + return script; +} + +(async function() { + // Locate the GitHub Actions workflow and locate the check spelling step. + const configPath = path.join(process.cwd(), '.github', 'workflows', 'spelling.yml'); + const config = yaml.parse(await fs.readFile(configPath, { encoding: 'utf-8' })); + const step = config.jobs?.spelling?.steps?.find((step: any) => step?.id === 'spelling'); + const stepConfig = step?.with; + + if (!stepConfig) { + throw new Error('Failed to locate check-spelling CI configuration'); + } + // Remove configuration that does not make sense outside of CI. + delete stepConfig.experimental_apply_changes_via_bot; + delete stepConfig.use_sarif; + + // Set up configuration for the script. + process.env.INPUTS = JSON.stringify(stepConfig); + + // Find the check spelling script and run it. + const script = await findScript(step); + + await simpleSpawn(script); +})().catch((err) => { + console.error(err); + process.exit(1); +});