- name
- cran-submission
- description
- Complete guide to CRAN submission including policies, pre-submission checks, common issues, and the submission process
# CRAN Submission Guide
This skill covers the complete CRAN submission process, from pre-submission preparation through to acceptance and post-release tasks. CRAN (Comprehensive R Archive Network) is the primary repository for R packages and has strict quality requirements.
## Rules
1. **All exported functions** must have `@returns` and `@examples` documentation
2. **Version number** must be greater than the current CRAN version
3. **Test on multiple platforms** before submission (Windows, macOS, Linux, R-devel)
4. **Fix all ERRORs and WARNINGs** - CRAN will reject packages with any
5. **NOTEs should be explained** in cran-comments.md
6. **Title case for Title field** with no period at the end, under 65 characters
7. **Use cph role** for copyright holders in Authors@R
8. **Check all URLs** with urlchecker::url_check()
9. **Examples must run** without errors (use `\donttest{}` sparingly)
10. **Respond to CRAN within 2 weeks** or submission will be archived
## Pre-Submission Checklist
### Essential Documentation Requirements
Every exported function must have:
```r
#' Function Title
#'
#' @description
#' Detailed description of what the function does.
#'
#' @param x Description of parameter x
#' @param y Description of parameter y
#'
#' @returns A data.frame with columns:
#' \item{col1}{Description of column 1}
#' \item{col2}{Description of column 2}
#'
#' @examples
#' # Basic usage
#' result <- my_function(x = 1, y = 2)
#' print(result)
#'
#' # Advanced usage
#' result2 <- my_function(x = 1:10, y = 20)
#'
#' @export
my_function <- function(x, y) {
# implementation
}
```
**Critical**: Use `@returns` (not `@return`) for consistency with roxygen2 7.0+.
### DESCRIPTION File Requirements
```
Package: packagename
Title: A Package That Does Amazing Things # Title case, < 65 chars, no period
Version: 0.1.0 # Must be > current CRAN version
Authors@R: c(
person("First", "Last", email = "email@example.com",
role = c("aut", "cre"),
comment = c(ORCID = "0000-0000-0000-0000")),
person("Another", "Author", role = "aut"),
person("Company Name", role = "cph") # Copyright holder
)
Description: Provides tools for amazing analysis. This package implements
novel algorithms and provides intuitive interfaces. Functions include
data processing, visualization, and reporting capabilities.
License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.0
URL: https://username.github.io/packagename/, https://github.com/username/packagename
BugReports: https://github.com/username/packagename/issues
Suggests:
testthat (>= 3.0.0),
knitr,
rmarkdown
VignetteBuilder: knitr
Config/testthat/edition: 3
```
**Title field rules**:
- Title case (capitalize major words)
- No period at end
- Under 65 characters
- Don't start with "A Package for..." (redundant)
- Be specific about what it does
**Description field rules**:
- One paragraph
- Indent continuation lines with 4 spaces
- Don't start with "This package..."
- Explain what the package does, not just list features
- Mention key algorithms or papers if relevant
### Version Numbering
For new submissions:
```
Version: 0.1.0
```
For updates (must be > CRAN version):
```
# If CRAN has 0.1.0, use:
Version: 0.1.1 # Bug fixes
Version: 0.2.0 # New features
Version: 1.0.0 # Major release
```
Development versions (not for CRAN):
```
Version: 0.1.0.9000 # Development version after 0.1.0
```
## Multi-Platform Testing
### Local Testing
```r
# Standard check
devtools::check()
# Check with remote checking (stricter)
devtools::check(remote = TRUE, manual = TRUE)
# Check with --as-cran flag
devtools::check(args = c('--as-cran'))
```
### Windows Testing
```r
# Check on Windows builder (CRAN's Windows server)
devtools::check_win_devel() # R-devel
devtools::check_win_release() # R-release
devtools::check_win_oldrelease() # R-oldrelease
```
You'll receive an email with results in ~30 minutes.
### R-hub Testing
```r
# Install rhub
install.packages("rhub")
# Validate email first time
rhub::validate_email()
# Check on multiple platforms
rhub::check_for_cran()
# Specific platforms
rhub::check(platform = "windows-x86_64-devel")
rhub::check(platform = "ubuntu-gcc-release")
rhub::check(platform = "macos-highsierra-release-cran")
rhub::check(platform = "solaris-x86-patched")
# List available platforms
rhub::platforms()
```
**Note**: R-hub can be unreliable. GitHub Actions with r-lib/actions is often more reliable.
### GitHub Actions
Most reliable multi-platform testing:
```r
# Set up GitHub Actions
usethis::use_github_action("check-standard")
```
Tests on:
- macOS (release)
- Windows (release)
- Ubuntu (devel, release, oldrel-1)
## URL Checking
```r
# Check all URLs in documentation and vignettes
urlchecker::url_check()
# Fix or explain any broken URLs
```
Common issues:
- DOIs should use `https://doi.org/` not `http://dx.doi.org/`
- Use permanent URLs, not redirects
- Some URLs may be temporarily down (explain in cran-comments.md)
## Creating cran-comments.md
Create `cran-comments.md` in package root:
```markdown
## Test environments
* local R installation, R 4.4.0
* ubuntu 22.04 (on GitHub Actions), R-devel, R-release, R-oldrel-1
* windows-latest (on GitHub Actions), R-release
* macos-latest (on GitHub Actions), R-release
* win-builder (devel and release)
## R CMD check results
0 errors | 0 warnings | 1 note
* This is a new release.
## Downstream dependencies
There are currently no downstream dependencies for this package.
```
### For Updates
```markdown
## Test environments
* local R installation, R 4.4.0
* ubuntu 22.04 (on GitHub Actions), R-devel, R-release, R-oldrel-1
* windows-latest (on GitHub Actions), R-release
* macos-latest (on GitHub Actions), R-release
## R CMD check results
0 errors | 0 warnings | 0 notes
## What's changed
This is a minor release that fixes bugs and adds new features:
* Fixed issue with X (#123)
* Added new function Y
* Improved documentation for Z
## Downstream dependencies
I have run R CMD check on downstream dependencies of my package.
All packages passed.
```
### Explaining NOTEs
```markdown
## R CMD check results
0 errors | 0 warnings | 1 note
* Checking CRAN incoming feasibility ... NOTE
Maintainer: 'First Last <email@example.com>'
New submission
Possibly misspelled words in DESCRIPTION:
MCMC (3:49)
PyMC (9:31)
These are not misspelled:
* MCMC is a standard acronym for Markov Chain Monte Carlo
* PyMC is the name of a Python library
```
## Submission Process
### First Submission
```r
# 1. Final checks
devtools::check()
devtools::check_win_devel()
rhub::check_for_cran()
urlchecker::url_check()
# 2. Build the package
devtools::build()
# 3. Submit to CRAN
devtools::submit_cran()
# This will:
# - Build the package
# - Run R CMD check
# - Ask for confirmation
# - Submit to CRAN via web form
```
### Manual Submission
If `submit_cran()` doesn't work:
1. Build package: `devtools::build()`
2. Go to https://cran.r-project.org/submit.html
3. Upload .tar.gz file
4. Fill in maintainer email and comments
5. Submit
### Confirmation Email
You'll receive an email asking to confirm submission:
- Click the confirmation link within 24 hours
- CRAN will then review your package
## CRAN Review Process
### Timeline
1. **Submission**: Upload package
2. **Confirmation** (immediate): Confirm via email
3. **Automated checks** (minutes to hours): CRAN runs checks
4. **Human review** (days to weeks): CRAN volunteer reviews
5. **Acceptance or rejection**: Email notification
**Typical timeline**: 1-2 weeks, but can be longer during busy periods.
### Common Rejection Reasons
1. **ERRORs or WARNINGs** in R CMD check
2. **Missing documentation** (no @returns or @examples)
3. **Examples fail** or take too long (>5 seconds per example)
4. **License issues** (incompatible or missing LICENSE file)
5. **DESCRIPTION problems** (title, description formatting)
6. **Failed tests** on CRAN's systems
7. **Large package size** (>5 MB without justification)
8. **Writing to user's home directory** without permission
9. **Internet resources without checks** (must fail gracefully if offline)
10. **Non-standard file permissions**
## Common R CMD Check Issues and Fixes
### 1. Undefined Global Variables
**Problem**:
```
checking R code for possible problems ... NOTE
my_function: no visible binding for global variable 'x'
my_function: no visible binding for global variable 'y'
```
**Cause**: Using NSE (non-standard evaluation) with dplyr, data.table, etc.
**Solution**:
```r
# In R/globals.R
utils::globalVariables(c("x", "y", "z"))
# Or use .data pronoun
library(dplyr)
my_function <- function(df) {
df %>%
mutate(z = .data$x + .data$y)
}
```
### 2. Unused Imports
**Problem**:
```
checking dependencies in R code ... NOTE
Namespace in Imports field not imported from: 'package'
```
**Solution**: Remove from DESCRIPTION or use somewhere:
```r
#' @importFrom package function
```
### 3. Non-ASCII Characters
**Problem**:
```
checking R files for non-ASCII characters ... NOTE
```
**Solution**: Use Unicode escapes:
```r
# Bad
"Müller"
# Good
"M\u00fcller"
```
### 4. Examples Fail
**Problem**:
```
checking examples ... ERROR
```
**Solution**: Wrap problematic examples:
```r
#' @examples
#' # Basic example (always runs)
#' result <- my_function(x = 1)
#'
#' \donttest{
#' # Slow example (skipped on CRAN)
#' slow_result <- slow_function(x = 1:1000000)
#' }
#'
#' \dontrun{
#' # Requires authentication (never runs)
#' api_result <- call_api(key = "your-key")
#' }
```
**Rules**:
- `\donttest{}`: Runs locally and on CI, skipped on CRAN (for slow examples)
- `\dontrun{}`: Never runs automatically (for examples needing setup)
- Don't overuse - most examples should run
### 5. Missing Imports
**Problem**:
```
checking dependencies in R code ... WARNING
'::' or ':::' imports not declared from:
'package'
```
**Solution**: Add to DESCRIPTION Imports and use:
```r
#' @importFrom package function
```
Or declare in NAMESPACE:
```
importFrom(package, function)
```
### 6. LaTeX/PDF Errors
**Problem**:
```
checking PDF version of manual ... WARNING
```
**Solution**: Fix .Rd formatting issues or use:
```yaml
# In GitHub Actions
build_args: 'c("--no-manual")'
```
### 7. Vignette Build Fails
**Problem**:
```
checking re-building of vignette outputs ... WARNING
```
**Solution**: Ensure vignettes build:
```r
devtools::build_vignettes()
# Check for missing packages in Suggests
```
### 8. File Permissions
**Problem**:
```
checking file modes ... NOTE
```
**Solution**: Fix permissions:
```bash
chmod 644 R/*.R
chmod 644 man/*.Rd
chmod 755 configure
```
### 9. Package Size
**Problem**:
```
checking installed package size ... NOTE
installed size is X Mb
sub-directories of 1Mb or more:
data Y Mb
GitHub에서 보기