r-software-lifetime

This website offers a quick visualization of the lifespans of different R versions, along with detials about the project’s history. While this information exists on the web, it is often scattered. Here, it is brought together with help from the rversions package. You can click “Show the code” to see how each section was generated.

Version History

All historical versions of R as reported by rversions::r_versions(). R has adopted semantic versioning for all verions since version 1.4.1.

Show the code
## r_versions_data
r_versions_data <-
    rversions::r_versions() |> 
    dplyr::arrange(package_version(version)) |> 
    dplyr::rename(release_date = date) |> 
    dplyr::mutate(
        version_fct = factor(version, levels = rev(unique(package_version(version)))),
        major_version = stringr::str_extract(version, "^[0-9]+\\.[0-9]+"),
        major_version = dplyr::case_when(
          as.numeric(major_version) < 1 ~ NA_character_, 
          TRUE ~ major_version
          ),
        major_version_fct = factor(major_version, levels = rev(unique(package_version(major_version)))), 
        superseded_date = dplyr::lead(release_date),
        superseded_date = tidyr::replace_na(superseded_date, lubridate::now()),
        nickname = dplyr::case_when(
          is.na(nickname) ~ glue::glue('v{version}'), 
          TRUE ~ glue::glue('v{version}: {nickname}'))
    ) |> 
    dplyr::relocate(superseded_date, .after = release_date)

## osv-vulnerabilities
source('utils/cve.R')
r_base_vulns <- query_osv(name = 'r-base', ecosystem = 'Debian')
r_base_vulns_data <- 
  r_base_vulns |> 
  tidyr::separate(fixed, into = c('fixed_r_version', 'ecosystem_revision'), sep = '-')

## combined
combined <- 
  r_versions_data |> 
  dplyr::cross_join(r_base_vulns_data) |> 
  tibble::as_tibble() |> 
  dplyr::mutate(is_vulnerable = package_version(as.character(version)) < package_version(fixed_r_version)) |> 
  dplyr::group_by(major_version, major_version_fct) |> 
  dplyr::summarize(
    release_date = min(release_date, na.rm = TRUE),
    superseded_date = max(superseded_date, na.rm = TRUE),
    is_vulnerable = any(is_vulnerable), 
    nickname = nickname[which.min(release_date)],
    .groups = 'drop'
    )
Show the code
combined |>  
  plotly::plot_ly() |> 
  plotly::add_segments(
    x = ~release_date, xend = ~superseded_date, 
    y = ~major_version, yend = ~major_version,
    color = ~is_vulnerable,
    colors = c("FALSE" = "steelblue", "TRUE" = "red"),
    line = list(width = 6),
    hoverinfo = 'text', text = ~nickname
  ) |> 
  plotly::layout(
    title = "R Major Version Lifespan",
    xaxis = list(title = "Date"),
    yaxis = list(
      title = "Major Version",
      type = "category",
      categoryorder = "array",
      categoryarray = sort(unique(combined$major_version_fct))
    ),
    legend = list(
      title = list(text = "Impacted by CVE")
    )
  )
Show the code
r_versions_data |> 
  dplyr::select(-c(dplyr::ends_with("_fct"), major_version)) |> 
  DT::datatable(
    options = list(
      scrollY = 425,
      scroller = TRUE
      ), 
    rownames = FALSE
  )

R-Project Vulnerability Information

This resource tracks current and historical vulnerabilities for the r-base package in the Debian ecosystem, which generally serves as a proxy for vulnerabilities in the R interpreter itself. It is not intended as a precise indication of which version of R is best for your projects, but rather as a reference to help users stay informed and make decisions in light of official guidance and project documentation. Notably, recent vulnerabilities such as CVE-2024-27322 have been addressed starting with R version 4.4.0. Users are strongly encouraged to upgrade to R 4.4.0 or later so that they are not impacted by these known security issues.

Show the code
r_base_vulns |> 
  dplyr::mutate(
    id = glue::glue("<a href='https://osv.dev/vulnerability/{id}' target='_blank'>{id}</a>")
    ) |> 
  dplyr::select(-references) |> 
  DT::datatable(
    options = list(
      scrollX = TRUE,
      scrollY = 425,
      scroller = TRUE,
      columnDefs = list(
      list(
        targets = 6,
        render = DT::JS('$.fn.dataTable.render.ellipsis( 65 )')
      )
    )
      ), 
    rownames = FALSE,
    escape = FALSE,
    plugins = 'ellipsis'
  )

CVE information provided by osv.dev