- CI/CD
- DevOps
【免费下载链接】woodpecker
Woodpecker is a simple, yet powerful CI/CD engine with great extensibility.
状态徽章(Status Badge)是 Woodpecker CI/CD 内置的仓库状态展示能力,可通过一个 SVG 图片端点把默认分支上最近一次流水线的构建结果直接嵌入到网站首页或项目 README 中。本文将以 80-badges.md 为主线,结合 server/api/badge.go、server/badges/badges.go 等源码,完整讲解徽章端点的 URL 结构、branch/events/workflow/step等查询参数、状态与颜色映射规则,以及后端从取数到渲染 SVG 的完整调用链,帮助你快速把 Woodpecker 流水线状态接入任何外部页面。
什么是状态徽章
Woodpecker 为每个仓库内置了状态徽章(status badge)支持。徽章本质上是一张由服务端动态生成的 SVG 图片,展示仓库代码的流水线构建状态,可以方便地嵌入到你的网站或项目 README 文件中。与直接查看 Web UI 相比,徽章是一种轻量、可分享、可嵌入的实时状态展示方式,非常适合开源项目首页、文档站点或团队内部看板。
徽章由服务端渲染并即时返回,其内容始终反映当前仓库最近一次流水线的真实结果,而不是一张静态图片,因此无需手动更新。
徽章端点(Badge Endpoint)
状态徽章的访问端点为:
<scheme>://<hostname>/api/badges/<repo-id>/status.svg其中<scheme>与<hostname>是你部署的 Woodpecker 服务地址,<repo-id>是仓库在 Woodpecker 中的数字 ID。例如,如果你的服务部署在https://ci.example.com,仓库 ID 为42,则徽章 URL 为:
https://ci.example.com/api/badges/42/status.svg在 README 中通常这样嵌入:
值得注意的是,路由的实际注册方式支持两种形式。从 server/router/api.go 可以看到,徽章端点同时注册了按仓库 ID 和按「所有者 + 仓库名」两种路径:
badges := apiBase.Group("/badges/:repo_id_or_owner") { badges.GET("/status.svg", api.GetBadge) badges.GET("/cc.xml", api.GetCC) } _badges := apiBase.Group("/badges/:repo_id_or_owner/:repo_name") { _badges.GET("/status.svg", api.GetBadge) _badges.GET("/cc.xml", api.GetCC) }对应到 server/api/badge.go 中的处理逻辑:如果 URL 中带有repo_name参数,则按owner/repo名称查询仓库;否则将repo_id_or_owner解析为数字仓库 ID。也就是说,除了数字 ID,你也可以用可读的仓库名形式:
<scheme>://<hostname>/api/badges/<owner>/<repo>/status.svg例如https://ci.example.com/api/badges/woodpecker-ci/woodpecker/status.svg。需要提醒的是,数字 ID 形式要求传入合法整数,否则接口会直接返回400 Bad Request。
指定分支:branch 参数
状态徽章默认展示默认分支(例如main)上最近一次构建的状态。你可以在查询字符串中追加branch参数来指定其他分支:
-<scheme>://<hostname>/api/badges/<repo-id>/status.svg +<scheme>://<hostname>/api/badges/<repo-id>/status.svg?branch=<branch>例如展示develop分支的状态:
https://ci.example.com/api/badges/42/status.svg?branch=develop从源码看,branch参数的默认值取自仓库配置的默认分支。在 server/api/badge.go 中:
branch := c.Query("branch") if len(branch) == 0 { branch = repo.Branch }也就是说:显式传入branch时使用传入值,否则回退到仓库的默认分支。查询底层落在 server/store/datastore/pipeline.go 的GetPipelineBadge:
func (s storage) GetPipelineBadge(repo *model.Repo, branch string, events []model.WebhookEvent) (*model.Pipeline, error) { pipeline := new(model.Pipeline) return pipeline, wrapGet(s.engine. Desc("number"). Where(builder.Eq{"repo_id": repo.ID, "branch": branch}). Where(builder.In("event", events)). Where(builder.Neq{"status": model.StatusBlocked}). Get(pipeline)) }可见徽章取的是该分支上number最大的流水线,同时要求其事件类型在指定集合内、且状态不是blocked(例如因审批门控被阻塞的流水线不会被计入)。
限定事件类型:events 参数
默认情况下,状态徽章不包含拉取请求(pull request)的结果,因为 PR 的构建状态并不能准确代表仓库主干代码的真实状态。默认徽章只反映最近一次push 事件的状态。
如果你希望纳入其他或更多事件类型,可以追加events查询参数,多个事件用逗号分隔:
-<scheme>://<hostname>/api/badges/<repo-id>/status.svg +<scheme>://<hostname>/api/badges/<repo-id>/status.svg?events=manual,cron例如同时统计push、tag与manual事件:
https://ci.example.com/api/badges/42/status.svg?events=push,tag,manualevents参数可用的合法取值定义在 server/model/const.go 中,完整枚举如下:
| 事件值 | 含义 |
|---|---|
push | 代码推送(默认) |
pull_request | 拉取请求 |
pull_request_closed | 拉取请求关闭 |
pull_request_metadata | 拉取请求元数据变更 |
tag | 标签推送 |
release | 发布 |
deployment | 部署 |
cron | 定时任务触发 |
manual | 手动触发 |
在 server/api/badge.go 中,未传events时默认使用push;传入了则按逗号切分,并逐一对事件值调用Validate()校验,遇到非法值会返回400 Bad Request:
var events []model.WebhookEvent eventsQuery := c.Query("events") // If none given, fallback to default "push" if len(eventsQuery) == 0 { events = []model.WebhookEvent{model.EventPush} } else { strEvents := strings.Split(eventsQuery, ",") events = make([]model.WebhookEvent, len(strEvents)) for i, strEvent := range strEvents { event := model.WebhookEvent(strEvent) if err := event.Validate(); err == nil { events[i] = event } else { _ = c.AbortWithError(http.StatusBadRequest, err) return } } }更细粒度:workflow 与 step 参数
除了文档中提到的branch与events,server/api/badge.go 还支持按工作流(workflow)甚至按具体步骤(step)生成徽章,这在多工作流配置中非常实用:
workflow=<name>:徽章只统计指定工作流的运行状态,文案(subject)从默认的pipeline变为工作流名称;- 在指定
workflow的基础上追加step=<name>:文案变为<workflow>: <step>,只反映该步骤的状态。
实现上,GetBadge会先取出该流水线的完整工作流树(WorkflowGetTree),再按名称匹配工作流及其子步骤,并将多个匹配结果通过pipeline.MergeStatusValues合并成一个聚合状态。多工作流配置的写法可参考 25-workflows.md。
状态标签与颜色映射
徽章右侧的状态文案与颜色由 server/badges/badges.go 中的getBadgeStatusLabelAndColor决定:
| 流水线状态 | 徽章文案 | 徽章颜色 |
|---|---|---|
success | success | 绿色(#44cc11) |
failure | failure | 红色(#e05d44) |
pending/running | started | 黄色(#dfb317) |
error/killed | error | 灰色(#9f9f9f) |
| 其他 / 无记录 | none | 灰色(#9f9f9f) |
值得注意的细节是:当仓库里查不到符合条件的流水线时,徽章不会报错,而是显示灰色的none。这一点在 server/api/badge.go 中有明确注释(“display the 'none' badge, instead of throwing an error response”),且ErrRecordNotExist之外的查询错误只会被记录日志而不会导致 5xx。
后端渲染链路:从请求到 SVG
一次徽章请求的完整链路如下:
- 路由匹配:
/api/badges/:repo_id_or_owner[/:repo_name]/status.svg命中api.GetBadge(见 server/router/api.go); - 仓库解析:按 ID 或
owner/repo名称加载仓库(server/api/badge.go); - 参数归一:解析
branch、events,必要时解析workflow、step; - 取最新流水线:
GetPipelineBadge按repo_id、branch、事件集合查询number最大的流水线(server/store/datastore/pipeline.go); - 生成 SVG:
badges.Generate(name, status)根据状态映射文案与颜色,调用RenderBytes渲染出 SVG(server/badges/badges.go); - 返回响应:响应头设置为
Content-Type: image/svg+xml,返回 200 与 SVG 内容(server/api/badge.go)。
SVG 的绘制实现在 server/badges/drawer.go 中:它使用内置的DejaVuSans字体测量文案宽度(字号 11、DPI 72),再通过 HTML 模板(flat 风格、圆角矩形、平滑渐变)拼出最终的扁平徽章;字体资源内嵌在 server/badges/fonts 目录中,因此徽章服务不依赖外部字体或图片资源。由于渲染器内部使用互斥锁与sync.Once单例初始化(drawer.go),并发请求下依然线程安全。
验证与测试
仓库自带一组徽章渲染的单元测试,位于 server/badges/badges_test.go,其中TestGenerate覆盖了success、failure、error、killed、pending、running及未知状态共 7 种场景,并逐字节断言生成的 SVG 与预期一致;TestBadgeDrawerRender则验证了文案宽度测量与模板渲染的坐标计算结果。
你也可以直接通过命令行验证徽章端点的实际输出:
curl -s "https://<hostname>/api/badges/<repo-id>/status.svg?branch=main"返回的即是一段image/svg+xml文本。若返回的 XML 中状态为none,说明该分支上还没有符合条件的流水线记录。
延伸:CCMenu 徽章(cc.xml)
除status.svg外,server/router/api.go 还注册了/api/badges/<repo_id>/cc.xml端点,对应 server/api/badge.go 中的GetCC。它按 CCTray v1 规范输出 XML 格式的流水线状态,供 macOS 菜单栏工具 CCMenu 订阅展示。虽然本文档未展开讲解,但它与状态徽章共用同一批路由与仓库解析逻辑,可作为需要桌面端状态通知时的补充方案。
小结
Woodpecker 的状态徽章开箱即用、无需额外配置,只需拼接/api/badges/<repo-id>/status.svg即可嵌入任意页面。核心要点可归纳为:
- 默认展示默认分支最近一次 push 事件的流水线状态;
- 用
?branch=切换分支,用?events=纳入更多事件类型(如manual、cron、tag); - 进阶可用
?workflow=与?step=做更细粒度的状态展示; - 无记录时优雅降级为灰色
none,不会破坏页面布局; - 整个功能由 server/api/badge.go → server/store/datastore/pipeline.go → server/badges 三段代码协同完成,状态映射与 SVG 渲染均有测试用例可查。
将徽章放入 README 的第一屏,或嵌入团队文档站点,即可让所有访问者一眼看到主干代码的最新构建健康状况。
- CI/CD
- DevOps
【免费下载链接】woodpecker
Woodpecker is a simple, yet powerful CI/CD engine with great extensibility.
相关推荐
Woodpecker 仓库状态徽章(Status Badges)完全指南:端点、参数与 SVG 渲染原理
Woodpecker 仓库状态徽章(Status Badges)完全指南:端点、参数与 SVG 渲染原理 Woodpecker 内置了仓库状态徽章(Status
CI/CDDevOpsWoodpecker 状态徽章(Status Badges)使用指南:端点、查询参数与源码级原理
Woodpecker 状态徽章(Status Badges)使用指南:端点、查询参数与源码级原理 Woodpecker CI/CD 引擎内置了对仓库状态徽章(S
CI/CDDevOps3 步跑通 browser-use 自动下载:让 AI 替你批量保存网页文件的完整指南
3 步跑通 browser use 自动下载:让 AI 替你批量保存网页文件的完整指南 周一早上九点,你要从三个平台后台各导一份上月流水,老规矩:打开页面、找按
人工智能AI Agent浏览器控制GUI 自动化MCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考