Files
nexu-io__open-design/e2e/tests/scripts/dsh-upstream-drift.test.ts
lefarcen d18ada9e35 fix(ci): make the DSH upstream drift card readable (#7824)
The maintainer who received this alert could not tell what it was. The
headline jumped straight to a verdict, so nothing said an upstream release
had been detected or where the message came from; the body opened with
semver theory; the blocking branch never mentioned the version we pin,
making the most urgent card the least informative one; and nothing said
when upstream shipped, so there was no way to tell a release from this
morning apart from one that had been sitting for a fortnight.

The headline now names the check and only the check — severity travels in
the header template, which Feishu renders before any text. The first
sentence is three facts with no reasoning attached: what upstream
released, when, and what we still pin, on both severities. The
consequence follows, and the semver rationale is compressed into a
parenthetical behind it. The three-file checklist is untouched.

Reading the publish date means asking npm for the full packument: the
compact one (`application/vnd.npm.install-v1+json`) carries no `time` map
at all. `readPublishedAt` degrades to null for every shape short of that,
because the date is one sentence of context on an alert whose entire
reason to exist is being sent.

Also replaces a self-check assertion that could never fail:
`String(card.header).length === 0` is "[object Object]".length whatever
the card says. It now reads the fields a human reads.

Claude-Session: https://claude.ai/code/session_01B8MaA1ABkvbnfaYUKw3UH3
2026-09-07 07:01:15 +00:00

320 lines
12 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// The upstream watch exists because the in-repo drift check cannot see the one
// thing that actually went wrong twice: our installers and our agent def
// agreeing with each other while both sat behind what npm serves. These cases
// pin that distinction, plus the parsing that lets the checker read either side
// out of source rather than being told the versions twice.
import { readFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { describe, expect, it, vi } from 'vitest';
import {
type DriftCard,
buildCard,
classifyDrift,
describePublishedAt,
interpretFeishuResponse,
readAcceptedPattern,
readListedVersions,
readPinnedVersion,
readPublishedAt,
} from '../../../.github/scripts/dsh-upstream-drift.ts';
const repoRoot = fileURLToPath(new URL('../../../', import.meta.url));
const INSTALLER_SH = `${repoRoot}tools/release/resources/dsh-bootstrap/install-dsh.sh`;
const AGENT_DEF = `${repoRoot}apps/daemon/src/runtimes/defs/deepseek-harness.ts`;
const DRIFT_SCRIPT = `${repoRoot}.github/scripts/dsh-upstream-drift.ts`;
const WORKFLOW = `${repoRoot}.github/workflows/dsh-upstream-drift.yml`;
/** A fixed "now" so the card's relative age is a fact, not a moving target. */
const NOW = new Date('2026-09-07T00:00:00.000Z');
const PUBLISHED_AT = '2026-09-03T06:21:52.107Z';
function headlineOf(card: DriftCard): string {
return card.header.title.content;
}
/** Everything the reader actually reads under the headline. */
function bodyOf(card: DriftCard): string {
return card.elements.map((element) => element.text?.content ?? '').join('\n');
}
describe('DeepSeek Harness upstream drift', () => {
it('reads what we currently ship out of the real files', async () => {
const [installer, def, script] = await Promise.all([
readFile(INSTALLER_SH, 'utf8'),
readFile(AGENT_DEF, 'utf8'),
readFile(DRIFT_SCRIPT, 'utf8'),
]);
// Canonical product path — not the temporary landing public copies.
expect(script).toContain(
'tools/release/resources/dsh-bootstrap/install-dsh.sh',
);
expect(script).not.toContain('apps/landing-page/public/install-dsh.sh');
const pinned = readPinnedVersion(installer);
expect(pinned).toMatch(/^\d+\.\d+\.\d+/u);
// Whatever the installer hands a user has to be a version the daemon
// accepts, or we ship an "untested" warning to anyone who follows our own
// instructions. The dedicated guard for that pairing is
// `e2e/tests/dsh-installer-version-policy.test.ts`; this asserts the
// checker can see both sides, which is what makes its verdict meaningful.
const pattern = readAcceptedPattern(def);
const listed = readListedVersions(def);
expect(listed.length).toBeGreaterThan(0);
expect(listed.includes(pinned) || (pattern?.test(pinned) ?? false)).toBe(true);
});
// The state that shipped twice. Both halves of our config agree, so the
// in-repo check is green, and a user on what npm serves is outside what we
// support — Settings calls their CLI untested and the peer ranges will not
// resolve. Anything that reports this as healthy has lost the point.
it('calls an accepted-nowhere latest unsupported, not merely behind', () => {
const verdict = classifyDrift({
accepted: false,
latest: '0.1.1-rc.2',
pinned: '0.1.0-rc.8',
publishedAt: PUBLISHED_AT,
});
expect(verdict.severity).toBe('unsupported');
expect(JSON.stringify(buildCard(verdict, NOW))).toContain('0.1.1-rc.2');
});
it('separates "we ship an older version" from "we do not support theirs"', () => {
expect(
classifyDrift({
accepted: true,
latest: '0.1.2',
pinned: '0.1.1-rc.2',
publishedAt: PUBLISHED_AT,
}).severity,
).toBe('behind');
expect(
classifyDrift({
accepted: true,
latest: '0.1.1-rc.2',
pinned: '0.1.1-rc.2',
publishedAt: PUBLISHED_AT,
}).severity,
).toBe('in-sync');
});
// The maintainer who received this card could not tell what it was: the
// headline jumped straight to a verdict, so nothing said "an upstream release
// was detected" or where the message came from. The check's name belongs in
// the headline; how bad it is belongs in the header colour, which is the one
// thing a Feishu card renders before any text.
it('names the check in the headline instead of announcing a verdict there', () => {
const blocking = buildCard(
classifyDrift({
accepted: false,
latest: '0.1.2-rc.1',
pinned: '0.1.1-rc.2',
publishedAt: PUBLISHED_AT,
}),
NOW,
);
const behind = buildCard(
classifyDrift({
accepted: true,
latest: '0.1.2',
pinned: '0.1.1-rc.2',
publishedAt: PUBLISHED_AT,
}),
NOW,
);
expect(headlineOf(blocking)).toContain('DeepSeek Harness');
expect(headlineOf(blocking)).toContain('新版检测');
// Same check, same name. Severity travels in the template, not the title.
expect(headlineOf(behind)).toBe(headlineOf(blocking));
expect(blocking.header.template).toBe('red');
expect(behind.header.template).toBe('orange');
});
// The blocking branch used to be the least informative one: its body never
// mentioned `pinned` at all, so the most urgent card was the one that hid
// what we currently ship. Both severities owe the reader the same three
// facts before any explanation: what upstream released, when, and where we
// still sit.
it.each([
{ accepted: false, latest: '0.1.2-rc.1', severity: 'unsupported' },
{ accepted: true, latest: '0.1.2', severity: 'behind' },
])('states upstream version, publish date and our pin ($severity)', (scenario) => {
const verdict = classifyDrift({
accepted: scenario.accepted,
latest: scenario.latest,
pinned: '0.1.1-rc.2',
publishedAt: PUBLISHED_AT,
});
expect(verdict.severity).toBe(scenario.severity);
const body = bodyOf(buildCard(verdict, NOW));
expect(body).toContain(scenario.latest);
expect(body).toContain('0.1.1-rc.2');
expect(body).toContain('2026-09-03');
// "Is this fresh, or has it been sitting for two weeks?" is the question a
// bare timestamp still leaves open.
expect(body).toContain('4 天前');
// What happened comes before why it matters: the semver rationale used to
// be the opening sentence of the card.
const firstBlock = buildCard(verdict, NOW).elements[0]?.text?.content ?? '';
expect(firstBlock).toContain(scenario.latest);
expect(firstBlock).toContain('0.1.1-rc.2');
expect(firstBlock).not.toContain('semver');
// The three-file checklist is the useful half of the old card; keep it.
expect(body).toContain('packages/dsh-runtime/package.json');
});
// The publish date is decoration on an alert whose only job is to be sent.
// A registry response without it must cost the card one sentence, not the
// whole alert.
it('drops the publish date rather than the alert when the registry omits it', () => {
const card = buildCard(
classifyDrift({
accepted: false,
latest: '0.1.2-rc.1',
pinned: '0.1.1-rc.2',
publishedAt: null,
}),
NOW,
);
const body = bodyOf(card);
expect(headlineOf(card)).toContain('新版检测');
expect(body).toContain('0.1.2-rc.1');
expect(body).toContain('0.1.1-rc.2');
expect(body).not.toContain('null');
expect(body).not.toContain('Invalid Date');
expect(body).not.toContain('NaN');
});
// The compact packument (`application/vnd.npm.install-v1+json`) carries only
// name / dist-tags / versions / modified — no `time` map at all — so reading
// the publish date has to survive every shape short of the full document.
it('reads the publish date out of a packument, and null out of anything else', () => {
const full = {
'dist-tags': { latest: '0.1.2-rc.1' },
name: '@deepseek-ai/dsh',
time: {
'0.1.1-rc.2': '2026-08-21T09:02:11.000Z',
'0.1.2-rc.1': PUBLISHED_AT,
created: '2026-01-04T00:00:00.000Z',
modified: PUBLISHED_AT,
},
};
expect(readPublishedAt(full, '0.1.2-rc.1')).toBe(PUBLISHED_AT);
expect(readPublishedAt(full, '9.9.9')).toBeNull();
// The compact packument shape.
expect(
readPublishedAt(
{ 'dist-tags': { latest: '0.1.2-rc.1' }, modified: PUBLISHED_AT, name: 'x' },
'0.1.2-rc.1',
),
).toBeNull();
expect(readPublishedAt({ time: { '0.1.2-rc.1': 17 } }, '0.1.2-rc.1')).toBeNull();
expect(readPublishedAt(null, '0.1.2-rc.1')).toBeNull();
expect(readPublishedAt('not json', '0.1.2-rc.1')).toBeNull();
});
it('turns a publish timestamp into a date plus an age, and garbage into nothing', () => {
expect(describePublishedAt(PUBLISHED_AT, NOW)).toContain('2026-09-03');
expect(describePublishedAt(PUBLISHED_AT, NOW)).toContain('4 天前');
expect(describePublishedAt('2026-09-07T01:00:00.000Z', new Date('2026-09-07T05:00:00Z'))).toBe(
'2026-09-07(今天)',
);
expect(describePublishedAt(null, NOW)).toBeNull();
expect(describePublishedAt('yesterday-ish', NOW)).toBeNull();
});
it('rebuilds the accepted pattern from source rather than restating it', () => {
const pattern = readAcceptedPattern(
" supportedVersionPattern: /^0\\.1\\.\\d+(?:-rc\\.\\d+)?$/u,",
);
expect(pattern?.test('0.1.1-rc.2')).toBe(true);
expect(pattern?.test('0.1.9')).toBe(true);
expect(pattern?.test('0.2.0-rc.1')).toBe(false);
});
it('treats a def with no pattern as accepting only what it lists', () => {
expect(readAcceptedPattern(" supportedVersions: ['0.1.0-rc.8'],")).toBeNull();
});
// Importing the module used to run the CLI: collecting this very file fetched
// the live registry and, once drift existed, would have tried to post to
// Feishu before a single assertion ran. A watcher that fires from a test run
// is worse than no watcher.
it('does not touch the network when imported', async () => {
const realFetch = globalThis.fetch;
const calls: string[] = [];
globalThis.fetch = (async (input: unknown) => {
calls.push(String(input));
throw new Error('the drift script must not fetch on import');
}) as typeof globalThis.fetch;
try {
vi.resetModules();
await import('../../../.github/scripts/dsh-upstream-drift.ts');
expect(calls).toEqual([]);
} finally {
globalThis.fetch = realFetch;
}
});
// Feishu answers a rejected webhook with HTTP 200 and a nonzero code, so
// "2xx means delivered" throws the alert away and reports success doing it.
it('only counts a Feishu response as delivered when the app-level code says so', () => {
expect(interpretFeishuResponse({ status: 200, text: '{"code":0}' })).toMatchObject({
delivered: true,
});
expect(interpretFeishuResponse({ status: 200, text: '{"StatusCode":0}' })).toMatchObject({
delivered: true,
});
expect(
interpretFeishuResponse({ status: 200, text: '{"code":19021,"msg":"sign match fail"}' }),
).toMatchObject({ code: 19021, delivered: false, retryable: false });
});
it('retries only what is worth retrying', () => {
expect(interpretFeishuResponse({ status: 429, text: '' }).retryable).toBe(true);
expect(interpretFeishuResponse({ status: 503, text: '' }).retryable).toBe(true);
expect(interpretFeishuResponse({ status: 200, text: '{"code":9499}' }).retryable).toBe(true);
expect(interpretFeishuResponse({ status: 400, text: '{"code":19001}' }).retryable).toBe(false);
});
// A watch that only runs on a green PR would never fire, since an upstream
// release does not touch this repo.
it('runs on a schedule and stays outside the merge gate', async () => {
const workflow = await readFile(WORKFLOW, 'utf8');
expect(workflow).toMatch(/^on:\n\s+schedule:/mu);
expect(workflow).toContain('workflow_dispatch');
expect(workflow).toContain('dsh-upstream-drift.ts self-check');
expect(workflow).not.toContain('pull_request');
});
// The webhook and its signing secret are a pair. Selecting the landing bot
// while signing with the release bot's secret sends a card Feishu rejects,
// which is a silent loss of the only message this workflow exists to send.
it('signs with the secret belonging to the webhook it chose', async () => {
const workflow = await readFile(WORKFLOW, 'utf8');
expect(workflow).toContain(
'secrets.FEISHU_LANDING_WEBHOOK || secrets.FEISHU_RELEASE_WEBHOOK',
);
expect(workflow).toContain(
'secrets.FEISHU_LANDING_SIGN_SECRET || secrets.FEISHU_RELEASE_SIGN_SECRET',
);
});
});