evilmartians / lefthook Goto Github PK
View Code? Open in Web Editor NEWFast and powerful Git hooks manager for any type of projects.
License: MIT License
Fast and powerful Git hooks manager for any type of projects.
License: MIT License
My RuboCop is configured to ignore schema changes:
require: 'rubocop-rails'
inherit_from: .rubocop_todo.yml
AllCops:
TargetRubyVersion: 2.6
Exclude:
- 'db/schema.rb' # auto-generated
When I run RuboCop directly, there are no issues.
I have Lefthook configured with:
run: bundle exec rubocop {staged_files} --parallel
When it's triggered through Lefthook, it seems to ignore the config.
I tried changing it to explicitly specify the config file, but it made no difference:
run: bundle exec rubocop --config .rubocop.yml {staged_files} --parallel
We want to have lefthook in some library and use node_modules/@some/package/.lefthook.yml as a base config.
It would be great if we could add some parameters in package.json
or use something like inheritance in yaml like
# lefthook.yml
extends: @some/package/.lefthook.yml
Is it real to setup a global config in my user root and directory and use the same config for all my projects?
In overcommit, I can run SKIP=ALL git commit -m 'Commit message'
and it skips running everything.
I often use this when I want to commit a branch & push up for someone else to look at, but I've tagged one or more specs with focus
and rubocop would normally half lefthook/overcommit because of that focus (we don't want those to go into master, for example)
I'm able to mirror this kind of behavior in my lefthook.yml
file using an inline shell script, but it would be nice if there was a syntax similar to what overcommit provides (SKIP=rubocop,bundler
)
rubocop:
files: if [[ -z "${SKIP}" ]]; then git diff --name-only --staged; else ""; fi;
glob: "*.{rb}"
run: bundle exec rubocop -DEPS {files}
This seems to work fine but it's not as flexible as being able to pass in named commands to skip without making the shell script overly complex. I could probably move it out into separate bin/
scripts for each command but I think this might be a nice feature addition for lefthook
This scenario is a little different than the skip: true
flag, because it's a conditional skip based on a CLI arg I prefix in my commands that run lefthook
lefthook is great library, thanks!
I would like to use like
--auto-correct
by RuboCop, --fix
by ESLint)first, I tried like
pre-commit:
commands:
backend-linter:
glob: "*.rb"
run: bundle exec rubocop --auto-correct --force-exclusion {staged_files} && git add {staged_files}
but it does not work like I expected.
should be alright if the staged range is whole file,
but in the case of staged as hunk(like git add -p ...
), re-add whole file.
Does any one know a solution?
I used use lint-staged and husky like that.
{
"lint-staged": {
"*.rb": [
"bundle exec rubocop --auto-correct --force-exclusion",
"git add"
]
}
}
in this case include the result of changing by auto-correct to a commit.
I fixed typo force-exclution
= > force-exclusion
Hello, I'm having trouble getting this pre-push hook to detect files, specifically for the style
command:
pre-push:
parallel: true
commands:
javascript:
files: git diff --name-only HEAD @{push}
glob: "*.{ts,tsx,js,jsx}"
run: npx eslint -- {files}
styles:
files: git diff --name-only HEAD @{push}
glob: "*.{less,css}"
run: npx stylelint -- {files}
types:
run: npm run type-check
When I manually run git diff --name-only HEAD @{push}
, I see an expected .less
file in the output. However, when I run ./node_modules/.bin/lefthook -v run styles
, I see this output:
Lefthook v0.6.3
RUNNING HOOKS GROUP: styles
SUMMARY: (SKIP EMPTY)
Any idea why this may be? It seems like the glob is failing somehow. This is not a new file but rather modifying an existing file in the repo.
Now we have 3 binaries in npm and script which run necessary binary depends on the current platform.
There are 2 big problems with current behavior:
Solution:
postinstall
script download necessary binary (many npm packages use this approach, for instance puppeter
).index.js
Is there a way to make glob
case-insenstive?
It would avoid having to write:
glob: "*.{jpg,JPG,Jpg,jPg,jpG,JPg,jPG}"
(I hope nobody uses those extensions, but you get the idea. 😀)
lefthook doesn't properly handle lots of files. Here's a trivial example:
FROM ubuntu:bionic
RUN : \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates \
curl \
git \
python3-pip \
&& apt-get clean
RUN : \
&& curl --location --silent --output /tmp/lefthook.gz https://github.com/Arkweid/lefthook/releases/download/v0.6.3/lefthook_0.6.3_Linux_x86_64.gz \
&& echo '0876ae7a862cb26aa5bd50173502dfd836cd16317f7af18be0797deeb3e1cfcd /tmp/lefthook.gz' | sha256sum --check \
&& gunzip /tmp/lefthook.gz \
&& mv /tmp/lefthook /usr/local/bin \
&& chmod +x /usr/local/bin/lefthook \
&& which lefthook
WORKDIR /src
COPY lefthook.yml .
ENV \
[email protected] \
GIT_AUTHOR_NAME='A A' \
[email protected] \
GIT_COMMITTER_NAME='A A'
RUN : \
&& git init . \
&& bash -c 'touch aaaaaaaaaaaaaa{1..10000}' \
&& lefthook install \
&& git add .
CMD ["git", "commit", "-m", "test"]
pre-commit:
commands:
identity:
run: echo {staged_files}
docker build -t test .
docker run --rm -ti test
$ docker run --rm -ti test
Lefthook v0.6.3
RUNNING HOOKS GROUP: pre-commit
EXECUTE > identity
fork/exec /bin/sh: argument list too long
SUMMARY: (done in 0.04 seconds)
🥊 identity
Related: #41
On the first run, it creates hookah.yml file only
On the second run open bla-bla-bla/test-hookah/.hookah: no such file or directory
Hello,
Possible bug I saw during test lefthook.
When no {staged_files}
is empty (SKIP. NO FILES FOR INSPECTING)
is output but the command is called.
The command is not called
Herve-M
Running a script like
react-templates:
glob: '*.{jsx,tsx}'
run: >
npx eslint {staged_files} --fix &&
npx prettier {staged_files} --write &&
git add {staged_files}
when there are lots of files throws the The command line is too long
on Windows. Haven't had this issue with husky
For example, when you working with monorepo you may want to have config like this:
pre-commit:
commands:
elixir_format:
root: "/backend"
glob: "*.{ex,exs}"
run: mix format --check-formatted {staged_files}
ts_format:
root: "/frontend"
glob: "*.{ts,tsx}"
run: npm run format_check {staged_files}
Possible root
option behaviour:
{staged_files}
should return paths relative to provided root pathfiles
should use root path as working dirrun
should use root path as working dirHere's a trivial example:
FROM ubuntu:bionic
RUN : \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates \
curl \
git \
python3-pip \
python3-setuptools \
&& apt-get clean
RUN : \
&& curl --location --silent --output /tmp/lefthook.gz https://github.com/Arkweid/lefthook/releases/download/v0.6.3/lefthook_0.6.3_Linux_x86_64.gz \
&& echo '0876ae7a862cb26aa5bd50173502dfd836cd16317f7af18be0797deeb3e1cfcd /tmp/lefthook.gz' | sha256sum --check \
&& gunzip /tmp/lefthook.gz \
&& mv /tmp/lefthook /usr/local/bin \
&& chmod +x /usr/local/bin/lefthook \
&& which lefthook
RUN pip3 install autopep8
WORKDIR /src
COPY lefthook.yml .
ENV \
[email protected] \
GIT_AUTHOR_NAME='A A' \
[email protected] \
GIT_COMMITTER_NAME='A A'
RUN : \
&& git init . \
&& echo 'print(1 +1)' > t.py \
&& lefthook install \
&& git add .
CMD ["bash", "-xc", "git commit -m test && git status && cat t.py"]
pre-commit:
commands:
autopep8:
files: git diff --staged --name-only -- '*.py'
run: autopep8 -i {files}
docker build -t test .
docker run --rm -ti test
$ docker run --rm -ti test
+ git commit -m test
Lefthook v0.6.3
RUNNING HOOKS GROUP: pre-commit
EXECUTE > autopep8
SUMMARY: (done in 0.17 seconds)
✔️ autopep8
[master (root-commit) 2858089] test
2 files changed, 6 insertions(+)
create mode 100644 lefthook.yml
create mode 100644 t.py
+ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: t.py
no changes added to commit (use "git add" and/or "git commit -a")
+ cat t.py
print(1 + 1)
The commit should have been blocked as autopep8
modified a file
Thanks for your amazing work, Alexander!
I have a large, legacy codebase riddled with RuboCop offenses. I want to introduce RuboCop into our development pipeline gradually.
I'm interested in having RuboCop lint files when committing them, with two caveats:
Overcommit implements both of these:
problem_on_unmodified_line: {report,warn,ignore}
on_fail: warn
Using Lefthook, I can achieve the effect of # 2 within the linter itself: rubocop --fail-level=E
, or perhaps by replacing the 1-line call to rubocop with a script that always returns true.
However, how can I achieve the effect of # 1?
Hello! I want to use lefthook with Dart. I can make a PR for that, but I have a couple of questions.
Do you publish all packages manaully? Who will publish new versions to pub
(Dart package registry)?
P.S. Thanks for lib, it is really great! 😻
lefthook.yml
:
pre-commit:
parallel: true
commands:
typecheck:
run: 'npx tsc -p .'
react-templates:
glob: '*.{jsx,tsx}'
run: >
npx eslint {staged_files} --fix &&
npx prettier {staged_files} --write &&
git add {staged_files}
scripts:
glob: '*.{js,ts}'
exclude: '.eslintrc.js'
run: >
npx eslint {staged_files} --fix &&
npx prettier {staged_files} --write &&
git add {staged_files}
css:
glob: '*.{css,scss}'
run: >
npx prettier {staged_files} --write &&
npx stylelint {staged_files} --fix &&
git add {staged_files}
other:
glob: '*.{html,md,yml}'
run: >
npx prettier {staged_files} --write &&
git add {staged_files}
This is the error output:
RUNNING HOOKS GROUP: pre-commit
EXECUTE > css
(SKIP. NO FILES FOR INSPECTING)
EXECUTE > other
[error] Unable to expand glob patterns: !**/node_modules/** !./node_modules/** !**/.{git,svn,hg}/** !./.{git,svn,hg}/**
[error] must provide pattern
lefthook.yml 79ms
EXECUTE > scripts
(SKIP. NO FILES FOR INSPECTING)
EXECUTE > react-templates
(SKIP. NO FILES FOR INSPECTING)
EXECUTE > typecheck
[error] Unable to expand glob patterns: !**/node_modules/** !./node_modules/** !**/.{git,svn,hg}/** !./.{git,svn,hg}/**
[error] must provide pattern
[error] Unable to expand glob patterns: !**/node_modules/** !./node_modules/** !**/.{git,svn,hg}/** !./.{git,svn,hg}/**
[error] must provide pattern
SUMMARY: (done in 13.20 seconds)
✔️ other
✔️ typecheck
.git/hooks
), гибкость (там пару примеров которые очень сложно сделать без lefthook), простота (установки и развёртывания? Ибо один бинарник и сахар)Given the example:
commit-msg:
scripts:
"template_checker":
runner: bash
How would I pass {staged_files}
to the template_checker
script?
(If this is possible, I suggest adding it to the docs.)
Thanks!
Are the hooks from Git LFS supported?
They probably should be run internally?...
I use awslabs/git-secrets
as a pre-install hook for all Git clone operations, and I would like to maintain having that when using Lefthook. In looking how lefthook install
works, it won't take the existing hooks and import it, and I'm not sure how to enable a global set of hooks that will be run.
I'd prefer if there were an option to not replace my .git/hooks
with lefthook's, and instead append the lefthook configuration. Barring that, I'd like to see some options for global hooks that could be installed or set up once in your $HOME/.lefthook
dir, so it could be included by default for all lefthook
operations.
Seem slike someone forgot one underscore here: https://github.com/Arkweid/lefthook/blob/master/.npm/postinstall.js#L18
/Users/marvinheilemann/.npm/_npx/8422/lib/node_modules/@arkweid/lefthook/postinstall.js:18
binpath = join(_dirname, 'bin', binary);
^
ReferenceError: _dirname is not defined
at Object.<anonymous> (/Users/marvinheilemann/.npm/_npx/8422/lib/node_modules/@arkweid/lefthook/postinstall.js:18:18)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @arkweid/[email protected] postinstall: `node postinstall.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the @arkweid/[email protected] postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/marvinheilemann/.npm/_logs/2019-11-09T12_38_14_448Z-debug.log
Die Installation von @arkweid/lefthook@latest ist mit dem Code 1 fehlgeschlagen
This prevents me from updating/installing my project deps (Angular project).
I have a bunch of commands in post-merge that are rarely run. I was thinking if the output could be made more compact since the info here is not super important to show every time a merge is done.
Throwing out some ideas:
This is an example of how it looks today:
Lefthook v0.6.3
RUNNING HOOKS GROUP: post-merge
EXECUTE > command1
(SKIP. NO FILES FOR INSPECTING)
EXECUTE > command2
(SKIP. NO FILES FOR INSPECTING)
EXECUTE > command3
(SKIP. NO FILES FOR INSPECTING)
EXECUTE > command4
(SKIP. NO FILES FOR INSPECTING)
EXECUTE > command5
(SKIP. NO FILES FOR INSPECTING)
SUMMARY: (SKIP EMPTY)
README.md
(for instance, we definitely should have Migration from Husky
link)Thank you for the nice tool. I've made a simple wrapper to install lefthook from python environment:
https://github.com/life4/lefthook
@Arkweid, I can give you access to the repository and PyPI to let you have control over it.
Hi,
I have a task (i18n-tasks for Rails) that needs to run whenever I update the yml files.
I expect to be able to write
pre-push:
commands:
i18n-linting:
files: git diff --name-only HEAD master # only changes
glob: "*.yml"
run: i18n-tasks check-normalized
However, when I do this, it always runs, even when there are no changes to the yml files (as according to git). Btw, I'm fine with the command running whenever there are changes to yml files not related to the task, that is not the issue here.
I get the correct behaviour if i add {files} to the run command:
run: i18n-tasks check-normalized {files}
The problem is that i18n-tasks does not take files as an argument. So I must remove {files} from the run command.
So my expected behaviour would be to not run it if files return 0 files even when not used in the run command.
Hi there, I stumbled upon this project from a cool EvilMartians blog post.
I went to implement in my own project, and I tried both the homebrew binary and the Node module, and when I run lefthook install
or yarn lefthook install
I get the same error:
runtime error: index out of range
All I have done at this point is create the lefthook.yml
file and download the binary, so I'm petty sure I'm not doing anything wrong.
Dear lefthook team,
lefthook.yml
pre-push:
parallel: true
scripts:
"rubocop":
runner: docker exec -it <container-name> {cmd}
.lefthook/pre-push
#!/bin/bash
rubocop
on push
/home/user/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/lefthook-0.6.3/libexec/lefthook-linux run pre-push origin [email protected]:repo/repo.git
Lefthook v0.6.3
RUNNING HOOKS GROUP: pre-pushEXECUTE > rubocop
the input device is not a TTYSUMMARY: (done in 0.03 seconds)
🥊 rubocop
error: Fehler beim Versenden einiger Referenzen nach '[email protected]:repo/repo.git
any ideas how to fix this?
thanks in advance!
lukas
p.s.: docs (https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md) docker exec -it --rm <container_id_or_name> {cmd}
the --rm
option shouldn't be there
Result of execution in windows bash. Please take a look below
Looks like issue like there rs/zerolog#153
Can you check it?
$ lefthook run pre-commit
?[36mRUNNING HOOKS GROUP:?[0m ?[1mpre-commit?[0m
?[36m
EXECUTE >?[0m ?[1mtests?[0m
? github.com/sochisic/tg-retard-jokes-bot [no test files]
?[36m
SUMMARY: (done in 2.15 seconds)?[0m
✔️ ?[32mtests?[0m
I have Dockerfile
FROM $some_user/$some_project:1.0.1
WORKDIR /app
RUN ...
and my project pwd is /home/$user/Projects/project
i try to run post-checkout hook from example with docker runner.
I get result
Lefthook v0.6.3
RUNNING HOOKS GROUP: post-checkout
EXECUTE > 01-bundle-checkinstall
EXECUTE > 02-db-migrate
Starting project_redis_1 ... done
Starting project_postgres_1 ... done
Traceback (most recent call last):
ruby: No such file or directory -- /home/$user/Projects/project/.lefthook/post-checkout/02-db-migrate (LoadError)
Is it possible to transfer the relative path to the runner instead of absolute?
I tried to create images with copy host pwd
FROM $some_user/$some_project:1.0.1
ARG APP_DIR
WORKDIR APP_DIR
RUN ...
docker build --build-arg APP_DIR=$(pwd)...
it helped me, but this is a bad hack.
Hard-Coded path in container also not an option.
Thank you for your attention.
We have tons of symlinks in a project. Is it possible to add a filter to skip symlinks in {staged_files}
, {all_files}
, etc., so that the same file won't be linted twice when the symlinks gets resolved?
Would be nice to generate some commented out YAML in lefthook.yml
with common usage scenarios to increase adoption speed.
Hello,
Context:
lefthook_0.6.5_Windows_x86_64.zip
Problem: lefthook.exe version
should return the current version.
In a non git repo. without lefthook.yml
, exit status 128
is returned
In a git repo. with lefthook.yml
, 0.6.5
is returned.
0.6.5
must be returned
Herve-M
Hello.
First of all, thank you very much for Lefthook! There are about 60 people in our team who commit to our mono repository. We recently migrated to Lefthook to manage the hooks. We chose between Overcommit, Husky, pre-commit and a few other alternatives and decided on Lefthook.
I've discovered that prepare-commit-msg
hooks are not supported. I found this commit 24bd1f7, but I can't find any information about why this change was made. Could you clarify, please?
When running lefthook on a checked out submodule the directory structure is not as expected.
$ lefthook install
SYNCING lefthook.yml
SERVED HOOKS: pre-commit, prepare-commit-msg
open {HOME}/{PROJECT}/{SUBMODULE_NAME}/.git/hooks/pre-commit: not a directory
This is because in a submodule .git
is a file with the following content:
gitdir: ../.git/modules/{SUBMODULE_NAME}
It sounds simple enough to have lefthook understand that and just follow that relative path instead and drop the hooks there.
(I did a quick test, that's all that's needed, if you drop the hooks in that folder instead it seems to work as expected)
On Windows 10 with lefthook 0.6.5, I get the following error:
exec: "sh": executable file not found in %PATH%
It even occurs when running lefthook version
.
I was working on adding Hashicorp Vault policy auto-formatting, but they allow only a single file to be passed. It would be nice of you can handle such commands and pass files one by one. It would be nice if this supports parallelism as well.
For this page: https://github.com/Arkweid/lefthook/wiki/Comprasion-with-other-solutions
The title:
- Comprasion with other solutions
+ Comparison with other solutions
Another utility to compare with: pre-commit
It has nice docs, but the syntax is a bit arcane. You can share hooks easily, though. It lacks a curated catalog of shared hooks, alas.
There's too much noise:
Lefthook v0.6.3
RUNNING HOOKS GROUP: pre-commit
EXECUTE > yamllint
(SKIP. NO FILES FOR INSPECTING)
EXECUTE > jsonnet-fmt
(SKIP. NO FILES FOR INSPECTING)
EXECUTE > vault-policy-fmt
SUMMARY: (done in 479.47 seconds)
✔️ vault-policy-fmt
This is good for debugging purposes, but if you have tens of different commands and just changed a single file, seeing all this is not signal, but noise. Showing the program and the version number is unnecessary either (if one cares, they can see that with lefthook version
).
Is there an API for incoming file changes from the post-merge
hook?
I have my hook setup to run db:migrate
after a merge. If I could have a check to see if any of the incoming files were migration files then I could skip the command altogether if none of the files match a regex filter of some kind to check if they're migrations.
maybe something like this?
post-merge:
commands:
glob: "db/migrate/*"
migrate: {incoming_files} && bundle exec rails db:migrate
I'm trying to use lefthook in monorepo. Config is located in root and lefthook is installed there, but on postinstall (literally - when I install any package to the subproject) it's trying to access lefthook binary in the inner node_modules.
You can see on the screenshot, lefthook is executed from paxshop-2.0/node_modules/@arkweid/lefthook
but trying to call paxshop-2.0/packages/paxshop/node_modules/@arkweid/lefthook/bin/lefthook-mac
It causes yarn to fail and not writing changes to package.json
.
unless you want me to just make a github issue CC @Arkweid
bin/lefthook
(don't see it in .rubygems
of this repo though) of the installed gem states:
when /windows/
'lefthook-win.exe'
else
Unfortunately in my environment RUBY_PLATFORM
is x64-mingw32
and I got:
$ lefthook install
C:/Tools/rubyinstaller-2.4.4-2-x64/lib/ruby/gems/2.4.0/gems/lefthook-0.6.3/bin/lefthook:11:in `<top (required)>': Invalid platform. (RuntimeError)
from C:/Tools/rubyinstaller-2.4.4-2-x64/bin/lefthook:23:in `load'
from C:/Tools/rubyinstaller-2.4.4-2-x64/bin/lefthook:23:in `<main>'
This can be solved: If I add the value to the when
I can install the hook.
When testing in my git-bash I get the color sequences as text, e.g.:
$ lefthook run pre-push
C:/Tools/rubyinstaller-2.4.4-2-x64/lib/ruby/gems/2.4.0/gems/lefthook-0.6.3/libexec/lefthook-win.exe run pre-push
←[36mRUNNING HOOKS GROUP:←[0m ←[1mpre-push←[0m
←[36m
EXECUTE >←[0m ←[1mrubocop←[0m
←[33m(SKIP. NO FILES FOR INSPECTING)←[0m
←[36m
EXECUTE >←[0m ←[1mtest←[0m
Not sure what's the root cause for that as for example I have a nicely colored prompt in that same bash.
Hello!
Appreciate if you can help me troubleshoot this issue I'm having. I'm trying to set up lefthook on my repo. So far, the pre-commit hook is returning "SKIP. NO FILES FOR INSPECTING" message even though there are staged files ready for commit. Please see below a description of the issue. Let me know if there's any other information you need! Thanks!
Given I have a git repo with a single file: a lefthook.yml
config:
pre-commit:
commands:
hello_world:
run: echo 'hello world!'
And I have installed lefthook like so:
sudo snap install --devmode lefthook
lefthook install
When I run echo 'test' > text.txt && git add -A && lefthook run pre-commit
Then I should see "hello world!"
lefthook-test 18:03:06 $ echo 'test' > text.txt && git add -A && lefthook run pre-commit
Lefthook v0.6.3
RUNNING HOOKS GROUP: pre-commit
EXECUTE > hello_world
(SKIP. NO FILES FOR INSPECTING)
SUMMARY: (SKIP EMPTY)
For exemple place it to projectDir/config
directory
For now we disable a colors if output a not a terminal.
Add a top level option
colors: false
And check it here:
https://github.com/Arkweid/lefthook/blob/0f8826ac9e85532143b8dec3256f5552d8c19745/cmd/root.go#L107-L109
Here's a minimal example:
FROM ubuntu:bionic
RUN : \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates \
curl \
git \
&& apt-get clean
RUN : \
&& curl --location --silent --output /tmp/lefthook.gz https://github.com/Arkweid/lefthook/releases/download/v0.6.3/lefthook_0.6.3_Linux_x86_64.gz \
&& echo '0876ae7a862cb26aa5bd50173502dfd836cd16317f7af18be0797deeb3e1cfcd /tmp/lefthook.gz' | sha256sum --check \
&& gunzip /tmp/lefthook.gz \
&& mv /tmp/lefthook /usr/local/bin \
&& chmod +x /usr/local/bin/lefthook \
&& which lefthook
WORKDIR /src
COPY lefthook.yml ./
ENV \
[email protected] \
GIT_AUTHOR_NAME='A A' \
[email protected] \
GIT_COMMITTER_NAME='A A'
RUN : \
&& git init . \
&& echo -n "staged contents" > t \
&& git add . \
&& : unstaged trailing whitespace, commit should succeed \
&& echo ' ' >> t \
&& lefthook install
CMD ["git", "commit", "-m", "test"]
pre-commit:
commands:
no-trailing-whitespace:
files: git diff --staged --name-only
run: if grep ' $' {files}; then exit 1; fi
docker build -t test .
docker run --rm -ti test
$ docker run --rm -ti test
Lefthook v0.6.3
RUNNING HOOKS GROUP: pre-commit
EXECUTE > no-trailing-whitespace
t:staged contents
SUMMARY: (done in 0.00 seconds)
🥊 no-trailing-whitespace
the commit should have succeeded as the trailing whitespace was only in the unstaged contents
A similar case exists but in the worse direction (commit allowed but the staged contents are incorrect)
adjusting the part of the dockerfile above:
$ diff -u Dockerfileold Dockerfile
--- Dockerfileold 2019-08-07 09:07:14.589180456 -0700
+++ Dockerfile 2019-08-07 09:09:58.543863227 -0700
@@ -26,10 +26,11 @@
RUN : \
&& git init . \
- && echo -n "staged contents" > t \
+ && : staged trailing whitespace should not be allowed \
+ && echo "staged contents " > t \
&& git add . \
- && : unstaged trailing whitespace, commit should succeed \
- && echo ' ' >> t \
+ && : remove the trailing whitespace but without staging \
+ && sed -i 's/ *$//g' t \
&& lefthook install
CMD ["git", "commit", "-m", "test"]
$ docker run --rm -ti test
Lefthook v0.6.3
RUNNING HOOKS GROUP: pre-commit
EXECUTE > no-trailing-whitespace
SUMMARY: (done in 0.00 seconds)
✔️ no-trailing-whitespace
[master (root-commit) 2e9d396] test
2 files changed, 6 insertions(+)
create mode 100644 lefthook.yml
create mode 100644 t
this should have failed, but instead allowed trailing whitespace to enter the repo
In any situation where fixers are involved, parallel: true
is unsafe
Here's a minimal example:
FROM ubuntu:bionic
RUN : \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates \
curl \
git \
python3-pip \
python3-setuptools \
&& apt-get clean
RUN : \
&& curl --location --silent --output /tmp/lefthook.gz https://github.com/Arkweid/lefthook/releases/download/v0.6.3/lefthook_0.6.3_Linux_x86_64.gz \
&& echo '0876ae7a862cb26aa5bd50173502dfd836cd16317f7af18be0797deeb3e1cfcd /tmp/lefthook.gz' | sha256sum --check \
&& gunzip /tmp/lefthook.gz \
&& mv /tmp/lefthook /usr/local/bin \
&& chmod +x /usr/local/bin/lefthook \
&& which lefthook
RUN pip3 install pyupgrade
WORKDIR /src
COPY lefthook.yml ./
ENV \
[email protected] \
GIT_AUTHOR_NAME='A A' \
[email protected] \
GIT_COMMITTER_NAME='A A'
RUN : \
&& git init . \
&& echo "world = 1; print('hello {}'.format(world)) # trailing ws " > t.py \
&& seq 1 1000 | xargs --replace cp t.py t{}.py \
&& lefthook install \
&& git add .
CMD ["bash", "-c", "git commit -m test >& /dev/null; sha256sum *.py | cut -d' ' -f1 | sort | uniq -c"]
pre-commit:
parallel: true
commands:
pyupgrade:
# tac is used to make this more reproducible, it happens without it
# just more rarely
files: git diff --staged --name-only -- '*.py' | tac
run: pyupgrade --py36-plus {files}
trailing-whitespace:
files: git diff --staged --name-only -- '*.py'
run: sed -i 's/ *$//g' {files}
docker build -t test .
docker run --rm -ti test
$ docker run --rm -ti test
1 d8a9bda5f09334903e4ba7bb0e3dc766106ccf379d71ce4eb3eba46b6274fd8f
1000 f6fadaa8047971e6253655ecee3a2ffcb5645983e913daa0f6110de6deea1d43
All files should have the same sha256sum as they were identical inputs (and therefore should have identical outputs)
I ran into a situation where I wanted to run parallel and piped commands.
So essentially on a post-merge, I'm hoping to capture any dependency updates and any migrations.
post-merge:
parallel: true
piped: true
commands:
yarn:
files: git diff --name-only HEAD master
glob: '{package.json,yarn.lock}'
run: yarn
tags: frontend
1_gem:
files: git diff --name-only HEAD master
glob: '{GEMFILE,GEMFILE.lock}'
run: bundle exec bundle check || bundle install
tags: backend
2_migrate:
files: git diff --name-only HEAD master
glob: '{db/migrate/*}'
run: bundle exec rails db:migrate && bundle exec rails db:test:prepare
tags: backend
So, I want to run the FE and BE commands in parallel, because neither of them depend on the output of the other.
I can't run a migration unless my bundle check passes, so I want it piped after a bundle check || bundle install. I could run them all piped, but they don't need to be and I figure lefthook could be smart enough to handle both, basically any commands without the prepended numbering system are run in parallel and commands with the numbering system are piped.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.