Tambo 外部发布更新周报 Playbook:基于 GitHub Release 与 Linear 的每周自动外发工单实践
2026/9/15 13:58:46 网站建设 项目流程

Tambo 外部发布更新周报 Playbook:基于 GitHub Release 与 Linear 的每周自动外发工单实践

【免费下载链接】hydra-aiGenerative UI SDK for React项目地址: https://gitcode.com/GitHub_Trending/hy/hydra-ai

导读

external-release-update.md是 Tambo(本仓库 hydra-ai 的开源 Generative UI SDK 项目)在.charlie/playbooks/下定义的一份周维度主动式(proactive)Playbook,用于自动汇总上周对 Tambo 外部开发者有影响的全部 GitHub Release,并生成一张发往 LinearTAM团队的周报工单。读完本文你将掌握:如何用 GNUdate+ghCLI +jq精确计算「洛杉矶时区上周一至周日」的发布窗口、如何将本地时区边界无损转换为 UTC 时间戳并与 GitHubpublishedAt对齐、如何按 tag 前缀将多包发布分组为面向外部开发者的 changelog,以及如何遵守该 Playbook 的 Guardrails 与 No-op 规则避免噪声工单。

一、Playbook 定位:它解决什么问题

Tambo 是一个 monorepo,同时发布多个对外包:React SDK(@tambo-ai/react)、TypeScript SDK(@tambo-ai/typescript-sdk)、CLI(tambo)、文档站、Showcase 以及 Tambo Cloud 的 API/Web 应用。发布动作由 release-please 自动驱动(详见 RELEASING.md),每天都会有新的 GitHub Release 产生。对 Tambo 的开发者用户而言,最关心的是「上周有没有新特性、有没有破坏性变更、有没有 API 变化需要迁移」——而不是零散的内部 chore。

这份 Playbook 的产出正是一份面向外部开发者的每周发布摘要

  • Artifact:1 张 Linear issue
  • TeamTAM
  • 标题模式External release update: <YYYY-MM-DD>–<YYYY-MM-DD>

它由.charlie/config.yml中的beta.proactive配置注册为每日运行(Playbook 中解释了为什么「每日运行 + 仅周一执行」等价于周报):

beta: proactive: - playbook: ".charlie/playbooks/external-release-update.md" - playbook: ".charlie/playbooks/team-update.md" # ... 其余 playbook

与同目录下的 team-update.md(面向内部团队,汇总 merged PR、贡献者、已完成 issue)互为补充:external-release-update只关注外部开发者视角

Guardrails(内容边界)

  • 只关注外部开发者影响:新特性、破坏性变更、迁移指南、API 更新。
  • 跳过纯内部 chore,除非它会改变外部可见行为,例如:
    • auth 变更
    • 构建产物(build output)变化
    • 影响使用方的依赖升级

二、数据采集:时区窗口计算是核心难点

所有 proactive 行为当前都是每日运行的。为了把「每日」变成「每周」,Playbook 的做法是:只在洛杉矶时间(America/Los_Angeles)的周一 00:00 触发时,把统计窗口定义为「上一个周一 00:00 ~ 周日 24:00」

真正的技术难点在于:GitHub 的publishedAt是 UTC 时间戳,而报告窗口是以洛杉矶本地日界定义的。若只比较YYYY-MM-DD字符串会因时区偏移与夏令时(DST)产生边界错位,因此必须把 LA 本地窗口边界换算成 UTC 时间戳再比较。

2.1 前置条件:GNU date

以下脚本依赖 GNUdate-d@epoch语法(Linux/Devbox 自带)。macOS 默认 BSDdate不兼容,需安装coreutils并使用gdate。脚本自带探测与提示逻辑:

if command -v gdate >/dev/null 2>&1; then DATE_BIN=gdate else DATE_BIN=date fi # Verify GNU-compatible `date` support for -d and @epoch. if ! "$DATE_BIN" -d @0 +%s >/dev/null 2>&1; then cat >&2 <<'EOF' This script requires GNU date (supports `-d` and @epoch). On macOS, the default `date` is BSD and will not work; install GNU coreutils and use `gdate`: brew install coreutils # then ensure `gdate` is on PATH On Debian: apt-get install coreutils On Alpine: apk add coreutils EOF exit 1 fi

2.2 计算 LA 本地窗口并转换为 UTC

核心思路:先算出「昨天」(即周日)作为end_date,往前推 6 天得到start_date(周一),再取next_date作为排他上界。随后把start_date 00:00next_date 00:00两个 LA 本地时刻转成 Unix 时间戳,最后用-u输出为 UTC ISO 字符串:

