Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
4c78916
fix(ci): extend the vitest RPC-timeout exemption to every unit suite …
qwen-code-dev-bot Aug 28, 2026
a7888a3
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 29, 2026
fb2e4fd
refactor(ci): collapse duplicated vitest exemption rationale to witne…
qwen-code-dev-bot Aug 29, 2026
1aedd30
refactor(ci): extend vitest rationale pointer consolidation to remain…
qwen-code-dev-bot Aug 29, 2026
137371c
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 29, 2026
a255ac8
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 29, 2026
19dd7fb
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 29, 2026
4986343
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 29, 2026
f6c711d
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 29, 2026
d64b692
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 30, 2026
f035ce0
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 30, 2026
a0ce123
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 30, 2026
57faaf9
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 30, 2026
44025dd
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 30, 2026
7dbf485
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 31, 2026
b2cb164
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 31, 2026
b15a89e
Merge branch 'main' into autofix/issue-10438
qwen-code-dev-bot Aug 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions integrations/external-context-mem0/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});
2 changes: 2 additions & 0 deletions integrations/external-context/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R1-1: This PR pastes one verbatim 8-line block — a 7-line rationale comment plus dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux' — into 20 config files, joining the 4 pre-existing copies in packages/core, packages/cli, scripts/tests and integration-tests: 24 copies of one rationale with no shared module owning it. The copies had already started drifting before this PR — the integration-tests exemption also reads RUNNER_ENVIRONMENT, and the four pre-existing sites tell the story differently — and the new witness pins only the flag's boolean value, not the comment text or the expression form. When the exemption's rationale or condition next changes, a maintainer must locate and hand-edit all 24 sites in lockstep, and divergence between copies accumulates silently until then.

