2020年9月17日

使用 TypeScript、PostgreSQL 和 Prisma 构建后端:持续集成与部署

在本系列的第四部分中,我们将使用 GitHub Actions 配置持续集成 (CI) 和持续部署 (CD),以便测试并将后端部署到 Heroku。

Backend with TypeScript, PostgreSQL & Prisma: CI & Deployment

引言

本系列的目标是通过解决一个具体问题来探索和演示现代后端的不同模式、问题和架构:一个在线课程的评分系统。选择这个问题是因为它具有多种关系类型,并且足够复杂,可以代表一个真实世界的用例。

上面提供了直播回放,其内容与本文相同。

本系列将涵盖的内容

本系列将重点关注数据库在后端开发各个方面的作用,涵盖

主题部分
数据建模第1部分
CRUD第1部分
聚合第1部分
REST API 层第2部分
验证第2部分
测试第2部分
无密码身份验证第3部分
授权第3部分
与外部 API 集成第3部分
持续集成第4部分 (当前)
部署第4部分 (当前)

在第一篇文章中,你为问题域设计了一个数据模型,并编写了一个种子脚本,该脚本使用Prisma Client将数据保存到数据库。

在本系列的第二篇文章中,你在第一篇文章的数据模型和Prisma schema之上构建了一个REST API。你使用Hapi来构建 REST API,它允许通过 HTTP 请求对资源执行 CRUD 操作。

在本系列的第三篇文章中,你实现了基于电子邮件的无密码身份验证和授权,使用JSON Web Tokens (JWT) 与 Hapi 结合来保护 REST API。此外,你还实现了基于资源的授权,以定义用户允许执行的操作。

今天你将学到什么

在本文中,你将通过定义一个工作流来设置 GitHub Actions 作为 CI/CD 服务器,该工作流运行测试并将后端部署到 Heroku,你将在 Heroku 上托管后端和 PostgreSQL 数据库。

Heroku 是一个平台即服务 (PaaS)。与无服务器部署模型不同,使用 Heroku,你的应用程序即使没有请求也会持续运行。虽然无服务器有很多好处,例如成本更低、运营开销更少,但这种方法避免了数据库连接流失和冷启动等无服务器方法常见的挑战。

要了解使用 Prisma 的应用程序部署范例之间的权衡,请查看Prisma 部署文档

注意:在整个指南中,你会发现各种检查点,它们可以帮助你验证步骤是否正确执行。

先决条件

要使用 GitHub Actions 将后端部署到 Heroku,你需要以下内容

  • Heroku 账户。
  • 已安装Heroku CLI
  • 用于发送电子邮件的SendGrid API token,你在本系列的第3部分创建的。

持续集成和持续部署

持续集成 (CI) 是一种技术,用于将个体开发人员的工作集成到主代码仓库中,以便尽早发现集成错误并加速协作开发。通常,CI 服务器连接到你的 Git 仓库,每次提交被推送到仓库时,CI 服务器都会运行。

持续部署 (CD) 是一种关注自动化部署流程的方法,以便可以快速且一致地部署更改。

虽然 CI 和 CD 关注不同的职责,但它们是相关的,并且通常使用同一个工具来处理。在本文中,你将使用 GitHub Actions 来处理 CI 和 CD。

持续集成管道

对于持续集成,主要构建块是管道 (pipeline)。管道是你定义的一系列步骤,用于确保你的更改不会引入 bug 或回归。例如,管道可能包含运行测试、代码 linter 和 TypeScript 编译器的步骤。如果其中一个步骤失败,CI 服务器将停止并将失败的步骤报告回 GitHub。

在团队中,如果使用拉取请求引入代码更改,CI 服务器通常会配置为自动为每个拉取请求运行管道。

你在前几个步骤中编写的测试通过模拟对 API 端点的请求来工作。由于这些端点的处理程序与数据库交互,因此在测试期间你需要一个具有后端 schema 的 PostgreSQL 数据库。在下一步中,你将配置 GitHub Actions 来运行测试数据库(在 CI 运行期间)并运行迁移,以便测试数据库与你的 Prisma schema 一致。

注意:CI 的有效性取决于你编写的测试。如果你的测试覆盖率较低,通过测试可能会产生虚假的信心。

使用 GitHub Actions 定义工作流

GitHub Actions 是一个可用于持续集成的自动化平台。它提供了一个 API,用于根据 GitHub 中的事件编排工作流,并可用于从 GitHub 构建、测试和部署你的代码。

要配置 GitHub Actions,你使用 yaml 定义工作流。工作流可以配置为在不同的仓库事件上运行,例如,当提交被推送到仓库时或创建拉取请求时。

每个工作流可以包含多个作业 (job),每个作业定义多个步骤 (step)。作业的每个步骤都是一个命令,并且可以访问正在测试的特定提交处的源代码。

注意:不同的 CI 服务对管道使用不同的术语;例如,GitHub Actions 使用术语工作流来指代相同的事物。

在本文中,你将使用仓库中的grading-app 工作流

让我们来看看这个工作流

grading-app 工作流有两个作业:testdeploy

test 作业将执行以下操作

  1. 检出仓库。
  2. 配置 node。
  3. 安装依赖项。
  4. 在使用 services 启动的测试数据库中创建数据库 schema。
  5. 运行测试。

注意:services 可用于运行附加服务。在上面的 test 作业中,它用于创建一个测试 PostgreSQL 数据库。

deploy 作业将执行以下操作

  1. 检出仓库
  2. 安装依赖项
  3. 针对生产数据库运行迁移
  4. 部署到 Heroku

注意:on: push 将为每次推送的提交触发工作流。条件 if: github.event_name == 'push' && github.ref == 'refs/heads/master' 确保 deploy 作业仅在推送到 master 分支时触发。

