持续集成
Deno
的内置工具使得为项目设置持续集成(CI)流水线变得轻而易举。您可以使用相应的命令
deno test
、deno lint
和 deno 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') }}