Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export(use_pkgdown_github_pages)
export(use_posit_cloud_badge)
export(use_proprietary_license)
export(use_r)
export(use_r_universe_badge)
export(use_rcpp)
export(use_rcpp_armadillo)
export(use_rcpp_eigen)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
* Reverse dependency checks are only suggested if they exist
(#1817, @seankross).

* New `use_r_universe_badge()` to indicate which version of your package is available on [R-universe](https://r-universe.dev) (@olivroy, #1883).

# usethis 3.0.0

## Transition to cli package for UI
Expand Down
36 changes: 35 additions & 1 deletion R/badge.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#' available on CRAN, powered by <https://www.r-pkg.org>
#' * `use_lifecycle_badge()`: badge declares the developmental stage of a
#' package according to <https://lifecycle.r-lib.org/articles/stages.html>.
#' * `use_r_universe_badge()`: `r lifecycle::badge("experimental")`: badge
#' indicates what version of your package is available on [R-universe
Copy link
Member

@jennybc jennybc Jul 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm: it's "R-universe" (lowercase "u"), yeah? As opposed to "R-Universe" (uppercase "U").

#' ](https://r-universe.dev/search/).
#' * `use_binder_badge()`: badge indicates that your repository can be launched
#' in an executable environment on <https://mybinder.org/>
#' * `use_posit_cloud_badge()`: badge indicates that your repository can be launched
Expand All @@ -28,13 +31,20 @@
#' @param stage Stage of the package lifecycle. One of "experimental",
#' "stable", "superseded", or "deprecated".
#' @seealso Functions that configure continuous integration, such as
#' [use_github_actions()], also create badges.
#' [use_github_action("check-standard")][use_github_action()], also create badges.
#'
#' @name badges
#' @examples
#' \dontrun{
#' use_cran_badge()
#' use_lifecycle_badge("stable")
#' # If you don't have a GitHub repo, or needs something extra
#' # you can create the r-universe badge
#' use_badge(
#' "R-universe",
#' "https://{organization}.r-universe.dev/badges/{package})",
#' "https://{organization}.r-universe.dev/{package}"
#' )
#' }
NULL

Expand Down Expand Up @@ -138,7 +148,31 @@ use_binder_badge <- function(ref = git_default_branch(), urlpath = NULL) {

invisible(TRUE)
}
#' @rdname badges
#' @export
use_r_universe_badge <- function() {
check_is_package("use_r_universe_badge()")
# The r-universe link needs the package name + organization.

pkg <- project_name()
url <- tryCatch(github_url(pkg), error = function(e) NULL)
# in order to get organization
desc <- proj_desc()
urls <- desc$get_urls()
dat <- parse_github_remotes(c(urls, url))
gh_org <- unique(dat$repo_owner[!is.na(dat$repo_owner)])
if (length(gh_org) == 0L) {
ui_abort(c(
"{.pkg {pkg}} must have a repo URL in DESCRITPION to create a badge.",
"Use {.fn usethis::use_badge} if you have a different configuration.",
"If {.pkg {pkg}} is on CRAN, you can also see {.url cran.dev/{pkg}}
for a redirect to the r-universe homepage."
))
}
src <- glue("https://{gh_org}.r-universe.dev/badges/{pkg}")
href <- glue("https://{gh_org}.r-universe.dev/{pkg}")
use_badge("R-universe", href, src)
}
#' @rdname badges
#' @param url A link to an existing [Posit Cloud](https://posit.cloud)
#' project. See the [Posit Cloud
Expand Down
14 changes: 13 additions & 1 deletion man/badges.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions tests/testthat/_snaps/badge.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@
! `stage` must be one of "experimental", "stable", "superseded", or "deprecated", not "eperimental".
i Did you mean "experimental"?

# use_r_universe_badge() needs a repository

Code
use_r_universe_badge()
Condition
Error in `use_r_universe_badge()`:
x {TESTPKG} must have a repo URL in DESCRITPION to create a badge.
i Use `usethis::use_badge()` if you have a different configuration.
i If {TESTPKG} is on CRAN, you can also see <cran.dev/{TESTPKG}> for a redirect to the r-universe homepage.

# use_posit_cloud_badge() handles bad and good input

Code
Expand Down
10 changes: 10 additions & 0 deletions tests/testthat/test-badge.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ test_that("use_binder_badge() needs a github repository", {
expect_error(use_binder_badge(), class = "usethis_error_bad_github_remote_config")
})

test_that("use_r_universe_badge() needs a repository", {
skip_if_no_git_user()
create_local_package()
use_git()
expect_snapshot(error = TRUE,
use_r_universe_badge(),
transform = scrub_testpkg
)
})

test_that("use_posit_cloud_badge() handles bad and good input", {
create_local_project()
expect_snapshot(use_posit_cloud_badge(), error = TRUE)
Expand Down