# 发布流程(维护者) 本项目发布到 npm:**`dsh-task-guard`**。 > `dsh-todo-guard` 已被其他作者占用(`wxlei2004`,2026-09-28),不能覆盖;本项目因此改名为 `dsh-task-guard`(与 GitHub 仓库同名)。 ## 当前状态(重要) - npm 账号 `mcviseron` 因**登录时使用 recovery code**,被 npm 预防性暂停 72 小时;暂停期只读,不能发布、创建 token 或修改包设置。 - 恢复时间:**2026-10-20 03:55 UTC = 北京时间 2026-10-20 11:55**。 - 恢复前**不要重试 `npm publish`**;403 不会因为重试而消失。 - 恢复后**不要再用 recovery code 发布**:用验证器 App 的 6 位 OTP,或带 **Bypass 2FA** 的 Granular Access Token。 - 当前 npm 上还没有 `dsh-task-guard`(404);GitHub 仓库、tag `v1.0.0`、CI 已完成。 ## 发布前检查 ```powershell cd pnpm check # typecheck + build + 18 tests npm pack --dry-run # 10 files; must include lib/index.js and cordis.patch.yml ``` `lib/` 不提交到 git,但 `npm publish` 会执行 `prepare` → `pnpm build`,并把 `lib/` 打进 tarball(`files` 字段包含 `lib`)。 ## 首次发布(手动) 首个版本必须手动发布:npm 的 Trusted Publisher 只能绑定**已存在**的包,OIDC 不能创建第一个版本。 ### 1. 确认登录 ```powershell npm whoami --registry=https://registry.npmjs.org/ # 期望:mcviseron ``` 如果 401: ```powershell npm login --registry=https://registry.npmjs.org/ ``` > 本机默认 registry 是 `registry.npmmirror.com`(只读镜像,不能发布)。所有发布命令都必须显式带 `--registry=https://registry.npmjs.org/`。 ### 2. 选择认证方式 优先用 **Granular Access Token + Bypass 2FA**(暂停结束后才能创建): 1. https://www.npmjs.com/settings/~/tokens 2. Generate New Token → Granular Access Token 3. Read and write;Packages 选 `dsh-task-guard` 4. 勾选 **Bypass 2FA** 5. 写入本机 `.npmrc`(不要把 token 发到聊天/issue): ```powershell npm config set //registry.npmjs.org/:_authToken "npm_xxx" --location=user ``` 或者使用验证器 App 的 OTP。**不要使用 recovery code**:npm 会将其视为安全敏感操作并再次暂停账号。 ### 3. 发布 ```powershell npm publish --registry=https://registry.npmjs.org/ --access public ``` 如果 npm 要求 OTP: ```powershell npm publish --registry=https://registry.npmjs.org/ --access public --otp=<6位验证码> ``` ### 4. 如果 npm 走了 staged publishing 现象: - npm 上出现 `0.0.0-stage`(336 B,描述 *Temporary package placeholder for staged publishing*); - 真实版本 `dsh-task-guard-1.0.0.tgz` 仍是 404; - 版本处于「等待分阶段发布」。 本机 npm 是 10.9.3,没有 `stage` 命令;用 npm 12: ```powershell npx --yes npm@12 publish --access public --registry=https://registry.npmjs.org/ --otp=<6位验证码> # 或先查看/批准暂存: npx --yes npm@12 stage list npx --yes npm@12 stage approve ``` > npm 12 要求 Node ≥ 22.22.2;本机 Node 22.19.0 会打 warning,但 `npx` 可以运行。 ### 5. 验证发布 ```powershell npm view dsh-task-guard version dist-tags.latest --registry=https://registry.npmjs.org/ # 期望:1.0.0 / latest 1.0.0 curl.exe -sI https://registry.npmjs.org/dsh-task-guard/-/dsh-task-guard-1.0.0.tgz | Select-Object -First 1 # 期望:HTTP/2 200 # 触发国内镜像同步(npmmirror 通常会自动同步,也可以主动踢一脚) curl.exe -X PUT "https://registry.npmmirror.com/-/package/dsh-task-guard/syncs" ``` 可选清理占位版(真实版本已上线后): ```powershell npx --yes npm@12 unpublish dsh-task-guard@0.0.0-stage --registry=https://registry.npmjs.org/ ``` ## 配置 Trusted Publisher(首次发布之后) 打开 npmjs.com → `dsh-task-guard` → **Settings → Trusted Publisher → GitHub Actions**: | 字段 | 值 | |---|---| | Organization or user | `MCviseron` | | Repository | `dsh-task-guard` | | Workflow filename | `publish.yml` | | Environment | 留空 | | Allow npm publish | 勾选 | | Allow npm dist-tag | 勾选 | 配好后,`publish.yml` 即可在推 tag 时用 OIDC 发布,无需 token/OTP,并带 **SLSA provenance**。 另外在 GitHub 仓库 **Settings → Actions → Variables** 新增: ```text NPM_PUBLISH_ENABLED=true ``` 在首次手动发布 + Trusted Publisher 配置完成前保持 false/不存在;`publish.yml` 会跑检查与打包,但跳过上传并输出 notice。 ## 后续发布(CI 自动) 1. 修改 `package.json` 版本(SemVer)和 `CHANGELOG.md`; 2. `pnpm check`; 3. 提交并打 tag,tag 必须与 `package.json` 版本一致: ```powershell git add -A git commit -m "feat: ..." git tag v0.1.1 git push origin main v0.1.1 ``` 4. GitHub Actions 的 `publish.yml` 自动执行: - `pnpm install --frozen-lockfile` - `typecheck` / `test` / `build` - 校验 tag 与 `package.json` 版本一致 - 校验 tarball 包含 `lib/index.js`、`cordis.patch.yml`、`README.md`、`LICENSE` - 当 `NPM_PUBLISH_ENABLED=true` 时执行 `npm publish --access public --provenance`(OIDC,无 token);否则只输出跳过 notice 手动触发 `workflow_dispatch` 默认只跑 `npm pack --dry-run`,不会发布;把 `dry-run` 设为 false 才会发布。 ## 版本与产物约定 - **npm 版本 = git tag = `package.json` 版本**(CI 强制校验)。 - `lib/` 不提交到 git;`prepare` 在 `npm publish` / `pnpm install` 时构建并打进 tarball。 - `files` 只包含 `lib`、`src`、`cordis.patch.yml`、README、CHANGELOG、CONTRIBUTING、SECURITY、LICENSE;`docs/` 与 `.github/` 不进 npm 包。 - 插件 `dsh.bundle.patch` 指向自带的 `cordis.patch.yml`;安装后 DSH 自动插入 `id: task-guard`。 ## 常见错误 | 错误 | 原因 | 处理 | |---|---|---| | `E401 Unauthorized` | npmjs token 失效 / 未登录 | `npm login --registry=https://registry.npmjs.org/` | | `EOTP` | 账号启用了 2FA,发布需要 OTP | 用验证器 OTP,或 Granular Access Token + Bypass 2FA | | `E403 ... temporarily suspended` | 使用了 recovery code 登录 | 等 72 小时自动恢复;不要重试;恢复后重新生成 recovery codes | | `E403 ... 2FA or granular access token with bypass 2fa` | 没带 OTP/token | 加 `--otp` 或配置 Bypass 2FA token | | `EPUBLISHCONFLICT` / 版本已存在 | 该版本已发布 | 提升版本号,重新打 tag | | `npm error code E404` 查不到包 | 还没发布,或用了只读镜像 | 发布时显式 `--registry=https://registry.npmjs.org/` | | staged `0.0.0-stage` | 没带 OTP,npm 暂存了发布 | 用 `npx npm@12 publish --otp` 或 `stage approve` |