优化
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readdir, readFile } from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import test from 'node:test'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const repositoryRoot = path.resolve(fileURLToPath(new URL('..', import.meta.url)))
|
||||
const scriptsReadme = path.join(repositoryRoot, 'scripts', 'README.md')
|
||||
const excludedDirectoryNames = new Set([
|
||||
'.git', '.logs', 'dist', 'node_modules', 'output', 'outputs', 'reports', 'target', 'uni_modules',
|
||||
])
|
||||
const allowedDirectoryPrefixes = [
|
||||
'scripts/',
|
||||
'deploy/scripts/',
|
||||
'deploy/rocketmq/',
|
||||
'firstleg/scripts/',
|
||||
'lastleg-service/scripts/',
|
||||
'warehouse/scripts/',
|
||||
]
|
||||
|
||||
async function executableFiles(directory, extensions, { excludeTests = true } = {}) {
|
||||
const entries = await readdir(path.join(repositoryRoot, directory), { withFileTypes: true })
|
||||
return entries
|
||||
.filter((entry) => entry.isFile())
|
||||
.filter((entry) => extensions.some((extension) => entry.name.endsWith(extension)))
|
||||
.filter((entry) => !excludeTests || !entry.name.endsWith('.test.mjs'))
|
||||
.map((entry) => `${directory}/${entry.name}`.replaceAll('\\', '/'))
|
||||
}
|
||||
|
||||
async function discoverScriptFiles(directory = repositoryRoot) {
|
||||
const discovered = []
|
||||
const entries = await readdir(directory, { withFileTypes: true })
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory() && (
|
||||
excludedDirectoryNames.has(entry.name)
|
||||
|| entry.name.startsWith('node_modules.')
|
||||
|| entry.name.startsWith('.codex-')
|
||||
|| entry.name.startsWith('.runtime-')
|
||||
)) continue
|
||||
const absolute = path.join(directory, entry.name)
|
||||
if (entry.isDirectory()) {
|
||||
discovered.push(...await discoverScriptFiles(absolute))
|
||||
continue
|
||||
}
|
||||
if (!['.mjs', '.ps1', '.sh', '.groovy'].some((extension) => entry.name.endsWith(extension))) continue
|
||||
discovered.push(path.relative(repositoryRoot, absolute).replaceAll('\\', '/'))
|
||||
}
|
||||
return discovered
|
||||
}
|
||||
|
||||
test('executable scripts only live in documented directories', async () => {
|
||||
const files = await discoverScriptFiles()
|
||||
const misplaced = files.filter((file) => !allowedDirectoryPrefixes.some((prefix) => file.startsWith(prefix)))
|
||||
assert.deepEqual(misplaced, [], `以下脚本位于未登记目录:\n${misplaced.join('\n')}`)
|
||||
})
|
||||
|
||||
test('all directly runnable scripts are documented in scripts/README.md', async () => {
|
||||
const readme = await readFile(scriptsReadme, 'utf8')
|
||||
const files = [
|
||||
...await executableFiles('scripts', ['.mjs', '.ps1', '.groovy']),
|
||||
...await executableFiles('scripts/openapi-validation', ['.mjs']),
|
||||
...await executableFiles('deploy/scripts', ['.sh']),
|
||||
...await executableFiles('deploy/rocketmq', ['.sh']),
|
||||
...await executableFiles('firstleg/scripts', ['.mjs']),
|
||||
...await executableFiles('lastleg-service/scripts', ['.mjs']),
|
||||
]
|
||||
|
||||
const undocumented = files.filter((file) => {
|
||||
const relativeToScripts = file.startsWith('scripts/') ? file.slice('scripts/'.length) : file
|
||||
return !readme.includes(file) && !readme.includes(relativeToScripts)
|
||||
})
|
||||
|
||||
assert.deepEqual(undocumented, [], `以下可执行脚本未登记用途与边界:\n${undocumented.join('\n')}`)
|
||||
})
|
||||
|
||||
test('README explains internal modules and test scripts are not standalone entries', async () => {
|
||||
const readme = await readFile(scriptsReadme, 'utf8')
|
||||
assert.match(readme, /\*\.test\.mjs.*离线 Node 静态合同/)
|
||||
assert.match(readme, /admin-test-env-modules\/\*\.mjs.*逐模块说明/)
|
||||
assert.match(readme, /warehouse\/scripts\/warehouse-public-master-data-contract\.test\.mjs/)
|
||||
})
|
||||
Reference in New Issue
Block a user