Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ export(edit_r_profile)
export(edit_rstudio_prefs)
export(edit_rstudio_snippets)
export(edit_template)
export(gh_lock_branch)
Copy link
Member

Choose a reason for hiding this comment

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

What do we think of github_lock_branch()? Just want us to at least consider. I don't have a strong opinion.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't have a strong opinion either. If you want user-facing functions to use a github_ prefix I'm happy to change it.

export(gh_token_help)
export(gh_unlock_branch)
export(git_default_branch)
export(git_default_branch_configure)
export(git_default_branch_rediscover)
Expand Down
49 changes: 49 additions & 0 deletions R/github_token.R
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,52 @@ scold_for_scopes <- function(scopes) {
)
ui_bullets(message)
}

#' Lock and unlock a branch on GitHub
#'
#' @description
#' These functions lock and unlock a branch on GitHub so that it's not possible
#' for anyone to make any changes. This is used as part of the release process
#' to ensure that you don't accidentally merge any pull requests or push any
#' commits while you are waiting for CRAN to get back to you.
Comment on lines +303 to +306
Copy link
Member

Choose a reason for hiding this comment

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

Anything about permissions required to perform this action?

Copy link
Member Author

Choose a reason for hiding this comment

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

You need to be an admin or owner, which I've documented. It looks like this is already in line with our governance tidyup where the maintainer has admin access: https://github.com/tidyverse/tidyups/blob/main/004-governance.md#maintainer.

#'
#' You must be an admin or an owner of the repo in order to lock/unlock
#' a branch.
#'
#' @export
#' @param branch The branch to lock/unlock. If not supplied, uses the
#' default branch which is usually "main" or "master".
gh_lock_branch <- function(branch = NULL) {
cfg <- github_remote_config(github_get = TRUE)
repo <- target_repo(cfg)
Copy link
Member

@jennybc jennybc Sep 4, 2025

Choose a reason for hiding this comment

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

Right around here we could adapt this code we use in use_release_issue() and use_upkeep_issue() except I guess we just tell people that don't have enough permission to do this:

usethis/R/release.R

Lines 38 to 47 in 0592077

if (!isTRUE(tr$can_push)) {
ui_bullets(c(
"!" = "It is very unusual to open a release issue on a repo you can't push
to ({.val {tr$repo_spec}})."
))
if (ui_nah("Do you really want to do this?")) {
ui_bullets(c("x" = "Cancelling."))
return(invisible())
}
}

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it's probably fine to let the GitHub error bubble up, and then we can add more user-friendly errors if we discover it's causing substantial confusion.

branch <- branch %||% git_default_branch_(cfg)

invisible(gh::gh(
Copy link
Member

Choose a reason for hiding this comment

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

What happens if you lock an already locked branch?

Copy link
Member Author

Choose a reason for hiding this comment

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

Looks like it's idempotent

"PUT /repos/{owner}/{repo}/branches/{branch}/protection",
owner = repo$repo_owner,
repo = repo$repo_name,
Comment on lines +321 to +322
Copy link
Member

Choose a reason for hiding this comment

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

We usually do a different move to create these gh::gh() calls for the target repo, but I am happy to do this consistency pass myself before we merge.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks!

branch = branch,
# required parameters
required_status_checks = NA,
enforce_admins = TRUE,
required_pull_request_reviews = NA,
restrictions = NA,
# paramter that actually does what we want
lock_branch = TRUE
))
}

#' @export
#' @rdname gh_lock_branch
gh_unlock_branch <- function(branch = NULL) {
cfg <- github_remote_config(github_get = TRUE)
repo <- target_repo(cfg)
branch <- branch %||% git_default_branch_(cfg)

invisible(gh::gh(
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection",
owner = repo$repo_owner,
repo = repo$repo_name,
branch = branch
))
}
2 changes: 2 additions & 0 deletions R/release.R
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,15 @@ release_checklist <- function(version, on_cran, target_repo = NULL) {
"",
"Submit to CRAN:",
"",
todo("`usethis::gh_lock_branch()`"),
todo("`usethis::use_version('{type}')`"),
todo("`devtools::submit_cran()`"),
todo("Approve email"),
"",
"Wait for CRAN...",
"",
todo("Accepted :tada:"),
todo("`usethis::gh_unlock_branch()`"),
todo("Finish & publish blog post", type != "patch"),
todo("Add link to blog post in pkgdown news menu", type != "patch"),
todo("`usethis::use_github_release()`"),
Expand Down
1 change: 1 addition & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ reference:
- starts_with("use_github")
- git_sitrep
- create_github_token
- gh_lock_branch
- gh_token_help
- git_vaccinate
- use_git_config
Expand Down
24 changes: 24 additions & 0 deletions man/gh_lock_branch.Rd

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

2 changes: 1 addition & 1 deletion man/usethis-package.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/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@

Submit to CRAN:

* [ ] `usethis::gh_lock_branch()`
* [ ] `usethis::use_version('minor')`
* [ ] `devtools::submit_cran()`
* [ ] Approve email

Wait for CRAN...

* [ ] Accepted :tada:
* [ ] `usethis::gh_unlock_branch()`
* [ ] Finish & publish blog post
* [ ] Add link to blog post in pkgdown news menu
* [ ] `usethis::use_github_release()`
Expand Down Expand Up @@ -61,13 +63,15 @@

Submit to CRAN:

* [ ] `usethis::gh_lock_branch()`
* [ ] `usethis::use_version('patch')`
* [ ] `devtools::submit_cran()`
* [ ] Approve email

Wait for CRAN...

* [ ] Accepted :tada:
* [ ] `usethis::gh_unlock_branch()`
* [ ] `usethis::use_github_release()`
* [ ] `usethis::use_dev_version(push = TRUE)`
* [ ] `usethis::use_news_md()`
Expand All @@ -94,13 +98,15 @@

Submit to CRAN:

* [ ] `usethis::gh_lock_branch()`
* [ ] `usethis::use_version('major')`
* [ ] `devtools::submit_cran()`
* [ ] Approve email

Wait for CRAN...

* [ ] Accepted :tada:
* [ ] `usethis::gh_unlock_branch()`
* [ ] Finish & publish blog post
* [ ] Add link to blog post in pkgdown news menu
* [ ] `usethis::use_github_release()`
Expand Down Expand Up @@ -149,13 +155,15 @@

Submit to CRAN:

* [ ] `usethis::gh_lock_branch()`
* [ ] `usethis::use_version('major')`
* [ ] `devtools::submit_cran()`
* [ ] Approve email

Wait for CRAN...

* [ ] Accepted :tada:
* [ ] `usethis::gh_unlock_branch()`
* [ ] Finish & publish blog post
* [ ] Add link to blog post in pkgdown news menu
* [ ] `usethis::use_github_release()`
Expand Down Expand Up @@ -185,13 +193,15 @@

Submit to CRAN:

* [ ] `usethis::gh_lock_branch()`
* [ ] `usethis::use_version('major')`
* [ ] `devtools::submit_cran()`
* [ ] Approve email

Wait for CRAN...

* [ ] Accepted :tada:
* [ ] `usethis::gh_unlock_branch()`
* [ ] Finish & publish blog post
* [ ] Add link to blog post in pkgdown news menu
* [ ] `usethis::use_github_release()`
Expand Down
Loading