在之前的文章中,我们探讨了如何使用GitLab CI/CD自动化部署到Heroku。该设置会在每次我们将代码推送到main
分支时,将应用程序部署到生产环境。
在本文中,我们将考虑一个稍微复杂一些的方法:如果我们有多个环境该怎么办?大多数工程组织至少使用三个环境:本地开发环境、预发布环境(staging)和生产环境。
此外,一些工程团队遵循Gitflow分支策略,他们有一个dev
分支和一个main
分支。这种策略已经不再流行,并被基于主干的开发所取代,但仍然可以发现有些组织还在遵循这种做法。
今天,我们将了解如何配置GitLab CI/CD,以便当我们向dev
分支推送时,将我们的应用程序部署到我们的预发布环境,而当我们向main
分支推送时,将我们的应用程序部署到生产环境。
入门
在开始之前,我们需要两样东西:一个Heroku账户和一个GitLab账户。
Heroku是一个托管和部署应用程序的好地方。作为一个平台即服务(PaaS),Heroku允许您专注于构建酷炫的事物,同时抽象掉大部分基础设施复杂性。您可以在这里创建Heroku账户。
GitLab是一个存储代码的好地方。除了仅仅是一个源代码管理工具,GitLab还提供了原生CI/CD功能,因此您可以设置管道来测试和部署代码,而无需使用其他第三方工具。您可以在这里创建GitLab账户。
本文中展示的演示应用程序同时使用了GitLab和Heroku。您可以在这里找到GitLab仓库中所有的代码。
在本地运行我们的应用程序
你可以在本地运行应用程序,方法是将仓库克隆到本地,安装依赖项,然后运行启动命令。在终端中,执行以下操作:
$ git clone https://gitlab.com/tylerhawkins1/heroku-gitflow-staging-production-gitlab-cicd-demo.git $ cd heroku-gitflow-staging-production-gitlab-cicd-demo $ npm install $ npm start
启动应用程序后,在浏览器中访问这个本地主机,你将看到应用程序正在本地运行:
Heroku应用演示
将我们的应用程序部署到Heroku
现在应用程序已经在本地运行,让我们将其部署到Heroku,这样你就可以在任何地方访问它,而不仅仅是你的机器上。
请记住,我们将把你的应用程序部署到暂存环境和生产环境。这意味着我们将基于同一个GitLab仓库创建两个Heroku应用程序。
如果你的机器上还没有安装Heroku命令行界面,在继续操作之前,你需要安装它。
安装Heroku命令行界面后,从终端运行以下命令,以检出main
分支,创建新的生产Heroku应用程序,将其部署到生产环境,并在浏览器中打开它:
$ git checkout main $ heroku create heroku-gitlab-ci-cd-production --remote heroku-production $ git push heroku-production main $ heroku open --remote heroku-production
这样,你应该会看到相同的应用程序,但这次是在Heroku URL上运行,而不是在本地主机上。做得好——你已经将你的Heroku应用程序部署到生产环境了!
但是,我们还没有完成。我们还需要配置和部署你的暂存应用程序。为此,运行以下类似的一组命令:
$ git checkout dev $ heroku create heroku-gitlab-ci-cd-staging --remote heroku-staging $ git push heroku-staging main $ heroku open --remote heroku-staging
现在你将再次部署相同的应用程序,但这次部署到不同的URL,该URL将作为你的预发布环境。现在你的两个环境都已经配置好了!
注意生产环境和预发布环境应用程序命令之间的差异和相似之处:
- 生产环境应用程序使用
main
分支,而预发布环境应用程序使用dev
分支。 - 生产环境应用程序被称为
heroku-gitlab-ci-cd-production
,而预发布环境应用程序被称为heroku-gitlab-ci-cd-staging
。 - 生产环境的git远程仓库被称为
heroku-production
,而预发布环境的git远程仓库被称为heroku-staging
。 - 生产环境和预发布环境的git远程仓库都使用
main
分支,因为Heroku只有在代码被推送到它的主分支时才会部署应用程序。
请记住,这个main
分支与你的main
和dev
分支不同。你这里推送的main
分支是你git远程的main
分支——在这个案例中,是Heroku。
当您在本地main
分支上运行git push heroku-production main
时,您正在将您的main
分支推送到Heroku生产应用的main
分支。而当您在本地dev
分支上运行git push heroku-staging main
时,您正在将您的dev
分支推送到Heroku预发布应用的main
分支。
对我们的应用进行更改
现在我们的Heroku应用已经启动并运行,如果我们想要进行一些更改怎么办?遵循Gitflow分支策略的大致近似,我们可以这样做:
- 检出
dev
分支 - 对代码进行更改
- 添加、提交并将这些更改推送到
dev
分支 - 通过运行
git push heroku-staging main
将这些更改部署到预发布Heroku应用 - 检出
main
分支 - 将
dev
分支合并到main
分支 - 通过运行
git push heroku-production main
将这些更改部署到生产Heroku应用
(如果我们真正遵循Gitflow,我们会创建一个特性分支来合并到dev
,以及一个发布分支来合并到main
,但为了简化流程,我们省略了这些步骤。)
现在,如果我们能够自动化部署到我们的任何一个环境,而不是总是手动部署,那不是很好吗?
这就是GitLab CI/CD发挥作用的地方。
持续集成/持续部署
持续集成(CI)主要是关于频繁提交并保持构建始终处于良好状态。通常,您会通过在CI管道中运行检查来验证构建是否处于良好状态。这些检查可能包括代码分析工具、单元测试和/或端到端测试。
持续部署(CD)主要是关于频繁部署。如果CI管道中的检查通过,那么构建就会被部署。如果CI管道中的检查失败,那么构建则不会被部署。
使用GitLab CI/CD,我们可以配置我们的CI管道精确地做到这一点——运行我们的测试,如果所有测试都通过,然后将应用程序部署到Heroku。对我们设置最重要的是,我们可以在CI管道中配置规则,指定应用程序应该部署到哪里。
配置GitLab CI/CD
我们可以使用.gitlab-ci.yml
文件在GitLab中以编程方式创建CI管道。我们的文件看起来是这样的:
image: node:20.10.0
cache:
paths:
- node_modules/
before_script:
- node -v
- npm install
stages:
- test
- deploy
unit-test-job:
stage: test
script:
- npm test
deploy-job:
stage: deploy
variables:
HEROKU_APP_NAME: $HEROKU_APP_NAME_PRODUCTION
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables:
HEROKU_APP_NAME: $HEROKU_APP_NAME_PRODUCTION
- if: $CI_COMMIT_REF_NAME =~ /dev/
variables:
HEROKU_APP_NAME: $HEROKU_APP_NAME_STAGING
script:
- apt-get update -yq
- apt-get install -y ruby-dev
- gem install dpl
- dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_API_KEY
GitLab CI管道由阶段和任务组成。每个阶段可以包含一个或多个任务。在我们的管道中,我们有两个阶段:test
和deploy
。在test
阶段,我们在unit-test-job
中运行我们的单元测试。在deploy
阶段,我们在deploy-job
中把应用程序部署到Heroku。
只有当上一个阶段的所有任务都通过时,我们才能进入下一个阶段。这意味着如果单元测试失败,那么应用程序就不会被部署,这是件好事!我们肯定不想在应用程序状态不佳时部署它。
您会注意到deploy
阶段有一个包含一些条件逻辑的rules
部分。这是我们指定应用程序应该部署到哪个环境的地方。如果我们处于main
分支,那么我们会部署我们的生产应用程序。如果我们处于dev
分支,那么我们会部署我们的预发布应用程序。
您还会注意到deploy
阶段引用了几个名为$HEROKU_APP_NAME_PRODUCTION
、$HEROKU_APP_NAME_STAGING
和$HEROKU_API_KEY
的变量。这些是作为GitLab中的CI/CD变量存储的。
如果您在自己的GitLab账户中设置此内容,您需要首先在Heroku账户中找到您的API密钥。在您的Heroku账户设置中,您应该会看到API密钥的部分。如果您还没有生成API密钥,现在就生成一个。

