Files
ai-proj-helper/skills-dev/slark-dsh-cicd-plugin/skills/references/fork-release-and-post-checks.md
T
johnQ c74fe71f0a feat(slark-dsh-cicd): 新增 DSH/Slark 发布实战技能(REQ-20261007-0003)
- 新建 skills-dev/slark-dsh-cicd-plugin:plugin.json + skills/SKILL.md +
  skills/references/fork-release-and-post-checks.md
- 覆盖两条发布线(DSH 插件 pack 双资产 / Slark 宿主重打包+签名)、权限与身份三连
  (push:true 才可写,ls-remote 通 ≠ 能 push)、无上游写权限的 fork 发布且原仓库零改动、
  干净单提交 + git diff --stat <OURS> 树一致性 gate、改指向后必须重新 pack、
  draft→publish 与「更新检查看不到新版」的因果、GitHub HTTPS/fetch 卡死/无 macOS timeout
  的判死处置、发布后 SHA 逐项核对(verify-remote 仅 Windows)、app.asar 完整性约束、
  ai-proj staging→released 与 /req done 证据要求及文档接口故障绕过
- 与 slark-cicd 明确分工并交叉引用,不重复 staging/生产/Desktop 细节
- update-plugin-meta.py PLUGIN_MAP 增加 slark-dsh-cicd-plugin (skill/dev)
- generate-marketplace.py devops 分类补充 slark-dsh-cicd;marketplace.json 仅新增该条目
- 校验:claude plugin validate . 通过(警告为该仓库既有 install_name 字段提示)、git diff --check 干净
2026-10-07 17:06:36 +08:00

