0Pricing
R Academy · Lesson

CRAN Submission and Package Maintenance

Run R CMD check, resolve NOTE/WARNING issues, and submit to CRAN.

CRAN Submission and Package Maintenance is a free R Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The CRAN Submission Process

CRAN (Comprehensive R Archive Network) is the official R package repository. Submitting a package requires passing automated checks and human review against strict policies. The process: prepare → check → build → submit → revise based on feedback.

devtools::check() — Zero Errors and Warnings

Before submission, devtools::check() must produce 0 ERRORs and 0 WARNINGs. NOTEs are allowed but should be minimized. Common issues caught by check:

  • Undocumented functions or arguments
  • Missing package imports in DESCRIPTION
  • Examples that error or take too long
  • Global variable usage (use utils::globalVariables())
# devtools::check()  # or Ctrl+Shift+E
#
# Target output:
# -- R CMD check results -------------------------
# Duration: 45.3s
# 0 errors v | 0 warnings v | 1 note x
# NOTE: New submission.
#
# 'New submission' is an expected NOTE for first-time packages.
# All actual ERRORs and WARNINGs must be fixed before submitting.

CRAN Policies — Key Rules

CRAN enforces strict policies. The most commonly violated rules:

  • No internet access in examples, tests, or vignettes unless conditional on availability
  • Example runtime < 5 seconds total — use \dontrun{} or \donttest{} for slow examples
  • No writing to user's home directory — use tempdir() in examples
  • No hardcoded paths — all file ops use relative paths or tempdir()
# Correct: examples that write to tempdir
# #' @examples
# #' tmp <- tempfile()
# #' write.csv(mtcars, tmp)
# #' read.csv(tmp)
# #' unlink(tmp)
#
# Correct: skip slow or network examples
# #' @examples
# #' \dontrun{
# #'   # slow operation
# #'   fit_big_model(huge_dataset)
# #' }

devtools::build() — Creating the Package Bundle

devtools::build() creates a .tar.gz source bundle (e.g., mypackage_0.1.0.tar.gz) suitable for submission to CRAN. Use devtools::build(binary = TRUE) to create a binary package for distribution to your local OS.

# devtools::build()
# => mypackage_0.1.0.tar.gz
#
# What build does:
# 1. Runs devtools::document() to regenerate man/ and NAMESPACE
# 2. Compiles vignettes (if any)
# 3. Bundles R/, man/, DESCRIPTION, NAMESPACE, tests/ etc.
# 4. Excludes files listed in .Rbuildignore
#
# Inspect the bundle:
# tar -tzf mypackage_0.1.0.tar.gz | head -20

devtools::release() — Interactive Submission

devtools::release() runs an interactive checklist that guides you through final pre-submission checks, asks you to confirm CRAN policies, then submits the .tar.gz to https://cran.r-project.org/submit.html using CRAN's web API.

# devtools::release()
#
# Interactive questions include:
# - Have you checked on R-devel?
# - Have you checked on Windows with win-builder?
# - Is there a single top-level .R file in tests/?
# - Have you removed donttest{} for essential examples?
# - Is the package correctly versioned?
#
# After answering, it submits and emails the CRAN team.

Checking on Multiple Platforms

CRAN checks packages on multiple OS and R versions. Test broadly before submitting:

  • devtools::check_win_devel() — submit to win-builder (Windows, R-devel)
  • devtools::check_rhub() — check on multiple Linux/Windows platforms via R-hub
  • devtools::check_mac_release() — macOS check