Fork 仓库并启用工作流

首先 fork GitHub 仓库,以便你可以配置 GitHub actions。

注意:如果你已经 fork 了仓库,请合并来自原始仓库 master 分支的更改。

Fork 后,进入 Github 上的 Actions (操作) 选项卡

点击启用按钮启用工作流

现在,当你向仓库推送提交时,GitHub 将运行工作流。

Heroku CLI 登录

确保你已使用 Heroku CLI 登录 Heroku

创建 Heroku 应用

要将后端应用程序部署到 Heroku,你需要创建一个 Heroku 应用。从克隆的仓库文件夹中运行以下命令

注意:使用你选择的唯一名称替换 YOUR_APP_NAME

检查点 Heroku CLI 应记录应用已成功创建

在 Heroku 上配置 PostgreSQL 数据库

使用以下命令创建数据库

检查点:要验证数据库是否已创建,你应该看到以下内容

注意:Heroku 将自动为应用程序运行时设置 DATABASE_URL 环境变量。Prisma Client 将使用 DATABASE_URL,因为它与Prisma schema 中配置的环境变量匹配。

在 GitHub 中定义构建时 secrets

为了让 GitHub Actions 运行生产数据库迁移并将后端部署到 Heroku,你将在GitHub工作流中创建引用的四个 secrets。

注意:构建时 secrets 和运行时 secrets 是有区别的。构建时 secrets 将在 GitHub 中定义,并在 GitHub Actions 运行期间使用。另一方面,运行时 secrets 将在 Heroku 中定义,供后端使用。

Secrets

  • HEROKU_APP_NAME: 你在上一步中选择的应用名称。
  • HEROKU_EMAIL: 你在注册 Heroku 时使用的电子邮件。
  • HEROKU_API_KEY: Heroku API key
  • DATABASE_URL: Heroku 上的生产 PostgreSQL URL,在部署之前运行生产数据库迁移所需。

获取生产 DATABASE_URL

要获取 Heroku 在配置数据库时设置的 DATABASE_URL,请使用以下 Heroku CLI 命令

检查点:你应该在输出中看到 URL,例如 postgres://username:password@ec2-12.eu-west-1.compute.amazonaws.com:5432/dbname

获取 HEROKU_API_KEY

Heroku API key 可以从你的Heroku 账户设置中获取

Heroku API key in the Heroku account settings

在 GitHub 中创建 secrets

要创建这四个 secrets,请转到仓库设置并打开 Secrets (secrets) 选项卡

GitHub repository secrets

点击 New secret (新建 secret),使用名称字段作为 secret 名称,例如 HEROKU_APP_NAME,并设置值

检查点:创建这四个 secrets 后,你应该看到以下内容

GitHub repository secrets

在 Heroku 上定义环境变量

后端需要三个 secrets,它们将在运行时作为环境变量传递给应用程序

  • SENDGRID_API_KEY: SendGrid API key
  • JWT_SECRET: 用于签署 JWT token 的 secret。
  • DATABASE_URL: 由 Heroku 自动设置的数据库连接 URL。

注意:你可以通过在终端中运行以下命令生成 JWT_SECRETnode -e "console.log(require('crypto').randomBytes(256).toString('base64'));"

要使用 Heroku CLI 设置它们,请使用以下命令

检查点:要验证环境变量是否已设置,你应该看到以下内容

触发工作流以运行测试和部署

配置好工作流,在 Heroku 上创建好应用,并设置好所有 secrets 后,你现在可以触发工作流来运行测试和部署了。

要触发构建,创建一个空提交并推送它

推送提交后,转到 GitHub 仓库的 Actions (操作) 选项卡,你应该看到以下内容

点击表格中包含提交消息的第一行

查看 test 作业的日志

要查看 test 作业的日志,请点击 test,这将允许你查看每个步骤的日志。例如,在下面的截图中,你可以查看测试结果

验证部署到 Heroku

要验证 deploy 作业是否成功部署到 Heroku,请点击左侧的 deploy 并展开 Deploy to Heroku 步骤。你应该在日志的末尾看到以下行

要从浏览器访问 API,请在克隆的仓库文件夹中运行以下 Heroku CLI 命令

这将打开浏览器指向 https://YOUR_APP_NAME.herokuapp.com/

检查点:你应该在浏览器中看到 {"up":true},这是由状态端点提供的。

查看后端日志

要查看后端的日志,请在克隆的仓库文件夹中运行以下 Heroku CLI 命令

测试登录流程

要测试登录流程,你需要对 REST API 进行两次调用。

首先获取 API 的 URL

使用 curl 对登录端点进行 POST 调用

检查电子邮件中的 8 位数字 token,然后进行第二次调用

检查点:响应应具有 200 成功状态码,并包含带有 JWT token 的 Authorization

总结

你的后端现在已部署并运行。做得好!

你通过定义 GitHub Actions 工作流、创建 Heroku 应用、配置 PostgreSQL 数据库,并使用 GitHub Actions 将后端部署到 Heroku,从而配置了持续集成和持续部署。

当你通过提交到仓库并推送更改来引入新功能时,测试和 TypeScript 编译器将自动运行,如果成功,后端将被部署。

你可以通过进入 Heroku 控制面板查看内存使用、响应时间和吞吐量等指标。这有助于了解后端如何处理不同流量负载。例如,后端负载越高,响应时间可能会越慢。

通过将 TypeScript 与Prisma Client结合使用,可以消除通常在运行时检测到并需要调试的一类类型错误。

你可以在 GitHub 上找到后端完整的源代码。

虽然 Prisma 旨在简化关系数据库的操作,但了解底层数据库和Heroku 特定细节也很有用。

如果你有问题,请随时在 Twitter 上联系我。

不要错过下一篇文章!

订阅 Prisma 新闻通讯