Cheapest fix that keeps each config self-contained: collapse the 7-line comment in every config to a one-line pointer at the full rationale (the witness test's header comment owns it), keeping the flag line itself per-config. A shared preset/constant is the deeper variant; it must allow the integration-tests override.

Witness:

sweep dangerouslyIgnoreUnhandledErrors over the tree at HEAD -> 24 config files
(20 added by this diff + 4 pre-existing)
drift: integration-tests/vitest.config.ts:46-48 carries
  process.platform !== 'linux' || process.env['RUNNER_ENVIRONMENT'] === 'self-hosted'
all 20 pasted copies carry
  process.platform !== 'linux'

Any shared-module variant must stay loadable from npm run test:ci --workspaces --if-present --parallel (root package.json:48) and respect AGENTS.md's no-relative-imports-between-packages rule; integration-tests/vitest.config.ts:47 legitimately uses a different expression, so a shared constant must allow that override.

中文说明

本 PR 把一个逐字相同的 8 行块 —— 7 行理由注释加上 dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux' —— 粘贴进 20 个配置文件,加上 packages/corepackages/cliscripts/testsintegration-tests 中已有的 4 份副本:同一段理由共 24 份副本,没有任何共享模块拥有它。这些副本在本 PR 之前就已开始漂移 —— integration-tests 的豁免还会读取 RUNNER_ENVIRONMENT,四处既有站点的叙述各不相同 —— 而新的见证测试只钉住该标志的布尔值,不钉注释文本或表达式形式。当该豁免的理由或条件下次变更时,维护者必须同步手工编辑全部 24 处,副本间的分歧在此之前会悄悄累积。

保持各配置自包含的最便宜修法:把每个配置中的 7 行注释折叠成指向完整理由的单行指引(完整理由由见证测试的头部注释拥有),标志行本身保留在各配置中。共享预设/常量是更深层的方案;它必须允许 integration-tests 的覆盖。

任何共享模块方案必须能从 npm run test:ci --workspaces --if-present --parallel(根 package.json:48)加载,并遵守 AGENTS.md 的“包之间不得相对导入”规则;integration-tests/vitest.config.ts:47 合理地使用了不同的表达式,因此共享常量必须允许该覆盖。

— qwen3.8-max via Qwen Code /review (v0.22.3)

},
});
2 changes: 2 additions & 0 deletions packages/acp-bridge/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export default defineConfig({
: undefined,
reporters: ['default'],
silent: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
Comment thread
qwen-code-dev-bot marked this conversation as resolved.
coverage: {
enabled: false,
provider: 'v8',
Expand Down
2 changes: 2 additions & 0 deletions packages/audio-capture/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ export default defineConfig({
test: {
environment: 'node',
include: ['src/**/*.test.ts'],
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});
2 changes: 2 additions & 0 deletions packages/channels/base/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});
2 changes: 2 additions & 0 deletions packages/channels/dingtalk/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
resolve: {
alias: {
Expand Down
2 changes: 2 additions & 0 deletions packages/channels/dws/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
resolve: {
alias: {
Expand Down
2 changes: 2 additions & 0 deletions packages/channels/feishu/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
resolve: {
alias: {
Expand Down
2 changes: 2 additions & 0 deletions packages/channels/github/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});
2 changes: 2 additions & 0 deletions packages/channels/gitlab/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});
2 changes: 2 additions & 0 deletions packages/channels/qqbot/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
server: {
deps: {
inline: ['@qwen-code/channel-base'],
Expand Down
2 changes: 2 additions & 0 deletions packages/channels/telegram/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});
2 changes: 2 additions & 0 deletions packages/channels/wecom/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
resolve: {
alias: {
Expand Down
2 changes: 2 additions & 0 deletions packages/channels/weixin/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export default defineConfig({
test: {
include: ['src/**/*.test.ts'],
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
resolve: {
alias: {
Expand Down
2 changes: 2 additions & 0 deletions packages/chrome-extension/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ export default defineConfig({
include: ['src/**/*.test.ts', 'scripts/**/*.test.js'],
environment: 'jsdom',
globals: true,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});
8 changes: 1 addition & 7 deletions packages/cli/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,7 @@ export default defineConfig({
__dirname,
'../../scripts/vitest-global-setup.js',
),
// The worker->main `onTaskUpdate` RPC runs on a 60s budget; under the
// resource pressure of the Windows/macOS runners a stall longer than that
// surfaces as an unhandled error and exits an all-green run red
// (observed deterministic for this suite on the Windows lane). Test
// failures still fail the run; only unhandled errors stop being fatal,
// and only off Linux — the ubuntu lane and Linux local runs keep the
// unhandled-error signal.
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
coverage: {
// CI consumes coverage only from the ubuntu lane (the upload and the
Expand Down
8 changes: 1 addition & 7 deletions packages/core/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,7 @@ export default defineConfig({
outputFile: {
junit: 'junit.xml',
},
// The worker->main `onTaskUpdate` RPC runs on a 60s budget; under the
// resource pressure of the Windows/macOS runners a stall longer than that
// surfaces as an unhandled error and exits an all-green run red (same
// failure class the cli and scripts suites hit on these lanes). Test
// failures still fail the run; only unhandled errors stop being fatal,
// and only off Linux — the ubuntu lane and Linux local runs keep the
// unhandled-error signal.
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
coverage: {
// CI consumes coverage only from the ubuntu lane (the upload and the
Expand Down
2 changes: 2 additions & 0 deletions packages/node-repl/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ export default defineConfig({
// Kernel integration tests spawn real Node child processes.
testTimeout: 60_000,
hookTimeout: 60_000,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});
2 changes: 2 additions & 0 deletions packages/sdk-typescript/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export default defineConfig({
},
testTimeout: testTimeoutMs,
hookTimeout: 10000,
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
resolve: {
alias: {
Expand Down
2 changes: 2 additions & 0 deletions packages/vscode-ide-companion/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export default defineConfig({
globals: true,
environment: 'node',
include: ['src/**/*.test.ts', 'src/**/*.test.tsx', 'scripts/**/*.test.js'],
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html', 'clover'],
Expand Down
2 changes: 2 additions & 0 deletions packages/web-shell/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export default defineConfig({
outputFile: {
junit: '../junit.xml',
},
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
coverage: {
provider: 'v8',
reportsDirectory: '../coverage',
Expand Down
6 changes: 5 additions & 1 deletion packages/webui/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { defineConfig } from 'vite';
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import { resolve } from 'path';
Expand Down Expand Up @@ -72,4 +72,8 @@ export default defineConfig(({ command }) => ({
minify: false,
cssCodeSplit: false,
},
test: {
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
}));
87 changes: 87 additions & 0 deletions scripts/tests/unit-vitest-configs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* @license
* Copyright 2026 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*/

import { describe, expect, it } from 'vitest';

import externalContextConfig from '../../integrations/external-context/vitest.config.js';
import externalContextMem0Config from '../../integrations/external-context-mem0/vitest.config.js';
import acpBridgeConfig from '../../packages/acp-bridge/vitest.config.js';
import audioCaptureConfig from '../../packages/audio-capture/vitest.config.js';
import channelsBaseConfig from '../../packages/channels/base/vitest.config.js';
import dingtalkConfig from '../../packages/channels/dingtalk/vitest.config.js';
import dwsConfig from '../../packages/channels/dws/vitest.config.js';
import feishuConfig from '../../packages/channels/feishu/vitest.config.js';
import githubConfig from '../../packages/channels/github/vitest.config.js';
import gitlabConfig from '../../packages/channels/gitlab/vitest.config.js';
import qqbotConfig from '../../packages/channels/qqbot/vitest.config.js';
import telegramConfig from '../../packages/channels/telegram/vitest.config.js';
import wecomConfig from '../../packages/channels/wecom/vitest.config.js';
import weixinConfig from '../../packages/channels/weixin/vitest.config.js';
import chromeExtensionConfig from '../../packages/chrome-extension/vitest.config.js';
import cliConfig from '../../packages/cli/vitest.config.js';
import coreConfig from '../../packages/core/vitest.config.js';
import nodeReplConfig from '../../packages/node-repl/vitest.config.js';
import sdkTypescriptConfig from '../../packages/sdk-typescript/vitest.config.js';
import vscodeCompanionConfig from '../../packages/vscode-ide-companion/vitest.config.js';
import webShellConfig from '../../packages/web-shell/vitest.config.js';
import webuiConfig from '../../packages/webui/vite.config.js';
import scriptsTestsConfig from './vitest.config.js';

// Every vitest project that `npm run test:ci` runs on the Windows/macOS
// platform lanes carries the off-Linux unhandled-error exemption: vitest's
// worker->main `onTaskUpdate` RPC has a fixed 60s budget, and under runner
// resource pressure a stall longer than that exits an all-green run red
// (the nightly failure class behind #10438 and its predecessors). This
// witness pins the flag in every guarded config so removing it from any
// one of them fails the scripts suite on every platform.
type ExemptionConfig = {
test?: { dangerouslyIgnoreUnhandledErrors?: boolean };
};

const configs: Record<string, ExemptionConfig> = {
'integrations/external-context': externalContextConfig,
'integrations/external-context-mem0': externalContextMem0Config,
'packages/acp-bridge': acpBridgeConfig,
'packages/audio-capture': audioCaptureConfig,
'packages/channels/base': channelsBaseConfig,
'packages/channels/dingtalk': dingtalkConfig,
'packages/channels/dws': dwsConfig,
'packages/channels/feishu': feishuConfig,
'packages/channels/github': githubConfig,
'packages/channels/gitlab': gitlabConfig,
'packages/channels/qqbot': qqbotConfig,
'packages/channels/telegram': telegramConfig,
'packages/channels/wecom': wecomConfig,
'packages/channels/weixin': weixinConfig,
'packages/chrome-extension': chromeExtensionConfig,
'packages/cli': cliConfig,
'packages/core': coreConfig,
'packages/node-repl': nodeReplConfig,
'packages/sdk-typescript': sdkTypescriptConfig,
'packages/vscode-ide-companion': vscodeCompanionConfig,
'packages/web-shell': webShellConfig,
'scripts/tests': scriptsTestsConfig,
};

describe('unhandled-error exemption on the platform lanes', () => {
for (const [name, config] of Object.entries(configs)) {
it(`keeps unhandled errors fatal only on Linux in ${name}`, () => {
// toBe, not toBeFalsy: a deleted flag is `undefined` and must fail
// this pin on every platform, including Linux where the value is false.
expect(config.test?.dangerouslyIgnoreUnhandledErrors).toBe(
process.platform !== 'linux',
);
});
}

it('keeps unhandled errors fatal only on Linux in packages/webui', async () => {
// webui's vitest configuration is the function-form vite.config.ts.
const config = await webuiConfig({ command: 'serve', mode: 'test' });
expect(config.test?.dangerouslyIgnoreUnhandledErrors).toBe(
process.platform !== 'linux',
);
});
});
8 changes: 1 addition & 7 deletions scripts/tests/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,7 @@ export default defineConfig({
// the host cores, which is what every other suite in this repository
// uses.
//
// The long fake-timer suites here stall a worker's event loop long
// enough for vitest's worker->main `onTaskUpdate` RPC to hit its 60s
// timeout and surface as an unhandled error — with every test in the
// suite green, yet the run exiting 1 (observed deterministic on the
// macOS runners). Test failures still fail the run; only unhandled
// errors stop being fatal, and only off Linux — the ubuntu lane and
// Linux local runs keep the unhandled-error signal.
// RPC-timeout exemption; see scripts/tests/unit-vitest-configs.test.ts.
dangerouslyIgnoreUnhandledErrors: process.platform !== 'linux',
},
});
Loading