Why:
After the repository moves forward, updating a running service meant
manually figuring out the new commit, rebuilding and redeploying by hand;
the user asked for the tool to detect and update automatically.
Evidence:
- "update [name...] [--check] [--all] [--no-fetch]": fetches origin,
compares each service's registered source against the latest (Dev repo
origin/main for local@/dev@ sources, newest Releases version for
release@), prints a per-service table (current / latest / state), and
without --check refreshes outdated running services by reusing the full
deploy pipeline (stop → build/verify → start → health check; persisted
exec= config and tags survive; update events appended to history).
- local@ services: auto git pull --ff-only origin main + make sync before
rebuilding, guarded three ways (current branch == main, clean worktree,
ff-only) — dirty trees or non-main branches are skipped with a warning,
never touching uncommitted work.
- dev@ sources go straight to the remote main commit via an isolated
worktree; release@ sources deploy the newest Releases version with
sha256 verification; postgres and static --dir services are reported as
not applicable; sources that diverged from or lead the remote are never
force-updated.
- Verified end to end with five test services: dev@73b2802 → dev@ffda6d3
(real isolated build, HTTP 200, tag/port preserved, worktree recycled),
non-main-branch skip, stopped-service warning vs --all, release
sha256-verified update, --check read-only (svc.env checksums unchanged),
unregistered name exits 2.
- Fixed en route: a latent bug from the v2 refactor — materialize_dev_commit
leaked submodule/make stdout into the captured worktree path, breaking
every real dev@sha deploy since (cp: File name too long); build output
now goes to stderr. Also fixed an unbound-variable crash in the update
loop (local statement self-reference under set -u).
Impact:
New read-mostly operational command; no behavior change to existing
commands except dev@sha deploys now actually working end to end.
Makefile gains svc-update; --help and docs/svc.md document the command.
Refs: .task/feature-svc-auto-update.md(任务卡=PR 描述)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
feature/svc-auto-update 任务卡
任务主记录:<PR 链接,task-finish 时填写>;状态:进行中;owner:weichen
基线与授权
ffda6d33ea终点 = 实现合入 main 并回收工作区。仅改 Dev 仓 scripts/svc.sh / Makefile / docs/svc.md。
目标与非目标
目标:新增
svc.sh update [name...] [--check] [--all] [--no-fetch]——fetch 远端 → 逐服务比较登记 source 与最新(Dev 仓 origin/main / Releases 最新版本)→
--check 只报告;否则更新过时且运行中的服务(点名/--all 含已停止)。local 源自动 pull
三重防护(分支==main + 树干净 + --ff-only);dev@ 源部署远端 main 最新(隔离 worktree);
release@ 源部署 Releases 最新(sha256 校验);postgres/static --dir 不适用。复用 deploy
全链路与持久化配置;update 事件入 history。Makefile 加 svc-update;帮助与文档同步。
非目标:不做常驻轮询/守护(--watch 不在本轮);不自动 pull Releases 仓以外的主检出分支;
不处理 local 源工作树的未提交变更内容(脏树=跳过)。
同步记录
ffda6d33eaffda6d33ea关键实现与修复记录
git submodule update 与 make 的 stdout 混入捕获值 → 产物路径损坏(cp: File name too
long)。dev@sha 源的真实部署自 v2 起实际不可用(此前仅 dry-run 覆盖)。修复:构建期
stdout 全部改走 stderr,stdout 只留 worktree 路径。已实测修复后 dev@73b2802 部署成功。
local name=... rest=... from="${rest%%|*}..."同语句后项引用前项,set -u 下 unbound variable。拆分两条 local 语句。
结果与验证(完成后填写)
svc-update;--help(命令表/短帮助/lifecycle 主题)与 docs/svc.md(6.3 节/上手/配方/
事件表/排查表)同步;RESERVED_ENVS 加 update。
可更新 → update devold → 隔离构建
ffda6d3组合 → source=dev@ffda6d3、HTTP 200、标签 updtest 与端口 8794 保留(复用持久化 exec=)→ 构建 worktree 回收。
非 main——跳过自动 pull",汇总 跳过=1、exit 0、登记未动。"领先远端 main(不动作)"
路径由 local@ 天然覆盖(feature 分支领先 origin/main)。
sha256 校验通过)。
并在报告注明。history 记录 update begin/ok 事件。
真实使用首次触发验证;--watch 常驻轮询未做(用户选择按需命令);dirty-tree 跳过路径
代码就位(同防护块),工作区(feature 分支)无法真实触发,与 pull 路径一并留待验证。