# Check on Windows R-devel (submits to win-builder, results emailed):
# devtools::check_win_devel()
#
# Check on multiple platforms via R-hub:
# rhub::check_for_cran()   # requires rhub package and account
#
# Minimum: check locally + win-builder before every CRAN submission
cat('CRAN checks on Windows, macOS, and multiple Linux distros
')

NEWS.md — Communicating Changes

NEWS.md documents changes between versions. CRAN requires it for updates. Format each version as a heading with bullets describing what changed. Users and CRAN reviewers read this to understand what changed.

# NEWS.md format:
#
# # mypackage 0.2.0
# * Added subtract() function for element-wise subtraction.
# * add() now accepts complex numbers.
# * Fixed bug where add(NA, x) returned 0 instead of NA.
#
# # mypackage 0.1.0
# * Initial CRAN release.
# * Core add() function for numeric addition.
cat('usethis::use_news_md() creates NEWS.md with the right format
')

usethis::use_version() for Version Bumps

usethis::use_version('minor') increments the version number in DESCRIPTION and adds a new placeholder heading in NEWS.md. Use semantic versioning: major.minor.patch.

# Version bump commands:
# usethis::use_version('patch')   # 0.1.0 -> 0.1.1  (bug fixes)
# usethis::use_version('minor')   # 0.1.0 -> 0.2.0  (new features)
# usethis::use_version('major')   # 0.1.0 -> 1.0.0  (breaking changes)
# usethis::use_version('dev')     # 0.1.0 -> 0.1.0.9000 (dev suffix)
#
# CRAN packages should NOT have a dev suffix (e.g., 0.9000)
# Dev suffix signals work-in-progress on GitHub between releases

GitHub Actions for Continuous Integration

Automate R CMD check on every push using r-lib/actions. usethis::use_github_action('check-standard') creates a workflow that checks on Ubuntu, macOS, and Windows across multiple R versions.

# usethis::use_github_action('check-standard')
# Creates .github/workflows/R-CMD-check.yaml
#
# The workflow:
# - triggers on push and pull_request
# - runs on ubuntu-latest, macos-latest, windows-latest
# - tests on R release, R devel, and R oldrel
# - caches installed packages for faster runs
# - reports check results as GitHub status checks

Handling CRAN Reviewer Feedback

CRAN reviewers may request changes. Common requests:

  • Wrap long-running examples in \donttest{}
  • Use if (interactive()) guards for functions that open UIs
  • Fix spelling in documentation (use usethis::use_spell_check())
  • Add more descriptive error messages

Respond promptly and resubmit. Multiple rounds of review are normal.

# Spell check DESCRIPTION and man/ pages:
# usethis::use_spell_check()
# spelling::spell_check_package()  # run the check
#
# Add words to WORDLIST to ignore false positives:
# spelling::update_wordlist()
#
# After making all changes:
# devtools::check()  # confirm 0 errors/warnings
# devtools::release()  # resubmit

Package Maintenance After Release

After CRAN acceptance, ongoing maintenance includes:

  • Watch for deprecation warnings from dependencies in R-devel checks
  • Address CRAN check failures within 14 days (CRAN policy)
  • Use lifecycle::deprecate_warn() to gracefully deprecate old functions
  • Set up usethis::use_github_action('pkgdown') for a documentation website
# Mark a function as deprecated:
# library(lifecycle)
#
# old_add <- function(x, y) {
#   lifecycle::deprecate_warn('0.2.0', 'old_add()', 'add()')
#   add(x, y)
# }
#
# Users see: 'old_add()' was deprecated in mypackage 0.2.0.
# Please use 'add()' instead.

Quick Check: CRAN Example Policy

Which tag should you use to include a long-running example in your documentation without having CRAN's automated checker execute it?

CRAN Submission and Maintenance Recap

The CRAN release workflow:

  • devtools::check() — 0 ERRORs, 0 WARNINGs required
  • CRAN policies: no internet in examples, examples < 5 sec, use tempdir() for writes
  • devtools::build() — creates .tar.gz bundle
  • devtools::release() — interactive guided submission
  • Cross-platform checks: check_win_devel(), R-hub
  • NEWS.md with version headings; bump with use_version('minor')
  • GitHub Actions with r-lib/actions for CI on push
  • Respond to reviewer feedback within 14 days

Frequently asked questions

Is the “CRAN Submission and Package Maintenance” lesson free?

Yes — the full text of “CRAN Submission and Package Maintenance” is free to read here on the web, and the R Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the R Academy course, upgrade to CoddyKit PRO.

What will I learn in “CRAN Submission and Package Maintenance”?

Run R CMD check, resolve NOTE/WARNING issues, and submit to CRAN. You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start R Academy?

No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “CRAN Submission and Package Maintenance” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this R Academy lesson?

Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Package Structure with usethis and devtools
  2. Documenting Functions with roxygen2
  3. Unit Testing with testthat
  4. CRAN Submission and Package Maintenance
← Back to R Academy