Files
ai-proj-helper/skills-dev/slark-cicd-plugin/skills/SKILL.md
T

13 KiB
Raw Blame History

name, description
name description
slark-cicd Slark 仓库 staging、生产和 Desktop 安装包的端到端 CI/CD 可执行 runbook。覆盖本地预推快检、PR 与内网 ci/internal-gate 门禁、合并 origin/main、staging 真机预验、审批式生产发布,以及在 m5max 构建签名、公证并上传 macOS/Windows Desktop 包到 OSS。当用户要在 slarkqiudl/qiu-slark)里发布/上线、部署到生产或 staging、发布 Desktop 安装包、盯 CI/合并 PR、复现或验证运行时行为、或排查发布链/推送路由问题时使用。

Slark CI/CD runbook

驱动 Slark 从改代码到上线的端到端流程。权威流程与完整细节见仓库文档 docs/cicd-staging-production.md(本技能命令与之一致);本文件是可直接照做的分阶段清单。

仓库:qiudl/qiu-slark(本机克隆通常在 /Users/donglinlai/coding/slark)。所有命令在仓库根执行。 ai-proj 相关命令加 GODEBUG=netdns=go 前缀。

铁律(先记死)

  • GitHub origin/main 是唯一代码权威、合并入口与生产发布来源;internal 只用于 CI/镜像,永不发布。
  • 生产发布只接受最新 origin/main 的精确 40 位 SHAHEAD != origin/main 会被 deploy.sh 拒绝。
  • 生产发布必须在普通 clone 中执行,且 .git 必须是目录;release-prod.sh / deploy.sh 会拒绝 .git 为指针文件的 git worktree。不要污染现有 checkout:主目录脏或被占用时,新建干净的临时 clone。
  • 审批式部署,永不自动:亲手敲的 sudo/rm -rf/dd/curl|sh/包安装是 destructiveNEVER_AUTO), 每次都要人审;命中审批闸就等人批,绝不绕过、绝不把这些 key 加进 auto-approve 白名单。
  • staging 与生产硬隔离:staging 脚本带生产 IP 拒运行护栏、不 push origin、不反向 rsync。
  • 当前 Slark staging 权威目标是 AWS ap-southeast-2 实例 i-013e5ca3fdfddc13e Name=slark-staging2026-08-18 核验公网 IP 15.135.112.181)。公网 IP 自动分配,发布前必须按 实例 ID 重查并确认 Name/状态;不得凭历史 IP 判断目标。
  • 82.157.141.202 是 ai-proj 预生产宿主机。其 /opt/slark-staging cohost 是隔离的 Slark 兼容验收栈, 但不是 Slark 独立预生产;只有任务明确指定 cohost 时才能使用,不得作为普通 Slark staging 的默认目标。
  • staging 发布若影响 packages/daemonpackages/runtime、Server/daemon 公共协议或 Desktop 公共运行链, 必须把 server-stagingdaemon-staging 更新到同一精确 SHA;两者版本不一致不得宣告 staging 成功。
  • 只修 PR 范围内的 CI 失败;不为过检去改 CI/workflow 或做无关改动。

选择链路

  • 「发布/上线/部署生产」→ 生产发布链:阶段 1→2→4→5。
  • 「Desktop/桌面版打包、发布、上传 OSS」→ 阶段 1→2 后走 docs/desktop-oss-release.md 的 m5max 双平台链路。
  • 「盯 CI/合并 PR」→ 阶段 1→2(用 babysit 心态循环到 green + mergeable + 评论收口)。
  • 「复现/验证运行时行为、别碰生产」→ staging 预验链(阶段 3,可独立随时跑)。

阶段 1PR 与内网 gateci/internal-gate

真实门禁是内网 CIGitHub Actions 已停用)。检查与自查:

gh pr checks <PR>                       # 应见 ci/internal-gate
gh pr view <PR> --json state,mergeable,mergeStateStatus,isDraft,reviewDecision
  • 基础门(全 PR):release-contract / member-gate / authz-matrix / controlled-content-exits / onconflict-predicate / migration-idempotency / wsl-path-translation / typecheck / test(全量)。
  • 条件外部门(按改动路径):改 server DB/迁移/schema → postgresql-security;改 web → web-e2e android / daemon+desktop 各有门。
  • 本地复跑基础门可跑部分:pnpm -r typecheck && pnpm test

红了:只修本 PR 范围内的失败。疑似无关的合并阻塞→先 merge 最新 main(可能别的 PR 已修)。 BLOCKED: <label> requires <VAR> = runner 环境未配外部门命令,属运维问题,不是 PR 代码问题。

阶段 2:合并到 origin/main

合并前确认:mergeable=MERGEABLEmergeStateStatus=CLEAN、非 draft、ci/internal-gate 绿、评论收口。

