其他
准备 R 包提交 CRAN 时,如何通过…
在首次提交或重新提交 R 包到 CRAN 前,系统性地排查 CRAN 审阅者会强制要求但 devtools::check() 检测不到的常见问题。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 48/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 53/100 ×0.15
适用场景
准备 R 包提交 CRAN 时,如何通过通用
解决思路
- 先询问用户这是首次提交还是重新提交,然后按清单逐项检查、记录问题、提出修复建议,仅在用户批准后修改,最后确认所有更改完成。
- 若不存在则运行 usethis::use_news_md() 创建 NEWS.md。
- 若不存在则运行 usethis::use_cran_comments() 创建 cran-comments.md。
- 审查 README:确保安装说明在包被 CRAN 接受后有效(通常是 install.packages("pkgname"))。
- 审查 README:检查是否包含相对链接(在 GitHub 上可用但会被 CRAN 标记),改用完整 URL 或删除链接。
- 审查 README:确认其清楚说明包的用途和功能。
- 若存在 README.Rmd,只编辑 README.Rmd(README.md 会被覆盖),然后运行 devtools::build_readme() 重新渲染 README.md。
- 仔细校对 DESCRIPTION 的 Title: 和 Description: 字段。
- 检查函数文档:确认所有导出函数都有 @return 和 @examples。
- 确认 Authors@R: 中包含带 [cph] 角色的版权持有者。
- 检查任何随包附带的第三方文件的许可。
- 运行 urlchecker::url_check() 并修复所有问题。
- 为所有导出函数添加 @return 文档,即使标记为 @keywords internal 或函数无返回值(写 @return None 之类)也必须提供。
- 为有实际返回值的导出函数添加 @examples,即使标记为 @keywords internal 也需要;纯副作用函数(如创建目录)可例外;示例必须可执行。
- 若为未导出函数编写 roxygen 示例,必须用 ::: 调用(如 pkg:::my_fun())或用 @noRd 标签抑制 .Rd 文件生成。
- 谨慎使用 \dontrun{}:仅在示例确实无法执行时(缺少软件、API 密钥等)使用;展示错误时改用 try() 包裹;可用自定义谓词(如 googlesheets4::sheets_has_token())配合 if () 块;有时可用 interactive() 作条件;耗时超过 5 秒的示例可用 \donttest{}。
- 绝不在示例中注释掉代码,CRAN 明确要求示例代码行不得被注释掉,应寻找可正常执行的玩具示例。
- 对需要建议包的整段示例使用 @examplesIf(如 @examplesIf rlang::is_installed("dplyr"));对示例中的单个代码块使用 if (rlang::is_installed("dplyr")) { ... } 包裹。
- DESCRIPTION 的 Title: 使用标题大小写(除 a、the 等冠词外每个单词首字母大写),可用 tools::toTitleCase() 辅助格式化。
- Title: 中删除冗余短语,如 "A Toolkit for"、"Tools for"、"for R"。
- Title: 中所有软件和 R 包名用单引号括起(如 'Tiingo')。
- Title: 保持在 65 个字符以内。
- Description: 绝不以 "This package"、包名或 "Functions for" 开头。
- Description: 扩展到 3-4 句话,说明包做什么、为何有用、能解决哪类问题。
- Description: 软件、包、API 名称(包括 'R')用单引号,函数名不加引号。
- Description: 所有缩略语在首次提及时完整展开。
- Description: 双引号仅用于出版物标题,不用于短语或强调。
- 所有 URL 必须使用 https:// 协议,http 链接会被拒。
- 不得使用会重定向的 URL,用 urlchecker::url_check() 查找、urlchecker::url_update() 自动更新到最终地址。
- 对发布后才会存在的 URL(CRAN 徽章、CRAN 状态徽章、CRAN 检查结果、r-universe 或 pkgdown 文档 URL)保持原样,不要修改。
- 检查无效文件 URI:README 中的相对链接在包构建后必须存在;若文件在 .Rbuildignore 中会报错,解决方法是将其从 .Rbuildignore 移除,或用 usethis::use_code_of_conduct() 生成不含相对链接的章节。
- 始终在 Authors@R 中添加 [cph] 角色,即使只有一位作者。
- 对 Posit 相关 GitHub 组织(posit-dev、rstudio、r-lib、tidyverse、tidymodels)的包或维护者邮箱为 @posit.co 的包,加入 Posit Software, PBC 作为版权持有者和资助者:person("Posit Software, PBC", role = c("cph", "fnd"), comment = c(ROR = "03wc8by49"))。
- 将 LICENSE 年份更新为当前提交年份。
- 若包中有方法参考文献,在 description 字段中添加;若没有,回复邮件说明,并考虑在 cran-comments.md 中预先添加 "## Method References" 说明无已发表参考文献。
- 系统检查以下文件:DESCRIPTION(Title、Description、Authors@R、URLs、License 年份)、R/*.R(@return、@examples、@examplesIf、@noRd)、README.Rmd(若存在则编辑它而非 README.md,然后运行 devtools::build_readme())、README.md(安装说明、相对链接、URL)、cran-comments.md、NEWS.md、.Rbuildignore。
- 使用工具: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.md;usethis::use_code_of_conduct() 添加无相对链接的行为准则;usethis::use_build_ignore() 忽略构建文件;usethis::use_package() 添加依赖;usethis::use_tidy_description() 整理 DESCRIPTION 格式。
- 提交前用最终验证清单逐项确认:NEWS.md 存在并记录本版本变更;cran-comments.md 存在;若存在 README.Rmd 则编辑它并运行 devtools::build_readme();README 含有效安装说明且无相对链接;Title 用标题大小写、无冗余短语、软件名加单引号、少于 65 字符;Description 不以禁用短语开头、3-4 句、正确加引号、展开缩略语、双引号仅用于出版物标题;Authors@R 含 [cph];Posit 包含 Posit Software, PBC;LICENSE 年份正确;所有导出函数有 @return;有返回值的导出函数有 @examples;示例无注释代码;避免不必要的 \dontrun{};建议包示例用 @examplesIf 或 if 守卫;未导出函数示例用 ::: 或 @noRd;运行 urlchecker::url_check();所有 URL 为 https;无重定向 URL(CRAN 徽章除外);保留 aspirational URL;README 无指向 .Rbuildignore 文件的相对链接;如担心方法参考文献已在 cran-comments.md 中预先说明;如包含第三方文件已审查其许可。
适用边界 · 注意事项
- 不适用于非 R 包项目或不需要提交 CRAN 的场景。
- 不替代 devtools::check(),而是补充其未覆盖的 CRAN 临时性要求。
- 不适用于已发布包在 CRAN 上的日常维护,除非准备重新提交。