mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
main
11
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
aaf523cfc4 |
fix(ci): probe the apt mirror so mainland E2E hosts can build the sandbox image (#16218)
* fix(ci): probe the apt mirror so mainland E2E hosts can build the sandbox image The docker E2E leg builds the sandbox image per push under a SHA-scoped tag, so on any host whose image store no longer holds a recent build, the two apt-get layers are downloaded again. deb.debian.org serves the Hong Kong hosts at MB/s and the mainland-China hosts at 11-20 kB/s, which turns that build into 2-3 hours against the job's 60-minute cap. Over the past week 97 of 127 docker legs on the ecs-qwen-hz* hosts were cancelled this way, and the run reports `cancelled` instead of a verdict. Probe rather than pin a mirror or a host-name map: the build measures deb.debian.org and two domestic mirrors, and passes --build-arg APT_MIRROR only when the default is slower than 250 kB/s and a mirror beats it by 4x. The image keeps deb.debian.org as its default source, so release builds, local sandbox builds and the healthy Hong Kong hosts are unchanged, and no fleet inventory needs to be maintained. The probe's measurements are logged, so the next slow build can be diagnosed from its own output. Refs #16214 * fix(ci): require an absolutely fast mirror before overriding the apt source The relative guard alone only asked a mirror to be 4x faster than the default, so on a host where both endpoints were slow the mirror still "won" and moved the host onto a source it never needed. Require 1 MB/s in absolute terms too: below that the build is slow either way, and the extra cache key is not worth it. * test(ci): pin the apt-probe threshold values, not just the gate structure The new contract test asserted the gate variables and comparisons but not their values: mutating slow_default 10x up or fast_mirror 10x down left the suite green while flipping the both-slow host shape onto a still-slow mirror (review finding on #16218). Pin both literals with a word boundary — a plain substring pin would still match the 10x-up mutation — and witness both mutations reddening the suite before restoring the values. * test(ci): require the mirror ARG in both Dockerfile stages A single-match assertion survived deleting the runtime-stage ARG APT_MIRROR (R1-1, mutation-witnessed by review): the builder declaration satisfied the regex while the runtime apt layer silently kept the slow default. Count both declarations instead; deleting either stage's ARG now reddens the suite. |
||
|
|
1ac4f6cd1b |
fix(sandbox): install fonts-dejavu-core in the runtime image (#16032)
The capture card renderer in scripts/verify-capture.mjs requests DejaVu Sans Mono, but the runtime image installs no font packages at all. Patrol-Run: qwen-issue-patrol/jmvx4obxsrz Co-authored-by: yiliang114 <[email protected]> Co-authored-by: Qwen-Coder <[email protected]> Co-authored-by: Shaojin Wen <[email protected]> |
||
|
|
64dd058c9c |
ci(pnpm): install with pnpm everywhere and retire package-lock.json (#11859)
* ci(pnpm): install dependencies with pnpm in CI and release CI tests the graph release ships only if both install it the same way, so this moves both, keeping every `npm run` script and `npm publish` as they are. - ci.yml (7), release.yml (3) and release-vscode-companion.yml (2) install with `corepack pnpm install --frozen-lockfile`; release keeps --ignore-scripts plus its explicit postinstall and generate steps. - setup-node drops the npm cache and sets package-manager-cache: false, which setup-node v5+ needs once package.json declares a pnpm packageManager. - A composite action caches the pnpm store on the three always-hosted jobs; the ECS pool keeps its store on local disk. - version.js no longer lets npm reify node_modules: --no-workspaces-update on both `npm version` calls, and a package-lock-only refresh in step 9. - The notices generator, prepare-package's sharp pin and the standalone release's native package specs read the installed tree or pnpm-lock.yaml instead of package-lock.json keys. - New size baselines for the three workflows, which were already over them. * chore(vscode): regenerate NOTICES from the pnpm-installed tree Generated in CI (pnpm Worktree Smoke on ubuntu-latest) by the ported generator. Same entry set as before except the five packages npm and pnpm resolve differently: fdir 6.5.0, picomatch 4.0.5, mdurl 2.1.0, @types/node 22.20.1 and mime-db 1.52.0 (form-data's pinned copy). No entry lacks a license text or repository. * fix(pnpm): resolve undeclared zod peers to the repo's zod, as npm does The first CI run on this branch failed the export renderer's size budget: 1,930,015 bytes against 1,930,000, where the same commit built on npm's tree comes to 1,858,186. Comparing both trees' esbuild metafiles and prebuilt bundles put the whole difference in web-shell's transcript.js (+100,903 bytes pre-minify), and the added code is zod 4 plus the @modelcontextprotocol/ext-apps schemas; the sdk daemon bundle is identical. web-shell bundles ext-apps, whose zod and MCP SDK are peers, and declares no zod itself, so pnpm filled the peer with the highest locked zod (4.4.3) while npm serves the hoisted 3.25.76. Declaring zod 3.25.76 as a root devDependency makes pnpm resolve every such peer to it (resolve-peers-from-workspace-root is on by default), which is npm's hoisting behaviour. mobile-mcp keeps its own zod 4.4.3, as under npm; the npm tree does not change. * fix(pnpm): keep npm's root @types/node so root-level typechecks match The no-AK integration gate typechecks integration-tests/, which takes Node's types from the root node_modules. npm hoists @types/node 20.19.1 there, because acp-bridge and core pin it; pnpm, with no root declaration, hoisted 22.20.1, whose spawnSync overloads type process-registry.ts's stdout as string | NonSharedBuffer and fail TS2322. The same code passes on every npm-installed PR. Declaring 20.19.1 as a root devDependency puts npm's copy back where a root-level tsconfig looks. The npm tree does not change. * ci(pnpm): install with pnpm in the remaining workflows The follow-up to switching CI and release: every other workflow that installs the root workspace now uses the pinned pnpm with --frozen-lockfile, so no job tests a graph that release does not ship. - e2e, tui-parity, repo-hygiene, web-shell-visuals, serve-ab, sdk-java, windows-runner-smoke, qwen-autofix, the SDK releases, finalize-release, sync-release-to-oss, the root install in desktop-release and cd-cua-driver, and the sandbox Dockerfile. - setup-node drops the root npm cache (package-manager-cache: false); hosted jobs restore the pnpm store through the shared composite action, and qwen-autofix keeps af-012's rule that the persistent pool restores no remote cache. - serve-ab and web-shell-visuals install a separate base checkout that can predate pnpm-lock.yaml, so those installs fall back to npm ci there. - Out of scope, unchanged: packages with their own lockfile (cua-driver's TypeScript SDK, desktop-shell, live-host, mobile-mcp), and the triage lanes with npm-cache.yml and the npm audit gate, which move with the package-lock.json retirement. - New size baselines for the touched workflows; qwen-autofix stays under the 470000-byte gate. * fix(pnpm): link the workspace packages that root-level code imports npm links every workspace package into the root node_modules, so integration-tests/ and scripts/, which are not workspace packages themselves, can import @qwen-code/* by name. pnpm links a workspace package only where it is a declared dependency, and the root declared none, so the no-AK integration gate could not find @qwen-code/qwen-code-core. The root now declares the seven packages that root-level code imports at runtime as file: devDependencies: acp-bridge, channel-base, the CLI, core, sdk, web-shell and web-templates. npm already links them, so its tree does not change (letting npm re-resolve the lock reproduces the same root entry); .pnpmfile.mjs rewrites them to workspace:*, which pnpm links at the root. * ci(pnpm): move triage, the store producer and the root audit to pnpm - qwen-triage's verify and tmux-testing lanes install the PR with `corepack pnpm install --frozen-lockfile` from a restored pnpm store. The one retry clears node_modules first, because pnpm install, unlike npm ci, keeps it. - npm-cache.yml becomes pnpm-store.yml, keyed on pnpm-lock.yaml. - security-checks audits the root workspace with `pnpm audit`, which reads the lockfile, so the root install step goes. The vendored lockfiles keep npm, and the retry recognises pnpm's endpoint error too. - qwen-autofix drops the hosted-only store cache: its heavy jobs forbid local `uses: './...'` actions, and the file sits at the size gate. - cd-cua-driver: setup-node@v4 has no package-manager-cache input. - package-assets fixtures install sharp rather than listing it in package-lock.json, matching how prepare-package now resolves it. - AGENTS.md, CONTRIBUTING.md and the npm workspace guide install with pnpm. * feat(review): install pnpm repos in qwen review's build/test qwen review installed dependencies only for a repo with package-lock.json and reported a pnpm repo as unsupported, so reviews of qwen-code would lose their build and test once its npm lockfile goes. - lockfileInstaller() picks npm or pnpm from the committed lockfile. With both, `packageManager: pnpm@...` chooses pnpm; anything else keeps npm. - A pnpm repo installs with `corepack pnpm install --frozen-lockfile` through the same disk, budget and sandbox path as `npm ci`, and counts as installed once node_modules/.modules.yaml exists. - Scripts still run through `npm run`, and the npm path is unchanged. * ci(pnpm): retire the root package-lock.json pnpm-lock.yaml is now the only root lockfile. - check-lockfile keeps the pnpm integrity check and Playwright parity, which now reads pnpm importers and snapshots. The npm-vs-pnpm agreement and build-approval checks go: pnpm 11's strictDepBuilds and every CI install's --frozen-lockfile enforce what they covered. - pnpm-lock-freshness.yml goes; it regenerated pnpm-lock.yaml from package-lock.json. - Release: version.js drops its package-lock refresh, the release commit stages pnpm-lock.yaml and the SDK release stages no lockfile, so neither `git add` fails on the missing file. `npm version` in the SDK and mobile-mcp releases passes --no-workspaces-update so it cannot reinstall the root with npm. - cd-mobile-mcp installs from the root pnpm lockfile. setup-node in cd-mobile-mcp, qwen-code-pr-review and desktop-release no longer keys an npm cache on the root lockfile. - check-desktop-isolation reads pnpm importers; build.js, build_sandbox.js and preflight install with pnpm. - pnpm-lock.yaml, pnpm-workspace.yaml and .pnpmfile.mjs join the autofix supply-chain class and repo-hygiene's deny list; pnpm-lock.yaml joins autofix's generated-diff exclusions, sdk-java's path filter and the platform-sensitivity manifests. - .gitignore lists /package-lock.json so an npm install cannot commit it back. Tests and docs follow. * fix(standalone): read the node-pty versions from the pnpm lockfile * chore(vscode-ide-companion): regenerate NOTICES.txt after the lockfile swap * chore(vscode-ide-companion): regenerate NOTICES.txt from the pnpm dependency tree The committed NOTICES.txt was generated from an npm install and does not match the tree produced by the pnpm install the release pipeline now uses (659 resolved dependencies, differing @types/node and mime-db versions). Regenerating with the pinned pnpm install makes the freshness check reproducible. * fix(ci): drop the npm cache from the daily dependency audit actions/setup-node's npm cache keys off the root package-lock.json, which this branch retires, so the scheduled job would fail at Set up Node before the audit ran. No pull_request run reaches this workflow to catch it. The root tree is never installed here either: pnpm audit reads pnpm-lock.yaml directly. Matches the sibling workflows that already set package-manager-cache: false; scripts/tests/security-workflows.test.js now pins it. * chore(ci): stop banking main-side drift in the workflow size ratchet The ratchet exists to turn a workflow's growth into one reviewed line. This branch re-recorded entries for 17 workflows it never touches, several upward by 0.4-2.8 KB - drift that happened on main, banked into the manifest without review. Restore those to their merge-base values, so .size-baseline changes only for the 22 workflows this branch actually edits. The entries were not needed to go green: ci.yml passes the PR's base commit, so a file that drifted on main and is otherwise untouched earns a warning, not a failure. * fix(release): initialize standalone state before main * test(browser-use): read Playwright pin from pnpm lock * fix(ci): address pnpm migration review blockers * fix(desktop): stop reading the retired root lockfile --------- Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
1273fe2295 |
fix(ci): route release pipeline Linux jobs to the ECS runner pool (#10036)
* fix(ci): route release pipeline Linux jobs to the ECS runner pool
* fix(ci): restore ECS workspace before release checkout
Co-authored-by: Qwen Code <[email protected]>
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): record release workflow growth
The ECS routing and workspace ownership guards intentionally grow release.yml beyond the workflow-size ratchet allowance.
Co-authored-by: Qwen Code <[email protected]>
Co-authored-by: Qwen-Coder <[email protected]>
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): isolate release jobs on shared runners
Co-authored-by: Qwen-Coder <qwen-coder @alibabacloud.com>
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): bound shared release runner work
Disable redundant setup-node cache transfers on the persistent ECS pool and add explicit timeouts for the remaining shared-pool jobs. Pin both contracts in the release workflow test.\n\nCo-authored-by: Qwen-Coder <qwen-coder @alibabacloud.com>
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): harden the release wipe and pin the docker preflight fail-closed
Port the sibling wipe guards (realpath canonicalization, symlink heal,
root denylist, runner-workspace containment) onto all five release wipe
copies, remove planted user-level state the workspace wipe cannot see
(~/.npmrc script-shell, global git exec keys) with the qwen-autofix
pre-checkout denylist, and make the docker preflight print docker's own
error output before failing closed.
Co-authored-by: Qwen-Coder <qwen-coder @alibabacloud.com>
* test(ci): pin the canonical release wipe byte-identical at index 0
Replace substring tripwires with full-string equality against the shared
canonical wipe constant and require the step to stay first, so a
commented-out find, an inserted early exit, or a uniformly dropped
ownership ladder fails review instead of shipping green. Pin the docker
preflight's full fail-closed form (captured daemon output printed,
exit 1) so deleting the exit or inverting the guard fails the suite.
Co-authored-by: Qwen-Coder <qwen-coder @alibabacloud.com>
* fix(ci): deduplicate release runner cleanup
* fix(ci): keep the release failure notifier on hosted runners
notify_failure exists to report failures of the ECS pool, so routing it
onto that same pool wedges the alert chain in exactly the post-claim
failure modes it fires for (runner crash, host loss, pool-wide outage).
The job is gh/jq-only (both preinstalled on hosted images); pin it to an
ephemeral ubuntu-latest runner like the sibling failure notifiers
(release-sdk.yml, release-sdk-python.yml, release-vscode-companion.yml,
and qwen-code-pr-review.yml's fallback comment).
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): pin the release lanes' conditional ECS runs-on
No test pinned the migration itself: reverting any routed release job to
a hosted runner, or dropping the MAINTAINER_ECS_RUNNER_DISABLED clause,
shipped green. Pin each routed job's exact runs-on expression
(repository guard + kill switch + both branches) and the notifier's
hosted pin, matching qwen-autofix-workflow.test.js's tripwire style.
Verified by mutation: reverting prepare's runs-on to ubuntu-latest or
dropping the kill-switch clause now fails release-workflow.test.js.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): keep release publishing on hosted runners
* fix(ci): fail closed on release git scrub
* fix(ci): scrub ambient GIT_CONFIG_GLOBAL from the release wipe test
Mirror the sibling scrub harness in qwen-autofix-workflow.test.js: delete GIT_CONFIG_GLOBAL from the child env before spawning git, so setHook() and the post-scrub 'git config --global' assertion operate on the synthetic HOME instead of leaking through an ambient global config file.
Co-authored-by: Qwen-Coder <[email protected]>
* test(ci): add behavioral tests for workspace wipe guard branches
Drive the wipe half of canonicalWipe against fixtures so its guard
branches (symlink heal, realpath canonicalization, runner-workspace
allowlist) are executed, not just pinned by string equality:
- Happy path: leftover files are removed
- Symlink heal: symlinked workspace is removed and recreated
- Outside runner workspace: refused with error
- Path with '..': realpath resolves inside runner workspace, wipe proceeds
* fix(test): gate wipe behavioral test on GNU realpath, fix '..' path and heal assertions
- Add hasGnuRealpath capability probe and skip the behavioral wipe test
on non-GNU hosts (macOS BSD realpath lacks -m) and under root (uid 0
bypasses permission bits), matching the pattern used by every sibling
suite that executes this script lineage.
- Use string concatenation instead of path.join for the '..' sub-case so
the literal '..' segment reaches the script (path.join normalizes it
away, making the test equivalent to the happy path).
- Create a real decoy target file for the heal sub-case and assert it
survives the wipe, verifying that rm -f removes only the symlink
itself and does not follow/delete the target.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): guard chmod -R against symlinked workspace before validation
The recursive chmod ran on the raw $GITHUB_WORKSPACE before the
heal/canonicalize/guard block. GNU chmod -R follows a symlink given
as its starting operand, so a previous pool job that replaced the
workspace with a symlink would cause the chmod to descend into the
link target. Add a [-L] guard that skips chmod when the workspace
is not a real directory; the heal block below restores it before
the wipe runs.
Also plant a subdirectory in the behavioral wipe test's happy-path
fixture so recursive directory removal — the wipe's core property —
is actually exercised (R5-9).
Fixes R5-2, R5-9.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): bump release.yml size baseline to accommodate ECS runner changes
The check-workflow-size gate was 158 bytes short — release.yml at 52271
exceeded the old baseline (48017) + allowance (4096) = 52113 ceiling.
Raise the baseline to 48500 so the gate passes with headroom.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(test): create the sub directory in the wipe '..' sub-case setup
The '..' wipe sub-case drives the script at ${base}/sub/../workspace
without creating sub, so the heal block's mkdir fails ENOENT and the
payload exits 1 (fail-closed) while the test asserts 0. Create sub in
the setup so the path resolves and the suite goes green.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): skip ECS cleanup on hosted release jobs
* fix(ci): isolate persistent release runner state
* fix(ci): accept the pool's sibling tool cache in the release wipe
The wipe's tool-cache containment required RUNNER_TOOL_CACHE inside
RUNNER_WORKSPACE, but the standard self-hosted geometry the ecs-qwen
pool uses is a sibling (<root>/_work/_tool vs <root>/_work/qwen-code),
so every routed release job died at step 1. Anchor the containment to
the runner work root (allow the sibling _tool, keep refusing every
other outside path), and split Node setup the way ci.yml does: pool
runs reuse the machine's Node because the purge above empties the tool
cache and nodejs.org may be unreachable through the ECS egress proxy;
the hosted fallback keeps actions/setup-node.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): refuse a symlinked runner workspace before the release wipe
The wipe canonicalized RUNNER_WORKSPACE THROUGH symlinks, so a prior
pool job could plant _work/qwen-code -> /target and redirect the heal,
the containment allowlist, and the recursive rm to an attacker-chosen
location; the chown/chmod ladder additionally ran on the raw,
unvalidated path before any check. Refuse a symlinked runner workspace
outright and move the ownership/permission ladder after the geometry
validation so refused paths get no changes at all.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): isolate gh config from the persistent pool HOME
The isolation block redirected Git, npm, and Docker config away from
the attacker-writable persistent $HOME but not gh's, and prepare runs
gh with the job token on the pool. A prior pool job can plant
~/.config/gh with http_unix_socket and capture the token, the way
qwen-autofix.yml already defends against with a fresh GH_CONFIG_DIR.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): digest-pin the sandbox base image
Routing integration_docker onto the shared pool exposes the build to
the pool's persistent docker daemon store: a co-resident job can
pre-tag a poisoned image as node:22-slim, and an unpinned FROM
resolves against the local store with zero registry contact. Pin both
stages to the node:22-slim index digest (verified against two
independent registry mirrors) and pin the requirement in
release-workflow.test.js.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): ratchet the release.yml size baseline for the pool hardening
The pool security hardening (sibling tool-cache containment, symlinked-workspace refusal, GH_CONFIG_DIR isolation, and the hosted/self-hosted Node split across the four routed jobs) grew release.yml from 48500 to 54000 bytes — 5500 over the recorded baseline, past the 4096 allowance. The growth is real and deliberate: the attacker-model comments must stay next to the wipe steps they document, and the Node split repeats a small step block per job. Bump the ratchet per check-workflow-size.sh's own contract.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): reap cross-job processes and keep the pool tool cache in the release wipe
Round 9 R1-1: the pre-checkout isolation was a one-shot file-state sweep;
a detached postinstall child of a previous pool job (self-hosted runners do
not reap job processes) waits it out and tampers with the fresh tree while
secret-bearing steps run. Extend the restore step with qwen-triage.yml's
process-reap doctrine: kill every live process of the runner user outside
the runner agent's own tree (PPID-chain exclusion, zombies ignored), retry,
and fail closed naming any survivor.
Round 9 R7-4 (fix-induced): the round-8 geometry fix armed the
${RUNNER_TOOL_CACHE}/node purge on the pool, stripping the pool-wide Node
that five lanes in qwen-autofix.yml, serve-ab.yml and repo-hygiene.yml
resolve through un-gated setup-node, while the pool-routed release jobs
never read the tool cache. Drop the purge; document the pool-wide cache as
deliberately untouched.
Tests: canonicalWipe mirror regenerated byte-for-byte; the pool-geometry
sub-case now asserts _tool/node survives; new behavioral witnesses reap an
orphaned process and fail closed on an unkillable survivor (mutation-verified:
reap-condition inversion and purge re-addition both redden the suite; reap
leg exercised as a non-root user with orphan reap and stubbed unkillable
survivor probes).
Co-authored-by: Qwen-Coder <qwen-coder @alibabacloud.com>
* fix(ci): keep the release wipe suite green and kill-free on the pool
The round-4 behavioral suite goes red in non-root CI for three reasons:
1. The happy-path sub-case still asserted the tool-cache purge the
round-4 commit deliberately removed (the pool geometry sub-case was
flipped to expect _tool/node survival, the happy path was not).
Flip it to expect survival: the sweep is scoped to the workspace.
2. Every runWipe guard-branch sub-case (happy path, symlink heal, pool
geometry, '..' canonicalization) executed the genuine reap, which
kills every live process of the runner user outside the step's
ancestor tree — on the shared ECS pool that reaches into whatever
job is co-resident on the same member. Give those cases a ps stub
that lists nothing so the reap branch executes end to end yet kills
nothing; R1-1 keeps the one genuine reap probe, clearly marked.
3. The R1-1 orphan spawn inherited the spawnSync stdio pipes, so the
spawn blocked until the 30s sleeper exited and the test timed out
before the wipe even ran. Redirect the sleeper's stdio to /dev/null.
Verified: root run 23 passed / 1 skipped (behavioral suite skips by
design under root); a dedicated uid-1002 run passes all 24 tests with
the behavioral suite executing in ~6s.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(ci): keep concurrent registrations' jobs out of the release reap
The round-9 reap roots its keep set at this shell's ancestor chain
alone. One pool member hosts every registration under this same uid
(qwen-autofix.md af-014 documents ~27 registrations on one HOME), so a
concurrent job dispatched through another registration never reaches
that chain: the reap SIGKILLs its worker and processes mid-flight, and
a process (re)appearing during the retry window then fails the release
itself through the fail-closed survivor check.
Widen the keep set to every runner-agent tree of the user (runsvc.sh /
RunnerService / Runner.Listener / Runner.Worker roots). A process is
still killed when it is detached from ALL agent trees, which is the
documented shape of a cross-job leftover; concurrent jobs of other
registrations are spared. The canonicalWipe mirror carries the same
change byte-for-byte, the suite gains a disjoint-tree witness (a real
bystander parented under a second registration's tree must survive the
wipe while a genuine detached orphan dies), and the size ratchet moves
54000 -> 58255 per check-workflow-size.sh's same-PR contract.
Co-authored-by: Qwen-Coder <qwen-coder @alibabacloud.com>
* fix(ci): stop the R1-1 reap probe from enumerating the pool host
The R1-1 case was the suite's one deliberate real-reap probe: it ran
the wipe against the real ps, so every pool run of the suite (the
quality job this PR routes to the ECS pool runs test:scripts) listed
every live process of the runner user and SIGKILLed whatever sat
outside the test's ancestor tree — co-resident jobs' processes under
the shared pool uid included. It was also flaky-red by measurement: a
transient same-uid process during the reap window failed the
fail-closed leg on a machine with no co-resident jobs at all.
Stub ps the way the sibling cases do, but keep the probe genuine: the
live-listing arm prints only the test's own orphan (tracking reality
via kill -0, the way the real ps does once the orphan dies), so the
real SIGKILL path still runs end to end on a real detached sleeper
while the host is never enumerated. Mutating the orphan line away
makes the kill assertion go red.
Co-authored-by: Qwen-Coder <qwen-coder @alibabacloud.com>
* fix(ci): keep the release wipe suite off the hosted Windows lane
The behavioral wipe test gates on hasGnuRealpath and a non-root uid,
but that gate opens on the hosted Windows lane: Git for Windows ships
usr/bin/realpath.exe (GNU coreutils, -m works) and the installer adds
usr/bin to PATH (PathOption=CmdTools), so hasGnuRealpath is true on
windows-2022 — exactly the fallback lane ci.yml's test_windows runs
whenever MAINTAINER_ECS_RUNNER_DISABLED=true, a mode this PR
documents and pins. PortableGit ships no setsid, though, so the reap
fixture never writes its pid file there and readFileSync(pidFile)
throws ENOENT, turning the merge_group-gated lane red.
Add process.platform === 'win32' to the gate, the pattern this file
already uses for its other bash-driven case; the suite's YAML-parse
coverage keeps running on Windows.
Co-authored-by: Qwen-Coder <qwen-coder @alibabacloud.com>
* fix(ci): remove unsafe shared-runner process reaping
Keep release validation on the conditional ECS lane while limiting workflow cleanup to job-owned filesystem state.
Co-authored-by: Qwen-Coder <[email protected]>
* chore(ci): drop prettier reflow noise from teamHelpers.test.ts
Restore the type-annotation formatting from origin/main so this PR
contains zero non-CI hunks. CI's prettier step is write-only
(prettier --write ., no drift check), same as main carries today,
so this revert is CI-neutral.
Co-authored-by: Qwen-Coder <qwen-coder @alibabacloud.com>
* fix(ci): re-arm the release.yml size ratchet at its true floor (#10036)
The reap removal (
|
||
|
|
c7de1d7b7c |
perf(ci): cut the E2E suite from ~40min to ~24min (#7798)
* perf(ci): shard the E2E suite and stop building it twice per job A full E2E run took about 40 minutes, twice the median gap between merges on main, so the post-merge suite could never keep up with the merge rate. Two thirds of that was avoidable work. Every job installed dependencies with the default `prepare` behaviour, which builds and bundles the whole workspace, and then ran explicit build and bundle steps that did it all a second time — about 3.5 minutes on Linux and 5 on macOS. The docker leg additionally let the sandbox script re-run install, build, bundle and pack on the host before building the image, none of which the image consumes: its Dockerfile rebuilds and packs inside its own builder stage. The remaining cost is the test run itself, which is now split across shards: three for each Linux sandbox mode and two for macOS. Vitest assigns files to shards by path hash, so the long tail of slow sdk-typescript files spreads out rather than clustering in one shard; replaying the last green run's per-file timings through that algorithm puts the slowest shard at about 6 minutes against the 16 to 25 minutes each leg used to spend. The matrix no longer fails fast either, because a cancelled sibling shard would hide most of the suite and report an incomplete failure set. Expected wall clock per run drops from about 40 minutes to about 24, with the sandbox image build — 13 minutes, now paid once per docker shard — as the largest remaining item and the obvious next target via Docker layer caching. * fix(ci): set QWEN_SANDBOX=docker on the sandbox image build step (#7798) Co-authored-by: Qwen-Coder <[email protected]> * fix(ci): quote the sandbox env value so yamllint passes The value added for the image build step was unquoted, which the repository's quoted-strings rule rejects, and note why the variable is needed at all. * fix(ci): stream docker build output in the sandbox image step (#7798) * fix(ci): skip duplicate build in sandbox image npm ci (#7798) The Dockerfile builder stage runs npm ci followed by explicit build and bundle steps. npm ci triggers the prepare script, which builds and bundles the whole workspace — duplicating the two steps that follow. Set QWEN_SKIP_PREPARE=1 on the npm ci so prepare only generates git-commit.ts, matching the same fix already applied to the host CI install steps. --------- Co-authored-by: Qwen Code <[email protected]> Co-authored-by: Qwen-Coder <[email protected]> Co-authored-by: qwen-code-dev-bot <[email protected]> Co-authored-by: Qwen Code Bot <[email protected]> |
||
|
|
cadda23782 |
chore(deps): upgrade ink 6.2.3 → 7.0.2 + bump Node engine to 22 (#3860)
* chore(deps): upgrade ink 6.2.3 -> 7.0.2 + bump Node engine to 22
ink 7 requires Node >=22 and react-reconciler 0.33 with React >=19.2,
so this PR also bumps:
- Node engines (root + cli + core) 20 -> 22
- React/react-dom 19.1 -> 19.2.4 (pinned exact via overrides to keep
the transitive React graph deduped to a single instance)
- @types/node pinned to 20.19.1 via overrides to avoid an unrelated
Dirent NonSharedBuffer regression in sessionService tests
- @vitest/eslint-plugin pinned to 1.3.4 to avoid an unrelated lint
regression introduced by the 1.6.x rule additions
- react-devtools-core 4.28 -> 6.1 (ink 7 peerOptional requires >=6.1.2)
- ink hoisted to root devDeps so workspace-private peer-dep contention
doesn't push ink-link/spinner/gradient into nested workspace
installs (which would skip transitive resolution for terminal-link)
Workflow + image + installer alignment:
- .nvmrc 20 -> 22
- Dockerfile node:20-slim -> node:22-slim
- CI test matrix drops 20.x (keeps 22.x + 24.x)
- terminal-bench workflow Node 20 -> 22
- Linux/Windows install scripts upgrade their Node version targets
Documentation alignment:
- README.md badge + prerequisites
- AGENTS.md, CONTRIBUTING.md, docs/users/quickstart.md,
docs/users/configuration/settings.md, docs/developers/contributing.md,
docs/developers/sdk-typescript.md, docs/users/extension/extension-releasing.md,
packages/sdk-typescript/README.md, packages/zed-extension/README.md,
scripts/installation/INSTALLATION_GUIDE.md
Test gating:
- Two AuthDialog/AskUserQuestionDialog tests that drive <SelectInput>
through ink-testing-library now race ink 7's frame-throttled input
delivery and land on the wrong option. The maintainers had already
marked one of them unreliable (skip on Win32 + CI+Node20). Extend
that gate to cover all environments until upstream
ink-testing-library ships an ink-7-compatible release that flushes
input deterministically. The other test now uses it.skip with the
same comment. No business code changes.
Verified locally:
- npm run typecheck across all workspaces: clean
- npm run lint (root): clean
- npm run test --workspaces:
cli 312/312 files, 4918 passed, 9 skipped
core 266/266 files, 6836 passed, 3 skipped
webui 6/6, 201 passed
sdk 40/40, 283 passed, 1 skipped
- npm ls ink: single [email protected] instance across all peer deps
- single [email protected] instance
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* chore: align Node 22 floor across all shipping artifacts
Reviewer (tanzhenxin) flagged five surfaces where the >=22 engine bump
leaked: SDK package metadata, web-templates engines, /doctor runtime
check, main bundler target, and SDK bundler target. Each was a separate
escape hatch letting Node 18/20 consumers install or run the artifact
on an unsupported runtime.
- packages/sdk-typescript/package.json: engines.node >=18.0.0 -> >=22.0.0
- packages/web-templates/package.json: engines.node >=20 -> >=22
- packages/cli/src/utils/doctorChecks.ts: MIN_NODE_MAJOR 20 -> 22
- esbuild.config.js: target node20 -> node22 (main CLI bundle)
- packages/sdk-typescript/scripts/build.js: target node18 -> node22 (esm + cjs)
- packages/cli/src/utils/doctorChecks.test.ts: rename test label to v22+
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* ci(e2e): bump E2E workflow Node matrix to 22.x
Reviewer (tanzhenxin) flagged that e2e.yml still pinned node-version
20.x while root engines is now >=22, so every E2E run on push would
either fail at npm ci with engine error or silently exercise the bundle
on a runtime that's no longer in ci.yml's test matrix.
The macOS job in the same workflow already reads .nvmrc (which is 22)
so this only updates the Linux matrix.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* fix(deps): drop root wrap-ansi override so ink 7 gets its declared dep
Reviewer (tanzhenxin) flagged that the root overrides.wrap-ansi: 9.0.2
predates this upgrade and forces every consumer (including ink) to v9,
while ink 7 declares wrap-ansi: ^10.0.0. The lockfile had no nested
install under node_modules/ink/, so ink 7 was running with a transitive
dep one major below its declared minimum.
Dropping the global override lets ink resolve its own wrap-ansi 10
nested install (now visible in the lockfile under
node_modules/ink/node_modules/wrap-ansi), while the cli package's own
direct `wrap-ansi: 9.0.2` dependency keeps the cli code path
(TableRenderer.tsx) on the version it has been tested against. The
nested cliui override is preserved for yargs which still needs v7.
Verified via `npm ls wrap-ansi`:
- [email protected] -> [email protected] (newly nested)
- @qwen-code/qwen-code -> [email protected] (unchanged)
- yargs/cliui -> [email protected] (unchanged)
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* test(InputPrompt): un-skip placeholder ID reuse after deletion
Reviewer (tanzhenxin) flagged that the new it.skip on the
'should reuse placeholder ID after deletion' test was undisclosed in
the PR description and removed coverage of real product behavior
(freePlaceholderId / bracketed-paste backspace path) without a
TODO(#NNNN) link.
Their argument was sound: the skip rationale pointed at ink 7's input
throttle, but this same file just bumped the wait helper from 50ms to
150ms specifically to give ink 7 frame time. Re-running the test under
the bumped wait shows it passes reliably (5/5 runs in the full-file
context, 9/10 alone), so the skip was masking the throttle-flake that
the wait bump already addresses, not a real product bug.
Drop the it.skip and the now-stale comment so coverage of the
freePlaceholderId reuse logic is restored.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* test(InputPrompt): bump first prompt-suggestion test wait to 350ms
The "accepts and submits the prompt suggestion on Enter when the buffer
is empty" test is the first in its describe block, so it pays the
renderer cold-start cost. On macOS-22.x CI runners that pushes the
Enter → onSubmit microtask past the default 150ms post-Enter wait. Match
the 350ms initial render wait used immediately above to absorb the cold
start.
* Revert "test(InputPrompt): bump first prompt-suggestion test wait to 350ms"
This reverts commit 6add83b62ea80c551c81f54af1fda3e6e7478f55.
* test(InputPrompt): wait for followup suggestion debounce before pressing Enter
Root cause of the failing prompt-suggestion tests on macOS and Windows
CI is not flaky timing of the test post-Enter wait — it's the 300ms
debounce inside createFollowupController.setSuggestion (shared core).
The Enter handler reads followup.state.isVisible synchronously, so if
the debounce timer has not fired before stdin.write('\\r'), the
suggestion path is skipped and onSubmit never runs. No amount of
post-Enter wait can recover from that — the keypress was already
processed against stale state.
The original wait(350) only left ~50ms margin over the 300ms debounce,
which ink 7 / React 19.2 mount overhead consumed on slow Windows
runners. Bump the initial wait to 700ms (named SUGGESTION_VISIBLE_WAIT_MS)
to give the debounce timer + cold-start render a generous buffer.
Apply to the two sibling tests too — without the wait their "does not
accept" assertions pass trivially when suggestion is never visible,
which is a false green that hides regressions in the actual reject path.
* fix(deps): align cli wrap-ansi with ink 7 (9.0.2 -> ^10.0.0)
Ink 7 ships its own wrap-ansi@10. CLI's direct dep was pinned to 9.0.2,
causing two copies of wrap-ansi in node_modules and a potential drift in
CJK width / ANSI handling between ink's internal text wrapping and our
TableRenderer.
Upgrading the CLI's direct dep to ^10.0.0 lets npm dedupe to a single
wrap-ansi@10 used by both ink and TableRenderer. API surface is
identical; the only documented behaviour change is that tabs are
expanded to 8-column tab stops before wrapping, which TableRenderer
doesn't feed in.
TableRenderer test suite (43 tests) passes against wrap-ansi@10.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* chore(deps): document @types/node 20.x pin in overrides
The override pinning @types/node to 20.19.1 (while engines require
Node >=22) is intentional: bumping to @types/[email protected] re-introduces
a Dirent<NonSharedBuffer> type regression that breaks
@qwen-code/qwen-code-core/sessionService tests.
Add a sibling "//@types/node" note inside `overrides` so future
maintainers see the rationale and know when to revisit the pin
without having to dig through PR #3860 history.
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* test(AskUserQuestionDialog): link skipped Submit-tab test to tracking issue
The 'shows unanswered questions as (not answered) in Submit tab' test
was switched to `it.skip` in the ink 7 upgrade because
`[email protected]` doesn't flush input deterministically
through ink 7's 30fps throttle.
Add a `// TODO(#4036):` marker so the skip is greppable and can be
re-enabled once upstream ships an ink-7-compatible release.
Refs #4036
Generated with AI
Co-authored-by: Qwen-Coder <[email protected]>
* fix(deps): move @types/node pin comment out of overrides block
npm's `overrides` field requires every key to be a real package name —
the `"//@types/node"` comment-key added in 205855875 trips Arborist with
"Override without name" and breaks `npm ci` across all CI jobs.
Move the explanation to a sibling top-level `"//overrides"` key, which
npm ignores at the document root. Same documentation value, no
override-parser collateral damage.
---------
Co-authored-by: 秦奇 <[email protected]>
Co-authored-by: Qwen-Coder <[email protected]>
|
||
|
|
9e4c5ee891 |
refactor: Extract web-templates package and unify build/pack workflow
Moves export-html and insight templates from cli/assets to a new dedicated web-templates package. Updates Dockerfile and build scripts to use consolidated bundle/prepare:package/pack workflow. Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
9abb958a23 |
fix(docker): use scripts/build.js and update workflow for manual builds
Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
5c94913643 | Refactor Dockerfile with multi-stage build for smaller image size | ||
|
|
1bfe5a796a |
Fix Sandbox docker mode (#160)
* Fix E2E * Fix sandbox docker |
||
|
|
a9d6965bef | pre-release commit |