@noob-stupid/dsh-plugin-console 0.5.21 → 0.5.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -27,7 +27,7 @@ import { NPM_NAME_RE } from './dep-source.js'
|
|
|
27
27
|
import { runLockfileRepair } from './lockfile-health.js'
|
|
28
28
|
import { pinProfileDependency, specOf } from './manifest.js'
|
|
29
29
|
import { lockVersion } from './selfupdate.js'
|
|
30
|
-
import { buildPnpmEnv, pnpmAddArgs, runPnpmWithFallback } from '../infra/exec.js'
|
|
30
|
+
import { buildPnpmEnv, pnpmAddArgs, runPnpmWithFallback, unknownPnpmOption } from '../infra/exec.js'
|
|
31
31
|
|
|
32
32
|
const DEFAULT_REGISTRY = 'https://registry.npmmirror.com'
|
|
33
33
|
/** 动作白名单(客户端只能给这些 kind;执行分支与 argv 全在服务端)。 */
|
|
@@ -91,14 +91,18 @@ function isReleaseAgeBlock(message) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/** 跑一次 pnpm(原样),必要时**只对这一条命令**放宽供应链闸并如实标记。
|
|
94
|
-
* 返回 { ok, exitCode, stdout, stderr, relaxedReleaseAge, error }。
|
|
94
|
+
* 返回 { ok, exitCode, stdout, stderr, relaxedReleaseAge, error }。
|
|
95
|
+
*
|
|
96
|
+
* ★ 2026-09-27 CI 实测踩到(本函数的第一个版本):这里直接拼 `pnpmAddArgs` 却没有 `runPnpmAdd` 的
|
|
97
|
+
* **未知选项降级** —— 而 CI 的 corepack 解析到 pnpm 12,`--fetch-timeout/--fetch-retries` 在 pnpm 12
|
|
98
|
+
* 上是 `error: unexpected argument`(直接退出),于是"加固"变成了"动作跑不成"(真机 CI 红)。
|
|
99
|
+
* 现在与 `infra/exec.js#runPnpmAdd` 同一条规矩:认不出这两个选项就去掉加固选项重试一次。 */
|
|
95
100
|
async function runAddWithReleaseAgeRetry({ profileDir, spec, registry, runAdd, timeoutMs = 180000 }) {
|
|
96
|
-
const argv = pnpmAddArgs(spec, registry)
|
|
97
101
|
const execOpts = { cwd: profileDir, timeout: timeoutMs, windowsHide: true, maxBuffer: 4 * 1024 * 1024, env: buildPnpmEnv(registry) }
|
|
98
|
-
const
|
|
102
|
+
const once = async (args) => {
|
|
99
103
|
try {
|
|
100
104
|
const out = await runAdd(args, { execOpts })
|
|
101
|
-
return { ok: true, exitCode: 0, stdout: tail(out?.stdout), stderr: tail(out?.stderr), error: null }
|
|
105
|
+
return { ok: true, exitCode: 0, stdout: tail(out?.stdout), stderr: tail(out?.stderr), error: null, argv: args }
|
|
102
106
|
} catch (error) {
|
|
103
107
|
return {
|
|
104
108
|
ok: false,
|
|
@@ -106,14 +110,21 @@ async function runAddWithReleaseAgeRetry({ profileDir, spec, registry, runAdd, t
|
|
|
106
110
|
stdout: tail(error?.stdout),
|
|
107
111
|
stderr: tail(error?.stderr ?? error?.message ?? String(error)),
|
|
108
112
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
113
|
+
argv: args,
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
}
|
|
112
|
-
const
|
|
117
|
+
const attempt = async (extra) => {
|
|
118
|
+
const first = await once([...pnpmAddArgs(spec, registry), ...extra])
|
|
119
|
+
if (first.ok || !unknownPnpmOption(String(first.error?.message ?? ''))) return first
|
|
120
|
+
// 加固选项不被该版本 pnpm 认识 → 去掉它们重试一次(绝不让加固变成"跑不成")
|
|
121
|
+
return once([...pnpmAddArgs(spec, registry, { fetchFlags: false }), ...extra])
|
|
122
|
+
}
|
|
123
|
+
const first = await attempt([])
|
|
113
124
|
// 放宽条件**必须同时**成立:第一次真的失败了,且失败原因确定是供应链闸(文案/错误码认得出)
|
|
114
125
|
const blocked = !first.ok && (isReleaseAgeBlock(first.stderr) || isReleaseAgeBlock(String(first.error?.message ?? '')))
|
|
115
126
|
if (!blocked) return { ...first, relaxedReleaseAge: false }
|
|
116
|
-
const retried = await attempt([
|
|
127
|
+
const retried = await attempt(['--config.minimumReleaseAge=0'])
|
|
117
128
|
return { ...retried, relaxedReleaseAge: true }
|
|
118
129
|
}
|
|
119
130
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noob-stupid/dsh-plugin-console",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.22",
|
|
4
4
|
"description": "DSH 框架升级安全与插件升级门控:一键升级、失败自动回滚、升级后回滚上版、旧插件不适配自动禁用;内置多源插件市场为发现层,插件源全部可自定义,可指向公司内网私有源 / 私有索引 / 本地 Git 仓库,纯内网离线可用 | Framework upgrade safety & plugin version gating for DSH, with a customizable multi-source plugin market: point every source at internal mirrors or a local file:// repo for intranet-only, offline installs.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|