Skip to content

Commit 4406c7a

Browse files
committed
chore: add documentation linting step to presubmit workflow
Included a new step to run a smoke check on documentation as part of the presubmit workflow. Updated the documentation generation command in the error message for clarity. Added a new script command for linting documentation in package.json.
1 parent 319be18 commit 4406c7a

3 files changed

Lines changed: 99 additions & 1 deletion

File tree

.github/workflows/presubmit.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,15 @@ jobs:
5454
- name: Generate documents
5555
run: npm run docs
5656

57+
- name: Run docs smoke check
58+
run: npm run docs:lint
59+
5760
- name: Check if autogenerated docs differ
5861
run: |
5962
diff_file=$(mktemp doc_diff_XXXXXX)
6063
git diff --color > $diff_file
6164
if [[ -s $diff_file ]]; then
62-
echo "Please update the documentation by running 'npm run generate-docs'. The following was the diff"
65+
echo "Please update the documentation by running 'npm run docs'. The following was the diff"
6366
cat $diff_file
6467
rm $diff_file
6568
exit 1

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"check-format": "eslint --cache . && prettier --check --cache .;",
1515
"docs": "npm run build && npm run docs:generate && npm run format",
1616
"docs:generate": "node --experimental-strip-types scripts/generate-docs.ts",
17+
"docs:lint": "node --experimental-strip-types scripts/check-docs.ts",
1718
"start": "npm run build && node build/src/index.js",
1819
"start-debug": "DEBUG=mcp:* DEBUG_COLORS=false npm run build && node build/src/index.js",
1920
"test": "npm run build && node scripts/test.mjs",

scripts/check-docs.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* Minimal markdown smoke check for docs.
3+
*
4+
* Goals:
5+
* - Ensure all markdown files under docs/ are readable.
6+
* - Fail fast on obvious bad states (e.g. unresolved merge markers).
7+
*
8+
* This is intentionally lightweight and dependency-free so it can run quickly in CI.
9+
*/
10+
11+
import fs from 'node:fs';
12+
import path from 'node:path';
13+
14+
const DOCS_ROOT = path.join(process.cwd(), 'docs');
15+
16+
function isMarkdownFile(filePath: string): boolean {
17+
return filePath.toLowerCase().endsWith('.md');
18+
}
19+
20+
function findMarkdownFiles(root: string): string[] {
21+
const results: string[] = [];
22+
23+
function walk(current: string) {
24+
const entries = fs.readdirSync(current, {withFileTypes: true});
25+
for (const entry of entries) {
26+
const fullPath = path.join(current, entry.name);
27+
if (entry.isDirectory()) {
28+
walk(fullPath);
29+
} else if (entry.isFile() && isMarkdownFile(entry.name)) {
30+
results.push(fullPath);
31+
}
32+
}
33+
}
34+
35+
walk(root);
36+
return results;
37+
}
38+
39+
function checkFile(filePath: string): string[] {
40+
const errors: string[] = [];
41+
const content = fs.readFileSync(filePath, 'utf8');
42+
43+
if (!content.trim()) {
44+
errors.push('file is empty');
45+
}
46+
47+
const lines = content.split(/\r?\n/);
48+
lines.forEach((line, index) => {
49+
const lineNumber = index + 1;
50+
if (line.includes('<<<<<<<') || line.includes('=======') || line.includes('>>>>>>>')) {
51+
errors.push(`unresolved merge marker on line ${lineNumber}`);
52+
}
53+
});
54+
55+
return errors;
56+
}
57+
58+
function main() {
59+
if (!fs.existsSync(DOCS_ROOT)) {
60+
console.error(`Docs directory not found at ${DOCS_ROOT}`);
61+
process.exit(1);
62+
}
63+
64+
const markdownFiles = findMarkdownFiles(DOCS_ROOT);
65+
const allErrors: string[] = [];
66+
67+
for (const file of markdownFiles) {
68+
try {
69+
const errors = checkFile(file);
70+
for (const err of errors) {
71+
allErrors.push(`${path.relative(process.cwd(), file)}: ${err}`);
72+
}
73+
} catch (error) {
74+
allErrors.push(
75+
`${path.relative(process.cwd(), file)}: failed to read or parse file: ${
76+
(error as Error).message
77+
}`,
78+
);
79+
}
80+
}
81+
82+
if (allErrors.length > 0) {
83+
console.error('Docs smoke check failed with the following issues:\n');
84+
for (const msg of allErrors) {
85+
console.error(`- ${msg}`);
86+
}
87+
process.exit(1);
88+
}
89+
90+
console.log(`Docs smoke check passed for ${markdownFiles.length} markdown file(s).`);
91+
}
92+
93+
main();
94+

0 commit comments

Comments
 (0)