usethis 2.0.0

  devtools, r-lib, usethis

  Jenny Bryan

We’re ecstatic to announce the release of usethis v2.0.0 ( usethis.r-lib.org). usethis is a package that facilitates interactive workflows for R project creation and development. It’s mostly focussed on easing day-to-day package development, but many of its functions are also useful for non-package projects.

You can install usethis from CRAN with:

install.packages("usethis")

This is a major release, involving lots of change under the hood, and yet there are no big, brand new features. Instead, this release is about making more things “just work” the way you expect. Below, we list many functions and arguments that have been deprecated, because we’ve been able to deliver the same functionality (actually, a bit more) with a smaller and simpler user interface.

This blog post hits a few highlights, mostly relating to Git and GitHub functionality:

  • We’ve switched to a new package, gert, for Git operations. This resolves some long-standing difficulties around credential-finding and provides more reliable support for both HTTPS and SSH remotes.
  • Anything that works for github.com should now work for any GitHub Enterprise deployment.
  • GitHub personal access tokens are now handled in the same way as command line Git. This means we can all manage our tokens more securely and, for example, can have different tokens for different hosts.
  • We’ve added more functionality for working with GitHub pull requests.
  • A default branch named main should be fully supported.

You can see a full list of changes in the release notes.

Git/GitHub & credentials, hosts, and protocols

Usethis has various functions that help with Git-related tasks, which break down into two categories:

  1. Git tasks, such as clone, push, and pull. These are things you could do with command line Git.
  2. GitHub tasks, such as fork, release, and open an issue or pull request. These are things you could do in the browser or with the GitHub API.

