From 8cf2304c99986b7eecad4f765c0b70e79790b8d6 Mon Sep 17 00:00:00 2001 From: Yuhan Lei Date: Fri, 10 Apr 2026 17:05:59 +0800 Subject: [PATCH 1/3] fix(ci): repair adapter-test and doc coverage --- scripts/check-doc-coverage.sh | 5 ++ src/ci-regressions.test.ts | 115 ++++++++++++++++++++++++++++++++++ vitest.config.ts | 4 +- 3 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/ci-regressions.test.ts diff --git a/scripts/check-doc-coverage.sh b/scripts/check-doc-coverage.sh index 9174721f3..aea12bdbc 100755 --- a/scripts/check-doc-coverage.sh +++ b/scripts/check-doc-coverage.sh @@ -30,6 +30,11 @@ for adapter_dir in "$SRC_DIR"/*/; do adapter_name="$(basename "$adapter_dir")" # Skip internal directories (e.g., _shared) [[ "$adapter_name" == _* ]] && continue + # Skip helper-only directories that do not expose any top-level adapter commands. + top_level_files="$(find "$adapter_dir" -maxdepth 1 -type f | awk -F/ '{print $NF}')" + if [[ -n "$top_level_files" ]] && ! printf '%s\n' "$top_level_files" | grep -qv '^_'; then + continue + fi total=$((total + 1)) # Check if doc exists in browser/ or desktop/ subdirectories diff --git a/src/ci-regressions.test.ts b/src/ci-regressions.test.ts new file mode 100644 index 000000000..ac45d709c --- /dev/null +++ b/src/ci-regressions.test.ts @@ -0,0 +1,115 @@ +import { execFileSync } from 'node:child_process'; +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; +import { afterEach, describe, expect, it } from 'vitest'; + +const tempDirs: string[] = []; + +afterEach(() => { + for (const dir of tempDirs.splice(0)) { + fs.rmSync(dir, { recursive: true, force: true }); + } +}); + +describe('CI regression coverage', () => { + it('runs adapter tests from src/clis and keeps them out of the unit project', () => { + const adapterList = execFileSync( + 'npx', + ['vitest', 'list', '--project', 'adapter'], + { + cwd: process.cwd(), + encoding: 'utf8', + }, + ); + const unitList = execFileSync( + 'npx', + ['vitest', 'list', '--project', 'unit'], + { + cwd: process.cwd(), + encoding: 'utf8', + }, + ); + + expect(adapterList).toContain('src/clis/binance/commands.test.ts'); + expect(unitList).not.toContain('src/clis/binance/commands.test.ts'); + }); + + it('ignores helper-only adapter directories when checking docs coverage', () => { + const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-doc-coverage-')); + tempDirs.push(fixtureRoot); + + const scriptsDir = path.join(fixtureRoot, 'scripts'); + const clisDir = path.join(fixtureRoot, 'clis', 'slock'); + const docsBrowserDir = path.join(fixtureRoot, 'docs', 'adapters', 'browser'); + const docsDesktopDir = path.join(fixtureRoot, 'docs', 'adapters', 'desktop'); + + fs.mkdirSync(scriptsDir, { recursive: true }); + fs.mkdirSync(clisDir, { recursive: true }); + fs.mkdirSync(docsBrowserDir, { recursive: true }); + fs.mkdirSync(docsDesktopDir, { recursive: true }); + + fs.copyFileSync( + path.join(process.cwd(), 'scripts', 'check-doc-coverage.sh'), + path.join(scriptsDir, 'check-doc-coverage.sh'), + ); + fs.writeFileSync( + path.join(clisDir, '_utils.js'), + 'export const helper = () => "noop";\n', + ); + + const output = execFileSync( + 'bash', + [path.join(scriptsDir, 'check-doc-coverage.sh'), '--strict'], + { + cwd: fixtureRoot, + encoding: 'utf8', + }, + ); + + expect(output).toContain('Doc Coverage: 0/0 adapters documented'); + expect(output).toContain('All adapters have documentation'); + }); + + it('keeps nested-only adapter directories in doc coverage until they are documented', () => { + const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-doc-coverage-')); + tempDirs.push(fixtureRoot); + + const scriptsDir = path.join(fixtureRoot, 'scripts'); + const nestedAdapterDir = path.join(fixtureRoot, 'clis', 'ghost', 'nested'); + const docsBrowserDir = path.join(fixtureRoot, 'docs', 'adapters', 'browser'); + const docsDesktopDir = path.join(fixtureRoot, 'docs', 'adapters', 'desktop'); + + fs.mkdirSync(scriptsDir, { recursive: true }); + fs.mkdirSync(nestedAdapterDir, { recursive: true }); + fs.mkdirSync(docsBrowserDir, { recursive: true }); + fs.mkdirSync(docsDesktopDir, { recursive: true }); + + fs.copyFileSync( + path.join(process.cwd(), 'scripts', 'check-doc-coverage.sh'), + path.join(scriptsDir, 'check-doc-coverage.sh'), + ); + fs.writeFileSync( + path.join(nestedAdapterDir, 'read.js'), + 'export const command = "ghost";\n', + ); + + try { + execFileSync( + 'bash', + [path.join(scriptsDir, 'check-doc-coverage.sh'), '--strict'], + { + cwd: fixtureRoot, + encoding: 'utf8', + }, + ); + throw new Error('Expected nested-only adapter directory to fail doc coverage'); + } catch (error) { + const failure = error as NodeJS.ErrnoException & { stdout?: string; status?: number }; + + expect(failure.status).toBe(1); + expect(failure.stdout).toContain('Doc Coverage: 0/1 adapters documented'); + expect(failure.stdout).toContain('ghost'); + } + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts index 08834de62..1a3a679f2 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ test: { name: 'unit', include: ['src/**/*.test.ts'], - exclude: ['clis/**/*.test.ts'], + exclude: ['src/clis/**/*.test.ts'], sequence: { groupOrder: 0 }, }, }, @@ -23,7 +23,7 @@ export default defineConfig({ { test: { name: 'adapter', - include: ['clis/**/*.test.ts'], + include: ['src/clis/**/*.test.ts'], sequence: { groupOrder: 1 }, }, }, From 41fba155b54b3c84cd1250d911ab256b1807ac2f Mon Sep 17 00:00:00 2001 From: jackwener Date: Fri, 10 Apr 2026 20:27:51 +0800 Subject: [PATCH 2/3] test(ci): drop nested vitest regression check --- src/ci-regressions.test.ts | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/ci-regressions.test.ts b/src/ci-regressions.test.ts index ac45d709c..78a0f9268 100644 --- a/src/ci-regressions.test.ts +++ b/src/ci-regressions.test.ts @@ -13,28 +13,6 @@ afterEach(() => { }); describe('CI regression coverage', () => { - it('runs adapter tests from src/clis and keeps them out of the unit project', () => { - const adapterList = execFileSync( - 'npx', - ['vitest', 'list', '--project', 'adapter'], - { - cwd: process.cwd(), - encoding: 'utf8', - }, - ); - const unitList = execFileSync( - 'npx', - ['vitest', 'list', '--project', 'unit'], - { - cwd: process.cwd(), - encoding: 'utf8', - }, - ); - - expect(adapterList).toContain('src/clis/binance/commands.test.ts'); - expect(unitList).not.toContain('src/clis/binance/commands.test.ts'); - }); - it('ignores helper-only adapter directories when checking docs coverage', () => { const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-doc-coverage-')); tempDirs.push(fixtureRoot); From 1298dbcc5214d8d57ea1a42d9cd7b45b6ccee396 Mon Sep 17 00:00:00 2001 From: jackwener Date: Fri, 10 Apr 2026 20:48:05 +0800 Subject: [PATCH 3/3] fix(ci): align adapter test discovery --- clis/linux-do/topic-content.test.js | 8 +++--- src/ci-regressions.test.ts | 42 ----------------------------- vitest.config.ts | 2 +- 3 files changed, 5 insertions(+), 47 deletions(-) diff --git a/clis/linux-do/topic-content.test.js b/clis/linux-do/topic-content.test.js index d0dcd800e..3e4aa4dd9 100644 --- a/clis/linux-do/topic-content.test.js +++ b/clis/linux-do/topic-content.test.js @@ -51,9 +51,9 @@ describe('linux-do topic-content', () => { expect(command?.columns).toEqual(['content']); }); it('keeps topic adapter as a summarized first-page reader after the split', () => { - const topicTs = fs.readFileSync(new URL('./topic.ts', import.meta.url), 'utf8'); - expect(topicTs).not.toContain('main_only'); - expect(topicTs).toContain('slice(0, 200)'); - expect(topicTs).toContain('帖子首页摘要和回复'); + const topicSource = fs.readFileSync(new URL('./topic.js', import.meta.url), 'utf8'); + expect(topicSource).not.toContain('main_only'); + expect(topicSource).toContain('slice(0, 200)'); + expect(topicSource).toContain('帖子首页摘要和回复'); }); }); diff --git a/src/ci-regressions.test.ts b/src/ci-regressions.test.ts index 78a0f9268..ebf6dc160 100644 --- a/src/ci-regressions.test.ts +++ b/src/ci-regressions.test.ts @@ -48,46 +48,4 @@ describe('CI regression coverage', () => { expect(output).toContain('Doc Coverage: 0/0 adapters documented'); expect(output).toContain('All adapters have documentation'); }); - - it('keeps nested-only adapter directories in doc coverage until they are documented', () => { - const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-doc-coverage-')); - tempDirs.push(fixtureRoot); - - const scriptsDir = path.join(fixtureRoot, 'scripts'); - const nestedAdapterDir = path.join(fixtureRoot, 'clis', 'ghost', 'nested'); - const docsBrowserDir = path.join(fixtureRoot, 'docs', 'adapters', 'browser'); - const docsDesktopDir = path.join(fixtureRoot, 'docs', 'adapters', 'desktop'); - - fs.mkdirSync(scriptsDir, { recursive: true }); - fs.mkdirSync(nestedAdapterDir, { recursive: true }); - fs.mkdirSync(docsBrowserDir, { recursive: true }); - fs.mkdirSync(docsDesktopDir, { recursive: true }); - - fs.copyFileSync( - path.join(process.cwd(), 'scripts', 'check-doc-coverage.sh'), - path.join(scriptsDir, 'check-doc-coverage.sh'), - ); - fs.writeFileSync( - path.join(nestedAdapterDir, 'read.js'), - 'export const command = "ghost";\n', - ); - - try { - execFileSync( - 'bash', - [path.join(scriptsDir, 'check-doc-coverage.sh'), '--strict'], - { - cwd: fixtureRoot, - encoding: 'utf8', - }, - ); - throw new Error('Expected nested-only adapter directory to fail doc coverage'); - } catch (error) { - const failure = error as NodeJS.ErrnoException & { stdout?: string; status?: number }; - - expect(failure.status).toBe(1); - expect(failure.stdout).toContain('Doc Coverage: 0/1 adapters documented'); - expect(failure.stdout).toContain('ghost'); - } - }); }); diff --git a/vitest.config.ts b/vitest.config.ts index 1a3a679f2..e05db4a7a 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -23,7 +23,7 @@ export default defineConfig({ { test: { name: 'adapter', - include: ['src/clis/**/*.test.ts'], + include: ['clis/**/*.test.js', 'src/clis/**/*.test.ts'], sequence: { groupOrder: 1 }, }, },