跳到正文
DEV Community· Jeff·· 3 小時前AI 評分60

Agent 將 queue-client 升級至 v4,CI 綠燈仍漏過分頁故障

The Agent Bumped a Major Version and CI Stayed Green

AI 導讀

Agent 將 queue-client 升級至 v4 後,測試套件和 CI 仍通過,但三日後 nightly sync job 只回傳第一頁紀錄,原因是新版本的行為與測試 mock 不一致。文章列出回應欄位改名、設定選項移除及 callback 契約改變等靜默故障,並建議檢查 breaking changelog、在 sandbox 執行真實工作流程,以及手動檢查 lockfile。

正文

The PR looked like housekeeping. The agent bumped one dependency across a major version, updated the lockfile, described it as "chore: upgrade queue-client to v4," ran the suite, and merged. CI was green.

Three days later, the nightly sync job started returning only the first page of records. The queue library kept responding, the job kept logging success, and nobody had touched pagination logic. The bump had.

Why a green suite missed the break

Unit tests rarely call the real dependency. They build a fake that matches the surface the wrapper remembers from the previous version. That fake still answers when the code calls the old method with the old arguments, so the test passes whether or not the installed package still behaves that way.

A major version exists because something on the outside changed. The suite proves your wrapper compiles against your mock. It does not prove the installed package still returns what the wrapper expects. Agents usually resolve "upgrade" to "latest" and never open the upstream removed list; the context window fills with the diff it generated, not the document that explains what changed.

The three breaks tests cannot see

A renamed response field. The client used to return { "records": [...] }. v4 renamed the key to { "items": [...] }. The wrapper reads records, gets undefined, iterates an empty list, and logs a clean run. The hand-written fixture in the test still builds records, so the test never meets v4's real shape.

A dropped config option, silently ignored. v4 removed the maxPerPage setting and capped page size at the SDK default. Old code passes the key; the new client ignores it. No exception, no deprecation warning, just shorter pages.

A changed callback contract. A hook that used to receive a second argument (the raw page token) drops it in v4. The handler reads the argument, gets undefined, computes "no more pages," and stops after the first response.

Each of these fails quietly: the program keeps running, the log line looks normal, the test stays green. The failure lives in the gap between the mock and the real backend, which CI never bridges.

The habit that costs one extra pass

Keep one direct dependency per PR. Never let the agent fold a major bump into a feature diff. A reviewer reading both cannot tell which change altered runtime behavior, and the agent cannot reason about the upgrade when the feature context dominates the prompt.

Read the breaking-changelog section for the target range, not the marketing "what's new" line. The breaking list for a major bump is usually short — renamed exports, removed options, response-field changes. The "new features" section tells you what you gained; the removed list tells you what you lost.

Run the built app against a sandbox, not just the suite. Execute the real job path against a test backend and compare the record count, page length, and response shape before merge. A mocked suite cannot reveal a renamed field; one real call does.

Review the lockfile diff by hand. Major bumps ride transitive dependencies along for free. Pin those separately so the reviewer sees what moved and can skip the ride-along upgrades on the first pass.

When the dependency wraps your own backend

If the upgraded package is an API client generated for your own service, the cheapest check is to replay recorded request/response pairs against the local OpenAPI spec and a live sandbox endpoint before merge. A renamed response field or a dropped option shows up as a red diff against the contract instead of as a partial nightly job three days later. That is the local-first loop we built into Powerduck: the spec stays the source of truth, and drift appears in front of the reviewer rather than in the logs.

What I check now

Before approving an agent-authored major bump, I ask three things:

  1. Is this PR a single direct dependency, or did the upgrade ride along with feature work?
  2. Did anyone open the breaking-changelog section for the target range, or only the release-notes headline?
  3. Did the agent run the real path against a sandbox, or did it stop at the mocked suite?

A green CI on a major bump means your mocks still compile. It does not mean the new version behaves.

來源:DEV Community · dev.to