diff --git a/.gitignore b/.gitignore index 377d5bd0b..cc8371356 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ inst/doc docs internal + +/.quarto/ diff --git a/NAMESPACE b/NAMESPACE index 2c3fde50d..56663fee5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -158,6 +158,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 881496150..c1f530a30 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,8 @@ * `use_package(min_version = FALSE)` is treated the same as when `min_version` is not specified (#2117, @salim-b). +* `use_r_universe_badge()` is a new function that creates a README badge indicating your package is available on [R-universe](https://r-universe.dev) and reporting the latest version (@olivroy, #1883). + * usethis's criteria for recognizing a project have expanded to include (#2133): - a `.vscode/` directory, which Positron or VS Code might create - a `_quarto.yml` file, typical of a Quarto project diff --git a/R/badge.R b/R/badge.R index 8d6ba1e12..8952fd2b8 100644 --- a/R/badge.R +++ b/R/badge.R @@ -17,17 +17,23 @@ #' 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/). It is assumed that you have already +#' completed the +#' [necessary R-universe setup](https://docs.r-universe.dev/publish/set-up.html). #' * `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 #' in a [Posit Cloud](https://posit.cloud) project -#' * `use_rscloud_badge()`: `r lifecycle::badge("deprecated")`: Use +#' * `use_rscloud_badge()`: `r lifecycle::badge("deprecated")` Use #' [use_posit_cloud_badge()] instead. #' #' @param badge_name Badge name. Used in error message and alt text #' @param href,src Badge link and image src #' @param stage Stage of the package lifecycle. One of "experimental", #' "stable", "superseded", or "deprecated". +#' @eval param_repo_spec() #' @seealso [use_github_action()] helps with the setup of various continuous #' integration workflows, some of which will call these specialized badge #' helpers. @@ -144,6 +150,35 @@ use_binder_badge <- function(ref = git_default_branch(), urlpath = NULL) { invisible(TRUE) } +#' @rdname badges +#' @export +use_r_universe_badge <- function(repo_spec = NULL) { + check_is_package("use_r_universe_badge()") + pkg <- project_name() + + if (is.null(repo_spec)) { + this_env <- current_call() + tryCatch( + github_url <- github_url(), + error = function(e) { + ui_abort( + c( + "x" = "Can't determine the R-universe owner of the {.pkg {pkg}} package.", + "!" = "No GitHub URL found in DESCRIPTION or the Git remotes.", + "i" = "Update the project configuration or provide an explicit {.arg repo_spec}." + ), + call = this_env + ) + } + ) + repo_spec <- parse_repo_url(github_url)[["repo_spec"]] + } + + owner <- parse_repo_spec(repo_spec)[["owner"]] + src <- glue("https://{owner}.r-universe.dev/{pkg}/badges/version") + href <- glue("https://{owner}.r-universe.dev/{pkg}") + use_badge("R-universe version", href, src) +} #' @rdname badges #' @param url A link to an existing [Posit Cloud](https://posit.cloud) diff --git a/README.Rmd b/README.Rmd index e52b4b7ab..1b83b31e9 100644 --- a/README.Rmd +++ b/README.Rmd @@ -22,6 +22,7 @@ knitr::opts_chunk$set( [![CRAN status](https://www.r-pkg.org/badges/version/usethis)](https://CRAN.R-project.org/package=usethis) [![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) [![Codecov test coverage](https://codecov.io/gh/r-lib/usethis/graph/badge.svg)](https://app.codecov.io/gh/r-lib/usethis) +[![R-universe version](https://r-lib.r-universe.dev/usethis/badges/version)](https://r-lib.r-universe.dev/usethis) usethis is a workflow package: it automates repetitive tasks that arise during project setup and development, both for R packages and non-package projects. diff --git a/README.md b/README.md index 4defaa652..25ae934ea 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ status](https://www.r-pkg.org/badges/version/usethis)](https://CRAN.R-project.or stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) [![Codecov test coverage](https://codecov.io/gh/r-lib/usethis/graph/badge.svg)](https://app.codecov.io/gh/r-lib/usethis) +[![R-universe +version](https://r-lib.r-universe.dev/usethis/badges/version)](https://r-lib.r-universe.dev/usethis) usethis is a workflow package: it automates repetitive tasks that arise diff --git a/man/badges.Rd b/man/badges.Rd index dd04a230a..21ed0d9b4 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(repo_spec = NULL) + use_posit_cloud_badge(url) } \arguments{ @@ -37,6 +40,8 @@ use_posit_cloud_badge(url) \href{https://mybinder.readthedocs.io/en/latest/howto/user_interface.html}{binder documentation} for additional examples.} +\item{repo_spec}{Optional GitHub repo specification in this form: \code{owner/repo}. This can usually be inferred from the GitHub remotes of active project.} + \item{url}{A link to an existing \href{https://posit.cloud}{Posit Cloud} project. See the \href{https://posit.cloud/learn/guide#project-settings-access}{Posit Cloud documentation} for details on how to set project access and obtain a project link.} @@ -58,11 +63,15 @@ automatically, 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 }. It is assumed that you have already +completed the +\href{https://docs.r-universe.dev/publish/set-up.html}{necessary R-universe setup}. \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 in a \href{https://posit.cloud}{Posit Cloud} project -\item \code{use_rscloud_badge()}: \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}: Use +\item \code{use_rscloud_badge()}: \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Use \code{\link[=use_posit_cloud_badge]{use_posit_cloud_badge()}} instead. } } diff --git a/tests/testthat/_snaps/badge.md b/tests/testthat/_snaps/badge.md index 9546db429..9d249c1b8 100644 --- a/tests/testthat/_snaps/badge.md +++ b/tests/testthat/_snaps/badge.md @@ -7,6 +7,55 @@ ! `stage` must be one of "experimental", "stable", "superseded", or "deprecated", not "eperimental". i Did you mean "experimental"? +# use_r_universe_badge() needs to know the owner + + Code + use_r_universe_badge() + Condition + Error in `use_r_universe_badge()`: + x Can't determine the R-universe owner of the {TESTPKG} package. + ! No GitHub URL found in DESCRIPTION or the Git remotes. + i Update the project configuration or provide an explicit `repo_spec`. + +--- + + Code + use_r_universe_badge("OWNER_DIRECT/SCRUBBED") + Message + ! Can't find a README for the current project. + i See `usethis::use_readme_rmd()` for help creating this file. + i Badge link will only be printed to screen. + [ ] Copy and paste the following lines into 'README': + + [![R-universe version](https://OWNER_DIRECT.r-universe.dev/{TESTPKG}/badges/version)](https://OWNER_DIRECT.r-universe.dev/{TESTPKG}) + + +--- + + Code + use_r_universe_badge() + Message + ! Can't find a README for the current project. + i See `usethis::use_readme_rmd()` for help creating this file. + i Badge link will only be printed to screen. + [ ] Copy and paste the following lines into 'README': + + [![R-universe version](https://OWNER_DESCRIPTION.r-universe.dev/{TESTPKG}/badges/version)](https://OWNER_DESCRIPTION.r-universe.dev/{TESTPKG}) + + +--- + + Code + use_r_universe_badge() + Message + ! Can't find a README for the current project. + i See `usethis::use_readme_rmd()` for help creating this file. + i Badge link will only be printed to screen. + [ ] Copy and paste the following lines into 'README': + + [![R-universe version](https://OWNER_ORIGIN.r-universe.dev/{TESTPKG}/badges/version)](https://OWNER_ORIGIN.r-universe.dev/{TESTPKG}) + + # 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 cf9bb4dc1..cfd8d7ba2 100644 --- a/tests/testthat/test-badge.R +++ b/tests/testthat/test-badge.R @@ -24,6 +24,37 @@ test_that("use_binder_badge() needs a github repository", { ) }) +test_that("use_r_universe_badge() needs to know the owner", { + skip_if_no_git_user() + local_interactive(FALSE) + withr::local_options(usethis.quiet = FALSE) + create_local_package() + + expect_snapshot( + error = TRUE, + use_r_universe_badge(), + transform = scrub_testpkg + ) + + expect_snapshot( + use_r_universe_badge("OWNER_DIRECT/SCRUBBED"), + transform = scrub_testpkg + ) + + desc::desc_set_urls("https://github.com/OWNER_DESCRIPTION/SCRUBBED") + expect_snapshot( + use_r_universe_badge(), + transform = scrub_testpkg + ) + + use_git() + use_git_remote("origin", "https://github.com/OWNER_ORIGIN/SCRUBBED.git") + expect_snapshot( + 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)