We’ve switched from git2r to the gert package for Git operations (https://docs.ropensci.org/gert/). We continue to use the gh package for GitHub API work (https://gh.r-lib.org).

Many real-world goals can only be accomplished through a mix of Git and GitHub operations, therefore many usethis functions make use of both gert and gh. These packages, in turn, might need your credentials to prove to GitHub that you have the permission to do what you’re trying to do.

If you stop reading here, just know that gh_token_help() is a good way to assess your credential situation:

gh_token_help()
#> ● GitHub host: 'https://github.com'
#> ● Host online: TRUE
#> ● Personal access token for 'https://github.com': '<discovered>'
#>  Call `gh::gh_whoami()` to see info about your token, e.g. the associated user
#>  To see or update the token, call `gitcreds::gitcreds_set()`
#>  If those results are OK, you are good go to!
#>  Read more in the 'Managing Git(Hub) Credentials' article:
#>   https://usethis.r-lib.org/articles/articles/git-credentials.html

You can get even more diagnostic information with git_sitrep().

Finding Git credentials

One of the reasons we switched to the gert package is that it generally discovers the same Git credentials as command line Git, for both the HTTPS and SSH protocols, even on Windows. If things still go sideways, gert’s approach to credential finding is mercifully explicit and debuggable1.

This allows usethis to shed some of the workarounds we have needed in the past, to serve as a remedial “credential valet”. As a result, several functions and arguments are no longer needed and have been deprecated:

If you have any of these in your .Rprofile or muscle memory, you can let go of that now. (We’ll say more about host, repo_spec, and auth_token below.)

Host and GitHub Enterprise

Many companies and universities run their own instance of GitHub, using a pro product called GitHub Enterprise (GHE), that walks and talks just like github.com. It’s been frustrating that many usethis functions didn’t quite work for GHE. We had partial support for GHE, by adding a host argument to some functions, but that created new headaches around juggling personal access tokens.

We’ve completely refactored the “GitHub host” logic in usethis and GHE should be fully supported now. In an existing repo, usethis consults the configured Git remotes, filters for remotes that smell like a GitHub deployment, and deduces the target host and repo_spec, where applicable. As a result, we’ve deprecated those arguments in several functions (listed above).

In use_github() and create_from_github(), we still have a host argument, but there are also other ways to specify the host:

  • usethis no longer inserts its own opinion about the default host. This means we no longer get in the way of the existing default behaviour of the gh package, which is to consult the GITHUB_API_URL environment variable, if it is set. GitHub Enterprise users will probably want to lean heavily on this environment variable.
  • A couple functions now accept a full URL as the repo_spec and, if you do that, we discover the host from the URL.

Give me your full URLs!

The last point above is a nice quality-of-life improvement even when working on github.com. It means you can copy a URL straight from your browser and, as long as it points somewhere within the target repo, all will be well. For example, if you decide to fork-and-clone Matt Lincoln’s clipr package while perusing its issues, you can just copy the URL directly from your browser:

create_from_github("https://github.com/mdlincoln/clipr/issues")
#> ℹ Defaulting to https Git protocol
#> ✓ Setting `fork = TRUE`
#> ✓ Creating '/Users/jenny/Desktop/clipr/'
#> ✓ Forking 'mdlincoln/clipr'
#> ✓ Cloning repo from 'https://github.com/jennybc/clipr.git' into '/Users/jenny/Desktop/clipr'
#> ✓ Setting active project to '/Users/jenny/Desktop/clipr'
#> ℹ Default branch is 'master'
#> ✓ Adding 'upstream' remote: 'https://github.com/mdlincoln/clipr.git'
#> ✓ Pulling changes from 'upstream/master' (default branch of source repo)
#> ✓ Setting remote tracking branch for local 'master' branch to 'upstream/master'

URLs are supported by the repo_spec argument of create_from_github() and use_tidy_thanks(). In addition to browser URLs, you can also use HTTPS and SSH Git remote URLs.

Personal access tokens (PATs)

This diagram shows the different ways that usethis might interact with GitHub:

  1. As a Git server, via gert, using either the HTTPS or SSH protocol
  2. As a web service, via gh, using HTTPS (and OAuth)

The cheerful orange ovals indicate why we recommend HTTPS as your Git protocol: Once you set up your GitHub personal access token (PAT), usethis, gert, and gh (and possibly other packages) will all be able to find and use this common credential. (If you are an SSH person, you need to set up a GitHub PAT for work that involves the GitHub API, in addition to the SSH keys needed for Git work.)

You may have noticed that command line Git remembers your HTTPS credentials, after you’ve provided them once2. Git has an internal interface for storing and retrieving HTTPS credentials from system-specific helpers, such as the macOS Keychain and Windows Credential Manager. This interface is exposed for use by other applications in the git credential utility Both gert and gh (and, therefore, usethis) now use this utility to retrieve a PAT suitable for a specific host. It is now possible to attain Git credential nirvana, where command line Git, RStudio, and all your favourite R packages are working with the same credentials.

In the previous section, we explained how the host is now automatically discovered from Git remotes. And we’ve just explained that we now look up the PAT based on the host. Together, this means usethis no longer needs any explicit PAT management and finishes explaining why so many credential-, token-, and host-related functions and arguments have been deprecated. This is also a major reason why GitHub Enterprise “just works” now.

The new connection to the system-specific Git credential store also means we no longer need to set GITHUB_PAT in our .Renviron startup files. It is a better security practice anyway to avoid storing such secrets in a plain text file, if better alternatives exist.

WUT=yo
GITHUB_PAT=xyz  # <-- WE SUGGEST YOU REMOVE THIS LINE FROM .Renviron
OTHER_WEB_SERVICE=super-secret-very-powerful-token

The host-specific PAT is now retrieved from the Git credential store upon first need. Note that the PAT is still cached in an environment variable for reuse during the remainder of the current R session.

Our full recommendations for getting and configuring a PAT are in the new vignette Managing Git(Hub) Credentials.

Git protocol

When usethis configures a new Git remote, it must choose a protocol, either HTTPS or SSH. The new default in this situation is HTTPS, because as we explained above, we think HTTPS is the best choice for most users and projects.

git_protocol()
#>  Defaulting to https Git protocol
#> [1] "https"

As always, you can specify the default protocol for a single session with use_git_protocol() or for all sessions via the usethis.protocol option. Those who prefer SSH may want to set this option in .Rprofile going forward.

Pull request helpers

The team that maintains the tidyverse and r-lib packages makes heavy use of GitHub pull requests for managing internal and external contributions3. The pr_*() family of functions supports pull request workflows, for maintainers and contributors. This family has gained a couple of new functions and some improvements to existing functions:

  • pr_resume() resumes work on an existing local PR branch. It can be called argument-less, to select a branch interactively.

    > pr_resume()
    ℹ No branch specified ... looking up local branches and associated PRs
    Which branch do you want to checkout? (0 to exit) 
    
    1: avalcarcel9-add_use_author --> #833 ('@avalcarcel9'): Add use author
    2:                 latex-hell
    3:                     holder
    4:            patch-for-withr
    
    Selection: 
    
  • pr_fetch() and pr_view() now present a similar interactive choice, when the target PR is not specified or implied.

  • pr_forget() abandons a PR you initiated locally or fetched from GitHub. It only does local clean up and will never delete a remote branch or close a PR.

Other pr_*() functions have nice little improvements, so heavy users should definitely read the full release notes.

Other goodies

The use_*_license() functions have gotten a general overhaul and also now work for projects, not just for packages. This was part of a bigger effort related to re-licensing some tidyverse/r-lib packages and updating the licensing chapter of R Packages for its future second edition.

browse_package() and browse_project() are new additions to the browse_*() family that let the user choose from a list of URLs derived from local Git remotes and DESCRIPTION (local or possibly on CRAN). Implementing these reminded us of how handy the existing browse_*() functions are!

> browse_package()
Which URL do you want to visit? (0 to exit) 

1: https://github.com/r-lib/usethis        ('origin' remote)
2: https://github.com/avalcarcel9/usethis  ('avalcarcel9' remote)
3: https://usethis.r-lib.org               (URL field in DESCRIPTION)
4: https://github.com/r-lib/usethis        (URL field in DESCRIPTION)
5: https://github.com/r-lib/usethis/issues (BugReports field in DESCRIPTION)

Selection: 0

> browse_package("gert")
Which URL do you want to visit? (0 to exit) 

1: https://docs.ropensci.org/gert/      (URL field in DESCRIPTION)
2: https://github.com/r-lib/gert        (URL field in DESCRIPTION)
3: https://libgit2.org                  (URL field in DESCRIPTION)
4: https://github.com/r-lib/gert/issues (BugReports field in DESCRIPTION)

Selection: 0

> browse_cran("cowsay")
✓ Opening URL 'https://cran.r-project.org/package=cowsay'

> browse_github("cpp11")
✓ Opening URL 'https://github.com/r-lib/cpp11'

Here’s a sampler of other new features:

  • A default Git branch named main now works. git_branch_default() is a new function that tries to discover the default branch from the local or remote Git repo. Internally, it is used everywhere that we previously assumed a default branch named master.
  • use_github_pages() and use_tidy_pkgdown() are great for turning on GitHub Pages and for using GitHub Actions to build and deploy a pkgdown site.
  • usethis knows that RStudio >= 1.3 stores user preferences in a file, which means that use_blank_slate() can be used to opt in to the “never save to or restore .RData” lifestyle, globally, for a user.

For a full list of changes, see the release notes.

Acknowledgements

We’re especially grateful to Jeroen Ooms and Gábor Csárdi for a great deal of behind-the-scenes work in credentials, gert, gh, and gitcreds. This version of usethis would not be possible without coordinated development and CRAN releases across these five packages.

A big thanks to everyone who helped with this release by reporting bugs, discussing issues, and contributing code: @albersonmiranda, @andrader, @arashHaratian, @Athanasiamo, @batpigandme, @cderv, @cstepper, @dmenne, @friep, @hadley, @ijlyttle, @jamesmyatt, @jennybc, @jeroen, @jimhester, @jtr13, @KoderKow, @krlmlr, @lionel-, @maelle, @malcolmbarrett, @maurolepore, @mine-cetinkaya-rundel, @mrcaseb, @vinhtantran, and @whtns.


  1. gert uses a dedicated, standalone package: https://docs.ropensci.org/credentials/ ↩︎

  2. In our experience, on both macOS and Windows, recent Git versions come with credential caching that works out-of-the-box. If this is not your experience, it’s a good reason to update Git. ↩︎

  3. In 2019, we handled over 6,000 pull requests in the >180 public package repos owned by the GitHub organisations r-dbi, r-lib, rstudio, tidymodels, and tidyverse. ↩︎