gh pr merge <PR> --merge                # 仓库风格:merge commit

若本机 main 被其他 worktree 占用导致 --delete-branch 本地 checkout 失败(属本地副作用):

gh pr view <PR> --json state,mergedAt,mergeCommit   # 确认 GitHub 侧 MERGED
git push origin --delete <feature-branch>            # 删远端
git branch -D <feature-branch>                       # 删本地(先切走)

阶段 3:staging 真机预验(可选,随时)

3.1 当前权威路径:Slark 独立 staging

稳定目标是 AWS ap-southeast-2 实例 i-013e5ca3fdfddc13eName=slark-staging)。它使用自动分配 公网 IP,因此每次部署前先查询当前 IP;2026-08-18 核验值为 15.135.112.181

aws ec2 describe-instances --region ap-southeast-2 \
  --instance-ids i-013e5ca3fdfddc13e \
  --query 'Reservations[0].Instances[0].{Name:Tags[?Key==`Name`]|[0].Value,State:State.Name,PublicIp:PublicIpAddress}' \
  --output table

export STAGING_SSH_KEY=~/.ssh/cloud-server-syd.pem
export STAGING_REMOTE=ubuntu@15.135.112.181
export STAGING_REMOTE_IP=15.135.112.181
export STAGING_BASE=http://15.135.112.181

scripts/deploy-staging.sh --migrate-dry-run
scripts/deploy-staging.sh
STAGING_TOKEN=$(cat /tmp/.staging_token) scripts/staging-seed.sh
scripts/staging-verify-isolation.sh

不得把查询到的 Name 非 slark-staging 的机器当作目标。四件套细节与环境隔离约束见 docs/req-20260811-0059-staging-environment-design.md

3.2 非权威路径:ai-proj cohost(仅明确指定时)

ai-proj cohost 位于 ubuntu@82.157.141.202:/opt/slark-staging。全程使用隔离数据、数据库、密钥和状态目录, 但宿主机身份仍是 ai-proj staging;普通“Slark 预生产”不得走这里。仅在任务明确要求 cohost 兼容验收时, 先在干净的独立 worktree检出待验精确 SHA,再执行:

STAGING_SSH_KEY=~/.ssh/ai_proj_stg.pem \
STAGING_KNOWN_HOSTS_FILE=~/.ssh/known_hosts \
STAGING_REMOTE=ubuntu@82.157.141.202 \
STAGING_REMOTE_IP=82.157.141.202 \
  scripts/deploy-staging-cohost.sh

如果改动影响 daemon/runtime/公共协议,还需用 Compose daemon profile 更新 daemon-staging,并核对 Server/daemon revision 同为待验 SHA。

3.3 环境选择检查

普通 Slark staging 默认走 3.1;只有用户或需求明确说“ai-proj cohost”才走 3.2。任何验收都必须记录: 环境稳定身份、当次 IP、待验 40 位 SHA、Server/daemon revision/status、Server health 和目标功能结果。

routed-remote 要 network=enabled 必须同时满足:① agent workspace_access=write + repository_access=write;② per-agent 工作区是可写 git worktree。细节见 docs/req-20260811-0059-staging-environment-design.md。staging 刻意不碰 deploy.sh 的生产闸门。

阶段 4:生产发布(审批式)

唯一姿势:从干净的普通 clone 发布最新 origin/mainHEAD == origin/main 精确 SHA)。staging 可用 独立 worktree,但生产脚本为保证同步与发布边界,会拒绝 worktree;不要在用户已有脏 checkout 中清理或发布。

# 若当前仓库不是普通 clone,先在安全父目录创建一次性干净 clone:
git clone https://github.com/qiudl/qiu-slark.git <clean-production-clone>
cd <clean-production-clone>

git fetch origin main
test -d .git                                            # 必须通过;worktree 的 .git 是文件
git status --porcelain                                   # 必须干净
git checkout --detach "$(git rev-parse origin/main)"     # 在产品分支上时先 detach 到该 SHA

pnpm release:prod            # = release-prod.sh → deploy.sh --backend --no-install --no-mirror
# 备选:scripts/deploy.sh --pull --backend
  • deploy.shcheck-production-release-sha.shHEAD == origin/main SHA,不符即拒。
  • --backend 才跑迁移:owner 连接(DDL 权)与运行时 slark_app(DML-only)分离;幂等、失败即非零。
  • 命中审批闸(发布/sudo)→ 等人批;不要绕。脚本内部 SSH 载荷子进程的 sudo 不触发闸。
  • 普通工作 clone 发布完切回原分支:git checkout <branch>;一次性发布 clone 可保留作审计,清理时用可恢复方式。

