使用 github 操作从 monorepo 部署单个服务

den*_*dog 22 continuous-integration github continuous-deployment google-cloud-build github-actions

我有大约 10 个单独的微服务,它们主要是用于各种数据处理作业的云功能,它们都位于一个 github 存储库中。

目标是在推送到分支时触发将这些服务有选择地部署到 Google Cloud Functions - 当单个功能已更新时。

我必须避免单个服务更新导致部署所有云功能的情况。

我当前的存储库结构:

/repo
--/service_A
----/function
----/notebook
--/service_B
----/function
----/notebook
Run Code Online (Sandbox Code Playgroud)

附带说明一下,使用 Github Actions VS Google Cloud Build 进行此类自动化的优缺点是什么?

pet*_*ans 39

GitHub Actions 支持对工作流进行路径过滤的 monorepos。您可以创建工作流以在特定路径上的文件更改时有选择地触发。

https://help.github.com/en/articles/workflow-syntax-for-github-actions#onpushpull_requestpaths

例如,当路径下的任何文件service_A/发生更改时,此工作流将在推送时触发(注意**glob 匹配嵌套目录中的文件)。

on:
  push:
    paths:
      - 'service_A/**'
Run Code Online (Sandbox Code Playgroud)

  • 好的,谢谢,这可行,但要求每个服务本质上都有自己的工作流程。 (2认同)
  • @dendog 是的,完全正确。我认为在很多情况下,单一存储库中的不同服务无论如何都会由不同的团队拥有,因此每个团队都有自己的工作流程是有意义的。不过,可能会有很多重复的工作流程步骤,而且我认为 GitHub Actions 没有任何功能可以在工作流程之间共享步骤,例如 CircleCI orbs。 (2认同)
  • 我知道这是一个旧线程,我们发现您可以通过创建自定义操作来做到这一点。例如,我们托管在 IBM Cloud 上并使用 IBMCloud 容器注册表,因此我们有一个用于登录 IBMCloud CLI 的自定义操作,该操作可跨多个作业使用。 (2认同)
  • 请访问 [monorepo.tools](https://monorepo.tools/),它有助于解释 monorepo 的实际好处 - 它不会为每个项目创建重复的 yaml。 (2认同)

小智 5

您还可以运行一些脚本来发现哪些服务被更改,git diff并通过GitHub REST API触发相应的作业。

可能有两个工作流main.ymlservices.yml.

主工作流将被配置为始终在推送时启动,它只会启动脚本来找出哪些服务已更改。对于每个更改的服务存储库调度事件,将使用有效负载中的服务名称触发。

服务工作流将配置为在repository_dispatch上启动,并且将为每个服务包含一个作业。作业将具有基于事件负载的附加条件。

查看具有类似设置的展示:https : //github.com/zladovan/monorepo


air*_*nix 5

这不是 Monorepo

如果您只有应用程序,那么我很抱歉...但您拥有的只是许多应用程序的存储库。

monorepo 是一个包的集合,您可以在它们之间映射依赖关系图。

啊哈,我有一个 monorepo

但是,如果您有一组相互依赖的包,那么请继续阅读。

apps/
  one/
    depends:
      pkg/foo
  two/
    depends:
      pkg/bar
      pkg/foo
pkg/
  foo/
  bar/
  baz/
Run Code Online (Sandbox Code Playgroud)

答案是,您切换到一个可以描述当前 git ref 和其他 git ref 之间哪些包发生了更改的工具。

以下两个示例release在每个更改的包apps/* 及其依赖的所有包上运行 npm 脚本。

我不确定 pnpm 方法是否会默默地跳过没有release目标/命令/脚本的包。

使用 NX 开发

使用 NX.dev,它会用它的命令为你解决这个问题nx affected

  • 你需要nx.json在你的 monorepo 的根目录中
  • 它假设您将 package.json 方法与 nx.dev 一起使用,如果project.json每个包中都有,那么它们target将驻留在其中。
  • 你的 CI 将如下所示:
pnpx nx affected --target=release
Run Code Online (Sandbox Code Playgroud)

Pnpm 过滤

您的另一个选择是切换到 pnpm 并使用其过滤语法:

pnpm --filter "...{apps/**}[origin/master]" release
Run Code Online (Sandbox Code Playgroud)

朴素路径过滤

如果您只是尝试并依赖在此 git 提交中更改的“哪些路径”,那么您会错过影响您实际想要部署的包的瞬态更改。

如果你有一个 github 操作,例如:

on:
  push:
    paths:
      - 'app/**'
Run Code Online (Sandbox Code Playgroud)

那么当您只推送改变pkg/**.

其他有趣的 github 操作

  • 老实说,我不确定为什么人们否决了这个答案,monorepo 的含义远不止在同一根目录下有几个项目或应用程序,您可以共享配置和基础设施定义,定义指南(例如 eslint 和 prettier)以及更多的。我还推荐 [turborepo](https://turborepo.org/) 和 [monorepo.tools](https://monorepo.tools/) 以了解有关 monorepo 目的的更多信息 (3认同)