export TZ=America/Los_Angeles end_date=$($DATE_BIN -d 'yesterday' +%F) start_date=$($DATE_BIN -d "$end_date -6 days" +%F) next_date=$($DATE_BIN -d "$end_date +1 day" +%F) # Define the LA-local window, then convert to UTC ISO timestamps for comparison # with GitHub's `publishedAt` values. `start_ts` is inclusive; `next_ts` is the # exclusive upper bound. start_epoch=$($DATE_BIN -d "$start_date 00:00" +%s) next_epoch=$($DATE_BIN -d "$next_date 00:00" +%s) start_ts="$($DATE_BIN -u -d "@$start_epoch" +%FT%T)Z" next_ts="$($DATE_BIN -u -d "@$next_epoch" +%FT%T)Z" echo "window: $start_date..$end_date" echo "start_ts (UTC): $start_ts" echo "next_ts (UTC): $next_ts"
  • start_ts包含下界,next_ts排他上界(即publishedAt >= start_ts && publishedAt < next_ts)。
  • 由于 LA 存在夏令时切换,end_date 00:00next_date 00:00可能是 23 或 25 小时,直接字符串比较YYYY-MM-DD会在切换周出错——这正是必须比较完整 UTC 时间戳的原因。

三、拉取与过滤 GitHub Release

有了start_ts/next_ts后,用gh release list拉取发布列表,再用jq过滤窗口内的条目。Playbook 给出了带错误处理与容量告警的完整脚本:

: "${start_ts:?start_ts must be set (see snippet above)}" : "${next_ts:?next_ts must be set (see snippet above)}" RELEASE_LIMIT="${RELEASE_LIMIT:-500}" releases_file=$(mktemp 2>/dev/null) || { echo "Error: failed to create temporary file for releases." >&2 exit 1 } trap 'rm -f "$releases_file"' EXIT # Note: this assumes you've already computed `start_ts`/`next_ts` in the snippet # above. if ! gh release list --limit "$RELEASE_LIMIT" --json tagName,name,publishedAt,url > "$releases_file"; then echo "Error: failed to fetch releases via gh CLI." >&2 exit 1 fi count=$(jq 'length' "$releases_file") if [ "$count" -eq 0 ]; then echo "No releases returned by gh for this window; nothing to process." >&2 fi if [ "$count" -ge "$RELEASE_LIMIT" ]; then echo "Warning: fetched $count releases (limit=$RELEASE_LIMIT); there may be additional releases in the window. Consider increasing RELEASE_LIMIT." >&2 echo "Hint: re-run with a higher limit, e.g. 'RELEASE_LIMIT=2000 ...'" >&2 earliest=$(jq -r 'map(.publishedAt) | min // empty' "$releases_file") earliest_epoch=$($DATE_BIN -d "$earliest" +%s 2>/dev/null || echo "") start_epoch_check=$($DATE_BIN -d "$start_ts" +%s 2>/dev/null || echo "") if [ -n "$earliest_epoch" ] && [ -n "$start_epoch_check" ] && [ "$earliest_epoch" -gt "$start_epoch_check" ]; then echo "Warning: earliest fetched release ($earliest) is after start_ts ($start_ts); older releases in the window may be missing. Consider increasing RELEASE_LIMIT." >&2 echo "Hint: increase RELEASE_LIMIT and re-run the fetch step." >&2 fi fi # Note: `$start_ts` and `$next_ts` are UTC timestamps derived from LA-local day # bounds, and can be compared to GitHub's `publishedAt` (UTC). jq -r --arg start_ts "$start_ts" --arg next_ts "$next_ts" ' map(select(.publishedAt >= $start_ts and .publishedAt < $next_ts)) | sort_by(.publishedAt) | .[] | {tagName,name,publishedAt,url} | @json ' "$releases_file"

关键设计点:

  1. RELEASE_LIMIT默认 500,可用环境变量覆盖;当拉取数达到上限时脚本会主动告警,并通过比对「最早 release 的发布时间」与start_ts判断窗口内是否可能有遗漏,提示提高上限重跑。
  2. mktemp+trap 'rm -f ...' EXIT保证临时文件清理,避免残留。
  3. 过滤采用sort_by(.publishedAt)保证输出按时间升序,便于后续按周组织。

四、获取完整 Release Notes 并按包分组

对窗口内的每个 release,拉取完整正文:

gh release view <tagName> --json tagName,name,publishedAt,url,body

然后按 tag 前缀分组到对应的包/组件。Playbook 给出了本仓库的实际分组规则(该规则与 release-please-config.json 中的include-component-in-tag/include-v-in-tag配置一一对应):

