持续集成 CI/CD integration

导读

提示

本章介绍 Nest Devtools 与 Nest 框架的集成。如果您正在寻找 Devtools 应用程序,请访问 Devtools 网站。

CI/CD 集成适用于拥有 Enterprise 计划的用户。

您可以观看此视频以了解 CI/CD 集成为何以及如何帮助您:

发布图表

我们首先配置应用程序引导文件(main.ts)以使用GraphPublisher类(从@nestjs/devtools-integration导出 - 请参阅上一章了解更多详细信息),如下所示:

ts
async function bootstrap() {
  const shouldPublishGraph = process.env.PUBLISH_GRAPH === 'true'

  const app = await NestFactory.create(AppModule, {
    snapshot: true,
    preview: shouldPublishGraph,
  })

  if (shouldPublishGraph) {
    await app.init()

    const publishOptions = { /* ... */ } // NOTE: this options object will vary depending on the CI/CD provider you're using
    const graphPublisher = new GraphPublisher(app)
    await graphPublisher.publish(publishOptions)

    await app.close()
  }
  else {
    await app.listen(3000)
  }
}

如我们所见,我们在这里使用 GraphPublisher 将序列化图发布到集中式注册表。PUBLISH_GRAPH 是一个自定义环境变量,它允许我们控制是否发布图(CI/CD 工作流)或不发布图(常规应用程序引导)。此外,我们在此处将 preview 属性设置为 true。启用此标志后,我们的应用程序将在预览模式下引导 - 这基本上意味着我们应用程序中所有控制器、增强器和提供程序的构造函数(和生命周期挂钩)将不会被执行。注意 - 这不是必需的,但可以简化我们的工作,因为在这种情况下,在 CI/CD 管道中运行应用程序时,我们实际上不必连接到数据库等。

publishOptions 对象将根据您使用的 CI/CD 提供程序而有所不同。我们将在后面的部分中为您提供以下最受欢迎的 CI/CD 提供程序的说明。

图表成功发布后,您将在工作流视图中看到以下输出:

img

每次发布图表时,我们都会在项目的相应页面中看到一个新条目:

img

报告

Devtools 会为每个构建生成一份报告,如果 中央注册表中已经存储了相应的快照。例如,如果您针对已发布图表的 master 分支创建 PR - 那么应用程序将能够检测到差异并生成报告。否则,将不会生成报告。

要查看报告,请导航到项目的相应页面(参见组织)。

img

这对于识别代码审查期间可能被忽视的更改特别有用。例如,假设某人更改了深度嵌套提供程序的范围。此更改可能不会立即被审阅者察觉,但使用 Devtools,我们可以轻松发现此类更改并确保它们是有意为之。或者,如果我们从特定端点移除保护,它将在报告中显示为受影响。现在,如果我们没有对该路由进行集成或端到端测试,我们可能不会注意到它不再受保护,而等到我们注意到时,可能已经太晚了。

同样,如果我们正在处理大型代码库并将模块修改为全局模块,我们将看到图中添加了多少条边,在大多数情况下,这表明我们做错了什么。

构建预览

对于每个已发布的图表,我们可以通过单击预览按钮返回并预览它之前的样子。此外,如果生成了报告,我们应该看到图表上突出显示的差异:

  • 绿色节点代表添加的元素
  • 浅白色节点代表更新的元素
  • 红色节点代表删除的元素

参见下面的屏幕截图:

img

通过回溯功能,您可以通过将当前图表与前一个图表进行比较来调查和解决问题。根据您的设置方式,每个拉取请求(甚至每个提交)都会在注册表中有一个相应的快照,因此您可以轻松回溯并查看发生了什么变化。将 Devtools 视为 Git,但要了解 Nest 如何构建您的应用程序图,并具有 可视化 它的能力。

集成:GitHub Actions

首先,让我们从在项目中的 .github/workflows 目录中创建一个新的 GitHub 工作流开始,并将其命名为 publish-graph.yml。在这个文件中,我们使用以下定义:

yaml
name: Devtools

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - '*'

jobs:
  publish:
    if: github.actor!= 'dependabot[bot]'
    name: Publish graph
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '16'
          cache: npm
      - name: Install dependencies
        run: npm ci
      - name: Setup Environment (PR)
        if: ${{ github.event_name == 'pull_request' }}
        shell: bash
        run: |
          echo "COMMIT_SHA=${{ github.event.pull_request.head.sha }}" >>\${GITHUB_ENV}
      - name: Setup Environment (Push)
        if: ${{github.event_name == 'push'}}
        shell: bash
        run: |
          echo "COMMIT_SHA=\${GITHUB_SHA}" >> \${GITHUB_ENV}
      - name: Publish
        run: PUBLISH_GRAPH=true npm run start
        env:
          DEVTOOLS_API_KEY: CHANGE_THIS_TO_YOUR_API_KEY
          REPOSITORY_NAME: ${{ github.event.repository.name }}
          BRANCH_NAME: ${{github.head_ref || github.ref_name}}
          TARGET_SHA: ${{github.event.pull_request.base.sha}}

