fix: make client installation observable
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
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
This commit is contained in:
@@ -49,8 +49,12 @@
|
||||
|
||||
不要在浏览器中复制脚本内容,不要对 URL 解码、重新编码或手工拼接。必须先校验安装引导 SHA-256,再执行它。
|
||||
|
||||
为执行平台安装引导的 Agent 工具调用设置至少 10 分钟超时。引导和安装器会把 `[dingtalk-approval]` 开头的阶段进度写入 stderr,把唯一的最终结果 JSON 写入 stdout;进度文本不是失败,也不能混入 JSON 解析。进程仍在运行时不得并发启动第二次安装。
|
||||
|
||||
### Windows(PowerShell)
|
||||
|
||||
无论当前 Agent 默认使用 PowerShell、CMD 还是 Git Bash,Windows 都必须调用普通 PowerShell 执行下面的完整流程。不得从 Git Bash 直接运行内部的 `node dingtalk-approval-installer.mjs ...` 命令;内部安装器不是用户安装入口。
|
||||
|
||||
在普通 PowerShell 中逐行运行:
|
||||
|
||||
```powershell
|
||||
@@ -196,6 +200,7 @@ $dingLogin | ConvertTo-Json -Depth 20
|
||||
6. **连接器一直未出现**:确认已信任本地连接器并完整重启 Agent。不要通过反复重装刷新连接器。
|
||||
7. **授权链接过期**:MCP 已加载就再次调用 `approval_login`;否则执行保存的 `loginCommand`。不要重装。
|
||||
8. **Linux/macOS 缺少下载或校验命令**:必须先具备 `curl` 或 `wget`,以及 `sha256sum` 或 `shasum`;不能绕过 SHA-256 校验。系统 `tar` 必须支持 gzip 归档。
|
||||
9. **安装长时间无最终 JSON或被宿主终止**:先确认工具调用超时不少于 10 分钟,并查看 stderr 中最后一条 `[dingtalk-approval]` 阶段信息。不要改用内部安装器,也不要并发重试。原进程确认已经退出后,可重新执行同一平台引导;它会识别已经死亡的安装进程、清理残留 staging 并安全续装。若明确提示另一个安装仍在运行,应等待该进程结束。
|
||||
|
||||
## 更新
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@ ding_manifest_url='{{MANIFEST_URL}}'
|
||||
ding_temp_dir="$(mktemp -d "${TMPDIR:-/tmp}/dingmcp-install.XXXXXX")"
|
||||
trap 'rm -rf "$ding_temp_dir"' EXIT HUP INT TERM
|
||||
|
||||
ding_progress() {
|
||||
printf '[dingtalk-approval] %s\n' "$1" >&2
|
||||
}
|
||||
|
||||
ding_hash_file() {
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$1" | awk '{print $1}'
|
||||
@@ -68,6 +72,7 @@ ding_download_verified() {
|
||||
shift 2
|
||||
ding_download_succeeded=0
|
||||
for ding_download_url in "$@"; do
|
||||
ding_progress "正在下载并校验:$ding_download_url"
|
||||
rm -f "$ding_download_target"
|
||||
if ding_fetch "$ding_download_url" "$ding_download_target"; then
|
||||
ding_download_succeeded=1
|
||||
@@ -111,9 +116,11 @@ case "$ding_os-$ding_arch" in
|
||||
darwin-arm64) ding_node_file='{{NODE_DARWIN_ARM64_FILE}}'; ding_node_sha256='{{NODE_DARWIN_ARM64_SHA256}}' ;;
|
||||
esac
|
||||
|
||||
ding_progress "1/4 检查 $ding_os-$ding_arch 的 Node/npm 运行环境"
|
||||
ding_node_path=''
|
||||
if command -v node >/dev/null 2>&1 && command -v npm >/dev/null 2>&1 && ding_test_node "$(command -v node)"; then
|
||||
ding_node_path="$(command -v node)"
|
||||
ding_progress "2/4 复用兼容的系统 Node"
|
||||
else
|
||||
if [ -n "${DINGTALK_APPROVAL_CLIENT_HOME:-}" ]; then
|
||||
ding_client_root="$DINGTALK_APPROVAL_CLIENT_HOME"
|
||||
@@ -128,6 +135,7 @@ else
|
||||
ding_node_path="$ding_runtime_dir/bin/node"
|
||||
ding_npm_cli="$ding_runtime_dir/lib/node_modules/npm/bin/npm-cli.js"
|
||||
if ! ding_test_node "$ding_node_path" || [ ! -f "$ding_npm_cli" ]; then
|
||||
ding_progress "2/4 系统 Node 不可用,准备插件私有 Node;下载可能需要一些时间"
|
||||
mkdir -p "$ding_runtime_parent"
|
||||
chmod 700 "$ding_client_root" "$ding_runtime_parent" 2>/dev/null || true
|
||||
ding_runtime_archive="$ding_temp_dir/$ding_node_file"
|
||||
@@ -148,12 +156,16 @@ else
|
||||
fi
|
||||
rm -rf "$ding_runtime_dir"
|
||||
mv "$ding_extracted_dir" "$ding_runtime_dir"
|
||||
else
|
||||
ding_progress "2/4 复用已安装的插件私有 Node"
|
||||
fi
|
||||
fi
|
||||
|
||||
ding_progress '3/4 下载并校验签名安装器与发布公钥'
|
||||
ding_installer="$ding_temp_dir/installer.mjs"
|
||||
ding_public_key="$ding_temp_dir/release-signing-public.pem"
|
||||
ding_download_verified "$ding_installer" "$ding_installer_sha256" "$ding_installer_url"
|
||||
ding_download_verified "$ding_public_key" "$ding_public_key_sha256" "$ding_public_key_url"
|
||||
|
||||
ding_progress '4/4 执行安装器;最终 JSON 输出到 stdout,阶段进度输出到 stderr'
|
||||
"$ding_node_path" "$ding_installer" install --manifest-url "$ding_manifest_url" --public-key "$ding_public_key" --json
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
if (Get-Variable -Name PSNativeCommandUseErrorActionPreference -ErrorAction SilentlyContinue) {
|
||||
$PSNativeCommandUseErrorActionPreference = $false
|
||||
}
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
$dingSourceBases = @({{NODE_SOURCE_BASES_POWERSHELL}})
|
||||
@@ -9,6 +12,10 @@ $dingPublicKeyUrl = "{{PUBLIC_KEY_URL}}"
|
||||
$dingPublicKeySha256 = "{{PUBLIC_KEY_SHA256}}"
|
||||
$dingManifestUrl = "{{MANIFEST_URL}}"
|
||||
|
||||
function Write-DingProgress([string] $dingMessage) {
|
||||
[Console]::Error.WriteLine("[dingtalk-approval] $dingMessage")
|
||||
}
|
||||
|
||||
function Get-DingSha256([string] $dingPath) {
|
||||
return (Get-FileHash -Algorithm SHA256 -LiteralPath $dingPath).Hash.ToLowerInvariant()
|
||||
}
|
||||
@@ -16,6 +23,7 @@ function Get-DingSha256([string] $dingPath) {
|
||||
function Save-DingDownload([string[]] $dingUrls, [string] $dingTarget, [string] $dingExpectedSha256) {
|
||||
$dingLastError = $null
|
||||
foreach ($dingUrl in $dingUrls) {
|
||||
Write-DingProgress "正在下载并校验:$dingUrl"
|
||||
try {
|
||||
if (Test-Path -LiteralPath $dingTarget) { Remove-Item -LiteralPath $dingTarget -Force }
|
||||
Invoke-WebRequest -UseBasicParsing -Uri $dingUrl -OutFile $dingTarget -TimeoutSec 300
|
||||
@@ -57,6 +65,7 @@ switch ($dingArchitecture) {
|
||||
default { throw "不支持的 Windows CPU 架构:$dingArchitecture" }
|
||||
}
|
||||
|
||||
Write-DingProgress "1/4 检查 Windows-$dingArchitecture 的 Node/npm 运行环境"
|
||||
$dingSystemNode = Get-Command node -ErrorAction SilentlyContinue
|
||||
$dingNodePath = if ($dingSystemNode) { $dingSystemNode.Source } else { $null }
|
||||
if (-not (Test-DingNode $dingNodePath $false)) {
|
||||
@@ -73,6 +82,7 @@ if (-not (Test-DingNode $dingNodePath $false)) {
|
||||
$dingRuntimeDir = Join-Path $dingRuntimeParent $dingRuntimeName
|
||||
$dingNodePath = Join-Path $dingRuntimeDir "node.exe"
|
||||
if (-not (Test-DingNode $dingNodePath $true)) {
|
||||
Write-DingProgress "2/4 系统 Node 不可用,准备插件私有 Node;下载可能需要一些时间"
|
||||
New-Item -ItemType Directory -Path $dingRuntimeParent -Force | Out-Null
|
||||
$dingRuntimeTemp = Join-Path ([IO.Path]::GetTempPath()) ("dingmcp-node-" + [guid]::NewGuid().ToString("N"))
|
||||
New-Item -ItemType Directory -Path $dingRuntimeTemp -Force | Out-Null
|
||||
@@ -90,9 +100,14 @@ if (-not (Test-DingNode $dingNodePath $false)) {
|
||||
} finally {
|
||||
if (Test-Path -LiteralPath $dingRuntimeTemp) { Remove-Item -LiteralPath $dingRuntimeTemp -Recurse -Force }
|
||||
}
|
||||
} else {
|
||||
Write-DingProgress "2/4 复用已安装的插件私有 Node"
|
||||
}
|
||||
} else {
|
||||
Write-DingProgress "2/4 复用兼容的系统 Node"
|
||||
}
|
||||
|
||||
Write-DingProgress "3/4 下载并校验签名安装器与发布公钥"
|
||||
$dingInstallTemp = Join-Path ([IO.Path]::GetTempPath()) ("dingmcp-install-" + [guid]::NewGuid().ToString("N"))
|
||||
New-Item -ItemType Directory -Path $dingInstallTemp -Force | Out-Null
|
||||
try {
|
||||
@@ -100,6 +115,7 @@ try {
|
||||
$dingPublicKey = Join-Path $dingInstallTemp "release-signing-public.pem"
|
||||
Save-DingDownload @($dingInstallerUrl) $dingInstaller $dingInstallerSha256
|
||||
Save-DingDownload @($dingPublicKeyUrl) $dingPublicKey $dingPublicKeySha256
|
||||
Write-DingProgress "4/4 执行安装器;最终 JSON 输出到 stdout,阶段进度输出到 stderr"
|
||||
$dingInstallOutput = & $dingNodePath $dingInstaller install --manifest-url $dingManifestUrl --public-key $dingPublicKey --json
|
||||
$dingInstallExit = $LASTEXITCODE
|
||||
if ($dingInstallExit -ne 0) { throw "钉钉审批安装器执行失败:$dingInstallOutput" }
|
||||
|
||||
Reference in New Issue
Block a user