mcpField
C
cran-extrachecks

cran-extrachecks

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

关于 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、README 与包元数据问题

安装

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

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

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

详细介绍

CRAN 额外检查

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

工作流

  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(见下方详细指南)
  6. 确认版权所有者:检查 Authors@R: 是否包含角色为 [cph] 的版权所有者
  7. 检查打包文件的许可:检查所有包含的第三方文件的许可情况
  8. 运行 URL 检查:使用 urlchecker::url_check() 并修复发现的问题

CRAN 详细检查

文档要求

返回值文档(严格执行)

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

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

示例:

# 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,也必须提供
  • 纯粹用于产生副作用的函数(例如,创建目录)可例外
  • 示例必须可执行

未导出函数的示例

如果为未导出的函数编写了 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 Title 字段

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 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:Title、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 Title:

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

# After
Title: Construct Modeling Packages

DESCRIPTION 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 年份与当前提交年份一致
函数文档
  • 所有导出的函数都有 @return 文档
  • 所有具有有意义返回值的导出函数都有 @examples
  • 示例部分均未使用注释掉的代码
  • 示例避免使用 \dontrun{},除非确有必要
  • 需要建议包的示例使用 @examplesIf 或 if 保护
  • 包含示例的未导出函数使用 ::: 记法或 @noRd
URL 和链接
  • 已运行 urlchecker::url_check()
  • 所有 URL 均使用 https 协议(不含 http 链接)
  • 不含会重定向的 URL(CRAN 预期徽章 URL 除外)
  • 预期 URL(如 CRAN 徽章等)保持原样
  • README 中没有引用 .Rbuildignore 文件的相对链接
可选但建议
  • 如果担心方法引用问题,已在 cran-comments.md 中添加预先说明
  • 如果包含第三方文件,已审查随附文件的许可

评论

支持 Markdown