135 lines
5.5 KiB
Markdown
135 lines
5.5 KiB
Markdown
# 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 用到上游;保留本地提交并上报失败原文。
|