
CI/CDDevOps【免费下载链接】woodpeckerWoodpecker is a simple, yet powerful CI/CD engine with great extensibility.项目地址https://gitcode.com/gh_mirrors/wo/woodpecker点击查看免费下载本篇指南以 Woodpecker CI/CD 引擎的 workflow 配置文件语法为核心系统讲解steps、services、workspace、clone等顶层区块的完整写法深入剖析when条件过滤、depends_on依赖编排、failure失败策略与labels调度匹配等高级特性。读完本文你将掌握从零编写一份可投入生产使用的.woodpecker.yaml理解每一步在 yaml 前端解析器 与 编译器 中的底层执行逻辑并能利用条件执行、矩阵构建与 DAG 依赖实现精细化 CI 流程控制。Workflow 是什么Workflow工作流区块定义了一系列用于构建、测试和部署代码的步骤steps。默认情况下这些步骤按照定义的顺序串行执行如果某一步返回非零退出码则该 workflow 以及整个 pipeline 会立即终止并返回错误状态。steps: - name: backend image: golang commands: - go build - go test - name: frontend image: node commands: - npm install - npm run test - npm run build[!NOTE] 唯一的例外是带有status: [failure]条件的步骤见下文 status 过滤它保证在失败的运行中仍被执行。[!NOTE] Woodpecker 支持 YAML 1.2 的大部分特性同时为向后兼容保留部分 1.1 的行为底层使用 go-yaml v3 库解析。步骤命名上例定义了两个步骤frontend和backend它们的名称完全由你决定。name字段是可选的——如果省略步骤会被自动编号。除了列表形式步骤也可以用字典映射形式命名steps: backend: image: golang commands: - go build - go test frontend: image: node commands: - npm install - npm run test - npm run build从源码角度看steps、services、clone都被定义为ContainerList见 workflow.go即由Container组成的列表每个容器的字段在 container.go 中通过 YAML tag 明确定义包括name、image、pull、commands、entrypoint、directory、settings、environment、depends_on、when、failure、detach、volumes、dns、dns_search、backend_options、privileged等。Skip Commits跳过提交Woodpecker 允许通过在提交信息中添加[SKIP CI]或[CI SKIP]来跳过单个提交该匹配不区分大小写git commit -m updated README [CI SKIP]Steps步骤Workflow 中的每一步都在指定的容器container内执行命令。步骤默认按顺序执行如果需要并行可以使用depends_on。与提交关联的代码会通过 git 检出到一个 workspace该 workspace 会作为工作目录挂载到 workflow 的每一个步骤。steps: - name: backend image: golang commands: - go build - go test文件变更在步骤间是累积的Woodpecker 在 workflow 开始时克隆源代码由于同一个 volume 被挂载到所有步骤步骤之间对文件的修改会被持久保留。steps: - name: build image: debian commands: - echo test content myfile - name: a-test-step image: debian commands: - cat myfile上面的例子中build步骤写入的myfile可以在后续的a-test-step中被读取这正是 CI 场景中构建产物跨步骤共享的基础机制。imageWoodpecker 会拉取定义的镜像并将其作为执行 workflow 步骤命令、插件plugins和服务容器service containers的运行环境。当使用local后端时image条目用于指定执行命令所使用的 shell如 Bash 或 Fish。steps: - name: build image: golang:1.6 commands: - go build - go test - name: prettier image: woodpeckerci/plugin-prettier services: - name: database image: mysqlWoodpecker 支持来自任何 Docker 镜像仓库的合法镜像image: golang image: golang:1.7 image: library/golang:1.7 image: index.docker.io/library/golang image: index.docker.io/library/golang:1.7关于从不同仓库使用镜像的更多内容见 41-registries.md。pull默认情况下Woodpecker不会自动升级容器镜像仅在镜像尚未存在时才进行拉取。如需在有更新时总是拉取最新镜像使用pull选项steps: - name: build image: golang:latest pull: true在源码中Pull是Container上的布尔字段container.gopull: true会指示对应后端在启动容器前强制执行镜像拉取策略。commands每个步骤的命令会串行执行就像你在本地 shell 中逐条输入一样。steps: - name: backend image: golang commands: - go build - go test这里没有任何魔法。上述命令会被转换成一个简单的 shell 脚本大致如下#!/bin/sh set -e go build go test该脚本随后作为容器的 entrypoint 被执行。下面的 docker 命令是执行方式的一个不完整的示例docker run --entrypointbuild.sh golang[!NOTE] 只有**构建步骤build steps**可以定义commands。插件plugins和服务services不能使用 commands。entrypoint允许你为容器指定 entrypoint。注意它必须是命令及其参数的列表例如[/bin/sh, -c]。如果你定义了commands默认 entrypoint 将是[/bin/sh, -c, echo $CI_SCRIPT | base64 -d | /bin/sh -e]。你也可以在使用commands时通过CI_SCRIPTBase64 编码配合自定义 shell。environmentWoodpecker 支持向单个步骤传递环境变量。更多细节见 environment 文档。源码层面Environment是map[string]any类型的字段container.go既可以写为键值映射也可以与内置CI_变量一起注入步骤。failure某些步骤允许失败而不导致整个 workflow进而 pipeline报告失败——例如执行 lint 检查的步骤。为此给步骤添加failure: ignore。如果 Woodpecker 在执行该步骤时遇到错误它会将该步骤标记为失败但仍会继续执行后续步骤如果有且不影响 workflow 的状态。steps: - name: backend image: golang commands: - go build - go test failure: ignore如果希望在步骤失败时取消整个 pipeline可以设置failure: cancel默认行为是failure: fail失败即中断。when- 条件执行Woodpecker 支持通过when块为步骤定义一组条件。只要when块中至少一个条件求值为 true步骤就会执行否则被跳过。单个条件只有在其所有子条件都为 true 时才为 true。一个条件可以是类似这样的检查steps: - name: prettier image: woodpeckerci/plugin-prettier when: - event: pull_request repo: test/test - event: push branch: main上面的prettier步骤在满足以下任一条件时执行pipeline 由仓库test/test的 pull request 触发pipeline 由对main分支的 push 触发。这个列表内 OR、单个条件内 AND的语义在源码中有直接体现When.Match遍历所有约束Constraints只要其中一个Constraint.Match返回 true 即整体为 true见 constraint.go。when同时支持列表与映射两种 YAML 写法——映射形式会被包装成单元素约束列表UnmarshalYAML中yaml.MappingNode分支。repo按仓库执行条件示例steps: - name: prettier image: woodpeckerci/plugin-prettier when: - repo: test/testbranch[!NOTE] 分支条件不适用于 tag。按分支执行条件示例steps: - name: prettier image: woodpeckerci/plugin-prettier when: - branch: main此时步骤会在 main 分支触发但也会在 pull request 的目标分支为main时触发。如需进一步限制为仅 main 分支的 push请添加事件条件。当分支为main或develop时执行步骤when: - branch: [main, develop]当分支以prefix/*开头时执行步骤when: - branch: prefix/*分支匹配使用 doublestar 实现注意以*开头的模式应加引号字面/需要转义。几个示例*\\/*匹配恰好包含 1 个/的模式*\\/**匹配至少包含 1 个/的模式*匹配不包含/的模式**匹配一切。使用自定义 include/exclude 逻辑执行步骤when: - branch: include: [main, release/*] exclude: [release/1.0.0, release/1.1.*]底层实现中branch、repo、ref、instance等都复用constraint.List类型list.go它支持includeexclude两种模式匹配均通过doublestar.Match完成List.Match的规则是命中 exclude 返回 false命中 include 返回 true未设置 include 时默认 true。此外源码确认了文档中的行为——branch条件在m.Curr.Event metadata.EventTag时不会被匹配见 constraint.go 的Match方法。event可用事件包括push向分支推送提交时触发pull_request打开 pull request 或向其推送新提交时触发pull_request_closedpull request 被关闭或合并时触发pull_request_metadatapull request 元数据发生变化时触发如标题、正文、标签、里程碑等tag推送 tag 时触发release创建 release、预发布或草稿时触发可通过 evaluate 结合 环境变量 进一步过滤deployment在仓库中创建 deployment 时触发该事件可直接从 Woodpecker 触发GitHub 也支持 webhook 触发croncron 任务执行时触发manual用户手动触发 pipeline 时触发。构建事件为tag时执行步骤when: - event: tagpipeline 事件为对指定分支的push时执行步骤when: - event: push branch: main多个事件执行步骤when: - event: [push, tag, deployment]cron该过滤器仅适用于 cron 事件并按 cron 任务的名称过滤。同时请务必在when过滤器中也加上event: cron条件。when: - event: cron cron: sync_* # name of your cron jobcron 的更多内容见 45-cron.md。源码中cron过滤仅在m.Curr.Event metadata.EventCron时参与匹配constraint.go。refref过滤器比较 workflow 所针对的 git 引用ref。例如它可以过滤必须以v开头的 tagwhen: - event: tag ref: refs/tags/v*status默认情况下步骤只在 workflow 运行到该点之前一直成功时才执行这等价于status: [ success ]。status过滤器允许你覆盖这一行为。唯一接受的值是success和failure。一个常见场景是在失败时执行步骤例如为失败的 workflow/pipeline 发送通知。若希望无论结果如何都运行步骤可同时列出两个值steps: - name: notify image: alpine when: - status: [ success, failure ]该过滤器对其他过滤器是感知的。如果你希望在事件为tag的失败时运行而事件为pull_request时无论成败都运行when: - event: tag status: [ failure ] - event: pull_request status: [ success, failure ]如果没有匹配的过滤器或所有匹配的过滤器都未设置status则使用默认行为——仅在成功时运行。上面的例子中当事件既不是tag也不是pull_request时就会发生这种情况。源码中对status的语义做了精细处理IncludesStatusFailure要求某条匹配的约束显式包含failure而IncludesStatusSuccess则假定 success 被隐式包含除非约束明确列出且不含success见 constraint.go。platform[!NOTE] 该条件应与 matrix矩阵 workflow 配合使用因为常规 workflow 只会被单个 agent 执行而该 agent 只有一种架构。为特定平台执行步骤when: - platform: linux/amd64使用通配符为特定平台执行步骤when: - platform: [linux/*, windows/amd64]matrix为单个矩阵组合执行步骤when: - matrix: GO_VERSION: 1.5 REDIS_VERSION: 2.8源码中matrix过滤只在步骤级globalfalse参与匹配用于将矩阵变量与当前执行的矩阵组合比对constraint.go 的Constraint.Match。instance仅在指定主机名的某个 Woodpecker 实例上执行步骤when: - instance: stage.woodpecker.company.compath[!INFO] 路径条件仅应用于push和pull_request事件。仅当 pipeline 修改了某些文件时执行步骤when: - path: src/*你可以使用 glob 模式 匹配变更文件并通过include指定命中即执行、exclude指定未变更才执行。对于没有文件变更的 pipeline空提交或tag等无文件变更的事件可用on_empty设置该条件在这些情况下应为true默认还是false。when: - path: include: [.woodpecker/*.yaml, *.ini] exclude: [*.md, docs/**] ignore_message: [ALL] on_empty: true[!INFO] 在提交信息中传入类似[ALL]的定义 ignore-message会忽略所有路径条件以及on_empty设置。Path类型的完整字段include、exclude、ignore_message、on_empty定义在 path.go其匹配逻辑依次为提交信息包含ignore_message大小写不敏感直接返回 true → 无变更文件时返回on_empty的取值 → 命中 exclude 返回 false → 未命中 include 返回 false。注意Match方法仅当事件是 pull 事件或 push 事件时才被调用constraint.go这与文档仅适用于 push/pull_request的说明一致。evaluate仅当提供的 evaluate 表达式求值为 true 时执行步骤。表达式中可以使用内置的CI_变量和自定义变量。表达式语法见底层库 expr-lang 的语言定义文档。在仓库owner/repo的默认分支上进行 push 时运行when: - evaluate: CI_PIPELINE_EVENT push CI_REPO owner/repo CI_COMMIT_BRANCH CI_REPO_DEFAULT_BRANCH在用户woodpecker-ci创建的提交上运行when: - evaluate: CI_COMMIT_AUTHOR woodpecker-ci跳过所有提交信息中包含please ignore me的提交when: - evaluate: not (CI_COMMIT_MESSAGE contains please ignore me)在带有deploy标签的 pull request 上运行when: - evaluate: CI_COMMIT_PULL_REQUEST_LABELS contains deploy仅在SKIPtrue时跳过步骤否则或未定义时运行when: - evaluate: SKIP ! true源码实现中evaluate表达式通过expr.Compile(c.Evaluate, expr.Env(env), expr.AllowUndefinedVariables(), expr.AsBool())编译并求值constraint.goAllowUndefinedVariables()意味着未定义的变量不会导致编译失败——这正是SKIP ! true在SKIP未定义时仍可工作的原因。depends_on正常情况下workflow 中的步骤按照定义顺序串行执行。一旦为某个步骤设置了depends_on就会启用有向无环图DAG调度除设置了依赖关系的步骤外workflow 中的所有步骤都会并行执行steps: - name: build # build 立即执行 image: golang commands: - go build - name: deploy image: woodpeckerci/plugin-s3 settings: bucket: my-bucket-name source: some-file-name target: /target/some-file depends_on: [build, test] # deploy 在 build 和 test 完成后执行 - name: test # 未设置依赖立即执行 image: golang commands: - go test[!NOTE] 可以通过添加空数组depends_on: []定义一个无依赖、立即开始的步骤。为单个步骤设置depends_on后如果其他步骤未指定进一步依赖它们也会被立即执行。steps: - name: check code format image: mstruebing/editorconfig-checker depends_on: [] # 启用并行步骤 ...底层调度在 dag.go 中实现只要任一步骤的depends_on非 nil即 YAML 中出现过该字段isDAG()返回 true整个 workflow 改用compileByDependsOn()构建阶段否则退回compileSequence()纯串行模式。DAG 编译还会做三类校验重名步骤报ErrStepDuplicateName、缺失的必需依赖报ErrStepMissingDependency、依赖成环报ErrStepDependencyCycle通过 DFS 检测。同一层内无依赖的步骤会按原始配置位置排序保证多次运行顺序稳定。volumesWoodpecker 允许在 YAML 中定义 Docker 卷。你可以用该参数将宿主机的文件或文件夹挂载进容器。更多细节见 volumes 文档。detachWoodpecker 允许将步骤分离detach使其在后台运行直到 workflow 结束。更多细节见 services 文档中的 detachment 小节。directory使用directory可以设置仓库的子目录或 Docker 容器内的绝对路径命令将在此目录中运行。backend_options通过backend_options可以定义针对具体后端backend的选项。例如可以指定 Docker 容器中使用的用户和/或组或指定 Kubernetes 的 service account。更多细节见所用后端的文档Docker 后端Kubernetes 后端servicesWoodpecker 可以提供服务容器service containers例如在 workflow 执行期间运行数据库或缓存容器。更多细节见 services 文档。workspaceworkspace 定义了所有 workflow 步骤共享的卷和工作目录。默认的 workspace 基路径是/woodpecker路径会附加仓库 URLsrc/{url-without-schema}。例如/woodpecker/src/github.com/octocat/hello-world。可以通过 YAML 中的 workspace 块自定义workspace: base: /go path: src/github.com/octocat/hello-world steps: - name: build image: golang:latest commands: - go get - go test[!NOTE] 插件plugins的 workspace 基路径始终为/woodpecker。base属性定义所有步骤共享的基础卷。这确保你的源代码、依赖和编译产物能在步骤之间持久保存与共享workspace: base: /go path: src/github.com/octocat/hello-world steps: - name: deps image: golang:latest commands: - go get - go test - name: build image: node:latest commands: - go build这等价于下面的 docker 命令docker volume create my-named-volume docker run --volumemy-named-volume:/go golang:latest docker run --volumemy-named-volume:/go node:latestpath属性定义构建的工作目录代码会被克隆到这里它也是构建过程中每个步骤的默认工作目录。path必须是相对路径并与base路径组合workspace: base: /go path: src/github.com/octocat/hello-worldgit clone https://github.com/octocat/hello-world \ /go/src/github.com/octocat/hello-world在 workflow.go 中Workspace结构体仅含Base与Path两个字段默认值/woodpecker基路径、src/{url}组合方式由编译阶段注入最终会转换成对应后端Docker/Kubernetes/local 等的卷与工作目录配置。matrixWoodpecker 内置了对矩阵构建matrix builds的支持。Woodpecker 会为矩阵中的每种组合分别执行一个构建任务使你能够用多个配置构建和测试同一次提交。更多细节见 matrix 构建文档。labels你可以为 workflow 定义标签以便选择执行该 workflow 的 agent。一个 agent 只有在每一个分配给它的标签都与该 agent 的标签匹配时才会接手并执行该 workflow。要指定额外的 agent 标签见 Agent 配置选项。agent 至少有四个默认标签platformagent-os/agent-arch、hostnamemy-agent、backenddockeragent 后端的类型和repo*。agent 可以使用*作为标签的通配符例如repo*匹配任意仓库。值为空的 workflow 标签会被忽略。默认情况下每个 workflow 至少带有repoyour-user/your-repo-name标签如果为 workflow 设置了 platform 属性它还会带有类似platformyour-os/your-arch的标签。[!WARNING] 带有woodpecker-ci.org前缀的标签由 Woodpecker 管理不能在 pipeline 定义中设置。可以以键值映射的形式添加额外标签labels: location: europe # 只有 locationeurope 或 location* 的 agent 会被使用 weather: sun hostname: # 空标签会被忽略 steps: - name: build image: golang commands: - go build - go test按平台过滤要将 workflow 配置为仅在具有特定平台的 agent 上执行可以使用platform键。可用平台参见官方 go 文档。平台语法为GOOS/GOARCH形式如linux/arm64或linux/amd64。示例假设有两个 agent一个linux/arm一个linux/amd64。之前该 workflow 可能会在任意 agent上执行Woodpecker 对在哪里运行并不挑剔。通过如下设置它只会在平台为linux/arm64的 agent 上执行labels: platform: linux/arm64 steps: - name: build image: golang commands: - go build - go testvariablesWoodpecker 支持使用 YAML 锚点与别名 作为 workflow 配置中的变量。更多细节与示例见 Advanced usage 文档。clone如果没有显式定义 clone 步骤Woodpecker 会自动配置一个默认的 clone 步骤。如果使用local后端默认 clone 步骤正常工作要求 plugin-git 二进制位于你的$PATH中否则你仍可以手写一个 clone 步骤。你可以手动配置 workflow 中的 clone 步骤以自定义它clone: git: image: woodpeckerci/plugin-git steps: - name: build image: golang commands: - go build - go test覆盖深度的配置示例clone: - name: git image: woodpeckerci/plugin-git settings: partial: false depth: 50使用自定义 clone 插件的配置示例clone: - name: git image: octocat/custom-git-pluginGit Submodules子模块若要使用克隆仓库所用的凭据来克隆其子模块请将.gitmodules中的 url 从git改为https[submodule my-module] path my-module -url gitgithub.com:octocat/my-module.git url https://github.com/octocat/my-module.git如果希望使用 ssh 克隆的用户在.gitmodules中保留 ssh url而 Woodpecker 使用 https url可以添加submodule_overrideclone: - name: git image: woodpeckerci/plugin-git settings: recursive: true submodule_override: my-module: https://github.com/octocat/my-module.git steps: ...skip_clone[!WARNING] 默认 clone 步骤以root身份执行以确保 workspace 目录可被任何用户访问权限0777。这是为了让 rootless 步骤容器能够写入 workspace 目录。如果 rootless 步骤容器配合skip_clone使用用户必须确保提供一个无特权容器可访问的合适 workspace 目录例如/tmp。默认情况下 Woodpecker 会自动添加 clone 步骤可通过 clone 属性配置。如果完全不需要 clone 步骤可以用下面的方式跳过skip_clone: true在 workflow.go 中SkipClone是Workflow结构体的布尔字段编译器在配置默认 clone 步骤时会检查该开关见 compiler.go 中的defaultCloneName常量与相关逻辑。when- 全局 workflow 条件Woodpecker 允许基于某些条件跳过整个 workflow而不只是步骤。只有当when块中的所有条件都求值为 true 时workflow 才会执行否则它不会包含在 pipeline 中。其他通过depends_on引用了被跳过 workflow 的 workflow 也会被排除。若希望在被引用的 workflow 不在 pipeline 中时忽略该依赖请在依赖上使用optional: true。关于各过滤器的更多信息参见步骤级when过滤器。按分支执行条件示例when: branch: main steps: - name: prettier image: woodpeckerci/plugin-prettier此时 workflow 在main上触发但也会在 pull request 的目标分支为main时触发。depends_onworkflow 级Woodpecker 支持为一个仓库定义多个 workflow这些 workflow 相互独立运行。若要让它们互相依赖可以使用depends_on关键字。depends_on中的可选依赖depends_on的每个条目可以是字符串必需依赖也可以是带有name和optional: true的对象。当被引用的 workflow 或步骤不在 pipeline 中时例如被when条件过滤掉可选依赖会被静默忽略如果存在workflow 会照常等待它们。详见可选依赖。depends_on: - check-a - name: check-b optional: true该语法由 depends_on.go 中的DependsOn类型实现UnmarshalYAML同时接受纯字符串、字符串数组、对象数组及混合数组四种形式OptionalNames()与RequiredNames()区分两类依赖而编译期dag.go 的convertDAGToStages会为被过滤掉的依赖做解析——可选依赖被静默丢弃必需依赖缺失则报ErrStepMissingDependency。步骤的高级网络选项[!WARNING] 仅在仓库设置中由管理员开启 Trusted Network可信网络选项后才允许使用。dns如果后端引擎支持修改 DNS 服务器和查找域该选项可用于为特定步骤将默认 DNS 配置改为自定义配置。steps: - name: build image: plugin/abc dns: 1.2.3.4 dns_search: internal.company特权模式Privileged modeWoodpecker 允许在 YAML 中配置特权模式。你可以用该参数以提升的能力escalated capabilities启动容器。[!INFO] 特权模式仅对受信任的仓库trusted repositories开放出于安全考虑应仅在私有环境中使用。参见项目设置启用 trusted 模式。steps: - name: build image: docker environment: - DOCKER_HOSTtcp://docker:2375 commands: - docker --tlsfalse ps services: - name: docker image: docker:dind commands: dockerd-entrypoint.sh --storage-drivervfs --tlsfalse privileged: true在 container.go 中Privileged被标注为 Docker and Kubernetes SpecificDocker 与 Kubernetes 专用字段最终由对应后端将其转换为容器运行时权限配置。配置校验与常见误区Woodpecker 仓库内置了一套完整的配置 schema 校验器位于 schema.json。它定义了配置文件的顶层结构steps为必填项其余如when、workspace、clone、services、matrix、labels、depends_on、concurrency、skip_clone均为可选并给出了depends_on条目字符串或{name, optional}对象、concurrency整数或对象等类型的合法形态。编写配置时注意以下几点可避免大部分报错步骤必须声明imagecommands仅限构建步骤使用插件与服务容器不能使用status只接受success与failure且默认成功时才运行branch不作用于 tag 事件tag 过滤请使用refpath仅对 push 与 pull_request 事件生效空提交时由on_empty决定cron过滤需要同时声明event: cron为步骤设置depends_on会触发整个 workflow 进入 DAG 并行模式重名步骤、依赖缺失与循环依赖都会被编译器拒绝带woodpecker-ci.org前缀的标签不可自定义。小结本文从 Workflow 定义出发完整梳理了 Woodpecker 步骤语法image、pull、commands、entrypoint、failure、environment等与顶层区块services、workspace、matrix、labels、variables、clone、skip_clone重点剖析了when条件执行的十类过滤器及其列表 OR、单条 AND的求值语义、depends_on从串行切换到 DAG 并行调度的机制以及特权模式、高级网络选项等进阶能力。所有语法行为都能在 pipeline/frontend/yaml 的源码类型定义、约束匹配、DAG 编译、schema 校验中找到对应实现。掌握这些语法之后你可以编写出既有精细条件控制、又能最大化并行效率的 Woodpecker pipeline 配置。赞分享CI/CDDevOps【免费下载链接】woodpeckerWoodpecker is a simple, yet powerful CI/CD engine with great extensibility.项目地址https://gitcode.com/gh_mirrors/wo/woodpecker点击查看免费下载相关推荐Woodpecker Workflow 语法完全指南从 steps 定义到条件执行与并行编排Woodpecker Workflow 语法完全指南从 steps 定义到条件执行与并行编排 本篇技术指南以 Woodpecker CI/CD 引擎的 WorCI/CDDevOpsWoodpecker 工作流语法完全指南从 steps 定义到条件执行与 DAG 编排Woodpecker 工作流语法完全指南从 steps 定义到条件执行与 DAG 编排 Woodpecker 使用一个位于仓库根目录默认 .woodpeckCI/CDDevOpsWoodpecker Workflow 语法完全指南从步骤定义到条件执行与并行调度Woodpecker Workflow 语法完全指南从步骤定义到条件执行与并行调度 导读 本文是 Woodpecker CI/CD 引擎中 WorkflowCI/CDDevOps上一篇270M参数撬动百亿边缘市场Gemma 3微型模型如何重塑AI终端格局下一篇WeChatMsg颠覆性微信聊天记录智能备份与深度分析解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考