尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Woodpecker 插件开发实战指南:用 `PLUGIN_` 环境变量约定构建你的第一个 CI/CD 插件

Woodpecker 插件开发实战指南:用 `PLUGIN_` 环境变量约定构建你的第一个 CI/CD 插件 CI/CDDevOps【免费下载链接】woodpeckerWoodpecker is a simple, yet powerful CI/CD engine with great extensibility.项目地址https://gitcode.com/gh_mirrors/wo/woodpecker点击查看免费下载插件Plugin是 Woodpecker 生态中最具扩展性的部分任何能被打包进容器并以ENTRYPOINT执行的逻辑都可以成为复用性极强的流水线插件。本篇指南以 Woodpecker 官方文档《Creating plugins》为核心骨架结合仓库内编译器的真实源码实现完整讲解插件的构建约定、settings参数到环境变量的映射规则、密钥注入、元数据声明、命令输出折叠并手把手完成一个可运行的 webhook 插件。读完本文你将能够独立开发、测试、发布一个符合 Woodpecker 规范、可被插件索引收录的插件。什么是插件流水线中的预制步骤在 Woodpecker 中插件本质上就是一个以插件逻辑作为 ENTRYPOINT 的容器镜像在流水线里它被声明为一个普通 step。与普通 step 通过commands执行任意脚本不同插件是开箱即用的黑盒用户只需通过settings提供参数插件镜像负责完成部署、发布制品、发送通知等预定义任务。插件镜像由 Agent 配置的默认容器仓库自动拉取因此创建插件的门槛极低——先构建一个 Docker 镜像再在.woodpecker.yaml中引用它即可。一个典型的最小插件镜像与流水线配置如下见 插件总览FROM cloud/kubectl COPY deploy /usr/local/deploy ENTRYPOINT [/usr/local/deploy]kubectl apply -f $PLUGIN_TEMPLATEsteps: - name: deploy-to-k8s image: cloud/my-k8s-plugin settings: template: config/k8s/service.yaml核心约定settings如何变成PLUGIN_环境变量要让用户能配置插件的运行行为插件作者应在流水线 YAML 中使用settings:。Woodpecker 编译器会将settings中的每一项转换后以大写环境变量形式注入容器变量名前缀为PLUGIN_。例如设置项url会被注入为环境变量PLUGIN_URL。命名转换规则字符-会被转换为下划线_例如some-String变成PLUGIN_SOME_STRINGCamelCase 不被保留anInt会变成PLUGIN_ANINT从源码看转换逻辑还会把.一并替换为_。该规则在 pipeline/frontend/yaml/compiler/settings/params.go 的sanitizeParamKey中实现先执行strings.ReplaceAll(k, ., _)与strings.ReplaceAll(k, -, _)再整体strings.ToUpper最后拼接前缀。其单元测试 params_test.go 验证了dry-run、dry_Run、dry.run三种写法最终都会归一化为PLUGIN_DRY_RUN。基础类型设置任何基础 YAML 标量scalar都会按字符串形式注入。官方文档给出的对照表如下Setting注入的环境变量some-bool: falsePLUGIN_SOME_BOOLfalsesome_String: helloPLUGIN_SOME_STRINGhelloanInt: 3PLUGIN_ANINT3也就是说布尔值、整数、浮点数等类型在进入容器时统一字符串化。对应源码sanitizeParamValueparams.go对Bool使用strconv.FormatBool、对Int/Float使用fmt.Sprintf生成字符串。复杂设置自动序列化为 JSON插件同样支持 map、list 这类复杂 YAML 结构例如steps: - name: plugin image: foo/plugin settings: complex: abc: 2 list: - 2 - 3这类值会被转换为JSON后注入插件。上例中环境变量PLUGIN_COMPLEX的内容将是{abc: 2, list: [ 2, 3 ]}从源码看该流程由handleComplex完成params.go先用yaml.Marshal序列化再通过go-yaml2json转为 JSON 字符串。还有一个值得注意的细节纯标量数组如[2, 3]不会被 JSON 化而是以逗号连接成字符串如PLUGIN_SLICE1,2,3仅当数组内包含复杂元素时才走 JSON 序列化路径——这一点在 params_test.go 中有明确断言。用from_secret向插件注入密钥密钥secret也应通过settings传入插件这是 Woodpecker 官方推荐的唯一方式。用户无需在流水线里硬编码敏感值只需使用from_secret语法引用密钥库中的变量steps: - name: plugin image: foo/plugin settings: TOKEN: from_secret: secret_token上述配置把名为secret_token的密钥赋给设置项TOKEN插件内以PLUGIN_TOKEN读取用法详见 密钥文档。注意该语法同时适用于settings与environmentfrom_secret的值必须是字符串。从源码看injectSecretparams.go会探测 map 中是否包含from_secret键命中时调用getSecretValue取回真实值并直接作为环境变量值注入对于嵌套在复杂结构内部的from_secretinjectSecretRecursive会递归展开params.go。而 convert.go 中的getSecretValue实现还会额外校验该密钥是否允许在当前流水线事件event下对当前容器可用未找到或无权使用时编译会直接报错从而保证密钥不会被误传给非授权步骤。Go 插件开发库如果你使用 Go 编写插件Woodpecker 社区提供了一个官方插件库用于便捷地读取内部环境变量与settings。该库位于 Codeberg 上的woodpecker-plugins/go-plugin仓库由 Woodpecker 社区维护文档中引用的官方位置。它封装了PLUGIN_环境变量的解析、常见类型的反序列化等工作让你可以专注于插件业务逻辑而不必手写环境变量解析代码。为插件声明元数据docs.md 头部为了让插件能被 [Woodpecker 插件索引] 收录并在文档中展示你可以在插件的 Markdown 文档中使用专门的头部header声明元数据。索引页面即插件列表页官方插件均通过此机制收录。支持的元数据字段如下字段说明name插件全名唯一必填字段icon插件图标的 URLdescription插件功能的简短描述author作者名称tags关键词列表例如 clone 插件可写[git, clone]containerImage容器镜像名称containerImageUrl容器镜像的链接url插件主页或仓库地址想被索引收录应尽可能填满这些字段但只有name是硬性要求。命令输出折叠▶前缀约定Woodpecker 的 UI 支持对单条命令的输出进行折叠。插件通常与普通流水线 step 结构类似——执行一组固定命令此时可以用相同方式为输出分节打印▶黑色三角后接两个空格加被执行的命令UI 便可将后续输出归入该命令的折叠块中。示例echo ▶ make test make test这样用户在 UI 中能清晰地看到每条命令的输出归属日志可读性大幅提升。下文的 webhook 示例也会采用这一约定。实战从零构建一个 webhook 插件下面通过一个完整的 webhook 插件教程把上述所有约定串起来用简单 shell 脚本在构建流水线中发起 HTTP 请求。第 1 步了解用户侧的配置形态插件发布后最终用户在.woodpecker.yaml中的使用方式如下steps: - name: webhook image: foo/webhook settings: url: https://example.com method: post body: | hello world三个设置项url、method、body会分别注入为PLUGIN_URL、PLUGIN_METHOD、PLUGIN_BODY。第 2 步编写插件逻辑创建一个简单的 shell 脚本用 curl 发送请求参数全部取自大写PLUGIN_前缀的环境变量#!/bin/sh echo ▶ curl -X ${PLUGIN_METHOD} -d ${PLUGIN_BODY} ${PLUGIN_URL} curl \ -X ${PLUGIN_METHOD} \ -d ${PLUGIN_BODY} \ ${PLUGIN_URL}第 3 步打包为镜像编写 Dockerfile把脚本加入镜像并配置为 ENTRYPOINT官方建议固定基础镜像版本如alpine:3.19# please pin the version, e.g. alpine:3.19 FROM alpine ADD script.sh /bin/ RUN chmod x /bin/script.sh RUN apk -Uuv add curl ca-certificates ENTRYPOINT /bin/script.sh构建并推送到容器仓库即可与整个 Woodpecker 社区共享docker build -t foo/webhook . docker push foo/webhook第 4 步本地验证发布前先在本地用docker run直接注入环境变量来验证插件行为效果等同于流水线内的执行docker run --rm \ -e PLUGIN_METHODpost \ -e PLUGIN_URLhttps://example.com \ -e PLUGIN_BODYhello world \ foo/webhook源码视角插件隔离与容器行为差异阅读源码可以发现插件容器与普通 step 在编译期有若干关键差异插件作者应理解这些行为以保证插件正确运行插件判定IsPlugin()的定义是没有commands、没有entrypoint、没有environment见 pipeline/frontend/yaml/types/container.go。一旦你在插件 step 上声明了commands或entrypoint它就不再被当作插件处理编译会失败使用environment虽可行但该容器将不再被视为插件——密钥的插件过滤将失效且不会自动获得特权。工作区固定为/woodpecker插件容器的工作区基础路径被固定为/woodpeckerconvert.go以保护 ENTRYPOINT 可执行文件不被篡改用户无需关心这一点。特权提升仅当插件镜像命中管理员配置的可提权镜像列表时才会被授予特权convert.go因此绝大多数插件默认运行在非特权模式。环境变量注入点settings通过ParamsToEnv(container.Settings, environment, PLUGIN_, true, ...)注入convert.go而普通environment则不带前缀注入二者共用同一套from_secret解析机制。插件开发最佳实践官方文档为插件作者总结了以下实践建议多架构构建为不同架构构建镜像让更多用户可用至少支持amd64和arm64。为local后端提供二进制使用 Woodpeckerlocal后端本地执行的用户无法运行容器镜像插件应额外发布针对不同 OS/架构的二进制文件。优先使用内置环境变量尽可能利用 Woodpecker 提供的内置环境变量如仓库、流水线、提交相关信息详见 内置环境变量文档而不是要求用户手动传入这类信息。只依赖settings与内部环境变量不要要求用户配置environment也不要强制依赖特定名称的密钥——把灵活性留给用户。附带docs.md为插件编写docs.md在其中列出全部settings与插件元数据官方插件如 plugin-git 即以docs.md作为文档与索引数据的来源。提交到插件索引将你的docs.md提交至 Woodpecker 插件索引使插件可以被社区发现和引用。小结Woodpecker 的插件机制建立在一条极简约定之上settings → 大写PLUGIN_环境变量 → ENTRYPOINT 脚本。掌握命名转换规则、复杂类型的 JSON 序列化、from_secret密钥注入再配合docs.md元数据与▶输出折叠约定你就能在十几分钟内交付一个规范、可复用、可被索引收录的 CI/CD 插件。对于更复杂的场景可以进一步参考 插件总览 中关于插件隔离与密钥过滤的说明或直接阅读仓库中的编译器源码 params.go 与 convert.go 理解底层行为。赞分享CI/CDDevOps【免费下载链接】woodpeckerWoodpecker is a simple, yet powerful CI/CD engine with great extensibility.项目地址https://gitcode.com/gh_mirrors/wo/woodpecker点击查看免费下载相关推荐Jasminum插件开发环境搭建从零开始构建你的第一个Zotero插件想要为Zotero开发中文元数据抓取插件Jasminum插件为你提供了完美的起点这个终极指南将带你从零开始快速搭建专业的Zotero插件开发环境让你轻松科研Woodpecker插件开发终极指南创建自定义CI/CD工具Woodpecker插件开发终极指南创建自定义CI/CD工具 Woodpecker是一个简单但功能强大的CI引擎具有出色的可扩展性。通过插件系统您可以轻松CI/CDDevOpsres-downloader免费的跨平台资源下载器3 分钟抓到第一条视频res downloader免费的跨平台资源下载器3 分钟抓到第一条视频 你肯定有过这种瞬间打开视频号看到想存的视频翻遍设置找不到下载入口。res d桌面应用网络音视频上一篇开源项目解析Papirus Folders脚本原理与自定义扩展指南下一篇国家中小学智慧教育平台电子课本解析工具让教育资源获取触手可及创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表