理想情况下,应从 GitHub Secrets 中检索 DEVTOOLS_API_KEY 环境变量,更多信息请阅读 此处

此工作流程将针对每个针对 master 分支的拉取请求运行,或者在直接提交到 master 分支的情况下运行。您可以随意将此配置与您的项目需求相匹配。这里最重要的是,我们为 GraphPublisher 类提供必要的环境变量(以运行)。

但是,在我们开始使用此工作流程之前,有一个变量需要更新 - DEVTOOLS_API_KEY。我们可以在此 页面 上为我们的项目生成专用的 API 密钥。

最后,让我们再次导航到main.ts文件并更新之前留空的publishOptions对象。

ts
const publishOptions = {
  apiKey: process.env.DEVTOOLS_API_KEY,
  repository: process.env.REPOSITORY_NAME,
  owner: process.env.GITHUB_REPOSITORY_OWNER,
  sha: process.env.COMMIT_SHA,
  target: process.env.TARGET_SHA,
  trigger: process.env.GITHUB_BASE_REF ? 'pull' : 'push',
  branch: process.env.BRANCH_NAME,
}

为了获得最佳的开发人员体验,请确保通过单击集成 GitHub 应用程序按钮(见下面的屏幕截图)为您的项目集成 GitHub 应用程序。注意 - 这不是必需的。

img

通过此集成,您将能够在拉取请求中直接查看预览/报告生成过程的状态:

img

集成:Gitlab 管道

首先,让我们从在项目的根目录中创建一个新的 Gitlab CI 配置文件开始,并将其命名为 .gitlab-ci.yml。在这个文件中,让我们使用以下定义:

ts
const publishOptions = {
  apiKey: process.env.DEVTOOLS_API_KEY,
  repository: process.env.REPOSITORY_NAME,
  owner: process.env.GITHUB_REPOSITORY_OWNER,
  sha: process.env.COMMIT_SHA,
  target: process.env.TARGET_SHA,
  trigger: process.env.GITHUB_BASE_REF ? 'pull' : 'push',
  branch: process.env.BRANCH_NAME,
}
提示

理想情况下,应从机密中检索 DEVTOOLS_API_KEY 环境变量。

此工作流将针对每个针对 master 分支的拉取请求运行,或者在直接提交到 master 分支的情况下运行。您可以随意将此配置与您的项目需求保持一致。这里最重要的是,我们为我们的 GraphPublisher 类(运行)提供必要的环境变量。

但是,在我们开始使用此工作流之前,有一个变量(在此工作流定义中)需要更新 - DEVTOOLS_API_KEY。我们可以在此 页面 上为我们的项目生成专用的 API 密钥。

最后,让我们再次导航到 main.ts 文件并更新我们之前留空的 publishOptions 对象。

yaml
image: node:16

stages:
  - build

cache:
  key:
    files:
      - package-lock.json
  paths:
    - node_modules/

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: always
    - if: $CI_COMMIT_BRANCH == "master" && $CI_PIPELINE_SOURCE == "push"
      when: always
    - when: never

install_dependencies:
  stage: build
  script:
    - npm ci

publish_graph:
  stage: build
  needs:
    - install_dependencies
  script: npm run start
  variables:
    PUBLISH_GRAPH: 'true'
    DEVTOOLS_API_KEY: CHANGE_THIS_TO_YOUR_API_KEY

其他 CI/CD 工具

Nest Devtools CI/CD 集成可与您选择的任何 CI/CD 工具一起使用(例如 Bitbucket PipelinesCircleCI 等),因此不要局限于我们在此处描述的提供商。

查看以下 publishOptions 对象配置,以了解发布给定提交/构建/PR 的图表所需的信息。

ts
const publishOptions = {
  apiKey: process.env.DEVTOOLS_API_KEY,
  repository: process.env.CI_PROJECT_NAME,
  owner: process.env.CI_PROJECT_ROOT_NAMESPACE,
  sha: process.env.CI_COMMIT_SHA,
  target: process.env.CI_MERGE_REQUEST_DIFF_BASE_SHA,
  trigger: process.env.CI_MERGE_REQUEST_DIFF_BASE_SHA ? 'pull' : 'push',
  branch:
    process.env.CI_COMMIT_BRANCH
    ?? process.env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME,
}

这些信息大部分是通过 CI/CD 内置环境变量提供的(请参阅 CircleCI 内置环境列表Bitbucket 变量 )。

对于发布图表的管道配置,我们建议使用以下触发器:

  • push 事件 - 仅当当前分支代表部署环境时,例如 mastermainstagingproduction 等。
  • pull request 事件 - 始终,或者当 目标分支 代表部署环境时(参见上文)