lefthook icon indicating copy to clipboard operation
lefthook copied to clipboard

Add a new option for detecting Ruby files

Open SamSaffron opened this issue 5 months ago • 4 comments

At the moment pre commit hooks can use

  1. mime type filters (but there is none for Ruby)
  2. globs (for .rb) files which miss stuff that has #!/usr/bin/env ruby at the top or Gemfile.
  3. files to run a custom command, which never gets the --file param that you can pass in

So there is no clean way to define a pre-commit hook that will simply scan all Ruby files, instead you need to rely on location in the filesystem.

Feature request here would be to implement something like:

filetype: ruby

This would make it trivial to build a pre-commit hook that scans all Ruby files in a repo.

SamSaffron avatar Nov 05 '25 23:11 SamSaffron

Hey @SamSaffron, I've prepared the update https://github.com/evilmartians/lefthook/pull/1185, so it adds text/x-ruby, but it will work only for scripts with shebang like #!/usr/bin/env ruby.

What you ask for is to filter by .rb, shebang, maybe the content, but that's a tricky thing to implement.

What you can do if you know the structure of the project:

pre-commit:
  jobs:
    - run: echo {staged_files}
      glob:
        - "Gemfile"
        - "ruby-scripts/*"
        - "*.rb"

So, in this case you'll have all Gemfiles, ruby scripts (if you know where they are located) and other .rb files. I hope this is helpful.

mrexox avatar Nov 07 '25 12:11 mrexox

Thanks so much!

In Discourse's case it is a bit tricky.

At the moment our /bin directory only contains Ruby files, but I worry that someone will check in a bash file there (which seems fair) and then be very confused about linting.

With the mime type change are you going to allow for a mix and match? Stuff that is text/x-ruby OR anything called Gemfile / *.thor and so on. (should we make .thor and .rake file extension ruby?)

We are here at the moment:

https://github.com/discourse/discourse/blob/main/lefthook.yml

SamSaffron avatar Nov 09 '25 23:11 SamSaffron

@SamSaffron filters are reducing the scope, so in your case adding both glob and file_types will work just like if filte_type is added (which is more restrictive I guess).

But it may work if you had a special job for testing only scripts, like this:

- run: bundle exec stree check Gemfile {staged_files}
  glob:
    - "bin/*"
  file_types:
    - "text/x-ruby"

Of course this is kind of duplication, but you may consider using jobs.

I see you're using commands. You can switch to jobs which allow grouping and using one glob setting for many underlying jobs, like this:

pre-commit:
  parallel: true
  jobs:
    - name: Ruby source linting
      glob:
        - "*.{rb,rake,thor}"
        - "Gemfile"
      group:
        parallel: true
        jobs:
          - run: bundle exec stree check Gemfile {staged_files}
          - run: bundle exec rubocop --force-exclusion {staged_files}
    - name: Ruby scripts linting
      glob:
        - "bin/*"
       file_types:
        - "text/x-ruby"
      group:
        parallel: true
        jobs:
          - run: bundle exec stree check Gemfile {staged_files}
          - run: bundle exec rubocop --force-exclusion {staged_files}

mrexox avatar Nov 10 '25 07:11 mrexox

Thanks Valentin, yeah makes sense to cut down some of the duplication

SamSaffron avatar Nov 10 '25 21:11 SamSaffron