阶段 5:发布后核查

scripts/verify-deploy.sh    # 健康(前端/api/health=200)、bundle、server/daemon SHA、迁移集、federation、凭据

预期 ✓ deploy verification passed: server=<sha> daemon=<sha><sha> == origin/main,舰队 online ≥ 发布前。 镜像落后告警(默认 --no-mirror)非阻断,需补推按告警的幂等命令(需 Bitwarden session);镜像仅单向 fast-forward。

Desktop m5max 双平台发布

Desktop 安装包不走 Server 生产部署脚本。权威流程见仓库 docs/desktop-oss-release.md,已验证基线为 REQ-20260819-0005 / Desktop 0.3.1

  • 版本 PR 通过 ci/internal-gate 并合并后,m5max 从最新 origin/main 精确 SHA 的干净普通 clone 构建。
  • m5max 原生构建、Developer ID 签名并公证/staple macOS DMG/ZIP;交叉构建 Windows x64 NSIS EXE。
  • Darwin 不能执行 Windows 原生 smoke:windows。只有发布负责人明确接手 Windows 原生验收时才能继续交叉打包,交付证据必须标注该边界。
  • 资产不回传开发机;由 m5max 直接上传 xiaoqu-public-file/slark/desktop/releases/v<version>/manifest 最后更新。
  • xiaoqu-public-file 的 canonical 凭证源是发布控制机上的 /Users/donglinlai/coding/param.rxt(必须为 0600);AK/SK 分别位于 XML 标签 ossAccessKeyId / ossAccessKeySecret。不得改猜 Bitwarden、Keychain、通用 credentials.env 或 m5max 本地配置;只有该文件缺失、权限不符或标签解析为空时才停止并报告。
  • m5max 不持久化 OSS 凭证。发布控制机从 param.rxt 提取 AK/SK 后,只用 printf '%s\n%s\n' ... | ssh m5max ... 经 SSH stdin 传两行;远端用 read -r 接收并仅为当次 shell 导出 OSS_ACCESS_KEY_ID / OSS_ACCESS_KEY_SECRET,随后运行上传脚本。禁止 scp 凭证文件、写远端临时文件或把值打印到日志。
  • m5max 非交互 SSH 必须显式补 PATH=/opt/homebrew/bin:/usr/local/bin:$HOME/.local/bin:$PATH;已验证 ossutil 位于 /Users/johnq/.local/bin/ossutil。执行前检查 Node、三个安装包、精确 main SHA 和干净工作树,避免因交互 shell 环境差异重新猜路径。
  • m5max 默认出口若走 utun,只为当次 ossutil 使用 --bind-address "$(ipconfig getifaddr en0)",不得修改整机 Tailscale/默认路由。
  • 完成前核对三份资产 SHA256/大小、macOS 签名与公证、公开 URL/manifest,并回写 ai-proj 证据。

推送路由自查(换机器/新克隆必做)

git remote -v                          # origin 收发都应是 https://github.com/qiudl/qiu-slark.git
git config --get-regexp '^url\.'       # 有输出 = pushInsteadOf 改写,push 可能被静默重定向到内网
scripts/git-release-governance.sh check-local
scripts/git-release-governance.sh status

故障分流

现象 处置
release-prod 拒绝 HEAD≠origin/main git fetch origin main 后 detach 到 origin/main SHA,工作树须干净
release-prod 拒绝 git worktree / .git 不是目录 改用干净的普通 clone,锁定最新 origin/main;不要在现有脏 checkout 中强行切换
ci/internal-gate red 看 gate 分组日志找 FAIL 项;pnpm -r typecheck && pnpm test 本地复现修复
BLOCKED: <label> requires <VAR> runner 未配外部门命令,报运维配 SLARK_CI_*_CMD,非 PR 问题
合并阻塞但与 PR 无关 merge 最新 main 再看
push 成功但 GitHub 没有 git config --get-regexp '^url\.',移除 pushInsteadOf 或显式指定 GitHub URL
staging routed-remote 恒断网 查两道放网杠杆(workspace_access=write + 可写 git worktree
cohost Server 已更新但 daemon 仍是旧 SHA --profile daemon up -d daemon-staging 更新 daemon;核对两容器 revision 后才算完成
cohost daemon 启动即退出/fatal docker logs slark_daemon_staging;修复凭据/环境或版本契约,禁止用旧 daemon 冒充验收通过
verify 失败 SHA 不符 部署到了旧码,重发

ai-proj 流程(强制)

任何改产品/代码行为的工作,动手前先在 ai-proj 立项 + 建 Task + 关联,实现/测试/交付回写; commit/PR 引用 REQ-...。纯文档/工具/只读排查除外。详见仓库 AGENTS.md / CLAUDE.md