Giter VIP home page Giter VIP logo

precommit's Introduction

editor_options
markdown
wrap
72

Useful git pre-commit hooks for R

CRAN status Lifecycle: stable R build status

Pre-commit hooks are tests that run each time you attempt to commit. If the tests pass, the commit will be made, otherwise not. A very basic test is to check if the code is parsable, making sure you have not forgotten a comma, brace or quote. You can run hooks locally and/or in the cloud:

  • As a check before local commits: This requires installing pre-commit.

  • As a CI check with https://pre-commit.ci: If you want to enforce passing hooks on pull requests (and auto-fix trivial problems like styling) even if the committer does not have a local installation.

Goals of the package

The goal of this package is to twofold:

  • Provide a set of hooks that are useful when your git repo contains R code.

  • Provide usethis-like functionality for common tasks such as installation and set-up and config file modification.

Why do I need pre-commit hooks?

By Mara Averick

For a more in-depth explanation and even more reasons, see vignette("why-use-hooks").

Documentation

The following online docs are available:

These only cover the functionality added on top of the pre-commit framework by this package. Everything else is covered in the extensive online documentation of the pre-commit framework itself, including how to create hooks for actions like git push or git checkout, create local hooks etc.

precommit's People

Contributors

adamblake avatar alessap avatar asottile avatar bart1 avatar bfgray3 avatar denn173 avatar dependabot[bot] avatar gravesti avatar indrajeetpatil avatar jcken95 avatar jonathanckt avatar jonmcalder avatar jsnel avatar katrinleinweber avatar kcphila avatar krzyslom avatar lorenzwalthert avatar lukashaenjes avatar m-muecke avatar maelle avatar maurolepore avatar michaelquinn32 avatar mpadge avatar pat-s avatar pre-commit-ci[bot] avatar pwildenhain avatar stefanoborini avatar tnonet avatar tymekdev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

precommit's Issues

"deps-in-desc" hook should ignore ::: calls

In our tests we have something like

mlr:::<function>

and precommit hook "deps-in-desc" errors because we haven't got package "mlr" in our DESC file (for pkg mlr).

I'd consider this as a false-positive here. Is there some way to omit checks for this hook on the pkg name of the current project?

(Maybe accounting for the triple doublecolons is a separate issue)

Problem with handling nested projects

Let's say that I have a project repo and within it I have a packages/ folder that stores the packages that are developed under this project. Every single package is also an R project.

Now I would like to have two .pre-commit-config.yaml templates, one for the project scope and the other for the packages. The former will have R package development hooks disabled while the latter will have them enabled. The following tree represents the desired architecture.

. (project)
├── .git
├── .pre-commit-config.yaml (with DISABLED R package development hooks)
├── notebooks
├── packages
│   ├── packageA
│   │   ├── .pre-commit-config.yaml (with ENABLED R package development hooks)
│   │   ├── DESCRIPTION
│   │   └── ...
│   └── packageB
│       ├── .pre-commit-config.yaml (with ENABLED R package development hooks)
│       ├── DESCRIPTION
│       └── ...
├── README.md
└── ...

When I create a package folder inside the project directory then the package is not treated as separate git repository. If I enter the package folder (by opening the package.Rproj) and run git status then I can also see the files from the root project folder i.e. ../../README.md.

Running precommit::use_precommit() and here::here() from inside the package folder will result in acknowledging the .pre-commit-conf.yaml file that lies within the package folder. git commit action also looks at the same config file. However it looks for DESCRIPTION file (as desc-in-deps hook is enabled in the package scope) inside the project root directory. This results in the following error:

