diff --git a/NAMESPACE b/NAMESPACE index 0a1e4ae87..c5d7f27f7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -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) diff --git a/NEWS.md b/NEWS.md index 311e2707d..07fb37602 100644 --- a/NEWS.md +++ b/NEWS.md @@ -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 diff --git a/R/badge.R b/R/badge.R index 1427a207d..d08364708 100644 --- a/R/badge.R +++ b/R/badge.R @@ -16,6 +16,9 @@ #' available on CRAN, powered by #' * `use_lifecycle_badge()`: badge declares the developmental stage of a #' package according to . +#' * `use_r_universe_badge()`: `r lifecycle::badge("experimental")`: badge +#' indicates what version of your package is available on [R-universe +#' ](https://r-universe.dev/search/). #' * `use_binder_badge()`: badge indicates that your repository can be launched #' in an executable environment on #' * `use_posit_cloud_badge()`: badge indicates that your repository can be launched @@ -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 @@ -138,7 +148,28 @@ 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() + # Get organization to construct R-universe link + repo_owner <- tryCatch(target_repo()$repo_owner, error = function(e) NA) + gh_org <- repo_owner[!is.na(repo_owner)] + if (length(gh_org) != 1L ) { + 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 https://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 diff --git a/man/badges.Rd b/man/badges.Rd index b69ea32b5..4478f3834 100644 --- a/man/badges.Rd +++ b/man/badges.Rd @@ -7,6 +7,7 @@ \alias{use_bioc_badge} \alias{use_lifecycle_badge} \alias{use_binder_badge} +\alias{use_r_universe_badge} \alias{use_posit_cloud_badge} \title{README badges} \usage{ @@ -20,6 +21,8 @@ use_lifecycle_badge(stage) use_binder_badge(ref = git_default_branch(), urlpath = NULL) +use_r_universe_badge() + use_posit_cloud_badge(url) } \arguments{ @@ -57,6 +60,8 @@ ensure your badge block starts with a line containing only available on CRAN, powered by \url{https://www.r-pkg.org} \item \code{use_lifecycle_badge()}: badge declares the developmental stage of a package according to \url{https://lifecycle.r-lib.org/articles/stages.html}. +\item \code{use_r_universe_badge()}: \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}: badge +indicates what version of your package is available on \href{https://r-universe.dev/search/}{R-universe }. \item \code{use_binder_badge()}: badge indicates that your repository can be launched in an executable environment on \url{https://mybinder.org/} \item \code{use_posit_cloud_badge()}: badge indicates that your repository can be launched @@ -69,9 +74,16 @@ in a \href{https://posit.cloud}{Posit Cloud} project \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}" +) } } \seealso{ Functions that configure continuous integration, such as -\code{\link[=use_github_actions]{use_github_actions()}}, also create badges. +\link[=use_github_action]{use_github_action("check-standard")}, also create badges. } diff --git a/tests/testthat/_snaps/badge.md b/tests/testthat/_snaps/badge.md index 9546db429..3eca7e800 100644 --- a/tests/testthat/_snaps/badge.md +++ b/tests/testthat/_snaps/badge.md @@ -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 for a redirect to the r-universe homepage. + # use_posit_cloud_badge() handles bad and good input Code diff --git a/tests/testthat/test-badge.R b/tests/testthat/test-badge.R index 6c9b8057d..3cac2d95b 100644 --- a/tests/testthat/test-badge.R +++ b/tests/testthat/test-badge.R @@ -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)