mcpField
R
r-cran-extrachecks

r-cran-extrachecks

github.com/posit-dev测试与质量55174 次安装今天更新
代码仓库

关于 r-cran-extrachecks

帮助 R 包开发者为 CRAN 提交做准备,系统检查常规检查工具可能遗漏的审查要求。它按清单审阅文档、元数据、示例和链接,并在获准后实施修正。

主要功能

  1. 01按 CRAN 清单逐项检查
  2. 02审阅 DESCRIPTION 和文档要求
  3. 03检查 README、链接及打包文件
  4. 04提出修复并经批准后修改
  5. 05核验修改结果

适用场景

  1. 01准备 R 包首次提交 CRAN
  2. 02处理 CRAN 重新提交前的审查要求
  3. 03检查导出函数的返回值和示例文档
  4. 04排查 URL、版权或许可问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posit-dev/skills --skill r-cran-extrachecks

安装后在 Claude Code 中输入/r-cran-extrachecks确认已加载。

详细介绍

CRAN 额外检查

帮助 R 包开发者为提交到 CRAN 做好准备,系统地检查 CRAN 审核人员会执行、但 devtools::check() 不会发现的常见临时要求。

工作流程

  1. 初步评估:询问用户这是首次提交还是重新提交
  2. 执行标准检查清单:逐项进行检查(见下文)
  3. 找出问题:检查文件时记录具体问题
  4. 提出修复方案:针对发现的每个问题提出具体修改建议
  5. 实施修改:仅在用户批准后编辑
  6. 验证:确认所有修改均已完成

CRAN 标准准备检查清单

按顺序系统地检查以下项目:

  1. 创建 NEWS.md:如果文件尚不存在,运行 usethis::use_news_md()
  2. 创建 cran-comments.md:如果文件尚不存在,运行 usethis::use_cran_comments()
  3. 检查 README:
    • 确保其中包含在包被 CRAN 接纳后仍有效的安装说明(通常为 install.packages("pkgname"))。
    • 检查其中是否包含相对链接。这类链接在 GitHub 上有效,但会被 CRAN 标记。请使用指向包文档的完整 URL,或删除这些链接。
    • README 是否清楚说明了包的用途和功能?
    • 重要:如果 README.Rmd 存在,只编辑 README.Rmd(README.md 会被覆盖),然后运行 devtools::build_readme() 重新生成 README.md
  4. 校对 DESCRIPTION:仔细检查 Title: 和 Description: 字段(详见下方指南)
  5. 检查函数文档:确认所有导出的函数都有 @return 和 @examples(详见下方指南)。请注意,S3 方法若仅使用 #' @export 编写文档,则属于豁免情况:这类方法不会生成 .Rd 文件,因此不要求包含这两个标签
  6. 核实版权持有者:检查 Authors@R: 是否包含带有 [cph] 角色的版权持有者
  7. 检查捆绑文件的许可:检查任何包含的第三方文件的许可情况
  8. 运行 URL 检查:使用 urlchecker::url_check() 并修复发现的问题

CRAN 详细检查

文档要求

返回值文档(严格执行)

CRAN 现在严格要求为所有导出的函数编写 @return 文档。使用 roxygen2 标签 @return 说明函数返回的内容。

  • 即使函数标记了 @keywords internal,也必须编写
  • 即使函数不返回任何内容,也必须编写——可注明 @return None 或类似内容
  • 每个导出的函数都必须包含此文档

这些规则仅适用于带有 .Rd 文件的函数。只有当代码块包含文档内容(标题或描述)时,roxygen2 才会创建 .Rd 文件。仅包含 #' @export 的代码块会将函数添加到 NAMESPACE,但不会生成 .Rd 文件,因此 CRAN 的文档检查无内容可检查。这是 S3 方法的惯用模式:

#' @export
print.my_class <- function(x, ...) {
  cat("my_class object\n")
  invisible(x)
}

