持续集成

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-22.04
    steps:
      - uses: actions/checkout@v3
      - uses: denoland/setup-deno@v1.1.1
        with:
          deno-version: v1.x # 使用最新稳定版 Deno 运行。

要扩展工作流程,只需添加所需的任何 deno 子命令:

      # 检查代码是否符合 Deno 的默认格式规范。
      - run: deno fmt --check

      # 扫描代码以查找语法错误和格式问题。如果您想使用自定义的 linter 配置,可以使用 --config <myconfig> 添加配置文件。
      - run: deno lint

      # 运行存储库中的所有测试文件并收集代码覆盖率。此示例运行时具有所有权限,但建议使用程序所需的最少权限运行(例如 --allow-read)。
      - run: deno test --allow-all --coverage=cov/

      # 这会从 `deno test --coverage` 中收集的覆盖收集报告。它以 .lcov 文件的形式存储,与 Codecov、Coveralls 和 Travis CI 等服务集成良好。
      - run: deno coverage --lcov cov/ > cov.lcov

跨平台工作流程

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

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

注意:GitHub Actions 存在已知问题( https://github.com/actions/checkout/issues/135),在处理 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 canary 版本的矩阵工作。这可以帮助尽早发现错误更改:

jobs:
  build:
    runs-on: ${{ matrix.os }}
    continue-on-error: ${{ matrix.canary }} # Continues execution if the canary run does not succeed
    strategy:
      matrix:
        os: [ ubuntu-22.04, macos-12, windows-2022 ]
        deno-version: [ v1.x ]
        canary: [ false ]
        include: 
          - deno-version: canary
            os: ubuntu-22.04
            canary: true

Speeding up Deno pipelines

减少重复操作

在跨平台的运行时,一些流程步骤不需要针对每个操作系统都运行。例如,在 Linux、MacOS 和 Windows 上生成相同的测试覆盖率报告有些冗余。在这种情况下,可以使用 GitHub Actions 中的 if 条件关键词。以下示例演示了如何仅在 ubuntu(Linux)运行器上运行代码覆盖率生成和上传步骤:

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

- name: Upload coverage to Coveralls.io
  if: matrix.os == 'ubuntu-22.04'
  # 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/std@$STD_VERSION/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') }}