Julia CI 日志排查实战:使用 buildkite-logs Skill 匿名抓取并分析 Buildkite 构建日志
【免费下载链接】juliaThe Julia Programming Language项目地址: https://gitcode.com/gh_mirrors/ju/julia
导读
Julia 的持续集成(CI)运行在 Buildkite 上,当 PR 测试失败或 master 构建挂起时,最快拿到第一手证据的方式是直接抓取构建日志。但 Buildkite 的公开网页需要登录才能下载raw_log,这对无人值守的调试流程很不友好。本指南基于仓库中的官方 Agent Skill(buildkite-logs,位于 doc/src/devdocs/agents/skills/buildkite-logs/SKILL.md),完整讲解如何仅用gh、curl、python3三个工具、不借助任何登录态,通过两个匿名可访问的前端 JSON 端点定位构建号、列出全部 job 并抓取单个 job 的完整日志,同时给出挂起测试(hung test)场景下的日志检索关键词与 core dump 线索,帮助你在 Buildkite MCP 不可用或需要快速核查时独立完成 CI 故障定位。
一、背景:Julia 的三条 Buildkite 管线与匿名抓取的原理
Julia 的 CI 由 Buildkite 承载,不同类型的构建分属不同管线:
julialang/julia-pr:PR 构建,每次 push 触发;julialang/julia-ci:master 合并后的构建;julialang/julia-master-scheduled:定时任务(旧的julia-master管线已不再存在)。
从仓库内可印证这一编排:构建系统说明文档 doc/src/devdocs/build/distributing.md 指出,发布分支的构建和测试由julia-ciBuildkite 管线承担,相关脚本托管在独立的构建系统仓库中;而 base/version_git.sh 中的build_system_directory="../.buildkite"也表明,在 Julia 完整源码树中.buildkite是构建系统的专属目录(本镜像仓库未包含该目录,其内容以独立仓库形式维护)。
关键事实:Buildkite 的公开网页端在下载raw_log时需要登录,但对于公开管线,有两个前端 JSON 端点可以匿名访问:
builds/<BUILD>/data/jobs—— 构建页前端自身用于渲染 job 列表的接口,一页返回全部 job;jobs/<JOB-UUID>/log—— 单个 job 的日志 JSON,文本存放在output字段中。
这两个端点就是本技能的全部数据来源。
二、前置条件
执行本技能需要:
gh(GitHub CLI):用于把 PR 号或 commit SHA 转换为构建号;curl:匿名请求 Buildkite 的 JSON 端点;python3:解析 JSON、剥离日志中的 HTML 与实体编码;- 能够访问 GitHub 与 Buildkite 的网络环境。
整个过程不需要 Buildkite API token,这正是该方案"免登录、免 MCP"的价值所在。
三、第 1 步:定位构建号(BUILD)
在发起任何请求前,先要确定目标构建号:
- PR 构建:运行
gh pr checks <PR-number>,输出中的 launcher-job URL 形如https://buildkite.com/julialang/julia-pr/builds/<BUILD>#<uuid>,从中即可提取构建号。 - master commit:改用 commit 状态接口
gh api repos/JuliaLang/julia/commits/<sha>/status获取对应的构建 URL。
需要特别注意的是:URL 中#<uuid>片段对应的只是顶层 launcher job(Build / Check / Test / …),并非每个平台的具体 job。真正的平台级 job(如各操作系统的编译与测试任务)必须通过第 2 步的/data/jobs端点枚举,这往往是被忽略的常见误区。
四、第 2 步:枚举构建内的全部 job
拿到构建号后,使用构建页前端同款接口拉取完整 job 列表:
curl -sS -H "Accept: application/json" \ "https://buildkite.com/julialang/<PIPELINE>/builds/<BUILD>/data/jobs" \ -o /tmp/bkjobs.json python3 -c "import json; [print(j['state'],'|',j.get('exit_status'),'|',j['name'],'|',j['id']) \ for j in json.load(open('/tmp/bkjobs.json'))['records']]"输出每一行的字段依次为:job 状态(state)、退出码(exit_status)、job 名称(name)、job UUID(id)。这些信息足以让你快速判断哪个平台、哪类任务(编译、测试、文档等)失败或挂起。
关于该接口的实现细节,从返回结构看:records是 job 数组,同时提供has_next_page字段。本技能明确建议不要使用builds/<BUILD>.json来做 job 发现——匿名访问时它只返回构建元数据,其jobs数组是空的(不过statistics字段仍会显示真实的 job 总数,可用作核对)。
五、第 3 步:抓取并清洗单个 job 的日志
确定目标 job 的 UUID 后,请求日志端点(将<PIPELINE>、<BUILD>、<JOB-UUID>替换为实际值):
curl -sS -H "Accept: application/json" \ "https://buildkite.com/organizations/julialang/pipelines/<PIPELINE>/builds/<BUILD>/jobs/<JOB-UUID>/log" \ -o /tmp/bk.json日志文本位于 JSON 的output字段中,但它是带格式的富文本:内嵌<time>时间戳、以<span>形式表示的 ANSI 颜色、以及实体编码(HTML entity)的 shell 输出。因此需要剥离标签并反转义,例如:
python3 -c "import json,re,html; s=json.load(open('/tmp/bk.json'))['output']; \ s=re.sub(r'<[^>]+>','',s); print(html.unescape(s))" > /tmp/bk.txt清洗后的纯文本务必写入文件后再检索,而不是整段灌入对话上下文——Julia 的单条 job 日志往往达数百 KB,直接整体传输既浪费 token 也难以定位关键信息。
该端点同样支持仍在运行中的 job:它会返回部分输出(partial output),因此可以用于观察长时间卡住的任务的实时进展。
六、挂起测试的日志检索:watchdog 与 core dump 线索
当某个测试 job 挂起(hung)时,构建系统内置的看门狗(watchdog)会在杀死任务前,打印每个 worker 的 per-task Julia 回溯。日志中应当检索以下关键词:
---- Task:各 worker 的任务回溯分隔标记;Waiting for:等待点信息,指示任务阻塞的位置;core dumped:core dump 产物上传为构建 artifact 的标志。
对应机制在源码结构上可追溯:构建系统仓库中的.buildkite/utilities/timeout.jl实现了超时处理逻辑,受环境变量JL_TERM_TIMEOUT控制(本镜像仓库不含.buildkite目录,该脚本随独立维护的构建系统仓库分发)。core dump 被上传为 artifact 后,日志末尾会附带一条lldb bt all的摘要,可直接用lldb对 dump 文件执行bt all获取全线程调用栈,定位挂起根因。
七、与其它 Agent Skill 的配合使用
buildkite-logs属于 Julia 官方 Agent Skills 体系,仓库的 doc/src/devdocs/agents/README.md 说明了其定位:所有 Skill 的权威版本(canonical)统一存放在doc/src/devdocs/agents/skills/,.agents/skills/与.claude/skills/只是供 Agent 自动发现的符号链接,修改必须走 canonical 路径。该文档同时列出全部 8 个 Skill,其中与本技能互补的是ci-timing:
- 当需要比较一个 PR 的 Buildkite job 时长与近期 CI 基线(过去 N 天的均值/最小/最大)时,运行
julia --startup-file=no --project=contrib/ci-timing contrib/ci-timing/ci_timing_compare.jl <PR-number>即可,无需 Buildkite token,仅靠gh把 PR 号转成构建号; - 而当某个 job 变慢或失败、需要深入日志时,
ci-timingSkill 明确指引"参见buildkite-logs技能"。
两者形成"先看时长趋势、再看具体日志"的完整 CI 诊断链路。
八、实操要点总结与注意事项
- 构建号来源:PR 用
gh pr checks,master commit 用gh api repos/JuliaLang/julia/commits/<sha>/status; - job 发现:只信任
/data/jobs端点(含records),不要用builds/<BUILD>.json(匿名时jobs为空); - 日志清洗:
output字段含<time>、<span>等 HTML 与 ANSI 颜色,必须剥离标签 +html.unescape; - token 纪律:抓取过程完全匿名,无需登录、无需 API token,适合 MCP 不可用时的应急排查;
- 挂起定位:检索
---- Task、Waiting for、core dumped,配合上传的 core dump artifact 与lldb bt all摘要进一步分析; - 日志体积:写入本地文件再
grep/搜索,避免大文本进入上下文。
遵循上述流程,即可在不登录 Buildkite 网页的情况下,完成从"拿到构建号"到"读取单个 job 清洗后的完整日志"的端到端 CI 排障,显著加快 Julia 相关 CI 失败与挂起问题的定位速度。
【免费下载链接】juliaThe Julia Programming Language项目地址: https://gitcode.com/gh_mirrors/ju/julia
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考