本页内容

持续集成

Deno 的内置工具使为您的项目设置持续集成 (CI) 管道变得容易。可以使用相应的命令 deno testdeno lintdeno fmt 对代码进行测试、代码风格检查和格式化。此外,您还可以使用 deno coverage 在管道中从测试结果生成代码覆盖率报告。

本页将讨论

设置基本管道 跳转到标题

本页将向您展示如何在 GitHub Actions 中为 Deno 项目设置基本管道。本页解释的概念在很大程度上也适用于其他 CI 提供商,例如 Azure Pipelines、CircleCI 或 GitLab。

为 Deno 构建管道通常从检出存储库和安装 Deno 开始

name: Build

on: push

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: denoland/setup-deno@v1
        with:
          deno-version: v1.x # Run with latest stable Deno.

要扩展工作流程,只需添加您可能需要的任何 deno 子命令

      # Check if the code is formatted according to Deno's default
      # formatting conventions.
      - run: deno fmt --check

      # Scan the code for syntax errors and style issues. If
      # you want to use a custom linter configuration you can add a configuration file with --config <myconfig>
      - run: deno lint

      # Run all test files in the repository and collect code coverage. The example
      # runs with all permissions, but it is recommended to run with the minimal permissions your program needs (for example --allow-read).
      - run: deno test --allow-all --coverage=cov/

      # This generates a report from the collected coverage in `deno test --coverage`. It is
      # stored as a .lcov file which integrates well with services such as Codecov, Coveralls and Travis CI.
      - run: deno coverage --lcov cov/ > cov.lcov

跨平台工作流程 跳转到标题

作为 Deno 模块维护者,您可能想知道您的代码在当今使用的所有主要操作系统上都能正常工作:Linux、MacOS 和 Windows。可以通过运行一系列并行作业来实现跨平台工作流程,每个作业都在不同的操作系统上运行构建

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ ubuntu-latest, macos-latest, windows-latest ]
    steps:
      - run: deno test --allow-all --coverage cov/

注意:GitHub Actions 在处理 Windows 式换行符 (CRLF) 方面存在已知问题。这可能会在运行在 windows 上的作业的管道中运行 deno fmt 时导致问题。为了防止这种情况,请在运行 actions/checkout@v3 步骤之前将 Actions 运行器配置为使用 Linux 式换行符

git config --system core.autocrlf false
git config --system core.eol lf

如果您正在使用实验性或不稳定的 Deno API,则可以包含一个运行 Deno 预览版本的矩阵作业。这有助于尽早发现重大更改

jobs:
  build:
    runs-on: ${{ matrix.os }}
    continue-on-error: ${{ matrix.canary }} # Continue in case the canary run does not succeed
    strategy:
      matrix:
        os: [ ubuntu-latest, macos-latest, windows-latest ]
        deno-version: [ v1.x ]
        canary: [ false ]
        include: 
          - deno-version: canary
            os: ubuntu-latest
            canary: true

加速 Deno 管道 跳转到标题

减少重复 跳转到标题

在跨平台运行中,管道中的某些步骤不一定需要为每个操作系统运行。例如,在 Linux、MacOS 和 Windows 上生成相同的测试覆盖率报告有点多余。在这种情况下,您可以使用 GitHub Actions 的 if 条件关键字。以下示例展示了如何仅在 ubuntu(Linux)运行器上运行代码覆盖率生成和上传步骤

- name: Generate coverage report
  if: matrix.os == 'ubuntu-latest'
  run: deno coverage --lcov cov > cov.lcov

- name: Upload coverage to Coveralls.io
  if: matrix.os == 'ubuntu-latest'
  # Any code coverage service can be used, Coveralls.io is used here as an example.
  uses: coverallsapp/github-action@master
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }} # Generated by GitHub.
    path-to-lcov: cov.lcov

缓存依赖项 跳转到标题

随着项目规模的增长,往往会包含越来越多的依赖项。Deno 会在测试期间下载这些依赖项,如果工作流程每天运行多次,这可能会成为一个耗时的过程。一个常见的解决方案是缓存依赖项,这样就不需要重新下载它们。

Deno 将依赖项存储在本地缓存目录中。在管道中,可以通过设置 DENO_DIR 环境变量并将缓存步骤添加到工作流程来在工作流程之间保留缓存

# Set DENO_DIR to an absolute or relative path on the runner.
env:
  DENO_DIR: my_cache_directory

steps:
  - name: Cache Deno dependencies 
    uses: actions/cache@v2
    with:
      path: ${{ env.DENO_DIR }}
      key: my_cache_key

一开始,当这个工作流运行时,缓存仍然是空的,像 `deno test` 这样的命令仍然需要下载依赖项。但是,当任务成功时,`DENO_DIR` 的内容会被保存,任何后续的运行都可以从缓存中恢复它们,而不是重新下载。

上面的工作流中仍然存在一个问题:目前缓存键的名称被硬编码为 `my_cache_key`,这将每次都恢复相同的缓存,即使一个或多个依赖项被更新。这会导致旧版本在管道中使用,即使你已经更新了一些依赖项。解决方案是每次需要更新缓存时生成一个不同的键,这可以通过使用锁定文件和使用 GitHub Actions 提供的 `hashFiles` 函数来实现。

key: ${{ hashFiles('deno.lock') }}

为了使这工作,你还需要在你的 Deno 项目中有一个锁定文件,这将在 这里 详细讨论。现在,如果 `deno.lock` 的内容发生变化,将会创建一个新的缓存,并在随后的管道运行中使用。

为了演示,假设你有一个使用 `deno.land/std` 中的日志记录器的项目。

import * as log from "https://deno.land/[email protected]/log/mod.ts";

为了增加这个版本,你可以更新 `import` 语句,然后重新加载缓存并在本地更新锁定文件。

deno cache --reload --lock=deno.lock --lock-write deps.ts

运行完之后,你应该会看到锁定文件内容的变化。当它被提交并通过管道运行时,你应该会看到 `hashFiles` 函数保存了一个新的缓存,并在任何后续的运行中使用它。

清除缓存 跳转到标题

偶尔你可能会遇到一个损坏或格式错误的缓存,这可能由于各种原因发生。可以从 GitHub Actions UI 中清除缓存,或者你可以简单地更改缓存键的名称。一种无需强制更改锁定文件即可实现此目的的实用方法是向缓存键名称添加一个变量,该变量可以存储为 GitHub 密钥,如果需要新的缓存,可以更改它。

key: ${{ secrets.CACHE_VERSION }}-${{ hashFiles('deno.lock') }}