Skip to content

chore(ops): track deploy-frontend.sh and its launchd plist - #443

Merged
jhfnetboy merged 3 commits into
masterfrom
chore/track-deploy-script
Aug 1, 2026
Merged

chore(ops): track deploy-frontend.sh and its launchd plist#443
jhfnetboy merged 3 commits into
masterfrom
chore/track-deploy-script

Conversation

@jhfnetboy

@jhfnetboy jhfnetboy commented Aug 1, 2026

Copy link
Copy Markdown
Member

把前端生产部署路径完整收进仓库:部署脚本 + 它依赖的 launchd 定义。

1. deploy-frontend.sh(根目录)

这个脚本一直在工作区里未跟踪,但它是前端实际的生产部署路径 —— 它编码的运维知识此前只存在于一台机器上。

它知道仓库里别处没有的事:前端跑在 launchd agent io.aastar.yaa-frontend 下(KeepAlive + RunAtLoadnext start -p 5173),前面挂 cloudflared 隧道。所以只跑 npm run build 是不够的 —— 正在运行的进程仍服务旧的 chunk manifest,/_next/static/chunks/* 返回 500,hydration 失败,白屏

脚本:build → kickstart agent → 等 :5173 → 逐个校验首页引用的每个 JS/CSS chunk 是否 200--public 再走一遍 Cloudflare 端到端)。且 build 失败时拒绝重启,坏构建不会把正在跑的站点带下去。

放根目录,和现有 backend.sh / dev.sh / frontend.sh 并列 —— frontend.sh 起开发,这个部署生产。模式 100755

2. scripts/ops/io.aastar.yaa-frontend.plist

没有它,脚本的前置条件在仓库里重建不出来 —— 只会报 launchd agent not loaded,而读者无从得知这个 agent 该长什么样。

从本机运行中的 ~/Library/LaunchAgents/ 定义原样复制。验证方式:plutil -lint 通过,并把两个文件都经 plutil -convert xml1 归一化后 diff —— 除新增的注释头外完全一致,即提交的就是本机在跑的那份。

遵循同目录 io.aastar.yaa-monitor.plist 已定的约定:带绝对 /Users/jason 路径原样提交(不做模板化),配一个安装命令注释头。注释头额外标注了写死的 nvm node 路径(v22.22.2)—— node 升级后 agent 会静默启动失败,唯一线索是 ~/Library/Logs/yaa-frontend.log

Verification

结果
bash -n deploy-frontend.sh 通过
plutil -lint plist OK
plist 与本机运行版归一化 diff 一致
密钥扫描(secret/token/key/长 hex) 两个文件均无命中
git ls-files -s 100755 可执行位保留

Claude-Session: https://claude.ai/code/session_01BxmyQj2A82DfFXu97kKACk

This has been sitting untracked in the working tree while being the actual
production deploy path for the frontend, so the knowledge it encodes lived on
one machine only.

What it knows that nothing else in the repo does: the frontend runs under the
launchd agent `io.aastar.yaa-frontend` (KeepAlive + RunAtLoad, `next start -p
5173`) behind the cloudflared tunnel, so `npm run build` alone leaves the
*running* process serving a stale chunk manifest — /_next/static/chunks/*
return 500, hydration fails, white screen. The script builds, kickstarts the
agent, waits for :5173, then verifies every chunk the homepage references
returns 200 (`--public` runs the same check through Cloudflare end-to-end).
It also refuses to restart if the build fails, so a broken build can't take the
running site down.

Sits at the repo root next to the existing dev helpers (backend.sh / dev.sh /
frontend.sh) — frontend.sh starts dev, this deploys prod. Mode 100755, no
secrets (public hostname, port and agent label only).

Gap noted, not addressed here: the referenced `io.aastar.yaa-frontend.plist`
lives in ~/Library/LaunchAgents and is still untracked, so the script's
precondition can't be reproduced from the repo. `scripts/ops/` already tracks
io.aastar.yaa-monitor.plist and would be its natural home — left out because
that file is machine-specific and its contents should be reviewed before
committing.

Claude-Session: https://claude.ai/code/session_01BxmyQj2A82DfFXu97kKACk
@jhfnetboy
jhfnetboy requested a review from fanhousanbu as a code owner August 1, 2026 16:19

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 21e6af1a6b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread deploy-frontend.sh
# 4) verify every referenced JS/CSS chunk is 200 (this is the white-screen guard)
verify_chunks() {
local base="$1" label="$2" total=0 bad=0 code
local home; home="$(curl -s "$base/")" || die "$label: could not fetch homepage"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail public verification on HTTP errors

When --public is used and Cloudflare/the public origin returns an HTTP error page such as 404 or 502, curl -s still exits successfully unless --fail is used (curl --help all describes --fail as failing on HTTP errors). That error HTML can contain no /_next/static/... links, leaving total=0 and bad=0, so the script reports deploy OK even though the end-to-end public site is down; check the homepage status or use curl -fsS before accepting the chunk check.

Useful? React with 👍 / 👎.

Without this, the script's own precondition can't be reproduced from the repo —
it just dies with "launchd agent io.aastar.yaa-frontend not loaded" and the
reader has no way to find out what that agent should contain.

Copied verbatim from the running ~/Library/LaunchAgents/ definition; verified
with `plutil -lint` and by diffing both files through `plutil -convert xml1`,
which match apart from the added comment header. No secrets (paths, a label and
a node path only).

Follows the convention io.aastar.yaa-monitor.plist already set in this
directory: committed as-is with absolute /Users/jason paths rather than
templated, plus an install-command header. The header additionally flags the
pinned nvm node path (v22.22.2), because a node upgrade makes the agent fail to
start silently — the only trace is ~/Library/Logs/yaa-frontend.log.

Claude-Session: https://claude.ai/code/session_01BxmyQj2A82DfFXu97kKACk
@jhfnetboy jhfnetboy changed the title chore(ops): track deploy-frontend.sh chore(ops): track deploy-frontend.sh and its launchd plist Aug 1, 2026

@clestons clestons left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — #443 (chore(ops): track deploy-frontend.sh + its 依赖的 launchd plist)

结论:APPROVE

把之前一直躺在工作区里没纳入版本控制、但实际是生产部署路径的 deploy-frontend.sh 和它依赖的 io.aastar.yaa-frontend.plist 收进仓库。2 个 commit,逻辑自洽:脚本本身 + 它引用的 launchd agent 定义,PR 描述里说得很清楚这两个东西为什么绑在一起(脚本的 precondition 靠 plist 才能在仓库里复现)。

独立动手验证(不是只信 PR 自述)

  • bash -n deploy-frontend.sh → 语法通过
  • 密钥扫描(grep -iE "sk-|api[_-]?key|secret|token|password|-----BEGIN") → 干净,没有真凭据
  • plutil -lint 新增的 plist → OK
  • 把 PR 里的 plist 跟你机器上实际装着的 ~/Library/LaunchAgents/io.aastar.yaa-frontend.plist 做了字节级 diff(先各自转成 xml1 规范化格式)——完全一致,坐实了 PR 描述里"逐字拷贝、已验证匹配"这个说法
  • 文件权限确认 deploy-frontend.sh755(可执行),符合预期

PK Summary

  • R1 DeepSeek(flash):跑了,2 条 finding,都站不住。① 说 curl -s "$base/" 没有 || die 兜底失败——直接读 diff,这行就在那,|| die "$label: could not fetch homepage" 字面意思都对不上它说的"没有"。② 说 chunk 正则可能漏掉带 query string 的 URL——技术上这条正则确实会把 ?v=123 这类后缀从匹配结果里去掉,但去掉 query string 不影响静态文件本身能不能拿到 200(chunk 文件本身不靠 query string 才能命中),所以"会漏掉验证"这个结论不成立,顶多是"验证的时候没带上 query string",检查本身不受影响。
  • Codex PK:跳过。纯 ops 脚本/配置追踪,我自己动手验证(语法+密钥扫描+plist 校验+跟活体文件字节比对)已经比读代码更硬,没有可对抗的业务逻辑。

自评 — #443

  • 轮数:R1 DeepSeek(真跑)+ 我独立动手验证(bash -n / 密钥扫描 / plutil -lint / 跟你机器上活体 plist 字节比对)。纯 ops 追踪 PR,未跑 Codex PK。
  • 机械证据:全部是真实命令的输出(不是读代码猜),尤其是跟活体 ~/Library/LaunchAgents/ 里的文件做字节级比对,这个验证力度比单纯审 diff 更强。
  • DeepSeek flash 评级:1/5 —— 2 条 finding 一条是明显误读自己输入内容的假阳性(跟之前几轮同类错误一样),一条技术上有影可循但结论不成立。样本 10/20,进度过半。
  • 与 skill 设计一致,未跑 Codex PK(无可挑战逻辑,我自己的动手验证已经足够)。

R1 DeepSeek 真跑 + 独立动手验证(语法/密钥扫描/plist lint/跟活体文件字节比对),纯 ops PR 未跑 Codex PK。

@jhfnetboy
jhfnetboy merged commit 3f5981e into master Aug 1, 2026
11 of 13 checks passed
@jhfnetboy
jhfnetboy deleted the chore/track-deploy-script branch August 1, 2026 16:49
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants