本教程包括。
- 开始使用LoopBack
- 自动部署LoopBack应用程序
- 为LoopBack APIs创建问题模型和数据源
在自动化被软件开发团队普遍使用之前,瓶颈、重复性任务和人为错误十分猖獗。自动化为企业释放了宝贵的人力资源,同时减少了因活跃的人脑试图执行平凡的重复性任务而导致的人为错误的风险。最近在持续集成和持续部署(CI/CD)领域取得的进展使自动部署软件应用程序的更新变得更加可行。在本教程中,我将向你展示如何将一个LoopBack应用程序自动部署到Heroku。使用CircleCI,我将指导你如何实现一个持续部署(CD)管道。CD管道将使你能够在变化被推送时自动发布应用程序的更新。
本教程是关于为你的LoopBack应用程序建立CI/CD实践的系列教程中的第二个。上一篇教程告诉你如何自动测试LoopBack API。
前提条件
在你开始之前,请确保这些项目已经安装在你的系统上。
对于资源库管理和持续集成/持续部署,你需要。
- 一个GitHub账户。
- 一个CircleCI账户。
- 一个Heroku账户。
我们的教程是与平台无关的,但使用CircleCI作为一个例子。如果你没有CircleCI账户,请**在这里注册一个免费账户。**
什么是LoopBack和Heroku?
LoopBack是一个高度可扩展的Node.js和TypeScript框架,用于构建API和微服务。Heroku是一个平台即服务(PaaS),使开发者能够完全在云中构建、运行和操作应用程序。通过处理维护基于云的应用程序的更多要求,Heroku允许开发人员专注于构建应用程序而不是管理服务器。
这个项目始于前一个教程,我们在那里为一个测验应用建立了一个API。
回顾一下:该API有处理以下操作的端点。
- 获取所有问题
- 获取数据库中的问题总数
- 获取一个具有特定ID的问题
开始使用
如果你还没有这样做,请通过运行这个命令安装LoopBack 4 CLI。
npm install -g @loopback/cli
使用Loopback CLI命令建立一个新项目。
lb4 app
当CLI提示时,请按下面的方式回答。注意,指定了一个与默认不同的应用类名称。
? Project name: circle-ci_heroku
? Project description: Loopback project to demonstrate automated deployment to h
eroku via CircleCI
? Project root directory: circle-ci_heroku
? Application class name: MainApplication
? Select features to enable in the project Enable eslint, Enable prettier, Enabl
e mocha, Enable loopbackBuild, Enable vscode, Enable docker, Enable repositories
, Enable services
? Yarn is available. Do you prefer to use it by default? Yes
配置Heroku
接下来要做的事情是在Heroku上创建一个新的应用程序。我们在Heroku仪表板上做这件事。点击新建,然后点击**新建应用程序。**填写表格。如果你愿意,你可以为该应用程序使用不同的名称和地区。
接下来,点击创建应用程序按钮,完成创建过程。然后,你将被转到新创建的应用程序的部署视图。
接下来是添加一个构建包;只需点击设置标签。在buildpacks部分,点击Add buildpack。
一个表格允许你选择一个官方支持的构建包或提供一个URL。选择nodejs以使用官方支持的Heroku nodejs构建包。点击保存更改。NodeJS将被用于构建你的下一个部署。
你需要的最后一件事是一个API密钥。你将使用它和应用程序的名称来连接CircleCI管道和Heroku。为了得到你的API密钥,打开账户设置页面,向下滚动到API密钥部分。
点击 "显示"按钮,复制显示的API密钥。
接下来,在你的项目的根部,创建一个新的文件,名为Procfile 。注意,这个文件没有扩展名。在其中,添加以下内容。
web: node .
如果没有这个procfile,Heroku将默认通过调用npm run 来启动应用程序。npm run 试图运行构建过程,这将导致一个应用程序错误,因为应用程序的dev依赖项没有安装。
配置CircleCI
接下来,添加CircleCI的管道配置。对于这个项目,流水线包括两个步骤。
- 构建步骤构建项目并安装项目的依赖性。理想情况下,你应该在这个阶段运行项目测试。为了简洁起见,我们将在这个演示中跳过测试。相反,使用你创建应用程序时提供的预建测试。
- 在部署到Heroku步骤中,当构建阶段成功完成后,你可以将最新的变化部署到Heroku。
创建CircleCI配置文件
在你项目的根部,创建一个名为.circleci 的文件夹,并在其中创建一个名为config.yml 的文件。在新创建的文件中,添加这个配置。
version: "2.1"
orbs:
heroku: circleci/heroku@1.2.6
node: circleci/node@4.7.0
jobs:
build-and-test:
docker:
- image: "cimg/base:stable"
steps:
- checkout
- node/install:
node-version: 16.0.0
install-yarn: true
- node/install-packages:
pkg-manager: yarn
cache-path: ~/project/node_modules
override-ci-command: yarn install
- run: yarn run test
workflows:
main:
jobs:
- build-and-test
- heroku/deploy-via-git:
force: true # this parameter instructs the push to use a force flag when pushing to the heroku remote, see: https://devcenter.heroku.com/articles/git
requires:
- build-and-test
该配置拉入了circleci/heroku orb,它自动让你访问一组强大的Heroku作业和命令。其中一个作业是heroku/deploy-via-git ,它可以将你的应用程序从GitHub repo直接部署到你的Heroku账户。该配置还使用circleci/node orb。在其他方面,这个轨道允许你安装默认启用缓存的软件包。
注意:你应该安装一个16的节点版本。在出版时,节点16是与LoopBack兼容的最新版本。
配置指定了build-and-test 工作,它。
- 检查出最新的代码
- 安装节点
- 安装node中声明的软件包
package.json - 运行项目中的测试
该配置还指定了一个工作流程,即先运行build-and-test 工作,然后再运行heroku/deploy-via-git 工作。注意,有一个requires 选项,告诉CircleCI只有在build-and-test 工作成功完成后才运行deploy-via-git 工作。
接下来,在GitHub上建立一个仓库,并将该项目链接到CircleCI。请参阅这篇文章,了解将项目推送到GitHub的帮助。
在推送代码之前,花点时间做一些内部管理。使用这个命令对你的代码进行润色并修复任何问题。
yarn run lint:fix
登录你的CircleCI账户。如果你用你的GitHub账户注册,你所有的仓库将显示在你的项目的仪表板上。
在你的circle-ci_heroku 项目旁边点击Set Up Project。
CircleCI会检测项目中的config.yml 文件。点击使用现有的配置,然后开始构建。你的第一个工作流程将开始运行,但它会失败。这是预料之中的事。
部署过程失败是因为你没有提供你的Heroku API密钥。现在去解决这个问题吧。点击项目设置按钮,然后点击环境变量。添加两个新的变量,如下所示。
HEROKU_APP_NAME变量的值是Heroku中的应用程序名称:loopback-heroku-circleci。HEROKU_API_KEY是你从账户设置页面获取的Heroku API密钥。
选择RerunWorkflow from Failed选项,重新运行Heroku部署。为了确认你的工作流是成功的,你可以在浏览器中打开你新部署的应用程序。你的应用程序的URL是:https://<HEROKU_APP_NAME>.herokuapp.com/ 。
你将会看到当前的索引页面。
现在我们已经有了一个管道,让我们来添加API的问题功能。
建立问题模型
在本教程中,一个问题将有这些属性的字段。
- 难度
- 问题
- 正确答案
在创建问题时,默认会分配一个唯一的主键。
你可以使用lb4 model 命令并回答提示来生成模型。用一个空的属性名称按回车键来生成模型。遵循这些步骤。
lb4 model question
? Please select the model base class Entity (A persisted model with an ID)
? Allow additional (free-form) properties? No
Model Question will be created in src/models/question.model.ts
Let's add a property to Question
Enter an empty property name when done
? Enter the property name: id
? Property type: number
? Is id the ID property? Yes
? Is id generated automatically? Yes
Let's add another property to Question
Enter an empty property name when done
? Enter the property name: difficulty
? Property type: string
? Is it required?: Yes
Let's add another property to Question
Enter an empty property name when done
? Enter the property name: question
? Property type: string
? Is it required?: Yes
Let's add another property to Question
Enter an empty property name when done
? Enter the property name: answer
? Property type: string
? Is it required?: Yes
Let's add another property to Question
Enter an empty property name when done
? Enter the property name:
一个新的模型将被创建在src/models/question.model.ts 。
建立一个数据源
接下来,创建一个数据源来保存API的问题。在本教程中,使用一个内存数据库。使用这个命令创建一个数据源。
lb4 datasource
如图所示,对提示作出回应。
? Datasource name: db
? Select the connector for db: In-memory db (supported by StrongLoop)
? window.localStorage key to use for persistence (browser only):
? Full path to file for persistence (server only): ./data/db.json
接下来,在项目的根目录下创建一个名为data 的文件夹。在data 目录中,创建一个名为db.json 的文件,并将此添加到其中。
{
"ids": {
"Question": 9
},
"models": {
"Question": {
"1": "{\"difficulty\":\"medium\",\"question\":\"The HTML5 standard was published in 2014.\",\"answer\":\"True\",\"id\":1}",
"2": "{\"difficulty\":\"medium\",\"question\":\"Which computer hardware device provides an interface for all other connected devices to communicate?\",\"answer\":\"Motherboard\",\"id\":2}",
"3": "{\"difficulty\":\"medium\",\"question\":\"On which day did the World Wide Web go online?\",\"answer\":\"December 20, 1990\",\"id\":3}",
"4": "{\"difficulty\":\"medium\",\"question\":\"Android versions are named in alphabetical order.\",\"answer\":\"True\",\"id\":4}",
"5": "{\"difficulty\":\"medium\",\"question\":\"What was the first Android version specifically optimized for tablets?\",\"answer\":\"Honeycomb\",\"id\":5}",
"6": "{\"difficulty\":\"medium\",\"question\":\"Which programming language shares its name with an island in Indonesia?\",\"answer\":\"Java\",\"id\":6}",
"7": "{\"difficulty\":\"medium\",\"question\":\"What does RAID stand for?\",\"answer\":\"Redundant Array of Independent Disks\",\"id\":7}",
"8": "{\"difficulty\":\"medium\",\"question\":\"Which of the following computer components can be built using only NAND gates?\",\"answer\":\"ALU\",\"id\":8}"
}
}
}
JSON文件的ids 关键让数据库知道下一个要分配给新问题的ID。在models 部分,我们提供每个模型的数据。同时指定的还有Question 模型和你数据库中的基础问题。
创建一个资源库
在本教程中,你将使用资源库在数据库和问题模型之间提供一个抽象层。使用这个命令创建一个新的资源库。
lb4 repository
如图所示,对提示作出回应。
? Please select the datasource DbDatasource
? Select the model(s) you want to generate a repository for Question
? Please select the repository base class DefaultCrudRepository (Juggler bridge)
新创建的类(位于src/repositories/question.repository.ts )拥有为你的模型执行CRUD操作所需的连接。
创建一个控制器
使用这个命令创建一个新的控制器。
lb4 controller
对CLI的提示做出回应,如图所示。
? Controller class name: question
Controller Question will be created in src/controllers/question.controller.ts
? What kind of controller would you like to generate? REST Controller with CRUD functions
? What is the name of the model to use with this CRUD repository? Question
? What is the name of your CRUD repository? QuestionRepository
? What is the name of ID property? id
? What is the type of your ID? number
? Is the id omitted when creating a new instance? Yes
? What is the base HTTP path name of the CRUD operations? /questions
CLI创建了一个能够处理所有CRUD操作的控制器,我们不需要做其他任何事情。很整洁吧?
提交你的代码并将最新的修改推送到你的GitHub仓库。这将触发CircleCIbuild-and-test ,它将成功运行并将你的新变化部署到Heroku--就像它之前做的那样。干得好!
导航到https://<HEROKU_APP_NAME>.herokuapp.com/questions 。那里有包含问题的API响应。
总结
在本教程中,我向您展示了如何使用GitHub、CircleCI和Heroku为LoopBackJS API建立CI/CD管道。通过自动化发布新功能的过程,大大降低了人为错误对生产环境造成负面影响的风险。
此外,您宝贵的开发人员时间可以更好地应用于开发中更复杂的方面。这使得软件管理过程更加有效,因为重复的、平凡的方面被自动化,而你的团队则专注于问题的解决。
本教程的整个代码库可在GitHub上找到。
Oluyemi是一位技术爱好者,拥有电信工程背景。他对解决用户遇到的日常问题有着浓厚的兴趣,因此开始涉足编程,并将其解决问题的技能用于构建网络和移动软件。作为一名全栈软件工程师,奥卢耶米热衷于分享知识,在全球多个博客上发表了大量技术文章和博文。由于精通技术,他的爱好包括尝试新的编程语言和框架。