Merge pull request #2252 from deepseek-harness/worktree/fix-1463-rich-content-bridge
fix: bridge durable image content across MCP and ACP
This commit is contained in:
@@ -72,6 +72,9 @@ describe('CI workflow', () => {
|
||||
expect(windowsNative['runs-on']).toContain('dsh-windows-2025-16core')
|
||||
expect(windowsNative.name).toBe('windows node 24 / native complete')
|
||||
expect(windowsNative.if).toBe("github.event_name == 'pull_request'")
|
||||
expect(windowsNative.env).toMatchObject({
|
||||
DSH_COVERAGE_TEST_TIMEOUT_MS: '30000',
|
||||
})
|
||||
const nativeCommandSteps = (windowsNative.steps as unknown[]).filter((step): step is Record<string, unknown> & { run: string } => (
|
||||
isRecord(step) && typeof step.run === 'string'
|
||||
))
|
||||
|
||||
@@ -38,4 +38,5 @@ export const coverageExemptHeavySuites: readonly CoverageExemptSuite[] = [
|
||||
{ filter: 'scripts/install-lefthook.spec.ts', exclude: 'scripts/install-lefthook.spec.ts' },
|
||||
{ filter: 'scripts/oxlint-contract.spec.ts', exclude: 'scripts/oxlint-contract.spec.ts' },
|
||||
{ filter: 'scripts/change-scope.spec.ts', exclude: 'scripts/change-scope.spec.ts' },
|
||||
{ filter: 'scripts/translation-pairing-merge.spec.ts', exclude: 'scripts/translation-pairing-merge.spec.ts' },
|
||||
]
|
||||
|
||||
@@ -23,7 +23,7 @@ const OWNERSHIP_MARKER_VERSION = 1
|
||||
const OWNERSHIP_MARKER_OWNER = 'deepseek-harness worktree-local lefthook hooks'
|
||||
const INSTALL_LOCK = 'dsh-lefthook-install.lock'
|
||||
const INSTALL_LOCK_TIMEOUT_MS = 30_000
|
||||
const INSTALL_LOCK_INITIALIZATION_TIMEOUT_MS = 1_000
|
||||
const INSTALL_LOCK_INITIALIZATION_TIMEOUT_MS = 5_000
|
||||
const INSTALL_LOCK_POLL_MS = 50
|
||||
const ALLOW_HOOKS_PATH_OVERRIDE = 'DSH_LEFTHOOK_ALLOW_HOOKS_PATH_OVERRIDE'
|
||||
const REPOSITORY_EXTENSION_PATTERN = '^extensions\\.'
|
||||
|
||||
@@ -23,9 +23,9 @@ const pairingMergeDriver = 'scripts/merge-translation-pairing-driver.sh %O %A %B
|
||||
const scriptsDirectory = fileURLToPath(new URL('.', import.meta.url))
|
||||
const tsxPackageDirectory = dirname(fileURLToPath(import.meta.resolve('tsx/package.json')))
|
||||
const fixtures: string[] = []
|
||||
// Multi-worktree cases spawn several Git and Node subprocesses; coverage concurrency can
|
||||
// legitimately exceed Vitest's default deadline without changing the installer behavior.
|
||||
const MULTI_PROCESS_TEST_TIMEOUT_MS = 20_000
|
||||
// Multi-worktree cases spawn several Git and Node subprocesses; native Windows
|
||||
// coverage concurrency can delay them without changing installer behavior.
|
||||
const MULTI_PROCESS_TEST_TIMEOUT_MS = 30_000
|
||||
|
||||
interface Fixture {
|
||||
container: string
|
||||
@@ -184,7 +184,7 @@ function installLockPath(fixture: Fixture): string {
|
||||
}
|
||||
|
||||
async function waitForPath(path: string): Promise<void> {
|
||||
const deadline = Date.now() + 5_000
|
||||
const deadline = Date.now() + 10_000
|
||||
while (!existsSync(path)) {
|
||||
if (Date.now() >= deadline) throw new Error(`timed out waiting for ${path}`)
|
||||
await new Promise(resolveWait => setTimeout(resolveWait, 10))
|
||||
@@ -211,7 +211,7 @@ function runInstaller(
|
||||
})
|
||||
}
|
||||
|
||||
describe('worktree-local Lefthook installer', { timeout: 15_000 }, () => {
|
||||
describe('worktree-local Lefthook installer', { timeout: 30_000 }, () => {
|
||||
for (const [label, extraEnv] of [
|
||||
['CI', { CI: 'true' }],
|
||||
['GitHub Actions', { GITHUB_ACTIONS: 'true' }],
|
||||
|
||||
@@ -101,6 +101,35 @@ describe('gate graph validation', () => {
|
||||
expect(byId.get('duplication')?.allowFailure).toBe(true)
|
||||
})
|
||||
|
||||
it('applies one configured test and polling timeout to both coverage gates', () => {
|
||||
const gates = withEnv('DSH_COVERAGE_TEST_TIMEOUT_MS', '15000', () =>
|
||||
withPnpmEntrypoint(() => gatesForMode('ci-windows-complete')))
|
||||
|
||||
for (const id of ['coverage', 'coverage-exempt-heavy']) {
|
||||
expect(gates.find(subject => subject.id === id)?.args).toEqual(expect.arrayContaining([
|
||||
'--testTimeout=15000',
|
||||
'--expect.poll.timeout=15000',
|
||||
]))
|
||||
}
|
||||
})
|
||||
|
||||
it('keeps Vitest timeout defaults when the coverage override is absent', () => {
|
||||
const gates = withEnv('DSH_COVERAGE_TEST_TIMEOUT_MS', undefined, () =>
|
||||
withPnpmEntrypoint(() => gatesForMode('ci-windows-complete')))
|
||||
|
||||
for (const id of ['coverage', 'coverage-exempt-heavy']) {
|
||||
expect(gates.find(subject => subject.id === id)?.args).not.toEqual(expect.arrayContaining([
|
||||
expect.stringMatching(/^--(?:testTimeout|expect\.poll\.timeout)=/),
|
||||
]))
|
||||
}
|
||||
})
|
||||
|
||||
it('rejects an invalid coverage timeout before starting a gate', () => {
|
||||
expect(() => withEnv('DSH_COVERAGE_TEST_TIMEOUT_MS', '0', () =>
|
||||
withPnpmEntrypoint(() => gatesForMode('ci-windows-complete'))))
|
||||
.toThrow('DSH_COVERAGE_TEST_TIMEOUT_MS must be a positive integer')
|
||||
})
|
||||
|
||||
it.each([
|
||||
['empty', [], /gate graph has no gates/],
|
||||
['duplicate ids', [gate('same'), gate('same')], /duplicate gate id "same"/],
|
||||
|
||||
@@ -485,6 +485,9 @@ function lintGate(options: { needs?: string[] } = {}): Gate {
|
||||
// small share. A budget of 1 gives each gate 1 worker; lanes that need a
|
||||
// strict total of one (the serial reference jobs) also set
|
||||
// DSH_GATE_CONCURRENCY=1, which keeps the gates from overlapping at all.
|
||||
// DSH_COVERAGE_TEST_TIMEOUT_MS raises Vitest's per-test and expect.poll
|
||||
// defaults together for instrumented lanes whose scheduling overhead exceeds
|
||||
// those defaults. Explicit fixture timeouts remain authoritative.
|
||||
function coverageWorkerArgs(): { instrumented: string[]; exempt: string[] } {
|
||||
const [flag] = positiveIntArg('DSH_COVERAGE_MAX_WORKERS', '--maxWorkers')
|
||||
if (flag === undefined) return { instrumented: [], exempt: [] }
|
||||
@@ -497,14 +500,23 @@ function coverageWorkerArgs(): { instrumented: string[]; exempt: string[] } {
|
||||
}
|
||||
}
|
||||
|
||||
function coverageTimeoutArgs(): string[] {
|
||||
return [
|
||||
...positiveIntArg('DSH_COVERAGE_TEST_TIMEOUT_MS', '--testTimeout'),
|
||||
...positiveIntArg('DSH_COVERAGE_TEST_TIMEOUT_MS', '--expect.poll.timeout'),
|
||||
]
|
||||
}
|
||||
|
||||
function coverageGates(): Gate[] {
|
||||
const workers = coverageWorkerArgs()
|
||||
const timeouts = coverageTimeoutArgs()
|
||||
return [
|
||||
pnpmExec('coverage', [
|
||||
'vitest',
|
||||
'run',
|
||||
'--coverage',
|
||||
...workers.instrumented,
|
||||
...timeouts,
|
||||
], {
|
||||
label: 'test:coverage',
|
||||
env: { [COVERAGE_EXEMPT_ENV]: '1' },
|
||||
@@ -514,6 +526,7 @@ function coverageGates(): Gate[] {
|
||||
'run',
|
||||
...coverageExemptHeavySuites.map(suite => suite.filter),
|
||||
...workers.exempt,
|
||||
...timeouts,
|
||||
], {
|
||||
label: 'test:coverage-exempt-heavy',
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user