dstockto / slartybartfast
工件构建和部署工具
Requires
- php: ^8.1|^8.2
- illuminate/collections: ^v9.0.0|^v10.0.0
- league/flysystem: ^3.0
- league/flysystem-aws-s3-v3: ^3.0
- symfony/console: ^6
Requires (Dev)
- phpspec/phpspec: ^7.2.0
- roave/security-advisories: dev-master
- squizlabs/php_codesniffer: ^3.5
README
Slarty Bartfast 是一个工件管理器,旨在简化处理 "工件" 和 "资源" 的构建和部署过程。
什么是工件?
工件是代码更改的结果——这意味着它可能是一个编译后的可执行文件、包含转译后的 JavaScript 的 zip 文件,甚至可能只是一个项目目录的内容,如果这是在服务器上运行应用程序所必需的。简而言之,工件最终会变成一个包含代码或二进制的 zip 文件,或者两者的组合,在我们需要构建应用程序时可以使用。
什么是资源?
资源是应用程序运行所需的东西,但不是您自己代码的结果。它可能是第三方库或其他代码或文件,理想情况下它们不会频繁更改。例如,可能是 ExtJS 框架的一个版本。应用程序需要它来运行,但它不与 npm 或 yarn 这样的常规包管理器一起工作。Slarty Bartfast 允许将这些资源作为 tar.gz 文件存储在存储库中,然后通过 slarty deploy-assets
命令检索和部署。
为什么创建 Slarty Bartfast?
在工作中,我们所有的项目都使用一个 "构建" 步骤来处理 UI 应用程序。这些通常是 React 应用程序,但没有任何理由这不能适用于任何其他应用程序,这些应用程序需要大量的源代码并创建一个捆绑或编译后的工件。我们的每个应用程序都由多个独立的 UI 应用程序组成。在某些情况下,某些应用程序可能长时间未进行修改或更新,并且任何给定的 PR(拉取请求)很可能只更新单个应用程序。重建未更改的应用程序是没有意义的。这也提供了一种确保我们在 QA、UAT、生产以及任何其他环境中使用的是应用程序的确切相同构建的不错方式。
将 Slarty 集成到我们的 PR 和构建过程中意味着我们节省了大量时间,因为我们没有做我们不需要的工作。之前在服务器上构建的部署现在可以下载和部署工件,只需几秒钟。
Slarty Bartfast 做什么?
Slarty Bartfast 使用 git 唯一标识目录的内容。目前它不会在非 git 控制的代码上工作,但如果这很重要,它可能在将来有所改变。想法是项目可能包含几个不同的应用程序或工件。而不是每次有更改或拉取请求时都构建每个子应用程序,如果我们能识别出成为或定义唯一工件的内容,我们就可以一次性构建并存储它。稍后我们可以只需下载并使用该工件,而不是重新创建它。
通过在构建和使用之前将目录的内容压缩为单个唯一值,以及使用可预测的方式来标识生成的工件文件,我们可以快速决定是否需要构建,或者我们已经为特定的唯一代码组合构建了工件。借助 artifacts.json
配置文件的帮助,Slarty Bartfast 可以程序化地确定是否需要构建,并在必要时启动它。完成后,它可以将该工件存储在存储库中,稍后可以用来确定在代码不同之前不需要再次构建。
此外,Slarty Bartfast 还可以下载和部署这些工件。目前部署实际上是在配置的位置下载和解压。这个下载和解压过程非常快,比在 web 服务器上构建节省了大量时间。这也意味着我们不需要在 web 服务器上安装 npm 或 node。
总结一下,Slarty Bartfast 允许进行可重复、可预测的部署,并消除了重新构建已构建工件的必要性。
配置
Slarty Bartfast 默认使用一个名为 artifacts.json
的 json 配置文件。该文件提供了 Slarty Bartfast 用于工作的信息。在根目录下是一个包含多个键的对象。我将详细介绍每个部分,并在需要时提供更多详细信息。
- application - 应用程序的名称。目前未使用
- root_directory - 项目根目录的位置。Slarty Bartfast 所做的一切都将相对于该目录。为了方便,您可以使用 "DIR" 值来表示项目的根目录与 artifacts.json 文件的位置相同。更改根目录和相对于该目录的应用程序位置将导致不同的标识符值,即使实际源没有改变,也可能导致不同的存档内容。强烈建议将 artifacts.json 放在项目的根目录中,并使用
__DIR__
- repository - 这是存储构建工件的配置。下面将详细介绍。
- artifacts - 这是配置每个构建的位置。稍后还会详细介绍。
- assets - 这是配置部署资产的地点。稍后也会详细介绍。
配置 - "repository" 部分
"repository" 部分是您配置存储构建工件结果的地点的地方。这里是 Slarty Bartfast 将确定是否需要创建构建、放置工件的位置,以及在部署时从哪里拉取工件的位置。
Slarty Bartfast 目前支持本地文件系统和 Amazon 的 S3 作为存储库位置。存储库对象需要一个 "adapter" 键,其值为 "local" 或 "s3"。值不区分大小写。它还有一个 "options" 键,它是另一个对象,它定义了我们使用存储库位置所需的值。
本地存储库
本地存储库配置很简单。选项中只需要 "root" 值。以下是一个示例本地配置
{
...
"repository": {
"adapter": "Local",
"options": {
"root": "/tmp/artifact-repo"
}
},
...
}
S3 存储库
要使用 AWS S3 作为存储库,需要一些额外的选项。以下是一个示例
{
...
"repository": {
"adapter": "s3",
"options": {
"region": "us-east-1",
"bucket-name": "<aws bucket name>",
"path-prefix": "path/to/repo",
"profile": "default (optional)"
}
},
...
}
大多数值应该很明显它们是什么。path-prefix 是唯一可选的值。如果提供,它将导致工件被放置在 S3 上的伪目录中。这是一种将不同应用程序的工件保存在同一个存储桶中但保持它们分离的好方法。您应该在将运行 Slarty Bartfast 的用户的 ~/.aws/credentials
文件中拥有您的 AWS 凭据。profile 键是可选的,默认值为 "default",但如果您希望 Slarty 使用凭据文件中不同配置文件部分的凭据,请在此处放置它。
配置 - "artifacts" 部分
工件部分是一个对象数组。每个对象定义了确定如何计算标识符、如何命名工件、如何触发构建以及将工件解压缩到部署的位置所需的信息。
一个示例
{
"name": "Models",
"directories": ["src/SlartyBartfast/Model"],
"command": "make Model",
"output_directory": "src/SlartyBartfast/Model",
"deploy_location": "build/murdles",
"artifact_prefix": "slarty-models",
"root": "optional/override"
}
- name - 工件或构建的名称用于 Slarty Bartfast 命令的输出
- 目录 - 尽管名称为“目录”,但它也可以与单个文件一起使用。这些用于确定唯一标识符。其理念是,如果一个或多个目录中的任何内容发生变化,构建输出就会不同。如果这些路径之外的文件发生变化并导致构建过程产生不同的输出,则应将这些文件或目录包含在此数组中。
- 命令 - 这是用于创建构建输出的命令。它应能从应用程序的根目录执行。
- 输出目录 - 这是将要压缩以形成存档文件并将其存储在仓库中的目录。
- 部署位置 - 这是存档应该解压缩到的位置。
- 存档前缀 - 此值用于存档 zip 文件的命名部分。存档名称基本上是 {archive_prefix}-{hash}.zip。它在文件系统中查找存档所属或来源时有助于识别。
- 根目录 - 存档级别的根值是可选的,你可能永远不需要使用它。默认情况下,每个存档都会使用配置的根目录。如果你需要,出于某种原因,从不同的起始位置计算应用程序的哈希值,你可以在其中提供不同的根目录。再次强调,在大多数情况下你不需要这个。
配置 - "资产"部分
资产部分是一个对象数组。每个对象定义了从存档仓库检索资产所需的信息以及它应该解压缩到的位置。目前,资产部分仅用于 deploy-assets
命令。没有其他命令使用或了解此部分。
一个示例
{
"name": "ExtJS 4.2",
"filename": "extjs-4.2.tar.gz",
"deploy_location": "library/extjs-4.2"
}
-
名称 - 存档的名称是一个友好的名称,可以用它来过滤。你可以通过在此名称上过滤来限制 deploy-assets 命令仅部署一些资产。
-
文件名 - 这是应在存档仓库中找到的文件名称。目前,该文件必须在所有其他存档相同的位置。
-
部署位置 - 这是资产将被下载和展开的位置。展开后,资产存档本身将被删除。
Slarty Bartfast 命令
Slarty Bartfast 提供了许多命令。所有命令都通过 ./slarty 或 /path/to/slarty 执行。
./slarty hash <root> <directories...>
hash 命令不需要存档配置。根值是从中开始计算哈希值的位置,目录是计算哈希值时使用的空格分隔的相对路径。提供的目录顺序不会影响哈希结果。
➜ SlartyBartfast git:(master) ✗ ./slarty hash ~/Projects/myproject mydirectory
c39bffc99a4277c31ad8185a8e2a0919bbe44a82
如果目录不存在或为空,你会看到错误。请注意:MacOSX 默认不使用大小写敏感的文件系统,但 git 是大小写敏感的。请确保目录和配置与文件或目录的实际大小写匹配。
./slarty artifact-names
artifact-names
命令可以接受 [-c|--config] 和 [-f|--filter] 选项。这两个选项都是可选的。如果没有指定配置文件,则默认为 ./artifacts.json。过滤器选项用于提供要提供存档名称的应用程序列表。此命令的结果是应用程序与其当前仓库状态的存档名称的表格。
➜ SlartyBartfast git:(master) ✗ ./slarty artifact-names
------------- --------------------------------------------------------------
Application Artifact Name
------------- --------------------------------------------------------------
source slarty-source-15ab98133cfacf640b76d7fdf7890211110e5041.zip
Services slarty-services-91f042b9df7c50b59ab08c657d09c81442e04a65.zip
Models slarty-models-51286ac4976b8dc1667d8f7bc033806e858cb7b7.zip
AMess slarty-mess-f2788bbe13c3240951a10d97593467a68502e2f7.zip
------------- --------------------------------------------------------------
./slarty hash-application
类似于 artifact-names,hash-application 采取相同的 [-c|--config] 和 [-f|--filter] 选项。而不是存档名称,它提供哈希值。
➜ SlartyBartfast git:(master) ✗ ./slarty hash-application
------------- ------------------------------------------
Application Hash
------------- ------------------------------------------
source 15ab98133cfacf640b76d7fdf7890211110e5041
Services 91f042b9df7c50b59ab08c657d09c81442e04a65
Models 51286ac4976b8dc1667d8f7bc033806e858cb7b7
AMess f2788bbe13c3240951a10d97593467a68502e2f7
------------- ------------------------------------------
./slarty should-build
should-build
命令接受与大多数 Slarty Bartfast 命令相同的选项,即 [-c|--config] 和 [-f|--filter]。此命令的目的是确定工件归档是否存在于存储库中。如果它存在,则不需要构建。如果不存在,则需要构建。此命令会进行此判断,但实际上不会执行构建。
➜ SlartyBartfast git:(master) ✗ ./slarty should-build
------------- --------------
Application Build Needed
------------- --------------
source YES
Services YES
Models NO
AMess NO
------------- --------------
在上面的示例中,Models
和 AMess
应用程序的工件已经存在于存储库中,但 source
和 Services
应用程序的构建在存储库中不存在。
./slarty do-builds
do-builds
命令,像上面大多数命令一样,也接受 [-c|--config]
和 [-f|--filter]
选项。它还接受 --force
选项。运行 do-builds
将确定构建后应该生成的工件名称。如果它存在于存储库中,则不会执行。如果不存在,则将执行工件配置中的 command
部分。一旦构建成功,将通过将 output_directory
压缩成与 artifact-names
命令中看到的类似名称的存档来创建存档。然后将其存储在存储库中。
如果您提供 --force
选项,则它将不会检查存档是否存在于存储库中。它将在存储库中构建并存储结果,这意味着如果它确实存在,将被覆盖。如果构建过程已更改但代码未更改,这将确保存储在存储库中的是正确的工件存档。
Doing build for source - YES
Doing build for Services - YES
Doing build for Models - NO
Doing build for AMess - NO
Beginning build for source application
--------------------------------------
<snip ...>
Build succeeded for source
1/2 [==============>-------------] 50%
-- Saved slarty-source-15ab98133cfacf640b76d7fdf7890211110e5041.zip to repository.
Beginning build for Services application
----------------------------------------
<snip ...>
2/2 [============================] 100%
如果在上面的示例中提供了 --force
选项,则所有四个构建都会执行,并将那些工件存储在存储库中。
./slarty do-deploys
像上面大多数命令一样,do-deploys
命令接受 [-c|--config]
和 [-f|--fiter]
选项。do-deploys
命令的目的是识别与当前存储库代码状态匹配的存档,从存储库中下载这些存档,并将它们解压缩到 deploy_location
目录。如果存档在存储库中找不到,则将其视为致命错误。这是为了严格分离构建和部署步骤。理想情况下,构建发生在持续集成(CI)服务器上,而部署将在网站或应用服务器上发生。
Found artifact slarty-source-15ab98133cfacf640b76d7fdf7890211110e5041.zip for source
- Downloaded artifact
- Unzipped artifact
- Deleted (zip) artifact
Found artifact slarty-services-91f042b9df7c50b59ab08c657d09c81442e04a65.zip for Services
- Downloaded artifact
- Unzipped artifact
- Deleted (zip) artifact
Found artifact slarty-models-51286ac4976b8dc1667d8f7bc033806e858cb7b7.zip for Models
- Downloaded artifact
- Unzipped artifact
- Deleted (zip) artifact
Found artifact slarty-mess-f2788bbe13c3240951a10d97593467a68502e2f7.zip for AMess
- Downloaded artifact
- Unzipped artifact
- Deleted (zip) artifact
do-deploy
过程将创建在 deploy_location
值中指定的目录结构。然而,如果该结构存在并且包含文件,则不会清除。这是应该在其他地方处理的单独责任。想法是,如果应用程序需要将多个工件部署到同一位置,它可以这样做。解压缩命令将覆盖在部署发生时在位置上的任何现有文件。它不会删除任何已存在的文件,所以如果文件在一个部署存档中存在,然后在下一个部署中不存在,它仍然存在于部署输出目录中。
./slarty deploy-assets
deploy-assets
命令接受 --filter
和 --config
选项。它们与其他命令的工作方式相同,只是过滤器作用于配置中的名称值。
如果您运行 slarty deploy-assets
,而 Slarty 无法在工件存储库中找到引用的文件之一,则命令将失败并告知缺少的资产。目前,它不会“预检查”是否存在。它将按顺序处理资产,并在第一个缺失的资产上失败。如果它失败,slarty 的返回代码将非零。
deploy-assets
命令将会在不存在的情况下创建输出目录路径。它将相对于根目录下的“root_directory”配置选项。
为什么是Slarty Bartfast?
Slarty Bartfast的名字来源于《银河系漫游指南》(HHGTTG)中的一个角色。在书中,Slartibartfast在Magrathea行星工作,担任定制行星的设计师。他最喜欢的工作是设计海岸线,并为挪威的峡湾赢得了奖项。对于Slarty Bartfast来说,行星是文物。
程序的名字经过了几个想法。最初的两个是“Artificer”和“Artifactory”,但后来发现这两个都是真实存在的事物。接下来是“Slartibartifact”,虽然读起来很有趣,但作为命令输入却不太方便。最终我回到了“Slarty Bartfast”,因为误记了如何拼写“Slartibartfast”,但现在这完全是有意为之,因为"./slarty"足够简单,如果这个程序发布出去,搜索“Slarty Bartfast”最终可能会找到这个程序。
完整示例配置
以下是一个完整的示例配置,适用于拥有两个独立构建和工件,并且使用S3作为工件存档存储位置的应用程序。
{
"application": "Sample Application",
"root_directory": "__DIR__",
"repository": {
"adapter": "s3",
"options": {
"key": "AKABAKWAMBALAMBADOOP",
"secret": "I+Kn0wS0m3th1ngY0uD0n+tKN0W4Ab0UTtRY2GU355",
"region": "us-east-1",
"bucket-name": "example-app-artifacts",
"path-prefix": "Example/App"
}
},
"artifacts": [
{
"name": "Purple App",
"directories": ["src/Purple"],
"command": "make srcPurple",
"output_directory": "build/purple",
"deploy_location": "public/purple",
"artifact_prefix": "purple-app"
},
{
"name": "Green App",
"directories": ["src/Green"],
"command": "make srcGren",
"output_directory": "build/green",
"deploy_location": "public/green",
"artifact_prefix": "green-app"
},
],
"assets": [
{
"name": "Some Asset",
"filename": "smurpy.tar.gz",
"deploy_location": "build/assets/smurpy"
},
{
"name": "Legitimate Business",
"filename": "opposite_of_murder-4.2.tar.gz",
"deploy_location": "build/assets/unicorns"
}
]
}
本地模式
可以使用Slarty在本地运行构建和测试部署。命令deploy-assets
、do-builds
、do-deploys
和should-build
都接受一个--local
标志,这将使得artifacts.json具有设置为本地的仓库适配器。为了帮助实现这一点,建议您还包括repository->options->root值。本地模式的目的在于允许更轻松地测试构建和部署,而无需更改artifacts.json文件,并记得不要将更改提交到您的源代码仓库。
有问题吗?
如果有任何未回答的问题、问题、期望的功能,请联系slarty-support@davidstockton.com,或者您可以自由地提交一个pull request。