codenamephp / deployer.base
提供非常基础的任务接口、功能抽象和一些对所有项目都很有用的初始任务,如文件传输
Requires
- php: ^8.1
- deployer/deployer: ^7.0
- symfony/console: ^6.1
Requires (Dev)
- mockery/mockery: ^1.5
- roave/security-advisories: dev-latest
README
提供非常基础的任务接口、功能抽象和一些对所有项目都很有用的初始任务,如文件传输
这是什么?
此软件包是deployer的扩展,添加了基本任务和接口,并抽象了实际的deployer API。Deployer仍可按常规使用,但建议将任务实现为类,并为它们编写单元测试。如果您有跨项目重用的任务,应创建自己的软件包。已有几个codenamephp/deployer.*软件包可供使用。
但是...为什么?
我真的很喜欢可测试的代码,因为实际的deploy.php只是一个回调函数的集合,难以测试,所以我添加了一些基本的接口和类,它们封装任务并使其可重用。
当然,您可以使用lambda函数来实现它,但鉴于PHP并非旨在成为函数式编程语言,所以混合一些类要容易得多。
安装
只需将软件包添加到composer中,理想情况下通过执行 composer require codenamephp/deployer.base
,这将使用semver范围安装最新版本。
使用
按常规创建您的 deploy.php
。然后只需添加现有任务或实现您自己的任务,并使用软件包函数添加它们
const PROJECT_ROOT = __DIR__ . '/..'; // I have deployer in a seperate folder so this makes creating paths easier $deployerFunctions = new All(); // Abstraction of deployer function and also has some additional methods $deployerFunctions->registerTask(new UploadTransferables( // My version of deploying code in NEOS projects new Simple(PROJECT_ROOT . '/Configuration', '{{release_path}}'), new Simple(PROJECT_ROOT . '/DistributionPackages', '{{release_path}}', ['Tests/']), new Simple(PROJECT_ROOT . '/Packages', '{{release_path}}'), new Simple(PROJECT_ROOT . '/Web', '{{release_path}}', ['_Resources/']), new Simple(PROJECT_ROOT . '/flow', '{{release_path}}'), )); // additional tasks from other packages $deployerFunctions->task('composer:install', new \de\codenamephp\deployer\composer\task\install\Production())->desc('Run composer install for production.'); $deployerFunctions->task('composer:install:development', new \de\codenamephp\deployer\composer\task\install\Development())->desc('Run composer install for production.'); (new ByTaskListAndMatchers(new AtLeastOne( // clean up the cli list new ByRegexTaskName('/provision:?.*/'), new ByRegexTaskName('/logs:caddy.*/'), new ByRegexTaskName('/deploy:.*/') )))->hide();
实现任务
Deployer只期望一个可调用的任务,从理论上讲,这就是任务所需的一切。此软件包包含 \de\codenamephp\deployer\base\task\iTask
接口,强制执行此操作,因此我们可以添加任务的新实例。
还有 \de\codenamephp\deployer\base\task\iTaskWithName
和 \de\codenamephp\deployer\base\task\iTaskWithDescription
接口。这些接口可以直接在类中设置任务的描述和名称,这样我们就不必在每个项目中设置相同的字符串,从而使我们的部署文件杂乱无章。至少,必须实现 \de\codenamephp\deployer\base\task\iTaskWithName
,这样我们就可以将任务传递给 \de\codenamephp\deployer\base\functions\iTask::registerTask
,该函数负责其余部分。
Deployer 函数
内置的deployer函数需要一个正在运行的Deployer实例,并且是全局的,因此它们非常难以模拟。为了使我们的任务可测试,有几个 \de\codenamephp\deployer\base\functions\*
接口,每个方法或方法组一个。还有一个 \de\codenamephp\deployer\base\functions\iAll
接口,将它们全部组合起来作为便利性接口,如果我们需要几个方法。同样,还有一个 \de\codenamephp\deployer\base\functions\All
实现作为全局方法的代理,同时也进行一些额外的类型检查。
这些接口与deployer内置方法大致相同,但添加了一些额外的类型提示和返回提示,以使API更清晰。
在您的任务中使用这些接口,并使用 \de\codenamephp\deployer\base\functions\All
实现或编写您自己的实现。在您的测试中,您可以轻松模拟这些接口。
主机检查
某些任务不应意外执行,例如将数据库从本地推送到生产。这可以通过将 \de\codenamephp\deployer\base\hostCheck\iHostCheck
接口作为任务的依赖项添加,并在您的 __invoke()
方法中调用 \de\codenamephp\deployer\base\hostCheck\iHostCheck::check
方法来实现。
不在生产上运行
本实现假设生产主机实际上具有“production”别名(可在构造函数中更改)并检查当前主机。如果别名匹配,将抛出\de\codenamephp\deployer\base\UnsafeOperationException
异常,这将停止部署程序运行。如果您有需要清理的内容(例如数据库备份),请在失败步骤中添加清理任务。
WithDisallowList
与DoNotRunOnProduction类似,但有一个不允许的别名列表。
SkippableByOption
这是一个用于添加\de\codenamephp\deployer\base\hostCheck\iHostCheck
的装饰器,它接受现有的主机检查,但仅在未设置--cpd:skip-host-check
(或缩写为-cpd:shc
)时执行。这样我们就可以在了解自己在做什么的情况下跳过主机检查……当然,这要自己承担风险。 ;)
任务隐藏器 / 任务匹配器
Deployer附带了一套默认任务,如整个provision
命名空间。这些通常只使用一次(如果使用的话),只会使CLI列表变得混乱。可以使用\de\codenamephp\deployer\base\taskHider\iTaskHider
来隐藏那些不需要的任务。默认实现\de\codenamephp\deployer\base\taskHider\ByTaskListAndMatchers
使用\de\codenamephp\deployer\base\taskMatcher\iTaskMatcher
实现来查找要隐藏的任务。还有一个集合,可以用来添加多个匹配器并隐藏所有匹配项。
示例可能如下所示
(new ByTaskListAndMatchers(new AtLeastOne( // clean up the cli list new ByRegexTaskName('/provision:?.*/'), new ByRegexTaskName('/logs:caddy.*/'), new ByRegexTaskName('/deploy:.*/') )))->hide();
可传输项
存在一个\de\codenamephp\deployer\base\transferable\iTransferable
接口,它通过清楚地说明什么是本地和远程,使文件传输更易于阅读。
任务
我可能在某个时候会包含一个由Open API生成的手册,但目前只需检查\de\codenamephp\deployer\base\task
命名空间中的类。