Files
dingMCP/test/distribution.test.ts
T
gitea-admin a08a2c1a96
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
fix: harden proxied client installation
2026-08-18 16:01:06 +00:00

94 lines
6.4 KiB
TypeScript
Raw 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.
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
import test from "node:test";
test("customer distribution is a generic single-login gateway bridge", () => {
const packageMetadata = JSON.parse(readFileSync("package.json", "utf8")) as { version: string };
assert.match(packageMetadata.version, /^\d+\.\d+\.\d+-rc\.\d+$/);
assert.equal(existsSync("plugins/dingtalk-approval"), false);
const installer = readFileSync("distribution/agent-install.template.md", "utf8");
assert.match(installer, /Ed25519/);
assert.match(installer, /唯一通用安装入口/);
assert.match(installer, /使用 `mcpConfig`/);
assert.match(installer, /安装器本身不会猜测或修改 Agent 的私有配置/);
assert.doesNotMatch(installer, /--host|WorkBuddy|Codex|Claude/);
assert.match(installer, /不会通过其他消息通道自动推送链接.*完整登录 URL.*当前回复/s);
assert.match(installer, /读取返回的 `postInstall`.*不得等到用户第一次查询审批/s);
assert.match(installer, /登录链接过期.*绝不能重新安装.*approval_login.*loginCommand/s);
assert.match(installer, /onboarding\.firstRun=true.*简短示例.*不要自动执行/s);
assert.match(installer, /Windows(PowerShell)/);
assert.match(installer, /Invoke-WebRequest[\s\S]*Get-FileHash[\s\S]*ConvertFrom-Json/);
assert.match(installer, /至少 10 分钟超时[\s\S]*stderr[\s\S]*stdout/);
assert.match(installer, /Git Bash[\s\S]*不得.*内部.*installer\.mjs/s);
assert.match(installer, /安装长时间无最终 JSON[\s\S]*残留 staging/s);
assert.match(installer, /系统无需预装 Node\.js/);
assert.match(installer, /阿里云精确版本.*npmmirror 精确版本.*Node 官方精确版本/s);
assert.match(installer, /国内备用发布源[\s\S]*主发布源.*国内 Gitea 备用源/s);
assert.match(installer, /不要设置全局 `NODE_OPTIONS=--use-env-proxy`[\s\S]*不要手工预装 `node_modules`/s);
assert.match(installer, /BOOTSTRAP_WINDOWS_URL|Windows 安装引导/);
assert.match(installer, /Linux\/macOS 安装引导/);
assert.match(installer, /dingtalk-approval-bridge\.cmd/);
assert.match(installer, /显示 302 或启动后立即退出[\s\S]*type: \"stdio\"[\s\S]*doctor --json/);
assert.match(installer, /sourceStatus[\s\S]*dingtalk\.status[\s\S]*xft\.status[\s\S]*都必须是 `ok`/);
assert.match(installer, /更新[\s\S]*update --json[\s\S]*卸载[\s\S]*uninstall --yes --json/);
assert.match(installer, /不能热加载[\s\S]*完整退出并重新启动 Agent/);
assert.doesNotMatch(installer, /npm install -g|npx\s/);
assert.doesNotMatch(installer, /通过当前 Messenger/);
assert.doesNotMatch(installer, /DWS_CLI_PATH|dingtalk-workspace-cli|APP_MODE=local/);
const runtime = JSON.parse(readFileSync("distribution/node-runtime.json", "utf8"));
assert.equal(runtime.version, "22.23.2");
assert.deepEqual(Object.keys(runtime.platforms).sort(), [
"darwin-arm64", "darwin-x64", "linux-arm64", "linux-x64", "win32-arm64", "win32-x64",
]);
assert.equal(runtime.sourceBases.length, 3);
assert.ok(runtime.sourceBases.every((value: string) => value.includes(`/v${runtime.version}/`) && !value.includes("latest")));
assert.ok(Object.values(runtime.platforms).every((value) => /^[a-f0-9]{64}$/.test((value as { sha256: string }).sha256)));
const windowsBootstrap = readFileSync("distribution/bootstrap-windows.template.ps1", "utf8");
const posixBootstrap = readFileSync("distribution/bootstrap-posix.template.sh", "utf8");
assert.match(windowsBootstrap, /OSArchitecture[\s\S]*Save-DingDownload[\s\S]*Expand-Archive/);
assert.match(windowsBootstrap, /SHA-256 不匹配,停止安装/);
assert.match(windowsBootstrap, /Write-DingProgress[\s\S]*\[dingtalk-approval\]/);
assert.match(windowsBootstrap, /dingInstallerUrls[\s\S]*dingManifestMirrorUrls[\s\S]*use-env-proxy/s);
assert.match(posixBootstrap, /^#!\/bin\/sh\nset -eu/);
assert.match(posixBootstrap, /uname -s[\s\S]*uname -m[\s\S]*tar -xzf/);
assert.match(posixBootstrap, /SHA-256 不匹配,停止安装/);
assert.match(posixBootstrap, /ding_progress[\s\S]*\[dingtalk-approval\]/);
assert.match(posixBootstrap, /ding_installer_urls[\s\S]*ding_manifest_mirror_urls[\s\S]*use-env-proxy/s);
assert.equal(spawnSync("sh", ["-n", "distribution/bootstrap-posix.template.sh"]).status, 0);
assert.doesNotMatch(`${windowsBootstrap}\n${posixBootstrap}`, /latest-v|npm install -g/);
const skill = readFileSync("skills/dingtalk-approval/SKILL.md", "utf8");
const createApproval = readFileSync("skills/dingtalk-approval/references/create-approval.md", "utf8");
assert.match(skill, /read `references\/create-approval\.md` completely/);
assert.doesNotMatch(skill, /XFT recall is experimental/);
assert.match(createApproval, /XFT recall is experimental.*XFTSYS9999/s);
assert.match(skill, /does not send or push.*current user-facing reply/s);
assert.match(skill, /handle the installer's `postInstall` result immediately.*waiting for the user's first approval request/s);
assert.match(skill, /onboarding\.firstRun=true.*Do not execute an example automatically/s);
assert.match(skill, /expired login link.*approval_login.*never reinstall/s);
const builder = readFileSync("scripts/build-release.mjs", "utf8");
assert.match(builder, /schemaVersion: 3,\s+version,/s);
assert.match(builder, /download-mirror-base-url[\s\S]*manifestMirrors[\s\S]*mirrors:/s);
assert.match(builder, /signData\(null, manifestBytes/);
assert.match(builder, /dingtalk-approval-client/);
assert.match(builder, /bootstrap-windows\.template\.ps1/);
assert.match(builder, /bootstrap-posix\.template\.sh/);
assert.match(builder, /validateNodeRuntime/);
assert.match(builder, /cpSync\(resolve\("skills\/dingtalk-approval"\).*recursive: true/s);
assert.doesNotMatch(builder, /codexPlugin|codex-plugin|\.codex-plugin|openai\.yaml/);
assert.doesNotMatch(builder, /dingtalk-workspace-cli|DWS_URL|DWS_SHA256/);
});
test("public install page explicitly declares UTF-8 for browser rendering", () => {
const nginx = readFileSync("deploy/approval.justconn.top.nginx.conf", "utf8");
const installLocation = nginx.match(/location = \/downloads\/dingmcp\/install\.md \{([\s\S]*?)\n \}/)?.[1] ?? "";
assert.match(installLocation, /default_type text\/markdown;/);
assert.match(installLocation, /charset utf-8;/);
assert.match(installLocation, /charset_types text\/markdown;/);
});