fix(test): keep E2E CI runs off the pool host's auth state (#14968) (#14972)

Co-authored-by: qwen-code-dev-bot <[email protected]>
This commit is contained in:
qwen-code-dev-botandqwen-code-dev-bot authored and GitHub committed 2026-10-21 10:37:46 +08:00
1 parent 68ba2fca59
commit ae65834aad
2 files changed
+89 -2

No files matched your search

+83
View File
@@ -229,3 +229,86 @@ describe('globalSetup hermetic qwen home', () => {
}
});
});
describe('globalSetup host config carry-over', () => {
let tmpRoot: string;
let homeDir: string;
let savedEnv: Map<string, string | undefined>;
beforeEach(async () => {
tmpRoot = await mkdtemp(join(tmpdir(), 'qwen-globalsetup-ci-'));
homeDir = await mkdtemp(join(tmpdir(), 'qwen-globalsetup-home-'));
savedEnv = new Map(
[...SETUP_ENV_KEYS, 'QWEN_HOME', 'HOME', 'CI', 'TMPDIR'].map((key) => [
key,
process.env[key],
]),
);
delete process.env['QWEN_HOME'];
process.env['HOME'] = homeDir;
process.env['TMPDIR'] = tmpRoot;
process.env['KEEP_OUTPUT'] = 'false';
process.env['QWEN_CODE_MODELS_DEV_REFRESH'] = 'on';
await mkdir(join(homeDir, '.qwen'), { recursive: true });
await writeFile(
join(homeDir, '.qwen', 'settings.json'),
JSON.stringify({ security: { auth: { selectedType: 'qwen-oauth' } } }),
'utf-8',
);
await writeFile(
join(homeDir, '.qwen', 'oauth_creds.json'),
'{"access_token":"host"}',
'utf-8',
);
});
afterEach(async () => {
for (const [key, value] of savedEnv) {
if (value === undefined) {
delete process.env[key];
} else {
process.env[key] = value;
}
}
vi.resetModules();
await rm(tmpRoot, { recursive: true, force: true });
await rm(homeDir, { recursive: true, force: true });
});
async function loadGlobalSetup() {
vi.resetModules();
return import('./globalSetup.js');
}
it('does not carry host auth state into the hermetic home on CI', async () => {
process.env['CI'] = 'true';
const { setup, teardown } = await loadGlobalSetup();
await setup();
const home = process.env['QWEN_HOME']!;
await expect(
readFile(join(home, 'settings.json'), 'utf-8'),
).rejects.toMatchObject({ code: 'ENOENT' });
await expect(
readFile(join(home, 'oauth_creds.json'), 'utf-8'),
).rejects.toMatchObject({ code: 'ENOENT' });
await teardown();
});
it('carries host config into the hermetic home outside CI', async () => {
delete process.env['CI'];
const { setup, teardown } = await loadGlobalSetup();
await setup();
const home = process.env['QWEN_HOME']!;
await expect(
readFile(join(home, 'settings.json'), 'utf-8'),
).resolves.toContain('qwen-oauth');
await expect(
readFile(join(home, 'oauth_creds.json'), 'utf-8'),
).resolves.toContain('host');
await teardown();
});
});
+6 -2
View File
@@ -93,13 +93,17 @@ let originalMemoryContent: string | null = null;
* the files without gambling on where CI's auth comes from.
*/
async function carryOverHostConfig() {
// CI supplies auth through the environment. A pool host's live settings can
// select an auth type that conflicts with the tests' credentials, failing
// every spawned CLI; keep CI runs independent of that state.
if (process.env['CI']) return;
for (const fileName of ['settings.json', 'oauth_creds.json']) {
await copyFile(
join(hostQwenDir, fileName),
join(hermeticQwenHome, fileName),
).catch(() => {
// Absent on CI and on a machine that has never run the CLI, and absent
// for whichever auth type the developer is not using.
// Absent on a machine that has never run the CLI, and absent for
// whichever auth type the developer is not using.
});
}
}