Deployer YAML Recipe 编写指南:声明式定义主机、任务与钩子,并由 schema.json 强制校验
DevOpsCI/CDCLI开发工具运维【免费下载链接】deployerThe PHP deployment tool with support for popular frameworks out of the box项目地址https://gitcode.com/gh_mirrors/de/deployer点击查看免费下载Deployer 是开箱支持主流 PHP 框架的部署工具除了传统的 PHP 配方recipe之外还提供基于 YAML 的声明式配方写法。本文以 docs/yaml.md 为核心结合仓库中的 schema.json、YamlRecipe.php 等源码与测试系统讲解 YAML 配方的顶层结构、主机与任务定义、步骤类型、PHP/YAML 互相导入机制以及常见注意事项帮助你在项目中写出可校验、可维护、可复用的 YAML 部署配方。YAML 配方在 Deployer 中的定位Deployer 支持三种配方文件格式PHPdeploy.php最灵活可以使用闭包、条件逻辑、自定义步骤是最底层的能力载体YAMLdeploy.yaml声明式、结构化的配方适合纯配置场景MAMLdeploy.mamlJSON 超集支持注释、多行字符串与尾逗号是 YAML 的增强替代品。YAML 配方的价值在于主机、配置、任务、钩子全部以数据的形式表达配合 schema 可以在加载阶段就发现问题。当前仓库中dep init交互式生成配方时仅提供php与maml两种选择见 InitCommand.phpYAML 配方需要手写或由其他文件导入但这并不影响它作为轻量声明式方案的价值。校验机制一切 YAML 配方都要过 schema.json文档明确说明YAML 配方会依据 schema.json 进行校验。该文件位于仓库根目录下src/目录中是一份标准的 JSON Schemadraft-07。从 schema.json 看顶层是一个 object合法顶层键只有顶层键类型说明import字符串或字符串数组导入其他配方.php/.yaml/.mamlconfigobject每个键值对调用set($key, $value)写入全局配置hostsobject每个条目注册一个主机host()或localhost()tasksobject每个条目注册一个任务task()beforeobject任务前置钩子映射值为任务名或任务名数组afterobject任务后置钩子映射failobject失败回退钩子映射值为单个任务名同时additionalProperties: falsesrc/schema.json意味着任何未声明的顶层键都会导致校验失败这是 YAML 配方写错即报错的第一道防线。对tasks下的每个步骤对象schema 要求每个步骤是恰好一个动作additionalProperties: false可选的动作类型包括仅cd的步骤run步骤可附带cd、cwd、env、secrets、nothrow、forceOutput、timeout、idleTimeoutrunLocally步骤可附带cwd、timeout、idleTimeout、secrets、env、nothrow、forceOutput、shellupload步骤srcdestsrc可为字符串或数组download步骤srcdest任务配置键步骤desc、once、hidden、limit、select。一个完整的 YAML 配方示例文档给出了如下标准示例它涵盖了 YAML 配方的全部核心要素import: - recipe/laravel.php config: repository: gitgithub.com:example/example.com.git remote_user: deployer hosts: example.com: deploy_path: ~/example tasks: build: - cd: {{release_path}} - run: npm run build after: deploy:failed: deploy:unlock逐段解读import导入内置的 Laravel 配方从而继承其全部任务deploy:prepare、deploy:release、deploy:publish等与默认配置config声明仓库地址与远程用户等价于 PHP 中的set(repository, ...)与set(remote_user, ...)hosts声明目标主机example.com并设置部署路径~/exampletasks定义名为build的任务先切到发布目录再执行npm run buildafter将deploy:unlock挂到deploy:failed之后保证失败时也能释放部署锁。关于 YAML 键名的小提示包含冒号的键如deploy:failed在 YAML 中只要冒号后不紧跟空格即可不加引号但为了可读性与编辑器高亮建议统一写成deploy:failed包含点号的主机名如example.com同样建议加引号。顶层章节逐个拆解import串联 PHP 与 YAML 配方import接受单个字符串或字符串数组路径指向其他配方文件。仓库中真实的测试示例 tests/spec/recipe/deploy.yaml 第一行就是import: recipe/common.php导入的分发逻辑在 Import.php 中按扩展名路由.php→ 直接require并用闭包包裹防止变量泄漏.maml→ 交给MamlRecipe解析.ya?ml兼容.yaml与.yml→ 交给YamlRecipe::exec()其他扩展名 → 抛出Unknown file format异常。内置的recipe/*与contrib/*路径已经位于 PHP 的 include path 上因此可以直接用相对路径导入你自己的文件建议用__DIR__定位详见 import()。config等价于 set()config下的每个键值对都会被转成set($key, $value)。在 YamlRecipe.php 中实现为protected static function config(array $config): void { foreach ($config as $key $value) { set($key, $value); } }因此几乎所有 Deployer 内置配置项都可以直接写进来例如keep_releases、shared_dirs、shared_files、http_user等测试样例 tests/spec/recipe/deploy.yaml 就展示了这类写法config: application: deployer shared_dirs: - uploads - storage/logs/ - storage/db shared_files: - .env - config/test.yaml keep_releases: 3 http_user: false注意config是纯数据不接受 PHP 闭包。需要运行时求值的配置如set(var, fn () ...)必须放在 PHP 配方里再导入。hosts声明目标主机hosts下每个条目对应一台主机。加载逻辑在 YamlRecipe.php当配置中出现local: true时调用localhost($alias)否则调用host($alias)其余键值全部通过$host-set($key, $value)转发因此标准的 host 选项都可用——remote_user、deploy_path、port、identity_file、labels、ssh_arguments等。hosts: prod.example.com: remote_user: deployer deploy_path: /var/www/prod labels: stage: production dev: local: true deploy_path: /tmp/devlocal: true对应本地主机例如仓库测试中的 tests/spec/recipe/deploy.yaml 就是用prod: local: true在本地模拟生产主机。YAML 锚点去重顶层以.开头的键会被加载器直接忽略YamlRecipe.php 用array_filter过滤掉.前缀键这正好配合 YAML 的锚点与合并键做主机配置复用.base: base remote_user: foo labels: stage: production hosts: acceptance: : *base labels: stage: acceptance production: : *base remote_user: bar这个写法在测试 tests/src/Import/YamlRecipeTest.php 中被完整验证.base锚点不会作为顶层键被处理而acceptance与production都会正确继承remote_user: foo并被各自的labels覆盖。tasks组任务与步骤任务tasks下每个键都是一个任务有两种形态判定逻辑在 YamlRecipe.php组任务group task值是纯字符串数组按顺序依次执行列出的任务。例如tasks: deploy: - deploy:prepare - deploy:vendors - deploy:publish等价于 PHP 的task(deploy, [deploy:prepare, deploy:vendors, deploy:publish])。步骤任务step task值包含对象步骤每个步骤执行一个动作。文档中的build任务即属此类tasks: build: - cd: {{release_path}} - run: npm run buildbefore / after钩子钩子映射任务名 → 任务名或任务名数组。数组形式在内部会被倒序处理后逐个注册YamlRecipe.php以保持声明顺序执行例如after: deploy:failed: deploy:unlock deploy: - deploy:cleanup - build文档强调的经典用法是after: deploy:failed: deploy:unlock——部署失败后自动执行解锁避免部署锁残留阻塞后续发布。fail失败回退钩子schema.json声明了fail顶层键值为单个任务名src/schema.json。不过需要说明的是当前 YAML 加载器 YamlRecipe.php 只实现了import、config、hosts、tasks、after、before六个顶层键的处理方法fail的落地实现位于 MAML 加载器 MamlRecipe.php 中。因此如果业务需要fail钩子建议改用 MAML 配方或 PHP 配方PHP 中使用fail()函数YAML 配方中优先使用after。YAML 步骤类型详解以源码实现为准文档给出了cd与run两种步骤实际上 YamlRecipe.php 支持五种动作步骤与五类任务配置键步骤键用途对应 PHP 函数cd切换后续run的工作目录cd()run在远程主机执行命令run()run_locally在本地机器执行命令runLocally()upload上传文件到主机srcdestupload()download从主机下载文件srcdestdownload()tasks: sync: - cd: {{release_path}} - run: php artisan migrate --force - run_locally: git rev-parse HEAD - upload: src: dist/app.js dest: {{release_path}}/public/assets/ - download: src: {{deploy_path}}/shared/.env dest: .env.production任务配置键步骤用于修饰任务元数据与 PHP 中 Tasks 的链式方法一一对应步骤键类型效果desc字符串任务描述显示在dep list中once布尔只在单台主机上执行hidden布尔从dep list中隐藏limit数字并行执行的最大主机数select字符串主机选择器表达式见 Selectortasks: migrate: - desc: Run database migrations - once: true - limit: 1 - select: stageproduction - run: php artisan migrate --force一个值得注意的约束run_locally与run、upload在同一步骤中互斥。源码中对此有显式检查YamlRecipe.php违反时会抛出ConfigurationExceptionTask step can not have both run and run_locally.这是 YAML 配方中比较容易踩的坑。深入源码YamlRecipe 的执行流程YamlRecipe.php 是整个 YAML 配方的解析引擎核心入口是exec()src/Import/YamlRecipe.php#L37-L49读取文件内容用 Symfony 的Yaml::parse()解析为数组通过array_filter过滤掉所有以.开头的顶层键这就是锚点定义的藏身之处遍历剩余顶层键用static::$key($root[$key])动态分发给import、hosts、config、tasks、before、after等处理方法。tasks的构建是其中最精巧的部分src/Import/YamlRecipe.php#L79-L182加载器先把每个步骤包装成闭包再通过闭包包裹闭包的方式把cd、run、upload等动作按声明顺序串联成任务主体最终调用$task-setCallback($body)注入。这也是为什么cd只影响同一个任务内后续的run步骤——它们被编译进同一条闭包链。另外run与run_locally抛出的异常会被设置上配方文件名setTaskFilename使报错信息能精确指向 YAML 文件便于排错。YAML 与 PHP 配方互相导入文档特别强调YAML 与 PHP 配方可以互相导入。这为声明式骨架 命令式细节的组合提供了自由需要闭包、条件逻辑、自定义步骤类型的任务写成 PHP 配方再从 YAML 中导入import: - recipe/laravel.php - deploy/extras.php反过来PHP 配方也可以把 YAML 当作库存清单或配置片段拉进来例如 docs/hosts.md 展示的独立主机清单// deploy.php import(inventory.yaml);# inventory.yaml hosts: example.org: remote_user: deployer这种互导机制让团队可以把谁部署到哪台机器、有哪些全局配置这类数据沉淀为 YAML把复杂逻辑保留在 PHP各取所长。仓库中tests/spec/recipe/deploy.yaml与tests/spec/recipe/deploy_test.php是一对互为镜像的配方前者用 YAML 声明主机与任务、后者用 PHP 实现等价逻辑正好可以对照阅读tests/spec/recipe/deploy.yaml、tests/spec/recipe/deploy_test.php。与 MAML 的选型对比文档末尾指向了 MAMLMAML作为更丰富的替代方案。两者的关系是YAML生态成熟、上手零成本任何编辑器和 CI 都认识.yaml缺点是不支持注释、多行字符串要绕行、尾逗号会报错MAMLJSON 超集支持#注释、原始多行字符串适合内嵌 shell 脚本、可选逗号与尾逗号、无序键值更宽松从 MamlRecipe.php 可以看到 MAML 还支持 YAML 加载器没有的fail钩子和更丰富的run参数cwd、env、secrets、timeout、nothrow、forceOutput等。两者的顶层结构、主机/任务/钩子模型完全同构选型主要看团队习惯与编辑器支持。如果配方以数据为主、追求简洁YAML 足够如果配方开始包含脚本、注释和复杂参数MAML 会更顺手——需要时随时用import在两者之间切换。实践要点小结让 schema 把关YAML 配方加载时就会对照 schema.json 校验拼错顶层键、步骤里塞了多余字段都会立刻失败所以写完后直接跑一次dep list或dep tree验证主机配置用锚点去重借助.base: base: *base的合并键语法已被 YamlRecipeTest.php 验证避免多环境主机配置重复复杂逻辑放 PHPconfig不接受闭包需要动态求值、条件判断、自定义步骤时写 PHP 配方再导入注意run_locally互斥同一步骤内run_locally不能与run/upload共存否则抛出ConfigurationException失败解锁别忘把deploy:unlock挂到deploy:failed之后保证异常路径也能释放部署锁按需选型纯配置用 YAML需要注释/多行脚本/fail钩子时切到 MAML。YAML 配方把 Deployer 最常用的配置—主机—任务—钩子四件事收敛成一份可校验的数据文件配合仓库中的 schema.json 与 YamlRecipe.php 源码你既能在项目里立刻上手也能在遇到诡异报错时顺藤摸瓜定位到加载器内部的行为。赞分享DevOpsCI/CDCLI开发工具运维【免费下载链接】deployerThe PHP deployment tool with support for popular frameworks out of the box项目地址https://gitcode.com/gh_mirrors/de/deployer点击查看免费下载相关推荐Wazuh SCA 如何编写并校验自定义合规策略 YAMLWazuh SCA 如何编写并校验自定义合规策略 YAML Wazuh 的 SCASecurity Configuration Assessment模块按网络安全IDS日志分析应用安全漏洞扫描Capistrano 自定义任务编写完全指南从任务定义到执行器钩子的实战详解Capistrano 自定义任务编写完全指南从任务定义到执行器钩子的实战详解 导读Capistrano 是一个基于 Ruby、Rake 与 SSH 构建的部DevOpsCLI如何用 Rake 编写 Capistrano 自定义任务before/after 钩子完全指南如何用 Rake 编写 Capistrano 自定义任务before/after 钩子完全指南 Capistrano 是一款基于 Ruby、Rake 和 SSDevOpsCLI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考