CI/CDDevOps【免费下载链接】woodpeckerWoodpecker is a simple, yet powerful CI/CD engine with great extensibility.项目地址https://gitcode.com/gh_mirrors/wo/woodpecker点击查看免费下载Woodpecker 的配置扩展Configuration Extension允许你用一个自建的 HTTP 端点接管、改写或生成 Pipeline 配置当流水线触发时Woodpecker 会先读取仓库中的原始配置文件再 POST 给扩展服务由扩展返回最终生效的 YAML 配置。本文基于 40-configuration-extension.md 展开结合仓库源码讲解全局/仓库级配置方式、请求与响应协议、签名安全机制与底层调用链帮助你独立实现一个安全、可用的配置扩展服务。一、配置扩展能解决什么问题在默认情况下Woodpecker 直接从代码仓库forge拉取.woodpecker.yaml/.woodpecker.yml等文件作为流水线配置。配置扩展把“如何得到配置”这个环节抽离成一段 HTTP 服务逻辑适合以下场景官方文档列出的典型用途用 Go template 等模板引擎预处理原始配置文件把仓库里自定义的字段/属性转换为 Woodpecker 标准属性为配置添加默认值例如为每个仓库自动注入默认步骤default steps把完全不同的配置格式如 GitLab CI 配置、Starlark、Jsonnet 等翻译成 Woodpecker 配置在一个中心位置集中管理多个仓库的配置避免在每个仓库重复维护。从源码看配置获取被抽象为config.Service接口server/services/config/service.gotype Service interface { Fetch(ctx context.Context, forge forge.Forge, user *model.User, repo *model.Repo, pipeline *model.Pipeline, oldConfigData []*types.FileMeta, restart bool) ([]*types.FileMeta, error) }Fetch接收旧配置数据返回新的配置文件列表。配置扩展就是该接口的一种 HTTP 实现与默认的 forge 拉取实现server/services/config/forge.go可以串联使用。二、安全前提所有请求都会被签名:::warning 安全警告 Woodpecker 会把 token 等私有信息传给扩展并且会执行扩展返回的配置因此必须确保外部扩展本身是可信的。作为防护Woodpecker 会对每一个发往扩展的请求进行签名。 :::扩展的整体安全模型记录在 Extensions 总览文档 中Woodpecker 使用一对ed25519 公私钥按 HTTP Signaturesdraft-cavage-http-signatures 规范对请求签名扩展侧必须用公钥验证每个请求的签名可参考httpsign这类库公钥获取方式访问http://my-woodpecker.tld/api/signature/public-key或在 Woodpecker UI 中进入仓库设置 → Extensions 页面查看。签名在服务端由 server/services/utils/http.go 实现服务端用 ed25519 私钥创建httpsign.NewEd25519Signer对request-target与content-digest两个头部签名Content-Digest 自动生成并携带签名名woodpecker-ci-extensionssigner, err : httpsign.NewEd25519Signer(ed25519Key, httpsign.NewSignConfig(), httpsign.Headers(request-target, content-digest))同时为防止扩展被滥用去访问内网/本机服务HTTP 客户端通过hostmatcher.NewDialContext限制了可访问主机server/services/utils/http.go默认仅允许external公网地址可通过WOODPECKER_EXTENSIONS_ALLOWED_HOSTS放开详见下文第六节。三、两种配置方式仓库级与全局级3.1 仓库级配置Extensions 标签页进入仓库设置Repository Settings的Extensions标签页可以为本仓库单独配置Configuration Extension Endpoint扩展的 HTTP 地址Exclusive独占勾选后本仓库只调用你的扩展不再从 forge 拉取任何配置Send netrc credentials发送 netrc 凭据勾选后请求中才会附带netrc字段。这些设置对应仓库模型上的三个字段server/model/repo.goConfigExtensionEndpoint string json:config_extension_endpoint ConfigExtensionExclusive bool json:config_extension_exclusive ConfigExtensionNetrc bool json:config_extension_netrc3.2 全局配置服务端环境变量在 Woodpecker服务端配置中设置全局端点即可让扩展对所有仓库生效。注意如果你与他人共用同一个 Woodpecker 服务器对方也会用到你配置的扩展需谨慎。WOODPECKER_CONFIG_EXTENSION_ENDPOINThttps://example.com/ciconfig全局端点在 cmd/server/flags.go 中定义共有三个相关环境变量环境变量默认值说明WOODPECKER_CONFIG_EXTENSION_ENDPOINT无全局配置扩展端点 URL旧名WOODPECKER_CONFIG_SERVICE_ENDPOINT仍兼容计划 v4.0.0 移除WOODPECKER_CONFIG_EXTENSION_EXCLUSIVEfalse全局扩展是否独占跳过 forge 拉取WOODPECKER_CONFIG_EXTENSION_NETRCfalse是否向全局扩展发送netrc凭据对应关系与默认值也记录在 服务端配置参考文档 中CONFIG_EXTENSION_ENDPOINT默认无、CONFIG_EXTENSION_EXCLUSIVE默认false、CONFIG_EXTENSION_NETRC默认false。3.3 全局与仓库级的组合规则全局扩展与仓库级扩展可以共存官方文档明确当两者都配置且仓库未开启 exclusive 时全局配置扩展会先被调用随后才是仓库级扩展。服务端的组合逻辑在 server/services/setup.go 与 server/services/manager.go 中仅配置全局端点时NewCombined(forgeFetcher, httpFetcher)即先 forge 拉取、再 HTTP 扩展改写全局端点 WOODPECKER_CONFIG_EXTENSION_EXCLUSIVEtrue直接返回httpFetcher完全跳过 forge仓库级端点非空时优先使用仓库级配置仓库级ConfigExtensionExclusive为真则只保留仓库级 HTTP 扩展否则与全局服务组合。多个服务通过config.NewCombinedserver/services/config/combined.go串联上一个服务的输出文件列表作为下一个服务的oldConfigData输入形成处理链。四、工作原理与调用流程当一次流水线被触发时Woodpecker 的执行顺序如下结合 server/services/config/http.go 源码还原拉取原始配置从仓库forge读取配置文件——默认按WOODPECKER_DEFAULT_PIPELINE_CONFIGS指定的顺序默认.woodpecker/、.woodpecker.yaml、.woodpecker.yml见服务端配置文档查找若仓库设置了自定义Config路径则优先使用该路径组装请求把仓库信息、流水线信息、已拉取到的配置文件打包成 JSONPOST 给扩展向配置好的扩展端点发送 HTTP POST 请求接收并采用结果扩展返回新的配置文件或204 No Content表示沿用旧配置最终配置被解析执行。其中 forge 拉取阶段还有重试与超时机制server/services/config/forge.go重试次数由WOODPECKER_FORGE_RETRY控制默认 3 次超时由WOODPECKER_FORGE_TIMEOUT控制默认 5s。独占模式Exclusive的行为差异启用 exclusive全局或仓库级均可后Woodpecker只会调用你的扩展不做任何其他获取从而可以完全跳过 forge。此时发往扩展的请求中不会附带configuration文件列表因为根本没去拉取。该行为在 server/services/config/http.go 中通过json:configuration,omitempty实现——没有配置数据时该字段直接不出现在 JSON 中。五、请求与响应协议详解5.1 请求Request扩展接收一个 HTTP POST 请求JSON payload 结构如下TypeScript 描述来自官方文档class Request { repo: Repo; pipeline: Pipeline; netrc?: Netrc; // 仅当启用了 netrc 发送时才包含见下 configuration?: { // 配置文件列表仓库中没有任何配置时不发送 name: string; // 配置文件名 data: string; // 配置文件内容 }[]; }各模型对应仓库源码Repo 模型server/model/repo.goPipeline 模型server/model/pipeline.goNetrc 模型server/model/netrc.gonetrc字段何时出现仅当全局环境变量WOODPECKER_CONFIG_EXTENSION_NETRCtrue默认false或仓库级设置了“Send netrc credentials”时请求中才会包含netrc。服务端在 server/services/config/http.go 中通过forge.Netrc(user, repo)从 forge 获取凭据后塞入请求体。:::tip 提示netrc数据非常强大——它包含访问仓库的凭据。你可以用它克隆仓库甚至调用 forgeGitHub、GitLab 等的 API 获取更多仓库信息。 :::netrc结构server/model/netrc.gotype Netrc struct { Machine string json:machine Login string json:login Password string json:password Type ForgeType json:type }官方文档给出的完整示例请求{ repo: { id: 100, uid: , user_id: 0, namespace: , name: woodpecker-test-pipeline, slug: , scm: git, git_http_url: , git_ssh_url: , link: , default_branch: , private: true, visibility: private, active: true, config: , trusted: false, protected: false, ignore_forks: false, ignore_pulls: false, cancel_pulls: false, timeout: 60, counter: 0, synced: 0, created: 0, updated: 0, version: 0 }, pipeline: { author: myUser, author_avatar: https://myforge.com/avatars/d6b3f7787a685fcdf2a44e2c685c7e03, author_email: myemail.com, branch: main, changed_files: [some-filename.txt], commit: 2fff90f8d288a4640e90f05049fe30e61a14fd50, created_at: 0, deploy_to: , enqueued_at: 0, error: , event: push, finished_at: 0, id: 0, link_url: https://myforge.com/myUser/woodpecker-testpipe/commit/2fff90f8d288a4640e90f05049fe30e61a14fd50, message: test old config\n, number: 0, parent: 0, ref: refs/heads/main, refspec: , clone_url: , reviewed_at: 0, reviewed_by: , sender: myUser, signed: false, started_at: 0, status: , timestamp: 1645962783, title: , updated_at: 0, verified: false }, configuration: [ { name: .woodpecker.yaml, data: steps:\n - name: backend\n image: alpine\n commands:\n - echo \Hello there from Repo (.woodpecker.yaml)\\n } ], netrc: { machine: myforge.com, login: myUser, password: forge-access-token } }请求的服务端组装代码server/services/config/http.gotype requestStructure struct { Repo *model.Repo json:repo Pipeline *model.Pipeline json:pipeline Netrc *model.Netrc json:netrc Configuration []*configData json:configuration,omitempty }5.2 响应Response扩展应返回一个 JSON payload其中包含符合 Woodpecker 官方 YAML 格式的新配置文件。若扩展想保留现有配置可以返回 HTTP204 No Content。class Response { configs: { name: string; // 配置文件名 data: string; // 配置文件内容 }[]; }官方文档给出的示例响应{ configs: [ { name: central-override, data: steps:\n - name: backend\n image: alpine\n commands:\n - echo \Hello there from ConfigAPI\\n } ] }响应解析与状态码处理逻辑server/services/config/http.go204 No Content沿用旧配置不做任何替换仅记录 debug 日志config endpoint returned 204 No Content, using fallback config200 OK把响应中configs数组逐项转换为FileMeta{Name, Data}返回给上层其他非预期状态码返回错误unexpected status code %d from config endpoint (expected 200 or 204)此时旧配置会被保留并随错误一起返回。// handle 204 - no new config available, return old config without error if status http.StatusNoContent { return oldConfigData, nil } // unexpected non-success status code if status ! http.StatusOK { return oldConfigData, fmt.Errorf(unexpected status code %d from config endpoint (expected 200 or 204), status) }六、扩展服务的网络访问限制与调用重试6.1 允许访问的主机WOODPECKER_EXTENSIONS_ALLOWED_HOSTS出于安全考虑默认只允许扩展访问外部公网主机防止扩展被诱导去探测内网服务。可通过WOODPECKER_EXTENSIONS_ALLOWED_HOSTS修改默认external见服务端配置文档支持逗号分隔的以下取值详见 Extensions 总览文档内置网络loopbackIPv4 的127.0.0.0/8与 IPv6 的::1/128含 localhostprivateRFC 191810.0.0.0/8、172.16.0.0/12、192.168.0.0/16与 RFC 4193FC00::/7即 LAN/内网external合法的非私有单播 IP即公网所有主机*允许所有主机CIDR 列表如 IPv4 的1.2.3.0/8、IPv6 的2001:db8::/32通配主机名如example.com、*.example.com、192.168.100.*。服务端在创建扩展 HTTP 客户端时解析该配置server/services/utils/http.goif allowedHostListValue { allowedHostListValue hostmatcher.MatchBuiltinExternal } allowedHostMatcher : hostmatcher.ParseHostMatchList(WOODPECKER_EXTENSIONS_ALLOWED_HOSTS, allowedHostListValue)6.2 请求超时与重试扩展 HTTP 请求通过 server/services/utils/http.go 的Send方法发送具备以下行为客户端总超时10 秒指数退避重试最多 3 次maxRetries 3网络错误连接拒绝、连接重置、DNS 解析失败、TLS 握手超时等与5xx 服务端错误可重试4xx 客户端错误与 2xx 成功响应不重试成功响应体2xx会自动 JSON 解码到out参数。// Retry on server errors (5xx) return statusCode http.StatusInternalServerError statusCode http.StatusNetworkAuthenticationRequired七、最小实现示例与排查建议7.1 一个最小可用的扩展服务综合上述协议一个用任意语言实现的配置扩展服务只需满足接收POST请求Content-Type: application/json验证请求签名使用 ed25519 公钥参见 Extensions 总览文档 中的公钥获取方式读取repo、pipeline、configuration可能缺失、netrc可能缺失字段返回{configs: [{name: ..., data: ...}]}或直接返回204沿用仓库原始配置。官方仓库还维护了一套简单的扩展端点示例config secret 扩展可作为参考实现。结合第五节的两个 JSON 示例即可快速搭建把请求中的configuration[0].data拿出来做模板渲染/格式转换再把结果放进响应的configs返回就能实现“集中管理配置”“格式转换”等目标。7.2 常见问题排查方向请求没有configuration字段检查是否开启了 exclusive 模式独占模式下本来就不拉取 forge 配置请求没有netrc字段确认全局WOODPECKER_CONFIG_EXTENSION_NETRCtrue或仓库级勾选了 “Send netrc credentials”扩展返回被忽略检查状态码是否为200或204其他状态码会触发unexpected status code ...错误并沿用旧配置请求无法到达扩展默认仅允许公网external主机内网/本机地址需通过WOODPECKER_EXTENSIONS_ALLOWED_HOSTS显式放开配置没有生效确认返回的 YAML 遵循 Woodpecker 官方格式steps、when、services等标准字段并核对name与data字段拼写。八、相关资源扩展机制总览含三种扩展类型与签名说明docs/versioned_docs/version-3.17/20-usage/72-extensions/index.md服务端相关环境变量参考docs/versioned_docs/version-3.17/30-administration/10-configuration/10-server.md核心实现HTTP 扩展服务server/services/config/http.go服务组合逻辑server/services/config/combined.go 与 server/services/manager.go全局配置装配server/services/setup.goforge 配置拉取server/services/config/forge.go签名与 HTTP 客户端server/services/utils/http.go数据模型仓库 server/model/repo.go、流水线 server/model/pipeline.go、netrc server/model/netrc.go相关测试server/services/config/forge_test.go含 204 沿用旧配置等场景验证赞分享CI/CDDevOps【免费下载链接】woodpeckerWoodpecker is a simple, yet powerful CI/CD engine with great extensibility.项目地址https://gitcode.com/gh_mirrors/wo/woodpecker点击查看免费下载相关推荐Woodpecker 配置扩展Configuration Extension完全指南动态修改与生成流水线配置Woodpecker 配置扩展Configuration Extension完全指南动态修改与生成流水线配置 配置扩展Configuration ExtCI/CDDevOpsWoodpecker 配置扩展Configuration Extension完全指南通过 HTTP 端点按需修改与生成流水线配置Woodpecker 配置扩展Configuration Extension完全指南通过 HTTP 端点按需修改与生成流水线配置 配置扩展ConfiguCI/CDDevOpsxunlei-lixian vs 官方客户端为什么命令行工具更高效xunlei lixian vs 官方客户端为什么命令行工具更高效 在数字化时代下载工具已成为我们日常工作和娱乐不可或缺的一部分。迅雷作为国内知名的下载工CLI网络上一篇Dagger TypeScript SDK 中 EnumTypeDef 类完全指南Module 自定义枚举的类型定义与源码级解析下一篇IoT-For-Beginners 第 3 课用传感器与执行器与物理世界交互——从光敏传感读到夜灯实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考