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

5.5 KiB
Raw Blame History

Fork 发布与发布后核对

本文件是 slark-dsh-cicd 的操作附件:需要无上游写权限发布,或需要逐项核对远端资产时读取。 把它当模板:替换 <...> 占位符,按阶段执行,每阶段的核验不通过就停下,不要"带病"推进。

0. 变量与前置

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
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. 改指向 → 重新打包(顺序不可颠倒)

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 与干净发布分支

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

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

原仓库零改动复核:

git ls-remote "git@github.com:$UP.git"            # 无 release/v… 分支、无新 tag
gh release list --repo "$UP"                      # 与发布前一致

Release notes 模板(draft 阶段就写全新值)

# <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 与发布后核对矩阵

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)

( 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 用到上游;保留本地提交并上报失败原文。