From 9c35f13217226867bf1dc92be31370cd22638d6a Mon Sep 17 00:00:00 2001 From: Lorenz Walthert <10477073+lorenzwalthert@users.noreply.github.com> Date: Fri, 2 Oct 2026 19:10:11 +0200 Subject: [PATCH 1/4] feat: add pre-commit.ci lite as default CI option --- R/setup.R | 79 +++++++++--- R/zzz.R | 2 +- inst/WORDLIST | 6 + inst/pre-commit-lite-autoupdate.yaml | 29 +++++ inst/pre-commit-lite.yaml | 19 +++ man/use_ci.Rd | 36 ++++-- man/use_precommit.Rd | 34 +++-- vignettes/.gitignore | 2 + vignettes/ci.Rmd | 184 ++++++++++++--------------- 9 files changed, 247 insertions(+), 144 deletions(-) create mode 100644 inst/pre-commit-lite-autoupdate.yaml create mode 100644 inst/pre-commit-lite.yaml diff --git a/R/setup.R b/R/setup.R index 5b57833ed..0495347f2 100644 --- a/R/setup.R +++ b/R/setup.R @@ -9,8 +9,8 @@ #' to fail if there are such hooks. "allow" will run these along with #' pre-commit. "remove" will delete them. #' @param open Whether or not to open `.pre-commit-config.yaml` after -#' it's been placed in your repo as well as -#' [pre-commit.ci](https://pre-commit.ci) (if `ci = "native"`). The default is +#' it's been placed in your repo, and the CI service's setup page +#' (see `open` in [use_ci()] for details). The default is #' `TRUE` when working in RStudio. #' @param autoupdate Whether or not to run [autoupdate()] as part of this #' function call. @@ -46,7 +46,7 @@ use_precommit <- function(config_source = getOption("precommit.config_source"), legacy_hooks = "forbid", open = rstudioapi::isAvailable(), install_hooks = TRUE, - ci = getOption("precommit.ci", "native"), + ci = getOption("precommit.ci", "lite"), autoupdate = install_hooks, root = here::here()) { rlang::arg_match(legacy_hooks, c("forbid", "allow", "remove")) @@ -70,18 +70,32 @@ use_precommit <- function(config_source = getOption("precommit.config_source"), #' Use continuous integration with pre-commit #' #' Sets up continuous integration, or prompts the user to do it manually. +#' See `vignette("ci", package = "precommit")` for a detailed comparison of +#' the available options. #' -#' @param ci Specifies which continuous integration service to use. See -#' `vignette("ci", package = "precommit")` for details. Defaults to -#' `getOption("precommit.ci", "native")`, which is set to -#' `"native"` on package loading (if unset). `"native"` sets up -#' [pre-commit.ci](https://pre-commit.ci). Alternatively, `"gha"` can be used -#' to set up [GitHub Actions](https://github.com/features/actions). Set value -#' to `NA` if you don't want to use a continuous integration. -#' @param force Whether or not to overwrite an existing ci config file (only -#' relevant for `ci = "gha"`). -#' @param open Whether or not to open [pre-commit.ci](https://pre-commit.ci) -#' (if `ci = "native"`). The default is `TRUE` when working in RStudio. +#' @param ci Specifies which continuous integration service to use. Defaults to +#' `getOption("precommit.ci", "lite")`, which is set to `"lite"` on package +#' loading (if unset). Valid values: +#' +#' - `"lite"`: Sets up [pre-commit.ci lite](https://github.com/apps/pre-commit-ci-lite), +#' a GitHub App that runs hooks on GitHub Actions and auto-fixes PRs. +#' Copies two workflow files to `.github/workflows/` and opens the app +#' installation page. **Recommended default.** +#' - `"native"`: Sets up the fully managed [pre-commit.ci](https://pre-commit.ci) +#' service. No workflow files are added; the user is prompted to +#' authenticate via the browser. +#' - `"gha"`: Sets up a self-contained +#' [GitHub Actions](https://github.com/features/actions) workflow copied +#' to `.github/workflows/pre-commit.yaml`. Auto-fixing requires additional +#' credential setup. +#' - `NA`: Skip CI setup entirely. +#' +#' @param force Whether or not to overwrite existing CI workflow files (only +#' relevant for `ci = "lite"` and `ci = "gha"`). +#' @param open Whether or not to open the CI service's setup page in the +#' browser (`ci = "lite"` opens the GitHub App page; +#' `ci = "native"` opens [pre-commit.ci](https://pre-commit.ci)). +#' The default is `TRUE` when working in RStudio. #' @inheritParams fallback_doc #' @export use_ci <- function(ci = getOption("precommit.ci", "native"), @@ -110,6 +124,41 @@ use_ci <- function(ci = getOption("precommit.ci", "native"), "run on pull requests. If workflow fails, please file an issue in ", "{.code https://github.com/lorenzwalthert/precommit}." )) + } else if (ci == "lite") { + dest <- fs::path(root, ".github/workflows/pre-commit.yml") + dest_autoupdate <- fs::path(root, ".github/workflows/pre-commit-autoupdate.yml") + fs::dir_create(fs::path_dir(dest)) + fs::file_copy( + system.file("pre-commit-lite.yaml", package = "precommit"), + dest, + overwrite = force + ) + fs::file_copy( + system.file("pre-commit-lite-autoupdate.yaml", package = "precommit"), + dest_autoupdate, + overwrite = force + ) + cli::cli_alert_success(paste0( + "Added pre-commit.ci lite workflow templates to ", + "{.code .github/workflows/pre-commit.yml} and ", + "{.code .github/workflows/pre-commit-autoupdate.yml}." + )) + cli::cli_ul(c( + paste0( + "Install the {.href [pre-commit.ci lite GitHub App](https://github.com/apps/pre-commit-ci-lite)} ", + "on your repository to enable automatic fixing of pull requests, ", + "then come back to complete the set-up process." + ), + paste0( + "To enable monthly autoupdates of hook versions, go to ", + "{.emph Settings \u2192 Actions \u2192 General \u2192 Workflow permissions} and enable ", + "{.emph Allow GitHub Actions to create and approve pull requests}." + ) + )) + Sys.sleep(2) + if (open) { + utils::browseURL("https://github.com/apps/pre-commit-ci-lite") + } } else if (ci == "native") { cli::cli_ul(paste0( "Sign in with GitHub to authenticate {.url https://pre-commit.ci} and ", @@ -121,7 +170,7 @@ use_ci <- function(ci = getOption("precommit.ci", "native"), } } else { rlang::abort( - 'Argument `ci` must be one of `"native"` (default), `"gha"` or `NULL`.' + 'Argument `ci` must be one of `"native"` (default), `"lite"`, `"gha"` or `NULL`.' ) } config <- readLines(fs::path(root, ".pre-commit-config.yaml")) diff --git a/R/zzz.R b/R/zzz.R index 0fd482f3a..3398f4bc5 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -3,7 +3,7 @@ op.precommit <- list( precommit.executable = path_derive_precommit_exec(), precommit.block_install_hooks = FALSE, - precommit.ci = "native" + precommit.ci = "lite" ) toset <- !(names(op.precommit) %in% names(op)) if (any(toset)) options(op.precommit[toset]) diff --git a/inst/WORDLIST b/inst/WORDLIST index c8a3f959d..1d58a8d37 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -142,6 +142,7 @@ prec precommit precommithooks proj +PRs purrr py qmd @@ -236,3 +237,8 @@ yaml yihui yml Za +️ +⚠ +✅ +❌ +🔜 diff --git a/inst/pre-commit-lite-autoupdate.yaml b/inst/pre-commit-lite-autoupdate.yaml new file mode 100644 index 000000000..9a9ac86c8 --- /dev/null +++ b/inst/pre-commit-lite-autoupdate.yaml @@ -0,0 +1,29 @@ +on: + schedule: + - cron: '0 0 1 * *' # monthly, 1st of each month + workflow_dispatch: + +jobs: + autoupdate: + runs-on: ubuntu-latest + # Requires: Settings → Actions → General → Workflow permissions → + # "Allow GitHub Actions to create and approve pull requests" + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: 3.x + - run: pip install pre-commit && pre-commit autoupdate + - uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11 + id: create-pr + with: + commit-message: 'pre-commit autoupdate' + title: 'pre-commit autoupdate' + branch: pre-commit-autoupdate + - name: Check PR creation result + if: failure() + run: | + echo "::error::Failed to create pull request. If you see a permissions error, go to Settings → Actions → General → Workflow permissions and enable 'Allow GitHub Actions to create and approve pull requests'." diff --git a/inst/pre-commit-lite.yaml b/inst/pre-commit-lite.yaml new file mode 100644 index 000000000..c794857fa --- /dev/null +++ b/inst/pre-commit-lite.yaml @@ -0,0 +1,19 @@ +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + env: + RENV_CONFIG_CACHE_ENABLED: 'FALSE' + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: 3.x + - uses: r-lib/actions/setup-r@f9a764fea8d5c63df6ef9a5c7795bf7deb5d7e05 # v2.14.0 + - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 + - uses: pre-commit-ci/lite-action@062bca0919bc9d6e66755cc05074b70c77e111fc # v1.2.0 + if: always() diff --git a/man/use_ci.Rd b/man/use_ci.Rd index 677f53da7..830eda2c6 100644 --- a/man/use_ci.Rd +++ b/man/use_ci.Rd @@ -12,22 +12,36 @@ use_ci( ) } \arguments{ -\item{ci}{Specifies which continuous integration service to use. See -\code{vignette("ci", package = "precommit")} for details. Defaults to -\code{getOption("precommit.ci", "native")}, which is set to -\code{"native"} on package loading (if unset). \code{"native"} sets up -\href{https://pre-commit.ci}{pre-commit.ci}. Alternatively, \code{"gha"} can be used -to set up \href{https://github.com/features/actions}{GitHub Actions}. Set value -to \code{NA} if you don't want to use a continuous integration.} +\item{ci}{Specifies which continuous integration service to use. Defaults to +\code{getOption("precommit.ci", "lite")}, which is set to \code{"lite"} on package +loading (if unset). Valid values: +\itemize{ +\item \code{"lite"}: Sets up \href{https://github.com/apps/pre-commit-ci-lite}{pre-commit.ci lite}, +a GitHub App that runs hooks on GitHub Actions and auto-fixes PRs. +Copies two workflow files to \verb{.github/workflows/} and opens the app +installation page. \strong{Recommended default.} +\item \code{"native"}: Sets up the fully managed \href{https://pre-commit.ci}{pre-commit.ci} +service. No workflow files are added; the user is prompted to +authenticate via the browser. +\item \code{"gha"}: Sets up a self-contained +\href{https://github.com/features/actions}{GitHub Actions} workflow copied +to \code{.github/workflows/pre-commit.yaml}. Auto-fixing requires additional +credential setup. +\item \code{NA}: Skip CI setup entirely. +}} -\item{force}{Whether or not to overwrite an existing ci config file (only -relevant for \code{ci = "gha"}).} +\item{force}{Whether or not to overwrite existing CI workflow files (only +relevant for \code{ci = "lite"} and \code{ci = "gha"}).} -\item{open}{Whether or not to open \href{https://pre-commit.ci}{pre-commit.ci} -(if \code{ci = "native"}). The default is \code{TRUE} when working in RStudio.} +\item{open}{Whether or not to open the CI service's setup page in the +browser (\code{ci = "lite"} opens the GitHub App page; +\code{ci = "native"} opens \href{https://pre-commit.ci}{pre-commit.ci}). +The default is \code{TRUE} when working in RStudio.} \item{root}{The path to the root directory of your project.} } \description{ Sets up continuous integration, or prompts the user to do it manually. +See \code{vignette("ci", package = "precommit")} for a detailed comparison of +the available options. } diff --git a/man/use_precommit.Rd b/man/use_precommit.Rd index b2b5c1f0b..0778a658c 100644 --- a/man/use_precommit.Rd +++ b/man/use_precommit.Rd @@ -10,7 +10,7 @@ use_precommit( legacy_hooks = "forbid", open = rstudioapi::isAvailable(), install_hooks = TRUE, - ci = getOption("precommit.ci", "native"), + ci = getOption("precommit.ci", "lite"), autoupdate = install_hooks, root = here::here() ) @@ -22,8 +22,8 @@ config file will be hard-copied into \code{root}. If \code{NULL}, we check if \code{\link[rprojroot:find_package_root_file]{rprojroot::find_package_root_file()}}, and resort to an appropriate default config. See section 'Copying an existing config file'.} -\item{force}{Whether or not to overwrite an existing ci config file (only -relevant for \code{ci = "gha"}).} +\item{force}{Whether or not to overwrite existing CI workflow files (only +relevant for \code{ci = "lite"} and \code{ci = "gha"}).} \item{legacy_hooks}{How to treat hooks already in the repo which are not managed by pre-commit. "forbid", the default, will cause \code{use_precommit()} @@ -31,20 +31,30 @@ to fail if there are such hooks. "allow" will run these along with pre-commit. "remove" will delete them.} \item{open}{Whether or not to open \code{.pre-commit-config.yaml} after -it's been placed in your repo as well as -\href{https://pre-commit.ci}{pre-commit.ci} (if \code{ci = "native"}). The default is +it's been placed in your repo, and the CI service's setup page +(see \code{open} in \code{\link[=use_ci]{use_ci()}} for details). The default is \code{TRUE} when working in RStudio.} \item{install_hooks}{Whether to install environments for all available hooks. If \code{FALSE}, environments are installed with first commit.} -\item{ci}{Specifies which continuous integration service to use. See -\code{vignette("ci", package = "precommit")} for details. Defaults to -\code{getOption("precommit.ci", "native")}, which is set to -\code{"native"} on package loading (if unset). \code{"native"} sets up -\href{https://pre-commit.ci}{pre-commit.ci}. Alternatively, \code{"gha"} can be used -to set up \href{https://github.com/features/actions}{GitHub Actions}. Set value -to \code{NA} if you don't want to use a continuous integration.} +\item{ci}{Specifies which continuous integration service to use. Defaults to +\code{getOption("precommit.ci", "lite")}, which is set to \code{"lite"} on package +loading (if unset). Valid values: +\itemize{ +\item \code{"lite"}: Sets up \href{https://github.com/apps/pre-commit-ci-lite}{pre-commit.ci lite}, +a GitHub App that runs hooks on GitHub Actions and auto-fixes PRs. +Copies two workflow files to \verb{.github/workflows/} and opens the app +installation page. \strong{Recommended default.} +\item \code{"native"}: Sets up the fully managed \href{https://pre-commit.ci}{pre-commit.ci} +service. No workflow files are added; the user is prompted to +authenticate via the browser. +\item \code{"gha"}: Sets up a self-contained +\href{https://github.com/features/actions}{GitHub Actions} workflow copied +to \code{.github/workflows/pre-commit.yaml}. Auto-fixing requires additional +credential setup. +\item \code{NA}: Skip CI setup entirely. +}} \item{autoupdate}{Whether or not to run \code{\link[=autoupdate]{autoupdate()}} as part of this function call.} diff --git a/vignettes/.gitignore b/vignettes/.gitignore index 3c0f6bdf8..5bc673b7b 100644 --- a/vignettes/.gitignore +++ b/vignettes/.gitignore @@ -1,2 +1,4 @@ +**/*.quarto_ipynb *.R *.html +/.quarto/ diff --git a/vignettes/ci.Rmd b/vignettes/ci.Rmd index 5a6be7cd9..f9b5008bd 100644 --- a/vignettes/ci.Rmd +++ b/vignettes/ci.Rmd @@ -1,7 +1,7 @@ --- title: "Continuous Integration" description: > - Understand how pre-commit can be used in a continuous integration settting. + Understand how pre-commit can be used in a continuous integration setting. output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Continuous Integration} @@ -15,130 +15,104 @@ editor_options: # Setting up CI When initializing pre-commit in your repo with -`precommit::use_precommit()`, you can specify the Continuous integration -provider with `ci = "native"` if you want to use -[pre-commit.ci](https://pre-commit.ci) or `ci = "gha"` if you want to -use GitHub Actions. For existing repos, use `precommit::use_ci()`. +`precommit::use_precommit()`, you can specify the continuous integration +provider with the `ci` argument: -Pre-commit will run the hooks on all files, so instead of pushing, -waiting and fixing issues locally, we recommend that you fix all -problems before pushing by invoking pre-commit (roughly) the same way as -it happens in the CI, which is described in the next section. +- `ci = "lite"` (default) sets up + [pre-commit.ci lite](https://github.com/apps/pre-commit-ci-lite), a + GitHub Actions workflow leveraging the pre-commit ci lite action by the + creator of pre-commit. +- `ci = "native"` sets up [pre-commit.ci](https://pre-commit.ci), a + fully managed service by the creator of pre-commit. +- `ci = "gha"` sets up a self-contained + [GitHub Actions](https://github.com/features/actions) workflow relaying + on an action by the creator of pre-commit in maintenance mode. + +For existing repos, use `precommit::use_ci()` directly. + +Pre-commit runs hooks on all files in CI, so we recommend fixing all +problems locally before pushing by running roughly the same command as +CI does — see the next section. # Emulate a CI run locally -In the CI run, a command roughly equivalent to the following will be ran -from the command line: +In CI, a command roughly equivalent to the following runs from the +command line: ``` bash pre-commit run --all-files ``` -If you get an error and `pre-commit` is not on your `$PATH` (e.g. -because you installed with `precommit::install_precommit()`), you can -locate the executable from R with +If `pre-commit` is not on your `$PATH` (e.g. because you installed it +with `precommit::install_precommit()`), locate the executable from R: ``` r precommit::path_pre_commit_exec() #> "/usr/local/bin/pre-commit" ``` -And run the command in your bash terminal like this: +Then run in your terminal: ``` bash /usr/local/bin/pre-commit run --all-files ``` -Then fix the problems, stage the files and re-try until the command -succeeds without more errors. +Fix any problems, stage the files, and re-run until the command +succeeds. # Comparison -Next, we quickly introduce the two options. We recommend -[pre-commit.ci](https://pre-commit.ci), but you might have to skip the -roxygenize hook in the ci run under certain circumstances as explained -below. - -## pre-commit.ci - -**Pros:** - -- by the creator of pre-commit. Certain CI settings in - `.pre-commit-config.yaml` [are supported](https://pre-commit.ci). -- actively developed. -- very fast. -- will at some point also be supported for repos hosted outside of - GitHub. -- No maintenance effort for you. -- No additional file in the repo. - -**Cons:** - -- You need to authenticate the [pre-commit.ci](https://pre-commit.ci) - App in GitHub. - -- Limitations for the roxygenize hook: - - - {roxygen2} [requires loading your package for the roxygenize - hook](https://github.com/r-lib/roxygen2/issues/771), which means - you must list all dependencies of the package explicitly in - `.pre-commit-config.yaml` under `id: roxygenize`. You can - generate the required code with - `precommit::snippet_generate('additional-deps-roxygenize')`. - This is also required to run the hook locally. - - There is a [timeout of 120s for building a hook - environment](https://github.com/pre-commit-ci/runner-image/issues/93#issuecomment-922505301), - which might not be enough time to build the hook environment for - the roxygenize hook (if you package has many dependencies). This - holds for local and remote execution. - - \`System dependencies are not supported. In particular, since - {roxygen2} [requires loading your package for the roxygenize - hook](https://github.com/r-lib/roxygen2/issues/771), this hook - will fail if your package has system dependencies or any of your - package's dependencies has system dependencies that are not - shipped with the package. - -- To overcome the above limitations, you can: - - - Disable the hook completely (by commenting out the respective - lines in `.pre-commit-config.yaml`). - - Use GitHub Actions as a CI provider instead with - `precommit::use_ci("gha")`. - - Skip it on CI as described below - - ``` yaml - ci: - skip: [roxygenize] - ``` - -**Customization:** - -Please see the documentation of [pre-commit.ci](https://pre-commit.ci/) -on whether or not to auto-fix problems as well as other configuration -options. - -## GitHub Actions - -**Pros:** - -- more control over environment, e.g. system dependencies. -- No new authentication needed. -- If your package has system dependencies and you want to use the - roxygenize hook, you can install them. - -**Cons:** - -- out-of-the-box action is in [maintenance only - mode](https://github.com/pre-commit/action) and less feature - complete than [pre-commit.ci](https://pre-commit.ci). For example, - if your hooks fail on first attempt, the corrections are committed - and pushed, but they won't trigger a new CI and you can't make them - do it without [exposing - credentials](https://github.com/pre-commit/action/pull/49). The only - way is to close and re-open the PR. -- No configuration options such as hook skipping supported that - [pre-commit.ci](https://pre-commit.ci) supports. -- You need to maintain the workflow file with a lot of boilerplate - code and when GitHub changes the syntax, you need to adapt it to - prevent failing builds. -- You'll have one additional file per provider (e.g. GitHub, Gitlab). +| Feature | `"lite"` | `"native"` | `"gha"` | +|---|:---:|:---:|:---:| +| Auto-fixes PRs | ✅ | ✅ | ⚠️ [^1] | +| Runs on GitHub Actions | ✅ | ❌ | ✅ | +| System dependency support | ✅ | ❌ | ✅ | +| Roxygenize hook support | ✅ | ⚠️ [^2] | ✅ | +| No workflow files in repo | ❌ | ✅ | ❌ | +| Periodic autoupdate PRs | ✅ [^3] | ✅ | ❌ | +| Requires GitHub App install | ✅ | ✅ | ❌ | +| Works outside GitHub | ❌ | 🔜 | ❌ | +| Workflow pinned to SHA | ✅ | n/a | ❌ | + +[^1]: `"gha"` pushes fix commits but they do not trigger a new CI run + without exposing credentials. You need to close and re-open the PR + to re-trigger. `"lite"` solves this via the GitHub App. + +[^2]: The roxygenize hook has limitations on pre-commit.ci: all package + dependencies must be listed explicitly under + `additional_dependencies`, there is a 120s build timeout, and system + dependencies are not supported. See below for workarounds. + +[^3]: Monthly autoupdate PRs require enabling *Allow GitHub Actions to + create and approve pull requests* in *Settings → Actions → General → + Workflow permissions*. + +We recommend **`"lite"`** as the default. It combines auto-fixing (like +`"native"`) with GitHub Actions flexibility (like `"gha"`), and the +workflow files are SHA-pinned for supply-chain security. + +## Notes on the roxygenize hook with `"native"` + +[pre-commit.ci](https://pre-commit.ci) has three limitations relevant to +the roxygenize hook: + +- {roxygen2} [requires loading your + package](https://github.com/r-lib/roxygen2/issues/771), so all + dependencies must be listed explicitly under `additional_dependencies` + in `.pre-commit-config.yaml`. Generate the required snippet with + `precommit::snippet_generate('additional-deps-roxygenize')`. +- There is a [120s timeout for building hook + environments](https://github.com/pre-commit-ci/runner-image/issues/93#issuecomment-922505301), + which may be exceeded for packages with many dependencies. +- System dependencies are not supported. + +To work around these, you can: + +- Disable the hook (comment out the relevant lines). +- Switch to `ci = "lite"` or `ci = "gha"`. +- Skip it on CI only: + +``` yaml +ci: + skip: [roxygenize] +``` From e73c65f8553e87febe71ef5dc3919b1d2f992481 Mon Sep 17 00:00:00 2001 From: Lorenz Walthert <10477073+lorenzwalthert@users.noreply.github.com> Date: Wed, 4 Nov 2026 21:16:16 +0100 Subject: [PATCH 2/4] fix: use 'lite' as default in use_ci() signature and error message --- .pre-commit-config.yaml | 2 +- R/setup.R | 4 ++-- man/use_ci.Rd | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 08df74b9f..8d123b8ac 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # R specific hooks: https://github.com/lorenzwalthert/precommit repos: - repo: https://github.com/lorenzwalthert/precommit - rev: v0.4.3.9034 + rev: v0.4.3.9033 hooks: - id: style-files args: [--style_pkg=styler, --style_fun=tidyverse_style, --cache-root=styler-perm] diff --git a/R/setup.R b/R/setup.R index 0495347f2..a3336f40f 100644 --- a/R/setup.R +++ b/R/setup.R @@ -98,7 +98,7 @@ use_precommit <- function(config_source = getOption("precommit.config_source"), #' The default is `TRUE` when working in RStudio. #' @inheritParams fallback_doc #' @export -use_ci <- function(ci = getOption("precommit.ci", "native"), +use_ci <- function(ci = getOption("precommit.ci", "lite"), force = FALSE, open = rstudioapi::isAvailable(), root = here::here()) { @@ -170,7 +170,7 @@ use_ci <- function(ci = getOption("precommit.ci", "native"), } } else { rlang::abort( - 'Argument `ci` must be one of `"native"` (default), `"lite"`, `"gha"` or `NULL`.' + 'Argument `ci` must be one of `"lite"` (default), `"native"`, `"gha"` or `NA`.' ) } config <- readLines(fs::path(root, ".pre-commit-config.yaml")) diff --git a/man/use_ci.Rd b/man/use_ci.Rd index 830eda2c6..75b9c1168 100644 --- a/man/use_ci.Rd +++ b/man/use_ci.Rd @@ -5,7 +5,7 @@ \title{Use continuous integration with pre-commit} \usage{ use_ci( - ci = getOption("precommit.ci", "native"), + ci = getOption("precommit.ci", "lite"), force = FALSE, open = rstudioapi::isAvailable(), root = here::here() From e6d8697fd74ffe1b5a17b40b70db818bb41eecf3 Mon Sep 17 00:00:00 2001 From: Lorenz Walthert <10477073+lorenzwalthert@users.noreply.github.com> Date: Wed, 4 Nov 2026 21:27:40 +0100 Subject: [PATCH 3/4] fix: handle existing lite workflow files gracefully and add tests --- R/setup.R | 7 +++++++ tests/testthat/test-setup.R | 26 +++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/R/setup.R b/R/setup.R index a3336f40f..7d813b2af 100644 --- a/R/setup.R +++ b/R/setup.R @@ -128,6 +128,13 @@ use_ci <- function(ci = getOption("precommit.ci", "lite"), dest <- fs::path(root, ".github/workflows/pre-commit.yml") dest_autoupdate <- fs::path(root, ".github/workflows/pre-commit-autoupdate.yml") fs::dir_create(fs::path_dir(dest)) + if (fs::file_exists(dest) && !force) { + cli::cli_alert_info(paste0( + "There is already a pre-commit.ci lite workflow file at ", + "{.code .github/workflows/pre-commit.yml}. Use {.code force = TRUE} to overwrite." + )) + return(invisible(NULL)) + } fs::file_copy( system.file("pre-commit-lite.yaml", package = "precommit"), dest, diff --git a/tests/testthat/test-setup.R b/tests/testthat/test-setup.R index 18685bb79..9e664e25a 100644 --- a/tests/testthat/test-setup.R +++ b/tests/testthat/test-setup.R @@ -94,6 +94,30 @@ test_that("Pre-commit CI GitHub Action template is parsable", { ) }) +test_that("Pre-commit CI lite setup works", { + local_test_setup( + git = FALSE, use_precommit = FALSE, package = TRUE, install_hooks = FALSE + ) + use_precommit_config( + root = getwd(), + open = FALSE, verbose = FALSE + ) + use_ci("lite", root = getwd(), open = FALSE) + expect_true(file_exists(".github/workflows/pre-commit.yml")) + expect_true(file_exists(".github/workflows/pre-commit-autoupdate.yml")) +}) + +test_that("Pre-commit CI lite workflow templates are parsable", { + expect_error( + yaml::read_yaml(system.file("pre-commit-lite.yaml", package = "precommit")), + NA + ) + expect_error( + yaml::read_yaml(system.file("pre-commit-lite-autoupdate.yaml", package = "precommit")), + NA + ) +}) + test_that("Pre-commit CI setup works", { local_test_setup( git = FALSE, use_precommit = FALSE, package = TRUE, install_hooks = FALSE @@ -102,7 +126,7 @@ test_that("Pre-commit CI setup works", { root = getwd(), open = FALSE, verbose = FALSE ) - use_ci(root = getwd(), open = FALSE) + use_ci("native", root = getwd(), open = FALSE) expect_false(file_exists(".github/workflows/pre-commit.yaml")) }) From e564659c3147b488de9b5355d87006dc7894dab1 Mon Sep 17 00:00:00 2001 From: Lorenz Walthert <10477073+lorenzwalthert@users.noreply.github.com> Date: Wed, 4 Nov 2026 21:28:58 +0100 Subject: [PATCH 4/4] fix: align gha and lite behavior when file exists and force = FALSE --- R/setup.R | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/R/setup.R b/R/setup.R index 7d813b2af..0e86dc3a8 100644 --- a/R/setup.R +++ b/R/setup.R @@ -113,6 +113,13 @@ use_ci <- function(ci = getOption("precommit.ci", "lite"), } else if (ci == "gha") { dest <- fs::path(root, ".github/workflows/pre-commit.yaml") fs::dir_create(fs::path_dir(dest)) + if (fs::file_exists(dest) && !force) { + cli::cli_alert_info(paste0( + "There is already a GitHub Actions workflow file at ", + "{.code .github/workflows/pre-commit.yaml}. Use {.code force = TRUE} to overwrite." + )) + return(invisible(NULL)) + } fs::file_copy( system.file("pre-commit-gha.yaml", package = "precommit"), dest,