此类方法无需编写 @return 或 @examples,且 R CMD check 不会将其标记为缺少文档(注册的 S3 方法不在未记录对象检查范围内)。

  • 仅当代码块中只有 @export(或 @exportS3Method)时,才适用此豁免。添加标题、@param、@rdname、@describeIn 或任何其他文档内容后,roxygen2 就会生成 .Rd 文件,函数必须满足所有文档规则,包括 @return。
  • 不要将这些方法与 S3 泛型本身混淆(例如,my_print <- function(x, ...) UseMethod("my_print"))。新导出的泛型是需要编写文档的普通导出函数,因此仍需包含 @return 和 @examples。
  • 通过 @rdname 或 @describeIn 与泛型共用页面的方法遵循与泛型相同的规则:合并后的 .Rd 只需包含一次所需标签,无需为每个方法重复添加。

示例:

# Missing @return - WILL BE REJECTED
#' Calculate sum
#' @export
my_sum <- function(x, y) {
  x + y
}

# Correct - includes @return
#' Calculate sum
#' @param x First number
#' @param y Second number
#' @return A numeric value
#' @export
my_sum <- function(x, y) {
  x + y
}

# For functions with no return value
#' Print message
#' @param msg Message to print
#' @return None, called for side effects
#' @export
print_msg <- function(msg) {
  cat(msg, "\n")
}

导出函数的示例

如果导出函数有实际意义的返回值,几乎肯定需要 @examples 部分。使用 roxygen2 标签 @examples。

  • 即使函数标记了 @keywords internal,也必须编写
  • 纯粹用于产生副作用的函数(例如创建目录)可以例外
  • 示例必须可执行
  • 仅使用 @export 的 roxygen 代码块中的 S3 方法没有 .Rd 文件,因此无需示例(见上文)

带有示例的未导出函数

如果为未导出的函数编写 roxygen 示例,必须执行以下任一操作:

  1. 使用 ::: 记法调用:pkg:::my_fun()
  2. 使用 @noRd 标签来禁止创建 .Rd 文件

谨慎使用 \dontrun{}

只有在示例确实无法执行时(例如缺少其他软件、API 密钥等),才应使用 \dontrun{}。

  • 如果要展示错误,请改用 try() 包装调用
  • 考虑使用自定义谓词(例如 googlesheets4::sheets_has_token()),并配合 if () 代码块
  • 有时可使用 interactive() 作为条件
  • 较长的示例(> 5 秒)可使用 \donttest{}

切勿在示例中注释掉代码

# BAD - Will be rejected
#' @examples
#' # my_function(x)  # Don't do this!

CRAN 的指导原则:“示例/代码中的代码行不应被注释掉。理想情况下,应寻找可定期执行和检查的简单示例。”

使用建议包保护示例

对于需要建议包的整个示例部分,请使用 @examplesIf:

#' @examplesIf rlang::is_installed("dplyr")
#' library(dplyr)
#' my_data %>% my_function()

对于示例中的单个代码块:

#' @examples
#' if (rlang::is_installed("dplyr")) {
#'   library(dplyr)
#'   my_data %>% my_function()
#' }
DESCRIPTION 标题字段

CRAN 对 Title 字段有严格要求:

使用标题式大小写

除 ‘a’、‘the’ 等冠词外,所有单词首字母均大写。可使用 tools::toTitleCase() 辅助格式化。

避免冗余

常见的易触发警告的短语:

  • “A Toolkit for” → 删除
  • “Tools for” → 删除
  • “for R” → 删除

示例:

# BAD
Title: A Toolkit for the Construction of Modeling Packages for R

# GOOD
Title: Construct Modeling Packages

# BAD
Title: Command Argument Parsing for R

# GOOD
Title: Command Argument Parsing

为软件/包名称加引号

所有软件和 R 包名称都要用单引号括起来:

# GOOD
Title: Interface to 'Tiingo' Stock Price API

长度限制

标题应少于 65 个字符。

DESCRIPTION 字段

切勿以禁止使用的短语开头

CRAN 会拒绝以下开头的描述:

  • "This package"
  • 包名称
  • "Functions for"
# BAD
Description: This package provides functions for rendering slides.
Description: Functions for rendering slides to different formats.

# GOOD
Description: Render slides to different formats including HTML and PDF.

扩写为 3–4 个句子

单句描述不够充分。请更全面地说明:

  • 软件包的功能
  • 它可能有用的原因
  • 它有助于解决的问题类型
# BAD (too short)
Description: Render slides to different formats.