Tag 前缀对应的包/组件
react-v*@tambo-ai/react
tambo-v*tamboCLI
docs-v*@tambo-ai/docs
showcase-v*@tambo-ai/showcase
api-v*/web-v*Tambo Cloud apps

源码层面的印证

查看 .config/release-please/release-please-config.json 可以看到每个 package 的 tag 生成方式:

  • react-sdk配置为"component": "react"include-component-in-tag: trueinclude-v-in-tag: true→ 生成react-v*形式的 tag;
  • cli配置为"component": "tambo"→ 生成tambo-v*
  • apps/apiapps/web未设置 component → 按目录名生成api-v*web-v*
  • docsshowcase同理对应docs-v*showcase-v*

实际版本追踪见 .release-please-manifest.json,例如apps/api0.146.1cli0.56.2react-sdk1.3.0,对应的 tag 即api-v0.146.1tambo-v0.56.2react-v1.3.0。而各包 CHANGELOG 中的 tag 链接(如 packages/react-ui-base/CHANGELOG.md 中的@tambo-ai/react-ui-base-v0.1.12)也证实了「component-v版本号」的 tag 约定,脚本按 tag 前缀分组是可靠的。

说明:monorepo 内新增的包(如@tambo-ai/react-ui-basecreate-tambo-app)出现后,实际运行时可能产生 Playbook 示例之外的 tag 前缀,建议按 release-please-config.json 中的 packages 列表动态扩充分组规则。

五、No-op 条件:何时跳过本次运行

Playbook 明确给出两条跳过条件,防止产生空工单:

  1. 今天不是洛杉矶时间的周一

    test "$(TZ=America/Los_Angeles date +%u)" = "1"

    %u输出 1(周一)~7(周日),test ... = "1"为真表示周一才继续。

  2. 报告窗口内没有任何 GitHub Release(上一步jq过滤结果为空)。

六、执行步骤:从数据到 Linear 工单

  1. 计算start_dateend_date(洛杉矶时区,上一个周一~周日)。
  2. 列出窗口内发布的 GitHub Release,并按包/组件分组。
  3. 对每个包/组件,从 release notes 中提炼外部相关条目,改写为简短 changelog:
    • 新特性(New features)
    • 破坏性变更(Breaking changes,附迁移说明)
    • API 更新 / 弃用(API updates / deprecations)
    • Bug 修复(仅限外部可见的)
  4. 在 LinearTAM团队创建标题为External release update: <start_date>–<end_date>的 issue,Markdown 正文包含:
    • 明确的日期窗口
    • 按包维度的摘要(bullet 列表)
    • 每个 GitHub Release 的链接

七、验证清单(Verify)

创建工单后按下述标准自检:

  • 工单的窗口是明确且正确的(America/Los_Angeles,周一~周日);
  • 引用的每个 GitHub release 链接都能解析;
  • 摘要面向外部开发者(避免混入仅内部的工作)。

八、发布机制的背景知识

要真正读懂这份 Playbook 的 tag 约定与「外部可见变更」口径,需要理解 Tambo 的发布流水线(详见 RELEASING.md):

  • 所有 Tambo 仓库由release-please管理,Conventional Commits 提交合并后自动生成/更新 release PR,合并后触发 GitHub Release;库发布到 NPM,应用部署到 Vercel/Railway。
  • @tambo-ai/typescript-sdk由 OpenAPI spec 经stlc(Stainless 的 source-available CLI,托管在自有 CI 中)生成,属于外发 API 变更的高频来源。
  • release-please 配置中separate-pull-requests: truenode-workspace插件(见 release-please-config.json)保证每个包独立发版,这正是 Playbook 需要按 tag 前缀分组的根本原因——一个窗口内往往同时存在多个包的 release。

理解这条流水线后,「哪些变更会落到 GitHub Release 上」与「哪些是外部可见」的判断会更准确,比如 SDK 生成结果变化(build output 变更)就是 Guardrails 中明确要求关注的外部影响点。

九、参考文件索引

  • Playbook 本体:.charlie/playbooks/external-release-update.md
  • 同类周报 Playbook(内部视角):.charlie/playbooks/team-update.md
  • Proactive 注册配置:.charlie/config.yml
  • release-please 包与 tag 配置:.config/release-please/release-please-config.json
  • 版本追踪 manifest:.config/release-please/.release-please-manifest.json
  • 发布流程文档:RELEASING.md
  • 各包 CHANGELOG(tag 格式实例):packages/react-ui-base/CHANGELOG.md

【免费下载链接】hydra-aiGenerative UI SDK for React项目地址: https://gitcode.com/GitHub_Trending/hy/hydra-ai

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询