diff --git a/.github/workflows/end-to-end.yml b/.github/workflows/end-to-end.yml new file mode 100644 index 000000000..b01257602 --- /dev/null +++ b/.github/workflows/end-to-end.yml @@ -0,0 +1,76 @@ +on: + push: + branches: + - master + pull_request: + branches: + - master + +name: end-2-end + +jobs: + end-2-end: + runs-on: macOS-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: r-lib/actions/setup-r@v1 + + - uses: actions/checkout@v2 + + - name: Query dependencies + run: | + install.packages('remotes') + saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) + writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") + shell: Rscript {0} + + - name: Cache R packages + uses: actions/cache@v2 + with: + path: ${{ env.R_LIBS_USER }} + key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} + restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- + + - name: Install dependencies + run: | + remotes::install_deps(dependencies = TRUE) + remotes::install_cran('yaml') + shell: Rscript {0} + + - name: Install package + run: R CMD INSTALL . + + - name: Prepare pre-commit + run: | + config_name <- ".pre-commit-config.yaml" + ref_config <- file.path("tests", "testthat", "reference-objects", config_name) + len_declared <- length(yaml::read_yaml(".pre-commit-hooks.yaml")) + len_testing <- length(yaml::read_yaml(ref_config)$repos[[1]]$hooks) + if (len_declared != len_testing) { + rlang::abort("You don't test all hooks. Add them to `test_path('reference-objects/.pre-commit-config.yaml')`") + } + fs::file_delete(config_name) + fs::file_copy(ref_config, config_name) + shell: Rscript {0} + - name: Update Hook revision to current push + run: | + # hacky, maybe can use pre-commit try-repo? + # https://stackoverflow.com/questions/30871868/sed-replace-first-occurence-in-place-with-big-files + sed -i '' -e "1,/rev:.*/{s/rev:.*/rev: $GITHUB_SHA/;}" .pre-commit-config.yaml + + - name: Run pre-commit + run: | + echo 'one' >> README.Rmd + echo 'one' >> codemeta.json + echo 'one' >> README.md + echo "#' some code\n#'\n#' @param here.\n#' @name somethings\nNULL" > R/test.R # overwrite if anything there + brew install pre-commit + pre-commit install + pre-commit run --files R/test.R + pre-commit run --files DESCRIPTION + git add README* + pre-commit run --files README.Rmd + git reset HEAD --hard # restore initial state + env: + SKIP: consistent-release-tag diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1291701d8..d9519e445 100755 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,7 +39,7 @@ repos: (.*/|)WORDLIST| \.github/workflows/.*| data/.*| - inst/bin/.*| + inst/hooks/.*| inst/pre-commit-.*| )$ - id: readme-rmd-rendered @@ -56,17 +56,17 @@ repos: hooks: - id: consistent-release-tag name: consistent-release-tag - entry: inst/consistent-release-tag + entry: inst/hooks/local/consistent-release-tag.R language: script stages: [commit, push] - id: hooks-config-to-inst name: hooks-config-to-inst - entry: inst/hooks-config-to-inst + entry: inst/hooks/local/hooks-config-to-inst.R language: script stages: [commit, push] - id: spell-check-exclude-to-config name: spell-check-exclude-to-config - entry: inst/spell-check-exclude-to-config + entry: inst/hooks/local/spell-check-exclude-to-config.R language: script stages: [commit, push] - id: forbid-to-commit @@ -78,6 +78,6 @@ repos: - id: spell-check-ordered-exclude name: Ordered regex pattern for spell-check exclusion description: Ensure alphabetical order in `exclude:` key of spell check. - entry: inst/spell-check-ordered-exclude.R + entry: inst/hooks/local/spell-check-ordered-exclude.R language: script files: '^(.*/|)\.?pre-commit-config.*\.yaml$' diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index c984df30b..a5b3c41d3 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -1,7 +1,7 @@ - id: roxygenize name: roxygenize description: run roxygen2::roxygenize() - entry: inst/bin/roxygenize + entry: inst/hooks/exported/roxygenize.R language: script files: '^(R|man)/' require_serial: true @@ -9,14 +9,14 @@ - id: use-tidy-description name: use-tidy-description description: run usethis::use_tidy_description() - entry: inst/bin/use-tidy-description + entry: inst/hooks/exported/use-tidy-description.R language: script files: '^DESCRIPTION$' minimum_pre_commit_version: "2.13.0" - id: style-files name: style-files description: style files with styler - entry: inst/bin/style-files + entry: inst/hooks/exported/style-files.R language: script files: '(\.R|\.Rmd|\.Rnw|\.r|\.rmd|\.rnw)$' exclude: 'renv/activate\.R' @@ -24,35 +24,35 @@ - id: no-browser-statement name: no-browser-statement description: check if a .R file contains a `browser()` statement - entry: inst/bin/no-browser-statement + entry: inst/hooks/exported/no-browser-statement.R language: script files: '\.[rR]$' minimum_pre_commit_version: "2.13.0" - id: parsable-R name: parsable-R description: check if a .R file is parsable - entry: inst/bin/parsable-R + entry: inst/hooks/exported/parsable-R.R language: script files: '\.[rR]$' minimum_pre_commit_version: "2.13.0" - id: readme-rmd-rendered name: readme-rmd-rendered description: make sure README.Rmd hasn't been edited more recently than README.md - entry: inst/bin/readme-rmd-rendered + entry: inst/hooks/exported/readme-rmd-rendered language: script files: 'README\.[Rr]?md$' minimum_pre_commit_version: "2.13.0" - id: codemeta-description-updated name: codemeta-description-updated description: make sure codemeta.json is in sync with DESCRIPTION. It should be run after use-tidy-description. - entry: inst/bin/codemeta-description-updated + entry: inst/hooks/exported/codemeta-description-updated language: script files: '^DESCRIPTION$' minimum_pre_commit_version: "2.13.0" - id: spell-check name: spell-check description: perform a spell check with spelling::spell_check_files() - entry: inst/bin/spell-check + entry: inst/hooks/exported/spell-check.R language: script exclude: > (?x)^( @@ -86,7 +86,7 @@ - id: deps-in-desc name: deps-in-desc description: Check if dependencies that can be parsed from code are in DESCRIPTION. - entry: inst/bin/deps-in-desc + entry: inst/hooks/exported/deps-in-desc.R language: script files: '(\.[rR]profile|\.R|\.Rmd|\.Rnw|\.r|\.rmd|\.rnw)$' exclude: 'renv/activate\.R' @@ -94,7 +94,7 @@ - id: lintr name: lintr description: check if a .R file is lint free (using lintr) - entry: inst/bin/lintr + entry: inst/hooks/exported/lintr.R language: script files: '\.[rR]$' exclude: 'renv/activate\.R' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5f555abd0..26c961fa3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ This repo uses the [tic](https://github.com/ropenscilabs/tic) package for CI. To create a new hook, have a look at the [official documentation](https://pre-commit.com/#new-hooks) on creating new hooks, then have a look -at existing hooks in this repo. The actual executables are defined in [`inst/bin/`](https://github.com/lorenzwalthert/precommit/tree/master/inst/bin). In +at existing hooks in this repo. The actual executables are defined in [`inst/hooks/`](https://github.com/lorenzwalthert/precommit/tree/master/inst/hooks). In the script, you can expect the passed command line arguments to be all options, finally the files that should be processed with the hook. diff --git a/NEWS.md b/NEWS.md index 0464ddce3..7d4fca3c8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -56,6 +56,7 @@ depending on whether or not you previously used pre-commit. - The `deps-in-desc` hook now points to the hook argument `--allow_private_imports` when the hook fails due to private imports (#254). - roxygenize hook is now fully tested (#267). +- Hook scripts were relocated and R hooks now have a file extension (#280). # precommit v0.1.3 diff --git a/R/testing.R b/R/testing.R index 7226fce08..ce34a6d74 100644 --- a/R/testing.R +++ b/R/testing.R @@ -16,7 +16,8 @@ #' the message we expect. To check changed file content, we set `error_msg` to #' `NA`. #' -#' @param hook_name The name of the hook in `bin/`. +#' @param hook_name The name of the hook in `inst/hooks/exported/`, without +#' file extension. #' @param file_name The file to test in `tests/in` (without extension). Can be #' a named vector of length one where the name is the target location relative #' to the temporary location and the value is the source of the file. @@ -41,10 +42,13 @@ run_test <- function(hook_name, artifacts = NULL, file_transformer = function(files) files, env = character()) { - path_executable <- system.file( - fs::path("bin", hook_name), + path_executable <- fs::dir_ls(system.file( + fs::path("hooks", "exported"), package = "precommit" - ) + ), regexp = paste0("/", hook_name)) + if (length(path_executable) != 1) { + rlang::abort("Failed to derive hook path") + } path_candidate <- paste0(testthat::test_path("in", file_name), suffix) %>% ensure_named(names(file_name), fs::path_file) run_test_impl( diff --git a/inst/WORDLIST b/inst/WORDLIST index b8752d708..360800d12 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -123,6 +123,7 @@ RStudio rstudioapi saveCache seealso +SHA stderr stdout sterr diff --git a/inst/bin/codemeta-description-updated b/inst/hooks/exported/codemeta-description-updated similarity index 73% rename from inst/bin/codemeta-description-updated rename to inst/hooks/exported/codemeta-description-updated index 884478656..fc692923e 100755 --- a/inst/bin/codemeta-description-updated +++ b/inst/hooks/exported/codemeta-description-updated @@ -1,6 +1,6 @@ #!/bin/bash -# adapted from https://github.com/lorenzwalthert/precommit/blob/f4413cfe6282c84f7176160d06e1560860c8bd3d/inst/bin/readme-rmd-rendered +# adapted from https://github.com/lorenzwalthert/precommit/blob/f4413cfe6282c84f7176160d06e1560860c8bd3d/inst/hooks/exported/readme-rmd-rendered if [[ DESCRIPTION -nt codemeta.json ]] then diff --git a/inst/bin/deps-in-desc b/inst/hooks/exported/deps-in-desc.R similarity index 91% rename from inst/bin/deps-in-desc rename to inst/hooks/exported/deps-in-desc.R index 157b3e4a0..98349499b 100755 --- a/inst/bin/deps-in-desc +++ b/inst/hooks/exported/deps-in-desc.R @@ -1,12 +1,12 @@ #!/usr/bin/env Rscript -'Ensure all dependencies of the form pkg::fun are in DESCRIPTION +"Ensure all dependencies of the form pkg::fun are in DESCRIPTION Usage: deps-in-desc [--allow_private_imports] ... Options: --allow_private_imports Whether or not to allow the use of ::: on imported functions. -' -> doc +" -> doc pre_installed <- c( "base", "boot", "class", "cluster", "codetools", "compiler", "datasets", "foreign", "graphics", "grDevices", "grid", "KernSmooth", @@ -32,8 +32,8 @@ deps_in_desc <- function(file, arguments) { cat( "Not all packages used in your code are listed in DESCRIPTION. ", "The following are missing in file `", file, "`: ", - paste(unregistered, collapse = ", "), ".\n", - "You can add them with `usethis::use_package()` or ", + paste(unregistered, collapse = ", "), ".\n", + "You can add them with `usethis::use_package()` or ", "`usethis::use_dev_package()`.\n", sep = "" ) @@ -53,10 +53,10 @@ deps_in_desc <- function(file, arguments) { paste0(file, collapse = ", "), "\n\n", "If you still think `:::` is a good idea, you can ", "allow private imports in your `.pre-commit-config.yaml` like this: - + - id: deps-in-desc args: [--allow_private_imports] - + ", sep = "" ) diff --git a/inst/bin/lintr b/inst/hooks/exported/lintr.R similarity index 100% rename from inst/bin/lintr rename to inst/hooks/exported/lintr.R diff --git a/inst/bin/no-browser-statement b/inst/hooks/exported/no-browser-statement.R similarity index 84% rename from inst/bin/no-browser-statement rename to inst/hooks/exported/no-browser-statement.R index 43cfd661a..88dcebd18 100755 --- a/inst/bin/no-browser-statement +++ b/inst/hooks/exported/no-browser-statement.R @@ -2,10 +2,10 @@ files <- commandArgs(trailing = TRUE) no_browser_statement <- function(path) { - pd <- getParseData(parse(path, keep.source = TRUE)) + pd <- getParseData(parse(path, keep.source = TRUE)) if (any(pd$text[pd$token == "SYMBOL_FUNCTION_CALL"] == "browser")) { stop("File `", path, "` contains a `browser()` statement.", call. = FALSE) - } + } } for (file in files) { diff --git a/inst/bin/parsable-R b/inst/hooks/exported/parsable-R.R similarity index 91% rename from inst/bin/parsable-R rename to inst/hooks/exported/parsable-R.R index 54858fd37..ae2c1a997 100755 --- a/inst/bin/parsable-R +++ b/inst/hooks/exported/parsable-R.R @@ -3,7 +3,7 @@ files <- commandArgs(trailing = TRUE) out <- lapply(files, function(path) { tryCatch( - parse(path), + parse(path), error = function(x) stop("File ", path, " is not parsable", call. = FALSE) ) }) diff --git a/inst/bin/readme-rmd-rendered b/inst/hooks/exported/readme-rmd-rendered similarity index 100% rename from inst/bin/readme-rmd-rendered rename to inst/hooks/exported/readme-rmd-rendered diff --git a/inst/bin/roxygenize b/inst/hooks/exported/roxygenize.R similarity index 100% rename from inst/bin/roxygenize rename to inst/hooks/exported/roxygenize.R diff --git a/inst/bin/spell-check b/inst/hooks/exported/spell-check.R similarity index 88% rename from inst/bin/spell-check rename to inst/hooks/exported/spell-check.R index df7e4ee22..ec8416e21 100755 --- a/inst/bin/spell-check +++ b/inst/hooks/exported/spell-check.R @@ -1,13 +1,13 @@ #!/usr/bin/env Rscript -'Spell check for files +"Spell check for files Usage: spell-check [--lang=] ... Options: --lang= Passed to `spelling::spell_check_files()` [default: en_US] -' -> doc +" -> doc arguments <- docopt::docopt(doc) path_wordlist <- file.path("inst", "WORDLIST") @@ -26,23 +26,23 @@ if (file.exists(path_wordlist)) { spelling_errors <- spelling::spell_check_files( - files, - ignore = ignore, + files, + ignore = ignore, lang = arguments$lang ) if (nrow(spelling_errors) > 0) { - cat("The following spelling errors were found:\n" ) + cat("The following spelling errors were found:\n") print(spelling_errors) ignore <- sort(unique(c(ignore, spelling_errors$word))) ignore <- ignore[ignore != ""] # drop blanks if any writeLines(ignore, path_wordlist) cat( - "All spelling errors found were copied to inst/WORDLIST assuming they were", - "not spelling errors and will be ignored in the future. Please ", - "review the above list and for each word that is an actual typo:\n", + "All spelling errors found were copied to inst/WORDLIST assuming they were", + "not spelling errors and will be ignored in the future. Please ", + "review the above list and for each word that is an actual typo:\n", "- fix it in the source code.\n", - "- remove it again manually from inst/WORDLIST to make sure it's not\n", + "- remove it again manually from inst/WORDLIST to make sure it's not\n", " ignored in the future.\n", "Then, try committing again.\n" ) diff --git a/inst/bin/style-files b/inst/hooks/exported/style-files.R similarity index 97% rename from inst/bin/style-files rename to inst/hooks/exported/style-files.R index c0f208b71..30bf0b1db 100755 --- a/inst/bin/style-files +++ b/inst/hooks/exported/style-files.R @@ -71,7 +71,7 @@ tryCatch( }, warning = function(w) { msg <- conditionMessage(w) - if (grepl('Unknown or uninitialised column', msg, ignore.case = TRUE)) { + if (grepl("Unknown or uninitialised column", msg, ignore.case = TRUE)) { warning(msg, call. = FALSE) } else { stop(msg, call. = FALSE) diff --git a/inst/bin/use-tidy-description b/inst/hooks/exported/use-tidy-description.R similarity index 100% rename from inst/bin/use-tidy-description rename to inst/hooks/exported/use-tidy-description.R diff --git a/inst/consistent-release-tag b/inst/hooks/local/consistent-release-tag.R similarity index 85% rename from inst/consistent-release-tag rename to inst/hooks/local/consistent-release-tag.R index f27f2c786..fa98d35bd 100755 --- a/inst/consistent-release-tag +++ b/inst/hooks/local/consistent-release-tag.R @@ -1,11 +1,11 @@ #!/usr/bin/env Rscript -'This hook checks that all versions in config files and the git tag that +"This hook checks that all versions in config files and the git tag that is used by precommit to clone the repo is identical. Usage: consistent-release-tag [--release-mode] [...] -' -> doc +" -> doc arguments <- docopt::docopt(doc) @@ -13,7 +13,7 @@ arguments <- docopt::docopt(doc) # is used by precommit to clone the repo is identical. # DESCRIPTION is allowed to have higher version because the process is: # - release a version e.g. 0.1.0 on CRAN, all example configs should match DESCRIPTION -# - continue development: Should bump DESCRIPTION to dev, e.g. 0.1.0.9000, +# - continue development: Should bump DESCRIPTION to dev, e.g. 0.1.0.9000, # but not git tag or config examples. These should remain at 0.1.0. # - release new version on CRAN, make sure all tags correspond to 0.2.0. @@ -25,16 +25,16 @@ path_config <- c( assert_config_has_rev <- function(path_config, latest_tag) { - file <- yaml::read_yaml(path_config) - repo <- purrr::map(file$repos, "repo") - + file <- yaml::read_yaml(path_config) + repo <- purrr::map(file$repos, "repo") + lorenzwalthert_precommit_idx <- which(repo == "https://github.com/lorenzwalthert/precommit") stopifnot(length(lorenzwalthert_precommit_idx) == 1) rev <- file$repos[[lorenzwalthert_precommit_idx]]$rev - + if (latest_tag != rev) { rlang::abort(glue::glue( - "latest git tag is `{latest_tag}`, but in `{path_config}`, you the ", + "latest git tag is `{latest_tag}`, but in `{path_config}`, you the ", "revision is set to `{rev}` Please make the two correspond." )) } @@ -50,8 +50,8 @@ latest_tag <- get_latest_tag() purrr::walk(path_config, assert_config_has_rev, latest_tag = latest_tag) latest_tag_without_prefix <- gsub("^v", "", latest_tag) -if (!(latest_tag_without_prefix < desc::desc_get_field('Version'))) { - if (latest_tag_without_prefix > desc::desc_get_field('Version')) { +if (!(latest_tag_without_prefix < desc::desc_get_field("Version"))) { + if (latest_tag_without_prefix > desc::desc_get_field("Version")) { rlang::abort(paste( "git tag should never be greater than description. At most they should", "be equal." @@ -60,8 +60,6 @@ if (!(latest_tag_without_prefix < desc::desc_get_field('Version'))) { rlang::abort(paste( "DESCRIPTION version must be larger than git tag unless the check is", " performed during a release. Then turn this off with --release-mode" - )) } - } diff --git a/inst/hooks-config-to-inst b/inst/hooks/local/hooks-config-to-inst.R similarity index 80% rename from inst/hooks-config-to-inst rename to inst/hooks/local/hooks-config-to-inst.R index 411566a14..980dfa580 100755 --- a/inst/hooks-config-to-inst +++ b/inst/hooks/local/hooks-config-to-inst.R @@ -1,9 +1,10 @@ #!/usr/bin/env Rscript -# because we need access of .pre-commit-hooks.yaml in the vignette +# because we need access of .pre-commit-hooks.yaml in the vignette # available-hooks and maybe more general in other places, we must put this # file under inst/ because otherwise it cannot be accessed (leaving it on top # level will fail r cmd check, the same when used as hidden file in inst/) fs::file_copy( - ".pre-commit-hooks.yaml", "inst/pre-commit-hooks.yaml", overwrite = TRUE + ".pre-commit-hooks.yaml", "inst/pre-commit-hooks.yaml", + overwrite = TRUE ) diff --git a/inst/spell-check-exclude-to-config b/inst/hooks/local/spell-check-exclude-to-config.R similarity index 84% rename from inst/spell-check-exclude-to-config rename to inst/hooks/local/spell-check-exclude-to-config.R index 7272ae752..41f026438 100755 --- a/inst/spell-check-exclude-to-config +++ b/inst/hooks/local/spell-check-exclude-to-config.R @@ -3,27 +3,27 @@ library(magrittr) exclude_hooks <- yaml::read_yaml(here::here(".pre-commit-hooks.yaml")) %>% purrr::keep(~ .x$id == "spell-check") %>% magrittr::extract2(1) %>% - purrr::pluck('exclude') + purrr::pluck("exclude") read_config <- function(path) { yaml::read_yaml(path) %>% - purrr::pluck('repos') %>% + purrr::pluck("repos") %>% purrr::keep(~ .x$repo == "https://github.com/lorenzwalthert/precommit") %>% purrr::pluck(1, "hooks") %>% purrr::keep(~ .x$id == "spell-check") %>% - purrr::pluck(1, 'exclude') + purrr::pluck(1, "exclude") } if (!identical(exclude_hooks, read_config(here::here("inst/pre-commit-config-pkg.yaml")))) { rlang::abort(paste0( - "The `exclude` key from the spell-check hook should be copied from `.pre-commit-hooks.yaml` to ", + "The `exclude` key from the spell-check hook should be copied from `.pre-commit-hooks.yaml` to ", "`inst/pre-commit-config-pkg.yaml` so the two match." )) } if (!identical(exclude_hooks, read_config(here::here("inst/pre-commit-config-proj.yaml")))) { rlang::abort(paste0( - "The `exclude` key from the spell-check hook should be copied from `.pre-commit-hooks.yaml` to ", + "The `exclude` key from the spell-check hook should be copied from `.pre-commit-hooks.yaml` to ", "`inst/pre-commit-config-proj.yaml` so the two match." )) } diff --git a/inst/spell-check-ordered-exclude.R b/inst/hooks/local/spell-check-ordered-exclude.R similarity index 100% rename from inst/spell-check-ordered-exclude.R rename to inst/hooks/local/spell-check-ordered-exclude.R diff --git a/inst/pre-commit-hooks.yaml b/inst/pre-commit-hooks.yaml index c984df30b..a5b3c41d3 100644 --- a/inst/pre-commit-hooks.yaml +++ b/inst/pre-commit-hooks.yaml @@ -1,7 +1,7 @@ - id: roxygenize name: roxygenize description: run roxygen2::roxygenize() - entry: inst/bin/roxygenize + entry: inst/hooks/exported/roxygenize.R language: script files: '^(R|man)/' require_serial: true @@ -9,14 +9,14 @@ - id: use-tidy-description name: use-tidy-description description: run usethis::use_tidy_description() - entry: inst/bin/use-tidy-description + entry: inst/hooks/exported/use-tidy-description.R language: script files: '^DESCRIPTION$' minimum_pre_commit_version: "2.13.0" - id: style-files name: style-files description: style files with styler - entry: inst/bin/style-files + entry: inst/hooks/exported/style-files.R language: script files: '(\.R|\.Rmd|\.Rnw|\.r|\.rmd|\.rnw)$' exclude: 'renv/activate\.R' @@ -24,35 +24,35 @@ - id: no-browser-statement name: no-browser-statement description: check if a .R file contains a `browser()` statement - entry: inst/bin/no-browser-statement + entry: inst/hooks/exported/no-browser-statement.R language: script files: '\.[rR]$' minimum_pre_commit_version: "2.13.0" - id: parsable-R name: parsable-R description: check if a .R file is parsable - entry: inst/bin/parsable-R + entry: inst/hooks/exported/parsable-R.R language: script files: '\.[rR]$' minimum_pre_commit_version: "2.13.0" - id: readme-rmd-rendered name: readme-rmd-rendered description: make sure README.Rmd hasn't been edited more recently than README.md - entry: inst/bin/readme-rmd-rendered + entry: inst/hooks/exported/readme-rmd-rendered language: script files: 'README\.[Rr]?md$' minimum_pre_commit_version: "2.13.0" - id: codemeta-description-updated name: codemeta-description-updated description: make sure codemeta.json is in sync with DESCRIPTION. It should be run after use-tidy-description. - entry: inst/bin/codemeta-description-updated + entry: inst/hooks/exported/codemeta-description-updated language: script files: '^DESCRIPTION$' minimum_pre_commit_version: "2.13.0" - id: spell-check name: spell-check description: perform a spell check with spelling::spell_check_files() - entry: inst/bin/spell-check + entry: inst/hooks/exported/spell-check.R language: script exclude: > (?x)^( @@ -86,7 +86,7 @@ - id: deps-in-desc name: deps-in-desc description: Check if dependencies that can be parsed from code are in DESCRIPTION. - entry: inst/bin/deps-in-desc + entry: inst/hooks/exported/deps-in-desc.R language: script files: '(\.[rR]profile|\.R|\.Rmd|\.Rnw|\.r|\.rmd|\.rnw)$' exclude: 'renv/activate\.R' @@ -94,7 +94,7 @@ - id: lintr name: lintr description: check if a .R file is lint free (using lintr) - entry: inst/bin/lintr + entry: inst/hooks/exported/lintr.R language: script files: '\.[rR]$' exclude: 'renv/activate\.R' diff --git a/man/run_test.Rd b/man/run_test.Rd index afd74b556..9266f01ca 100644 --- a/man/run_test.Rd +++ b/man/run_test.Rd @@ -17,7 +17,8 @@ run_test( ) } \arguments{ -\item{hook_name}{The name of the hook in \verb{bin/}.} +\item{hook_name}{The name of the hook in \verb{inst/hooks/exported/}, without +file extension.} \item{file_name}{The file to test in \verb{tests/in} (without extension). Can be a named vector of length one where the name is the target location relative diff --git a/tests/testthat/reference-objects/.pre-commit-config.yaml b/tests/testthat/reference-objects/.pre-commit-config.yaml new file mode 100644 index 000000000..7c996f30d --- /dev/null +++ b/tests/testthat/reference-objects/.pre-commit-config.yaml @@ -0,0 +1,79 @@ +# config used to run all hooks we have defined in this repo in .github/workflows/end-2-end.yml +# All available hooks: https://pre-commit.com/hooks.html +# R specific hooks: https://github.com/lorenzwalthert/precommit +default_stages: ["commit"] +repos: +- repo: https://github.com/lorenzwalthert/precommit + rev: v0.1.3.9008 + hooks: + - id: style-files + args: [--style_pkg=styler, --style_fun=tidyverse_style] + exclude: '^tests/testthat/in/.*\.R' + - id: roxygenize + # codemeta must be above use-tidy-description when both are used + - id: codemeta-description-updated + - id: lintr + - id: use-tidy-description + - id: spell-check + exclude: > + (?x)^( + .*\.[rR]| + .*\.feather| + .*\.jpeg| + .*\.pdf| + .*\.png| + .*\.py| + .*\.RData| + .*\.rds| + .*\.Rds| + .*\.Rproj| + .*\.sh| + (.*/|)\.gitignore| + (.*/|)\.pre-commit-.*| + (.*/|)\.Rbuildignore| + (.*/|)\.Renviron| + (.*/|)\.Rprofile| + (.*/|)\.travis\.yml| + (.*/|)appveyor\.yml| + (.*/|)NAMESPACE| + (.*/|)renv/settings\.dcf| + (.*/|)renv\.lock| + (.*/|)WORDLIST| + \.github/workflows/.*| + data/.*| + inst/hooks/.*| + inst/pre-commit-.*| + )$ + - id: readme-rmd-rendered + - id: parsable-R + - id: no-browser-statement + - id: deps-in-desc +- repo: local + hooks: + - id: consistent-release-tag + name: consistent-release-tag + entry: inst/hooks/local/consistent-release-tag.R + language: script + stages: [commit, push] + - id: hooks-config-to-inst + name: hooks-config-to-inst + entry: inst/hooks/local/hooks-config-to-inst.R + language: script + stages: [commit, push] + - id: spell-check-exclude-to-config + name: spell-check-exclude-to-config + entry: inst/hooks/local/spell-check-exclude-to-config.R + language: script + stages: [commit, push] + - id: forbid-to-commit + name: Don't commit common R artifacts + entry: Cannot commit .Rhistory, .Rdata, .csv and similar. + language: fail + files: '\.Rhistory|\.csv|\.RData|\.Rds|\.rds$' + # `exclude: ` to allow committing specific files. + - id: spell-check-ordered-exclude + name: Ordered regex pattern for spell-check exclusion + description: Ensure alphabetical order in `exclude:` key of spell check. + entry: inst/hooks/local/spell-check-ordered-exclude.R + language: script + files: '^(.*/|)\.?pre-commit-config.*\.yaml$' diff --git a/vignettes/testing.Rmd b/vignettes/testing.Rmd index e75c1b691..8d80bcdf9 100644 --- a/vignettes/testing.Rmd +++ b/vignettes/testing.Rmd @@ -18,7 +18,7 @@ pre-commit >= 2.11.0 supports R as a language and each hook repo has its own virtual environment with package versions locked. For that reason, we should also test with exactly these versions. -This package has four testing workflows: +This package has five testing workflows: * hook testing. Tests the hooks (as well as hook script helpers?) in the renv in which they'll be shipped. No R CMD Check or pre-commit executable needed. @@ -48,3 +48,9 @@ This package has four testing workflows: * CRAN testing. On CRAN, complete testing is ran, tests that check pre-commit executable access are disabled. + +* end-2-end testing: This simulates closely what happens when you run + `git commit` with pre-commit activated: We update the `.pre-commit-config.yaml` + to the pushed SHA and run `pre-commit run`, covering all hooks, to ensure in + particular file linking, file permissions etc. in `.pre-commit-hooks.yaml` are + correct for exported hooks.