diff --git a/NAMESPACE b/NAMESPACE index 3648d5db7..6f72b7215 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -168,6 +168,7 @@ export(use_pkgdown_travis) 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 550ba4a90..62f420abf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # usethis (development version) +* New `use_r_universe_badge()` to indicate which version of your package is available on [R-universe](https://r-universe.dev) (@olivroy, #1883). + * The URLs baked into the badge generated by `use_coverage(type = "codecov")` no longer specify a branch (#2008). diff --git a/R/badge.R b/R/badge.R index b97bf08d1..9d949d643 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,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 diff --git a/man/badges.Rd b/man/badges.Rd index 831a574c1..ece65b13b 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} \alias{use_rscloud_badge} \title{README badges} @@ -21,6 +22,8 @@ use_lifecycle_badge(stage) use_binder_badge(ref = git_default_branch(), urlpath = NULL) +use_r_universe_badge() + use_posit_cloud_badge(url) use_rscloud_badge(url) @@ -60,6 +63,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 @@ -72,9 +77,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 a212bab6b..211a15fd0 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_rscloud_badge() handles bad and good input Code diff --git a/tests/testthat/test-badge.R b/tests/testthat/test-badge.R index e90d05f56..22038c00d 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_rscloud_badge() handles bad and good input", { create_local_project() expect_snapshot(use_posit_cloud_badge(), error = TRUE)