refactor: migrate linting to Oxlint
This commit is contained in:
@@ -42,6 +42,18 @@ function withPnpmEntrypoint<T>(action: () => T): T {
|
||||
}
|
||||
}
|
||||
|
||||
function withEnv<T>(name: string, value: string | undefined, action: () => T): T {
|
||||
const previous = process.env[name]
|
||||
if (value === undefined) Reflect.deleteProperty(process.env, name)
|
||||
else process.env[name] = value
|
||||
try {
|
||||
return action()
|
||||
} finally {
|
||||
if (previous === undefined) Reflect.deleteProperty(process.env, name)
|
||||
else process.env[name] = previous
|
||||
}
|
||||
}
|
||||
|
||||
describe('gate graph validation', () => {
|
||||
it.each([
|
||||
'ci-primary',
|
||||
@@ -96,6 +108,38 @@ describe('gate graph validation', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('Oxlint gate', () => {
|
||||
it('uses the package script when no worker bound is configured', () => {
|
||||
const subject = withEnv('DSH_OXLINT_THREADS', undefined, () =>
|
||||
withPnpmEntrypoint(() => gatesForMode('ci-lint')[0]))
|
||||
|
||||
expect(subject).toMatchObject({
|
||||
id: 'lint',
|
||||
displayCommand: 'pnpm run lint',
|
||||
command: process.execPath,
|
||||
args: ['/private/pnpm.cjs', 'run', 'lint'],
|
||||
})
|
||||
})
|
||||
|
||||
it('passes the configured native thread bound to Oxlint', () => {
|
||||
const subject = withEnv('DSH_OXLINT_THREADS', '4', () =>
|
||||
withPnpmEntrypoint(() => gatesForMode('ci-lint')[0]))
|
||||
|
||||
expect(subject).toMatchObject({
|
||||
id: 'lint',
|
||||
displayCommand: 'pnpm exec oxlint . --threads=4',
|
||||
command: process.execPath,
|
||||
args: ['/private/pnpm.cjs', 'exec', 'oxlint', '.', '--threads=4'],
|
||||
})
|
||||
})
|
||||
|
||||
it('rejects a non-positive or non-integer native thread bound', () => {
|
||||
expect(() => withEnv('DSH_OXLINT_THREADS', 'auto', () =>
|
||||
withPnpmEntrypoint(() => gatesForMode('ci-lint'))))
|
||||
.toThrow('DSH_OXLINT_THREADS must be a positive integer')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Node 24 consumer graph', () => {
|
||||
it('owns the seven-command pool and orders restored-artifact consumers', () => {
|
||||
const subject = withPnpmEntrypoint(() => gatesForMode('ci-consumers'))
|
||||
|
||||
@@ -181,10 +181,6 @@ function pnpmInvocation(args: string[]): Pick<Gate, 'command' | 'args'> {
|
||||
return { command: process.execPath, args: [entrypoint, ...args] }
|
||||
}
|
||||
|
||||
function nodeOptions(...options: string[]): string {
|
||||
return [process.env.NODE_OPTIONS, ...options].filter(option => option !== undefined && option !== '').join(' ')
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the complete gate list for a named aggregate.
|
||||
* @param selected - aggregate mode to construct.
|
||||
@@ -375,43 +371,22 @@ function ciWindowsObservationalGates(): Gate[] {
|
||||
]
|
||||
}
|
||||
|
||||
function lintGate(eslintTargets: readonly string[] = ['.']): Gate {
|
||||
const concurrencyArgs = eslintConcurrencyArgs()
|
||||
if (process.env.DSH_ESLINT_CACHE === '1') {
|
||||
return pnpmExec('lint', [
|
||||
'eslint',
|
||||
...eslintTargets,
|
||||
...concurrencyArgs,
|
||||
'--cache',
|
||||
'--cache-location',
|
||||
'.cache/eslint/',
|
||||
'--cache-strategy',
|
||||
'content',
|
||||
], {
|
||||
label: 'lint',
|
||||
env: { NODE_OPTIONS: nodeOptions('--max-old-space-size=8192') },
|
||||
})
|
||||
function lintGate(oxlintTargets: readonly string[] = ['.']): Gate {
|
||||
const threadArgs = oxlintThreadArgs()
|
||||
if (threadArgs.length > 0) {
|
||||
return pnpmExec('lint', ['oxlint', ...oxlintTargets, ...threadArgs], { label: 'lint' })
|
||||
}
|
||||
if (concurrencyArgs.length > 0) {
|
||||
return pnpmExec('lint', ['eslint', ...eslintTargets, ...concurrencyArgs], {
|
||||
label: 'lint',
|
||||
env: { NODE_OPTIONS: nodeOptions('--max-old-space-size=8192') },
|
||||
})
|
||||
}
|
||||
return pnpmScript('lint', 'lint', {
|
||||
env: { NODE_OPTIONS: nodeOptions('--max-old-space-size=8192') },
|
||||
})
|
||||
return pnpmScript('lint', 'lint')
|
||||
}
|
||||
|
||||
function eslintConcurrencyArgs(): string[] {
|
||||
const raw = process.env.DSH_ESLINT_CONCURRENCY
|
||||
function oxlintThreadArgs(): string[] {
|
||||
const raw = process.env.DSH_OXLINT_THREADS
|
||||
if (raw === undefined || raw === '') return []
|
||||
if (raw === 'auto') return ['--concurrency=auto']
|
||||
const parsed = Number.parseInt(raw, 10)
|
||||
if (!Number.isSafeInteger(parsed) || parsed < 1 || String(parsed) !== raw) {
|
||||
throw new Error(`run-gates: DSH_ESLINT_CONCURRENCY must be a positive integer or auto, got ${JSON.stringify(raw)}.`)
|
||||
throw new Error(`run-gates: DSH_OXLINT_THREADS must be a positive integer, got ${JSON.stringify(raw)}.`)
|
||||
}
|
||||
return [`--concurrency=${raw}`]
|
||||
return [`--threads=${raw}`]
|
||||
}
|
||||
|
||||
function coverageGate(): Gate {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -44,7 +44,7 @@ interface InvariantHost {
|
||||
type PluginFiber = ReturnType<RegistryService['plugin']>
|
||||
|
||||
const hosts = new WeakMap<Context, InvariantHost>()
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method -- every call below supplies its RegistryService receiver explicitly.
|
||||
// oxlint-disable-next-line typescript/unbound-method -- every call below supplies its RegistryService receiver explicitly.
|
||||
const originalPlugin = RegistryService.prototype.plugin
|
||||
|
||||
RegistryService.prototype.plugin = function(plugin: Plugin, config?: unknown, getOuterStack?: () => string[]) {
|
||||
|
||||
@@ -126,7 +126,7 @@ function heritageExemption(
|
||||
returnType = d.type.type
|
||||
} else continue
|
||||
baseParams ??= new Set()
|
||||
// Leading underscores are the deliberately-unused marker (eslint
|
||||
// Leading underscores are the deliberately-unused marker (lint
|
||||
// argsIgnorePattern), not a rename: `_cwd` overriding `cwd` is the
|
||||
// same parameter, so compare underscore-stripped on both sides.
|
||||
for (const p of params) if (ts.isIdentifier(p.name)) baseParams.add(p.name.text.replace(/^_+/, ''))
|
||||
|
||||
Reference in New Issue
Block a user