135 lines
5.5 KiB
Markdown
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.
# Fork 发布与发布后核对
本文件是 `slark-dsh-cicd` 的操作附件:需要**无上游写权限发布**,或需要**逐项核对远端资产**时读取。
把它当模板:替换 `<...>` 占位符,按阶段执行,每阶段的核验不通过就停下,不要"带病"推进。
## 0. 变量与前置
```bash
export HOME="/Users/johnq"
export PATH="/Users/johnq/.local/node-v22.22.3-darwin-arm64/bin:/opt/homebrew/bin:$PATH"
UP=<upstream-owner>/<repo> # 例如 Aisland-SJL/dsh-worktable(外部作者,无写权限)
ME=<your-account> # 例如 qiudl
PKG=<repo>/01_content # 打包脚本所在目录
VER=0.4.1 # = package.json#version
```
```bash
gh auth status
ssh -T git@github.com 2>&1 | head -3
gh api "repos/$UP" --jq '.permissions' # push:false → 必须走 fork 发布
git remote -v
```
## 1. 改指向 → 重新打包(顺序不可颠倒)
```bash
cd "$PKG"
grep -rn "<upstream-owner>" .. --include='*.json' --include='*.ts' --include='*.tsx' --include='*.md' --include='*.mjs'
# 逐处改完只后再打包:
npm run check && npm run test:gate && npm run pack
shasum -a 256 dist/v$VER/*.tgz
TMP=$(mktemp -d) && tar -xzf dist/v$VER/dsh-worktable.tgz -C "$TMP"
grep -rn "<upstream-owner>" "$TMP" ; echo "grep exit=$? (1 = 无残留,正确)"
```
判据:`check`/`test:gate`/`pack` 全部 exit 0;两个 tgz 同 sha;解包无旧仓库名。
## 2. fork 与干净发布分支
```bash
cd <repo-root>
gh repo fork "$UP" --clone=false # 已存在会提示 already exists,可复用
git remote add fork "git@github.com:$ME/<repo>.git" # 已存在:git remote set-url fork …
git fetch --no-tags origin main
OURS=$(git rev-parse HEAD) # 本地"发布内容已就绪"的 HEAD
git diff --name-status origin/main "$OURS" | awk '$1 ~ /^[DR]/' # 期望空;有 D/R 先处理再用 gate
git checkout -B release/v$VER origin/main
git rm -rq --cached .
git checkout "$OURS" -- .
git add -A
git commit -m "release: <name> v$VER(REQ-…)<一句话说明>"
DIFFOUT="$(git diff --stat "$OURS")"
if [ -n "$DIFFOUT" ]; then
echo "GATE FAILED:"; echo "$DIFFOUT"
git checkout <原分支> && git branch -D release/v$VER # abort:不留半成品分支
exit 1
fi
echo "GATE PASSED: release tree == OURS tree"
```
## 3. 推送(只对 fork)与 draft Release
```bash
git push -u fork release/v$VER
git tag -f v$VER && git push -f fork v$VER # -f 仅限自己 fork 的 tag
gh release create v$VER \
dist/v$VER/dsh-worktable.tgz dist/v$VER/dsh-worktable-$VER.tgz \
--repo "$ME/<repo>" --draft --title "<name> v$VER" --notes-file /tmp/rel-notes.md
```
原仓库零改动复核:
```bash
git ls-remote "git@github.com:$UP.git" # 无 release/v… 分支、无新 tag
gh release list --repo "$UP" # 与发布前一致
```
### Release notes 模板(draft 阶段就写全新值)
```markdown
# <name> v<ver>
> 发布方:fork <ME>/<repo>(原仓库 <UP> 为上游来源)。插件内更新检查已指向本 fork。
## 新增 / 修复 / 清理
## 验证
- check / gate / pack 实际输出(测试条数、断言项)
- 双资产同 SHA:<sha256>
- 解包 grep 无旧仓库名
- 发布分支为干净单提交(父提交 = 上游 main),`git diff --stat <OURS>` 为空
## 安装
网页端 / 桌面端一行命令(指向 fork)
## 已知边界
- draft 期间 releases/latest 仍指旧版 → 更新检查看不到新版
- 保留的第三方外链、平台未验证范围
```
## 4. publish 与发布后核对矩阵
```bash
gh release edit v$VER --repo "$ME/<repo>" --draft=false
```
| 核对项 | 命令 | 通过判据 |
| --- | --- | --- |
| 资产列表与 digest | `gh release view v$VER --repo $ME/<repo> --json assets` | 两个资产 `digest` = 本地 sha |
| 下载后 sha | `gh release download v$VER --repo $ME/<repo> --dir "$D"` + `shasum -a 256 "$D"/*.tgz` | 与本地逐字一致 |
| 与本地验收件一致 | `cmp "$D/dsh-worktable.tgz" dist/v$VER/dsh-worktable.tgz` | 无差异(byte-identical) |
| 包内无旧仓库名 | 解包后 `grep -rn "<upstream-owner>"` | 无输出(exit 1) |
| 包内版本 = tag | 解包读 `package.json#version` | `v$VER` |
| 匿名可下载 | `curl -sL -o /dev/null -w '%{http_code}\n' <资产 URL>` | publish 后 200/302;draft 期 404 属预期 |
| 安装可用 | 临时目录 `npm install <tgz>` + `import()` 断言 | 导出/版本断言通过 |
- **`verify-remote.mjs` 的平台限制**:其下载走 `powershell Invoke-WebRequest`,只在 Windows 可用;
在 macOS 会 `FAIL: download fixed-name asset`。此时用上表的 `gh release view/download` + `shasum` + `cmp` 等价替代,
并说明该脚本的 GET URL 已证明改指生效。
- **"检查更新"看不到新版**的排查顺序:Release 是否 draft → `releases/latest` 指向 → 插件内 `UPDATE_REPO` 指向 →
`latest` 资产名与代码拼法一致。
## 5. 链路判死模板(macOS 无 `timeout`)
```bash
( git fetch --no-tags origin main ) & PID=$!
for i in $(seq 1 30); do sleep 1; kill -0 "$PID" 2>/dev/null || break; done
if kill -0 "$PID" 2>/dev/null; then kill -9 "$PID"; pkill -9 -f git-upload-pack; echo "TIMEOUT(30s)"; fi
```
- HTTPS 到 GitHub `curl` 返回 `000` → 整体不通,改 SSH(`git remote set-url`)。
- 30 秒内 `fatal: early EOF` → 链路被掐断;记录原文与时间,换网络/协议重试。
- 认证或网络失败时不做破坏性重试,也不要把 force 用到上游;保留本地提交并上报失败原文。