mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-09-11 19:46:21 +00:00
* perf(dev): add pnpm worktree bootstrap foundation Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(dev): harden worktree bootstrap process handling Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * perf(dev): prefer cache-only worktree installs Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(dev): preserve cached install cancellation Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(build): harden pnpm worktree bootstrap Validate pnpm lock updates in releases and exercise real installs and builds across supported hosts. Preserve npm release compatibility and keep dependency-only setup from rewriting npm-layout notices. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * chore: record merge attribution Record the required attribution for the Stage 1 merge without rewriting published history. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(dev): keep worktree bootstrap clean Use a bootstrap-scoped notice guard because nested npm lifecycle commands replace npm_lifecycle_event. This preserves explicit notice generation while preventing dependency setup from rewriting tracked output. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * ci: track pnpm smoke workflow size Register the new workflow in the repository size ratchet as required by the main CI gate. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(ci): drop stale importers from the new pnpm lockfile The lockfile was generated before the WebShell cutover (#9811) removed @qwen-code/webui from web-shell and the tailwind tooling plus @qwen-code/webui from vscode-ide-companion, so frozen-lockfile installs fail on all three smoke platforms with ERR_PNPM_OUTDATED_LOCKFILE. Drop the five stale importer entries so the lockfile matches the current package.json manifests; verified with pnpm 11.24.0 install --frozen-lockfile --lockfile-only. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(ci): refresh pnpm lockfile after merging main The merge of origin/main added remend@^1.3.1 to packages/cli/package.json without updating pnpm-lock.yaml, breaking the pnpm Worktree Smoke workflow frozen-lockfile install. Regenerated with pnpm install. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-conflict/jmtid3rse9h * fix(scripts): resolve the path variable case-insensitively on Windows A spread of process.env is an ordinary object, and native Windows shells expose the path variable as `Path`, so `env.PATH` was undefined there and findOnPath never located corepack — the offline-first Corepack bootstrap silently degraded to npx on exactly the hosts it exists for. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(scripts): pin the worktree bootstrap guards against mutation - Split the fallback log on /\r?\n/ like the sibling cmd.exe mocks, so the assertion holds on the Windows lane's CRLF output. - Add a win32 variant bootstrapping with the native `Path` casing to pin the case-insensitive lookup. - Assert the smoke workflow's fail-fast flag, the install-before-clean step order, and the no-build guard via a substring on the raw job text. - Extend the pnpmfile rewrite fixture to devDependencies and optionalDependencies, which the committed lockfile already uses. - Assert the notice-skip guard by effect (writeFile never called) and add the flag-absent companion test with I/O stubbed. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * chore(deps): sync pnpm-lock.yaml with qwen-live ACP backend deps Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-conflict/jmtjyz3tdco * fix(dev): stop patch-package from corrupting the pnpm store The root postinstall runs patch-package, which rewrites files under node_modules in place. With pnpm's default import method those files are hard links into the content-addressable store, so the patch rewrites the store entry too and its contents stop matching the sha512 it is filed under. Every subsequent fresh worktree then fails its --offline stage with ERR_PNPM_NO_OFFLINE_TARBALL, silently falls back to the registry (exit 0), and the fallback's postinstall corrupts the store again, so the offline path never hits. The advertised offline timing was only reachable on a same-tree reinstall, which needs no relinking. Set packageImportMethod to clone-or-copy: a copy-on-write clone where the filesystem supports it, a plain copy elsewhere. Either way patch-package edits only the worktree's own copy and the store entry stays intact, so later worktrees resolve entirely from the store. Verified on an isolated fixture store: under the default method the node_modules file and its store entry share an inode, and an in-place edit moves the store file's sha512 off its address, after which a fresh offline install fails with ERR_PNPM_NO_OFFLINE_TARBALL; under clone-or-copy the same edit leaves the store hash unchanged and the fresh offline install reports reused 1, downloaded 0. Also add pnpm-lock.yaml to .prettierignore. prettier reflows it into a shape pnpm does not emit, so `npm run format` and `pnpm install` fight over the file; .yamllint.yml already ignores it for the same reason. Both facts are pinned by tests in scripts/tests/package-scripts.test.js. Claude-Session: https://claude.ai/code/session_012797rgiteWJxLT9TLkKq8G * fix(ci): refresh pnpm-lock.yaml for qwen-live prompts deps Main added prompts/@types/prompts (and the ACP sdk) to packages/qwen-live/package.json after this branch generated its lockfile, so the pnpm Worktree Smoke frozen-lockfile install failed with ERR_PNPM_OUTDATED_LOCKFILE. Regenerated with pnpm 11.24.0 (--lockfile-only); frozen-lockfile and supply-chain policy checks pass. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-conflict/jmtlc9sozfg * fix(pnpm): close review findings on worktree bootstrap - Declare @qwen-code/qwen-code-core in vscode-ide-companion so the pnpm linker materializes it; regenerate both lockfiles and assert the link in the smoke workflow (R5-1) - Pin @types/node 20.19.1 in packages/core so the pnpm layout compiles against the same types npm hoists (D6-1) - Accept and pin the corepack +sha512 integrity suffix on packageManager; strip it for the npx fallback spec (D6-2) - Cover every workspace member in the pnpmfile rewrite set, mirror the npm channel list in pnpm-workspace.yaml, and cross-check both in tests - Run setup-worktree.js installs with cwd pinned to the checkout, gate the smoke clean-check on git status --porcelain, stop post-merge runs from cancelling each other, and extend check-lockfile.js to pnpm-lock.yaml * merge(main): realign pnpm workspace set and lockfiles Main removed the webui and cua-driver packages; drop both from the pnpm rewrite set and regenerate the pnpm lockfile against the merged manifests (picks up playwright, react-markdown, and the other main-side dependency changes) so the frozen bootstrap matches what the PR merge ref will run. * style(ci): quote smoke workflow scalars per yamllint * fix(dev): require Corepack for pnpm bootstrap * fix(dev): close pnpm bootstrap review blockers --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Co-authored-by: yiliang114 <jinjing.zzj@gmail.com>
113 lines
3.3 KiB
JavaScript
113 lines
3.3 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import fs from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
import { parse as parseYaml } from 'yaml';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const root = join(__dirname, '..');
|
|
const lockfilePath = join(root, 'package-lock.json');
|
|
|
|
function readJsonFile(filePath) {
|
|
try {
|
|
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
return JSON.parse(fileContent);
|
|
} catch (error) {
|
|
console.error(`Error reading or parsing ${filePath}:`, error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
console.log('Checking lockfile...');
|
|
|
|
const lockfile = readJsonFile(lockfilePath);
|
|
if (lockfile === null) {
|
|
process.exit(1);
|
|
}
|
|
const packages = lockfile.packages || {};
|
|
const invalidPackages = [];
|
|
|
|
for (const [location, details] of Object.entries(packages)) {
|
|
// 1. Skip the root package itself.
|
|
if (location === '') {
|
|
continue;
|
|
}
|
|
|
|
// 2. Skip local workspace packages.
|
|
// They are identifiable in two ways:
|
|
// a) As a symlink within node_modules.
|
|
// b) As the source package definition, whose path is not in node_modules.
|
|
if (details.link === true || !location.includes('node_modules')) {
|
|
continue;
|
|
}
|
|
|
|
// 3. Any remaining package should be a third-party dependency.
|
|
// 1) Registry package with both "resolved" and "integrity" fields is valid.
|
|
if (details.resolved && details.integrity) {
|
|
continue;
|
|
}
|
|
// 2) Git and file dependencies only need a "resolved" field.
|
|
const isGitOrFileDep =
|
|
details.resolved?.startsWith('git') ||
|
|
details.resolved?.startsWith('file:');
|
|
if (isGitOrFileDep) {
|
|
continue;
|
|
}
|
|
|
|
// Mark the left dependency as invalid.
|
|
invalidPackages.push(location);
|
|
}
|
|
|
|
if (invalidPackages.length > 0) {
|
|
console.error(
|
|
'\nError: The following dependencies in package-lock.json are missing the "resolved" or "integrity" field:',
|
|
);
|
|
invalidPackages.forEach((pkg) => console.error(`- ${pkg}`));
|
|
process.exitCode = 1;
|
|
} else {
|
|
console.log('Lockfile check passed.');
|
|
process.exitCode = 0;
|
|
}
|
|
|
|
console.log('Checking pnpm lockfile...');
|
|
|
|
const pnpmLockfilePath = join(root, 'pnpm-lock.yaml');
|
|
let pnpmLockfile;
|
|
try {
|
|
pnpmLockfile = parseYaml(fs.readFileSync(pnpmLockfilePath, 'utf-8'));
|
|
} catch (error) {
|
|
console.error(`Error reading or parsing ${pnpmLockfilePath}:`, error);
|
|
process.exit(1);
|
|
}
|
|
|
|
const invalidPnpmPackages = [];
|
|
for (const [key, details] of Object.entries(pnpmLockfile?.packages ?? {})) {
|
|
const resolution = details?.resolution ?? {};
|
|
// Registry packages carry a sha512 integrity hash; git and tarball
|
|
// resolutions identify their source directly, mirroring the npm rules
|
|
// above.
|
|
const hasIntegrity =
|
|
typeof resolution.integrity === 'string' &&
|
|
resolution.integrity.startsWith('sha512-');
|
|
const isGitOrTarball =
|
|
resolution.type === 'git' || typeof resolution.tarball === 'string';
|
|
if (!hasIntegrity && !isGitOrTarball) {
|
|
invalidPnpmPackages.push(key);
|
|
}
|
|
}
|
|
|
|
if (invalidPnpmPackages.length > 0) {
|
|
console.error(
|
|
'\nError: The following dependencies in pnpm-lock.yaml are missing "resolution.integrity":',
|
|
);
|
|
invalidPnpmPackages.forEach((pkg) => console.error(`- ${pkg}`));
|
|
process.exitCode = 1;
|
|
} else {
|
|
console.log('pnpm lockfile check passed.');
|
|
}
|