You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GitHub Actions中测试shiny_prerendered类型learnr教程的渲染?

解决learnr教程的CI自动渲染测试问题

我开发了一个提供learnr教程的R包,教程均为runtime: shiny_prerendered类型的交互式R Markdown文档。团队维护过程中常引入bug,希望通过GitHub Actions实现持续集成,自动检查所有教程能否无错误渲染。目前已能在Actions环境中运行R代码,但非交互式环境下存在三个核心问题:无法正确渲染教程、无法自动终止Shiny进程、无法捕获并报告错误案例。以下是修正后的完整配置和脚本:

修改后的GitHub Actions YAML配置

on:
  push:
    branches: main

jobs:
  test-tutorials:
    runs-on: ubuntu-latest
    steps:
      - name: 检出代码仓库
        uses: actions/checkout@v3

      - name: 设置R环境
        uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true

      - name: 安装包依赖
        uses: r-lib/actions/setup-r-dependencies@v2
        with:
          packages: |
            any::devtools
            any::learnr
            any::shiny
            any::rmarkdown
            any::renv
          cache: true

      - name: 测试教程渲染
        run: Rscript -e 'source("./.github/rscripts/tutorial_action.R")'

修正后的R测试脚本

# 安装本地包及其依赖
devtools::install_deps(dependencies = TRUE)
devtools::install()

# 1. 安装教程所需的额外依赖
tutorial_deps <- renv::dependencies(path = "./inst/tutorials")$Package
tutorial_deps <- unique(tutorial_deps)
installed_pkgs <- rownames(installed.packages())
missing_deps <- setdiff(tutorial_deps, installed_pkgs)

if (length(missing_deps) > 0) {
  install.packages(missing_deps, repos = "https://cloud.r-project.org/")
}

# 2. 获取所有教程的Rmd文件路径
tutorial_paths <- list.files(
  path = "./inst/tutorials",
  pattern = "\\.Rmd$",
  recursive = TRUE,
  full.names = TRUE
)

# 3. 批量测试渲染并捕获错误
failed_tutorials <- c()

for (path in tutorial_paths) {
  cat("=== 开始测试教程:", basename(path), "===\n")
  
  tryCatch({
    # 直接渲染shiny_prerendered文档,无需启动Shiny服务器
    rmarkdown::render(
      input = path,
      output_format = "learnr::tutorial",
      output_file = tempfile(fileext = ".html"),
      quiet = FALSE,
      envir = new.env()
    )
    cat("✅ 教程", basename(path), "渲染成功\n")
  }, error = function(e) {
    cat("❌ 教程", basename(path), "渲染失败,错误信息:\n", e$message, "\n")
    failed_tutorials <<- c(failed_tutorials, basename(path))
  })
  
  cat("=== 结束测试教程:", basename(path), "===\n\n")
}

# 如果有失败的教程,终止脚本并返回错误码
if (length(failed_tutorials) > 0) {
  cat("❌ 以下教程渲染失败:\n", paste(failed_tutorials, collapse = "\n "), "\n")
  quit(status = 1)
} else {
  cat("✅ 所有教程渲染成功!\n")
}

关键改动说明

  1. 替换渲染方式:放弃learnr::run_tutorial(该函数用于启动交互式Shiny应用,在非交互式CI环境中会阻塞进程),改用rmarkdown::render直接编译文档,能完全覆盖渲染阶段的错误检查(包括代码块语法、依赖缺失、逻辑错误等)。
  2. 错误捕获机制:用tryCatch包裹渲染过程,单个教程失败不会中断整个测试流程,同时记录所有失败案例,最后统一报告。
  3. 依赖管理优化:先通过devtools::install_deps安装包的完整依赖,再单独安装教程所需的额外包,避免依赖缺失导致的渲染失败。
  4. CI环境适配:设置use-public-rspm加速包安装,启用缓存减少重复安装时间,确保GitHub Actions环境稳定运行。

内容的提问来源于stack exchange,提问作者uke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 03:49:53