Error: No root directory found in <my/root/project/path> or its parent directories. Root criterion: contains a file `DESCRIPTION` with contents matching `^Package:

thrown by rprojroot package.

After the first commit failure, the package config is ignored. Now in second attempt (just hitting once more git commit) the one in the project root directory will be used. Now the git commit action will succeed because in the project root dir lies the config file that has desc-in-deps hook disabled. If I remove the yaml config from the project root directory then calling git commit from the package workdir sticks to looking at the config in the package workdir which again results in mentioned error.

Now if I create a totally new project from RStudio navbar, and inside that project I start another R package project with checked "Create a git repository" option and plant the yaml configs as previously, then everything will work just fine, since the precommit used within the package workdir will recognize it as the root folder since it is a separate git repository.

To sum it up - at the moment it seems like using more than one precommit config yaml file in many subfolders within a single git repository results in a failure at first attempt, and automatic switch to the config that lies in the git repo root directory for the next attempt of git commit.

Is it possible to change the functionality so that upon commiting, precommit won't execute the hooks from the perspective of the yaml config in the root directory of the git repository but from the perspective of the current working directory instead i.e. subfolder with a pacakge?

Handling dependencies

As long as R is not a supported language, I wonder how we can install R dependencies like R packages such as styler. They probably need to be installed manually. This is not really nice and hence R support in pre-commit would be nice anyways. But since R cannot provide an executable (see r-lib/styler#467 (comment)), it would be merely for managing dependencies and then we'd anyways use the system entry point with an R script as with the current implementation. Also see pre-commit/pre-commit#926. cc: @katrinleinweber.

codemeta hook should ignore "fileSize" field

When using this hook, it fails on every commit for me because the "fileSize" field changes during every hook run

diff --git a/codemeta.json b/codemeta.json
index 6ed3510..ddc28bb 100644
--- a/codemeta.json
+++ b/codemeta.json
@@ -212,7 +212,7 @@
   ],
   "releaseNotes": "https://github.com/pat-s/circle/blob/master/NEWS.md",
   "readme": "https://github.com/pat-s/circle/blob/master/README.md",
-  "fileSize": "16.507KB",
+  "fileSize": "16.508KB",
   "contIntegration": [
     "https://travis-ci.org/pat-s/circle3",
     "https://circleci.com/gh/pat-s/circle",

which makes it impossible for me to run this hook successfully.

check codemeta is up-to-date

Feature request :-)

Codemeta is a standard for metadata describing software. codemetar creates codemeta.json for R packages based on DESCRIPTION, README, etc. https://github.com/ropensci/codemetar

Current hook template: https://github.com/ropensci/codemetar/blob/master/inst/templates/description-codemetajson-pre-commit.sh

Could one make it a part of the default collection, if the script checked for codemeta.json existence?

As shown by #50, I am very new at all this stuff.

Suggestion for README

At first I thought that I have to replace the repo name and rev with the one from the repo I want to use. This is ofc wrong. Maybe you could add one sentence making it clearer that the repo needs to stay pre-commit-hooks as it will query the files in bin/ from here :)

Some docs notes

I'm actually very new to the package, I'll keep track of my thoughts when installing and trying it, maybe it can help. So that's not a full rOpenSci review, that's a full newbie review. 🐤 (mostly for the README)

  • How does it work? What's the magic?

No magic 😊. Git provides a mechanism for pre-commit hooks. Since it's cumbersome to copy bash scripts and keep them updated in some hidden .git/ directory, people wrote frameworks to basically maintain these files. One of them is pre-commit.com. So you call git to commit, git calls its internal hooks, these hooks (bash scripts in the simplest case) are provided by the pre-commit framework. And where does pre-commit get all it's nice hooks from? From us 😊.

  • Make it clearer it's wrapping a framework for git commit hooks?

This package contains: hooks and wrappers. Hooks are stored in inst/bin/. Every hook has an id and the executable (i.e. the path to it) is referenced via the .pre-commit-hooks.yaml in this repo. A user only has a .pre-commit-config.yaml file in his repo where he lists the ids of the hooks he want's pre-commit to run before every commit. Pre-commit clones this repo and will execute the scripts before every commit. It passes the file names to the executable script (always as last unnamed argument) and potentially other arguments. The repo also contains wrappers. They make extensive use of system2() to call the pre-commit executable provided by pre-commit.com. Examples are autoupdate(), use_precommit() and install_precommit(), open_config() and friends.

  • Make it clearer it's an R package, not a collection of hooks?

It's both 😊. The exported functions of the package are the wrappers, facilitators to use pre-commit from the R command line. We could also have put the hook definitions into another repo. Then, this second repo would contain .pre-commit-hooks.yaml and inst/bin/ only. But I felt why not one repo? Also, the repo meets all requirements for an R package and has tests for the hooks.

  • Add links for git (happygitwithr?), an intro to hooks somewhere?

Good idea to link happygitwithr. But I feel like hooks are not that complicated. As the readme states, they are just like tests that are executed before the commit.

  • Make system dependencies clearer and add links to how to install Conda on various platforms? e.g. I'm installing miniconda on Ubuntu. Say a further system dependency will be installed by the package, so it's clear what will be installed in the end (Conda, a framework, the package)

Right. So I think a link to how to install conda should be sufficient for the installation part of conda. What happens when? 1) user must install conda, 2) install the R package (does not install the hooks, although they will be in inst/bin/, but the pre-commit does not know about that. The package is installed to use the wrappers), 3) run precommit::install_precommit() installs the pre-commit executable into the conda environment, 3) precommit::use_precommit() installs pre-commit into a specific repo (i.e. it puts the hooks scripts into .git/ via git clone.

  • Make it clearer what's on the internet? How are hooks accessed? What happens if there's no internet connection?

No internet connection required, except during installation (precommit::install_precommit()and precommit::use_precommit()). As stated above, hooks will be placed into .git/ during calling the precommit::use_precommit() and afterwards you can precommit::autoupdate() to basically do a git pull (that's what I think happens).

  • What will happen when your collaborators don't have any of the things installed? Can they still commit?

Two solutions.

  • Can you use it outside RStudio?

Yes, all but the open_config() and open_wordlist() to open files in RStudio. The hooks are working even if you don't have the package installed but the pre-commit was installed via another way like brew or pip install (as pre-commit will handle these). The package can be used to avoid switching to the bash terminal to run pre-commit autoupdate and similar.

  • How does one create a new pre-commit hook? Would it help if you stored the pre-commit not in the same repo as your package, so one could see the minimal structure? E.g. I think r-lib/ghactions is different from r-lib/actions?

How to contribute new hooks is explained in CONTRIBUTING.md. It would help to see the minimal structure if the R package and the hook repo was not the same yes. The minimal structure for the hook repo is .pre-commit-hooks.yaml and executable files like the one in inst/bin. No idea about (gh)actions.

  • If I want to contribute a new hook to ensure codemeta.json (docs.ropensci.org/codemetar) is always up-to-date, how do I do that?

A hook fails if 1) any input file is modified by the hook or 2) if running the hook script fails. So it's pretty simple for your case. Just create a bash script with shebang, make it executable and run write_codemeta("."), link it in .pre-commit-hooks.yaml (with a file filter on DESCRIPTION). Just see the use-tidy-description hook here: https://github.com/lorenzwalthert/precommit/blob/master/inst/bin/use-tidy-description. In addition, please follow CONTRIBUTING.md

(to be continued)

autoupdate() fails due to "pkg_resources" not being available

On my HPC I successfully installed pre-commit and linked the executable.
However, when running precommit::autoupdate() I get

precommit::autoupdate()
Traceback (most recent call last):
  File "/opt/spack/opt/spack/linux-centos7-x86_64/gcc-9.2.0/py-pre-commit-1.20.0-ib4ogqnt3wwjan5pj6z6ud2ibz2ywh5e/bin/pre-commit", line 6, in <module>
    from pkg_resources import load_entry_point
ModuleNotFoundError: No module named 'pkg_resources'
Error: Running precommit autoupdate failed.
Call `rlang::last_error()` to see a backtrace

Any idea what python dep might be missing and how I can resolve this? I can also ask/look upstream if you say this is out of scope as it is related to a proper install of pre-commit and not the R package :)

Make it possible to store a preferred set of hooks as R options?

With more hooks becoming available, one might often want to use the same set of hooks for multiple repos.

It would be convenient to store a default set of hooks as R options which will be enabled in a repo if one calls precommit::use_precommit() in a new repo.

#55 sounds related. Just close if you consider this a duplicate.

Implementing tests routines

migrated from #2.

Yes, I think it's would be good to have some tests just right from the beginning. How would you implement them? They should run on all major platforms. One way would be to use a git interface from a language like python or R because that would make testing / try except ect. easier. Or simply use a a package like processx or the system command or a package like git2r but I think the last one might be an overkill. I imagine the tests to run as follows on a CI service:

  • adding a folder test to this repo with a script runner.R/py that contains code to execute for the tests.
  • clone this repo.
  • move files from resources to tests.
  • run tests/execute-test.R/py.

The structure of the tests would be:

  • execute $ git add && git commit -m "..." and either expect exit status 0 or 1 (we should test for errors too).

What do you think? If we use a package like tic, we could set this up for CI agnostic for appveyor and travis.

Error installing from Github

Currently I get

remotes::install_github("lorenzwalthert/pre-commit-hooks")

** byte-compile and prepare package for lazy loading
Linking to libgit2 v0.28.2, ssh support: YES, https support: YES
Default user: pat-s <patrick.schratz@gmail.com>
Error in parse(con, keep.source = FALSE, srcfile = NULL) : 
  3:9: unexpected symbol
2: 
3: jfaösf öl
           ^
Calls: <Anonymous> ... withCallingHandlers -> loadNamespace -> parseNamespaceFile -> parse
Execution halted
ERROR: lazy loadi

Conflict with usethis hooks

usethis creates an automatic hooks when usethis::use_readme_rmd() is ran. Has anyone gotten experience with this? Possibly the precommit framework will discover them and ask to run in migration mode. I think we should as the maintainer of usethis to:

  • expose an argument create_hook in usethis::use_readme_rmd()
  • defaulting to !rlang::is_installed("precommit").

Ensure people use new repo name

lorenzwalthert/pre-commit-hooks -> lorenzwalthert/precommit in .pre-commit-config.yaml. Probably validate when running precommit::autoupdate().

Suggestion: hooks to check that downstream files have also been updated

I'd love to see some hooks here that check if certain files are newer than others, e.g. the hook created by usethis::use_readme_rmd() for checking if README.Rmd has been modified since README.md was last rendered. Similarly, I think it might be helpful to have one that checks data/*.rda and R/sysdata.rda to see if any data-raw/*.R files have been modified more recently. I think it can be easy to forget to regenerate these downstream files before committing. Happy to help out if you think these would be useful.

Allow committing when `pre-commit.yml` is unstaged

Sometimes I have to turn off certain hooks for various reasons. This leads to a error stating that

[ERROR] Your pre-commit configuration is unstaged.

which makes it impossible to commit anything. Can this be turned off?
I neither want to change the hooks in general nor commit the changed YML file temporary.

devtools::check()

I'd be willing to de-hackify my personal hook that does a pre-commit CRAN check on a pkg repo to prevent sending an un-checkable change up (with all the cascade failures that result)

Hook for lintr

Have you considered a hook for lintr?

As far as I'm aware lintr supports some checks which might still be desirable and/or necessary since for example one can't yet rely on styler for enforcing max line length with r-lib/styler#247 remaining open for now.

go public

  • mention that people should can browser pre-commit files in RStudio with the option "Show all files" (rstudio/rstudio#1769).
  • mention other useful hooks.
  • mention that assumptions on dependencies (R and packages already installed).
  • require styler >= 1.1.1.9002
  • Ask people to unwatch github releases for news.
  • For installation: note on macOS Catalina users.

check for unused objects

E.g. in a package, when I remove a function, a helper function only used by that function might also not be used anywhere anymore. This should be removed in the same commit. Question: Where to look in the directory tree. R, Rmd, Rnw, Rmarkdown files everywhere?

Does lintr offer this already?
R CMD check looks for unused packages in DESCRIPTION.

Don't allow comitting unqualified objects

E.g. map_chr(...) should be purrr::map_chr(...) unless the function is explicitly imported in the namespace.

It would be handy to have a tool that:

  • searches for all exported object from the packages listed in DESCRIPTION.
  • check for all objects in code if they are declared in the package scope if they are unqualified. (i.e. without pkg::fun).
  • Add the qualifiers automatically if the specific functions are not listed in NAMESPACE as imports.

Spelling hook might require serial processing

Problem: when executed in parallel, we might overwrite some newly added entries to inst/WORDLIST. Alternative: Finding a way to append to file from multiple processes in parallel that works on all operating systems.

Add usethis version requirement

I get the following with usethis v1.4.0
Not sure which minimal version is needed, just FYI :)

precommit::install_precommit()
Error: 'ui_info' is not an exported object from 'namespace:usethis'

Fix pkgapi dependencies

In the DESCRIPTION, the roxygen block requires pkgapi. This is not in the Suggests or Remotes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.