DavidCastagna
DavidCastagna

Reputation: 101

Is Gerrit blocking my Git pre-receive hook?

I have the following setup (All of this on a single machine):

  1. Gerrit is configured and running.
  2. Git repositories for Gerrit are co-located on that machine.
  3. All relevant mounts are with options=defaults (meaning exec is allowed).
  4. A particular git has a single "pre-receive" hook defined in it.
  5. That git is also a Gerrit project.
  6. Gerrit is 2.4.* and Git is 1.7.4.1

I clone the repo mentioned in 4 and 5 above using:

  git clone ssh://<host>:29418/<project>.git

I create a simple change (I just "ls" to a new file and add that and then commit):

  cd <project>
  ls > tmp.txt
  git add tmp.txt
  git commit --message="This does not work"
  git push origin HEAD:refs/heads/master

And I fully expect the push to be blocked. Here's why:

The pre-receive hook is here:

  ..prompt..> ls -l <basestoragedir>/<project>.git/hooks
  total 4
  -rwxr-xr-x 1 ..user.. ..group.. 279 Jun 24 15:25 pre-receive

The pre-receive hook itself is just a bunch of echoes/dumps to a log file but with an error exit (which should effectively block every push):

  #!/bin/bash

  date >> /tmp/pre-receive.log
  echo "Got to the pre-receive hook." >> /tmp/pre-receive.log
  env >> /tmp/pre-receive.log      
  exit -1

So the log never updates. And every attempt to push a change to this repo succeeds.

Any ideas why?

I read a snippet in the Gerrit documentation:

Gerrit does not run any of the standard git hooks in the repositories it works with, but it does have its own hook mechanism included. Gerrit looks in '$site_path'/hooks for executables with names listed below.

But I interpreted this to mean that Gerrit doesn't use Git hooks to execute its functionality. Instead it provides its own behavior in addition to Git hooks. Is that true? Or does Gerrit actually clobber the Git hook execution mechanism?

So operating on the assumption that Gerrit clobbers Git hooks then what can I implement that will block a push? It seems pretty stupid of the Gerrit design to negate such an important policy enforcement tool.

Upvotes: 2

Views: 2367

Answers (2)

Mark Fisher
Mark Fisher

Reputation: 9886

The latest version of gerrit states on its config-hooks page that

ref-update

This is called when a push request is received by Gerrit. It allows a push to
be rejected before it is committed to the Gerrit repository. If the script
exits with non-zero return code the push will be rejected.

This doesn't exist in gerrit 2.4 looking at its config-hooks page.

I would say that gerrit is indeed (and deliberately) not running hooks for individual projects. Normally, if you want to block a push directly to master, don't give permissions on the project to refs/master/*, and use the standard review workflow to accept/reject check-ins to the project's repository.

Upvotes: 1

Brad
Brad

Reputation: 5532

But I interpreted this to mean that Gerrit doesn't use Git hooks to execute its functionality. Instead it provides its own behavior in addition to Git hooks. Is that true?

No. Gerrit doesn't run git hooks. There is no other server/service to run the hooks. Gerrit uses jgit to handle all git operations, and does not call the standard hooks.

So operating on the assumption that Gerrit clobbers Git hooks then what can I implement that will block a push?

There are a couple options. See the hooks documentation at http://gerrit-documentation.googlecode.com/svn/Documentation/2.6/config-hooks.html - here at $DAYJOB, we use a patchset-created hook to inspect the push and review it with a -2 score if something is wrong. This still lets the push go through, but blocks it from being merged into the codebase.

Another option is a plugin, such as the commit message length validator plugin - https://gerrit-review.googlesource.com/#/admin/projects/plugins/commit-message-length-validator. It will block a push if the commit message length doesn't match the requirements.

Upvotes: 0

Related Questions