# GOOD
Description: Render slides to different formats including HTML and PDF.
    Supports custom themes and progressive disclosure patterns. Integrates
    with 'reveal.js' for interactive presentations. Designed for technical
    presentations and teaching materials.

软件名称加引号,函数名称不加

# BAD
Description: Uses 'case_when()' to process data.

# GOOD
Description: Uses case_when() to process data with 'dplyr'.

软件、软件包和 API 名称使用单引号(包括 'R')。函数名称不加引号。

展开所有首字母缩略词

所有首字母缩略词在首次出现时都必须完整展开:

# BAD
Description: Implements X-SAMPA processing.

# GOOD
Description: Implements Extended Speech Assessment Methods Phonetic
    Alphabet (X-SAMPA) processing.

出版物标题才使用双引号

双引号仅用于出版物标题,不用于短语或强调:

# BAD
Description: Handles dates like "the first Monday of December".

# GOOD
Description: Handles dates like the first Monday of December.
URL 和链接验证

所有 URL 都必须使用 HTTPS

CRAN 要求所有 URL 使用 https:// 协议。HTTP 链接会被拒绝。

# BAD
URL: http://paleobiodb.org/

# GOOD
URL: https://paleobiodb.org/

不得使用会重定向的 URL

CRAN 会拒绝重定向到其他位置的 URL。拒绝示例:

Found the following (possibly) invalid URLs:
URL: https://h3geo.org/docs/core-library/coordsystems#faceijk-coordinates
     (moved to https://h3geo.org/docs/core-library/coordsystems/)

使用 urlchecker 软件包

# Find redirecting URLs
urlchecker::url_check()

# Automatically update to final destinations
urlchecker::url_update()

忽略发布后才会生效的 URL

有些 URL 目前无法访问,但软件包发布到 CRAN 后便会生效。此类 URL 不应更改:

  • CRAN 徽章 URL(例如,https://cran.r-project.org/package=pkgname)
  • CRAN 状态徽章(例如,https://www.r-pkg.org/badges/version/pkgname)
  • CRAN 检查结果(例如,https://cranchecks.info/badges/pkgname)
  • 发布后才会部署到 r-universe 或 pkgdown 网站上的软件包文档 URL

如果 urlchecker::url_check() 标记了这些 URL,请保持原样。这些预期 URL 会在软件包发布到 CRAN 后生效。

检查无效的文件 URI

README 中的相对链接必须在软件包构建后仍然有效。常见问题:

Found the following (possibly) invalid file URI:
     URI: CODE_OF_CONDUCT.md
       From: README.md

这是因为文件位于 .Rbuildignore 中。解决方案:

  1. 从 .Rbuildignore 中移除该文件
  2. 使用 usethis::use_code_of_conduct(),它生成的章节不含相对链接
管理要求

版权所有者角色

始终在 Authors 字段中添加 [cph] 角色,即使你是唯一作者:

# Required
Authors@R: person("John", "Doe", role = c("aut", "cre", "cph"))

由 Posit 支持的软件包

对于属于 Posit 相关 GitHub 组织(posit-dev、rstudio、r-lib、tidyverse、tidymodels)的软件包,或由使用 @posit.co 邮箱地址的人维护的软件包,请将 Posit Software, PBC 列为版权所有者和资助方:

Authors@R: c(
  person("Jane", "Doe", role = c("aut", "cre"),
         email = "[email protected]"),
  person("Posit Software, PBC", role = c("cph", "fnd"),
         comment = c(ROR = "03wc8by49"))
)

LICENSE 年份

将 LICENSE 年份更新为当前提交年份:

# If LICENSE shows 2024 but submitting in 2026
# Update: 2024 → 2026

方法参考文献

CRAN 可能会询问:

如果有介绍软件包中所用方法的参考文献,请将其添加到 description 字段中……

如果没有参考文献,请回复邮件说明这一点。可以考虑在 cran-comments.md 中预先添加说明:

## Method References

There are no published references describing the methods in this package.
The package implements original functionality for [brief description].

需要检查的关键文件

按以下顺序系统地检查这些文件:

  • DESCRIPTION:标题、描述、Authors@R、URL、许可证年份
  • R/*.R:函数文档(@return、@examples、@examplesIf、@noRd)
  • README.Rmd(如果存在):编辑此文件(而非 README.md),然后运行 devtools::build_readme()
  • README.md:检查安装说明、相对链接和 URL。仅在 README.Rmd 不存在时直接编辑
  • cran-comments.md:给审核人员的预先说明
  • NEWS.md:本次发布的版本说明
  • .Rbuildignore:README 中引用的文件

常见修复模式

DESCRIPTION 标题:

# Before
Title: A Toolkit for the Construction of Modeling Packages for R

# After
Title: Construct Modeling Packages

DESCRIPTION 描述:

# Before
Description: This package provides functions for rendering slides.

# After
Description: Render slides to different formats including HTML and PDF.
    Supports custom themes and progressive disclosure. Integrates with
    'reveal.js' for interactive presentations.

函数文档:

# Before - Missing @return
#' Calculate total
#' @param x Values
#' @export
calc_total <- function(x) sum(x)

# After - Complete documentation
#' Calculate total
#' @param x Numeric values to sum
#' @return A numeric value representing the sum
#' @examples
#' calc_total(1:10)
#' @export
calc_total <- function(x) sum(x)

实用工具

  • tools::toTitleCase() - 使用规范的大小写格式化标题
  • urlchecker::url_check() - 查找有问题的 URL
  • urlchecker::url_update() - 修正会重定向的 URL
  • usethis::use_news_md() - 创建 NEWS.md
  • usethis::use_cran_comments() - 创建 cran-comments.md
  • devtools::build_readme() - 从 README.Rmd 重新生成 README.md
  • usethis::use_code_of_conduct() - 添加不含相对链接的行为准则
  • usethis::use_build_ignore() - 在 R 包构建中忽略文件
  • usethis::use_package() - 向 DESCRIPTION 添加包依赖项
  • usethis::use_tidy_description() - 整理 DESCRIPTION 的格式

最终验证清单

使用此清单确保提交前没有遗漏:

文件和结构
  • NEWS.md 存在,并记录此版本的更改
  • cran-comments.md 存在,并包含提交说明
  • 如果存在 README.Rmd,则已编辑该文件(而非 README.md),并已运行 devtools::build_readme()
  • README 包含有效的安装说明(install.packages("pkgname"))
  • README 不含相对链接(所有链接均为完整 URL,或已移除)
DESCRIPTION 文件
  • Title: 使用标题式大小写
  • Title: 不含多余短语(“A Toolkit for”“Tools for”“for R”)
  • Title: 中所有软件/包名称均以单引号括起
  • Title: 少于 65 个字符
  • Description: 不以“This package”、包名称或“Functions for”开头
  • Description: 用 3–4 个句子说明用途和效用
  • Description: 中的软件/包/API 名称均以引号括起(包括 'R'),但函数名称除外
  • Description: 在首次提及时展开所有缩写
  • Description: 仅对出版物标题使用双引号
  • Authors@R: 包含带有 [cph] 角色的版权持有者
  • 对于 Posit 包:包含 person("Posit Software, PBC", role = c("cph", "fnd"), comment = c(ROR = "03wc8by49"))
  • LICENSE 年份与当前提交年份一致
函数文档
  • 所有具有 .Rd 文件的导出函数都包含 @return 文档
  • 所有具有实际返回值的已文档化导出函数都包含 @examples
  • 仅使用 @export 标记的 S3 方法 roxygen 块可正确豁免(无需 .Rd 文件,也无需 @return/@examples)
  • 由包添加的 S3 泛型均有完整文档(@return、@examples),因为它们是普通的导出函数
  • 示例部分不使用注释掉的代码
  • 除非确有必要,否则示例避免使用 \dontrun{}
  • 需要建议包的示例使用 @examplesIf 或 if 守卫
  • 含有示例的未导出函数使用 ::: 表示法或 @noRd
URL 和链接
  • 已运行 urlchecker::url_check()
  • 所有 URL 均使用 https 协议(不含 http 链接)
  • 不含会重定向的 URL(期望中的 CRAN 徽章 URL 除外)
  • 期望中的 URL(如 CRAN 徽章等)保持原样
  • README 中不含指向 .Rbuildignore 文件的相对链接
可选但建议
  • 如果担心方法引用问题,已在 cran-comments.md 中添加预先说明
  • 如果包含第三方文件,已审核随附文件的许可协议

评论

支持 Markdown