接下来,在您的GitLab项目中,点击设置 > CI/CD > 变量。展开该部分并添加三个新变量:
$HEROKU_API_KEY
的值将是您Heroku账户中的API密钥。$HEROKU_APP_NAME_PRODUCTION
的值将是您的生产Heroku应用程序的名称。我的生产应用程序名称是heroku-gitlab-ci-cd-production
,但由于Heroku应用程序名称是全局唯一的,所以您的名称会有所不同。- `$HEROKU_APP_NAME_STAGING` 的值将是您的暂存 Heroku 应用的名称。我的暂存应用的名称是 `heroku-gitlab-ci-cd-staging`。再说一次,因为 Heroku 应用名称是全球唯一的,所以您的将有所不同。

有了这些,您的 GitLab CI 流水线已经准备好使用了!让我们来测试一下。
将我们的 Heroku 应用部署到暂存环境
让我们切换到 `dev` 分支,并对我们应用中的代码进行更改。我对标题文本进行了简单的更改,并在 UI 文本中添加了几行新内容。您可以在您的代码中做出类似的更改。
现在,将这个更改添加、提交并推送到 `dev` 分支。这将启动 GitLab CI 流水线。您可以在 GitLab 中查看流水线,并实时看到进度。

如果一切顺利,您应该会看到 `test` 和 `deploy` 阶段都已通过。现在,去查看您托管的 Heroku 应用在暂存环境 URL 上的情况。GitLab CI 流水线已经为您部署了应用,所以您现在会在暂存环境中看到您的更改生效!

有了暂存环境设置好,您现在有了一个很好的地方可以在托管环境中手动测试您的代码。这也是一个完美的地方,可以让 QA 测试员或产品经理在代码上线前验证更改。
现在,查看您的生产应用 URL。您会注意到它仍然显示旧的 UI,没有最新的更改。这是因为 GitLab CI 流水线只将更改部署到了暂存环境,而不是生产环境。
我们已经验证了代码在我们的预发布环境中运行良好,所以让我们将其部署到生产环境。
将我们的Heroku应用部署到生产环境
让我们切换到main
分支,然后将dev
分支合并到你的main
分支。你可以通过创建一个pull request或者运行git merge dev
然后git push
来完成这个操作。
这将再次启动GitLab CI流水线,但这次它将准备部署你的生产应用。

你还可以在GitLab的Pipelines页面查看所有流水线运行情况,以查看你的dev
和main
分支的各种构建:

一旦流水线完成,访问你的生产Heroku应用的URL。你现在应该能看到你的更改也已经被部署到了生产环境。干得好!
结论
A good CI pipeline allows you to ship new features quickly and confidently without manually managing the deployment process. Having multiple environments configured for local development, staging, and production gives you more control over where and when code is released.
Heroku和GitLab CI/CD允许你自动化所有这些操作,让你的DevOps流程变得轻松简单!
Source:
https://dzone.com/articles/deploying-heroku-apps-to-staging-and-production