Skip to content

Conversation

dblessing
Copy link
Member

This custom hook implementation support pre-receive, post-receive and update hooks. If a gitlab administrator wants to add a custom hook they need to follow these steps:

  1. Create a custom_hooks directory in the repository directory adjacent to the normal hooks directory. For example, if the repo path is /home/git/repositories/my_group/my_project.git, the custom hook path will be /home/git/repositories/my_group/my_project.git/custom_hooks
  2. Create/place a hook of the desired type in this custom_hooks directory.
  3. Make the hook file executable and owned by the git user.
  4. Profit. The new custom hook should be picked up by gitlab-shell on the next push. If there are errors in the custom hook the push may fail, unless it's post-receive. If the hook is not owned by git or is not executable the custom hook will silently fail.

What's missing?

  1. Other hooks types - pre-commit/etc

def hook_files(type)
# Get all files for this repo and hook type.
# i.e. ${custom_hooks_dir}/${namespace}/${repo_name}/(pre-receive|update|etc)
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this would not be multiple files. Only one hook per type per repo.

@dzaporozhets
Copy link
Contributor

The idea is ok. Ping me when ready for review

else
exit 1
end
exit 1 unless GitlabCustomHook.new.pre_receive(repo_path, key_id, refs).exec
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi @dblessing. Good job. Where would the custom hooks be located?
Some comments on the pre-receive hook changes:

  1. You're calling the custom hook before the gitlab acccess control check. I think this is akin to making a pre-authorization hook and the hook name should reflect that.
  2. You should also have a call to the custom hook after the gitlab hook access control check. You can call this one the pre-receive one as it will then be equivalent (in my eyes) to where a standard git hook would be called. For example, if accessing that repo thru ssh.
    If you only intend to have one such call to a custom hook, I'd give a preference to have this be for a custom pre-receive hook and that it be called after the gitlab access control check.
  3. The gitlab pre-receive hooks sets up an environment variable called 'GL_ID' . Further on, the exec method in the gitLabCustomHook exec method unsets this variable if the access control check fails. A comment there says "reset GL_ID env since we stop git push here" (gitlab_access.rb). I didn't look into detail into the code to see why this environment variable has to be setup. However, as it's set up in one place and unset elsewhere, this seems to point out that you should do the same before the call to exit 1. You could do this in the GitlabCustomHook function and document that the custom hook must return true or false rather than exit.
    However, a best practice would be to set and unset those variables in the same place. That's what I would do myself and instead of having multiple exit 1, just have a single exit 0 and and an exit 1 and unset the env. variable before the call to the exit 1.

end

def hook_file(hook_type, repo_path)
hook_path = repo_path.gsub(/hooks$/, 'custom_hooks')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useless assignment to variable - hook_path.

@dblessing
Copy link
Member Author

@jkbzh I have a possible implementation (see commits). I'm still testing, but if you're interested I would appreciate some further testing by you and others in development/test environments. I'm not yet certain args are being passed correctly.

def pre_receive(old_value, new_value, ref_name, repo_path)
hook = hook_file('pre-receive', repo_path)
return 0 if hook.nil?
return system(*hook, old_value, new_value, ref_name) ? 0 : 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant return detected.

@dblessing dblessing force-pushed the feature/custom_hooks branch 3 times, most recently from a96367f to a876393 Compare November 4, 2014 14:31
@@ -23,9 +23,12 @@ def exec
def update_redis
queue = "#{config.redis_namespace}:queue:post_receive"
msg = JSON.dump({'class' => 'PostReceive', 'args' => [@repo_path, @actor, @changes]})
unless system(*config.redis_command, 'rpush', queue, msg, err: '/dev/null', out: '/dev/null')
if system(*config.redis_command, 'rpush', queue, msg,
err: '/dev/null', out: '/dev/null')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Align the parameters of a method call if they span more than one line.

@dblessing dblessing force-pushed the feature/custom_hooks branch from a876393 to 7f95e3f Compare November 4, 2014 14:33
@dblessing
Copy link
Member Author

@randx I think this is ready for your review.

@dblessing dblessing changed the title WIP - Custom hooks POC Custom hooks Nov 4, 2014
@dblessing
Copy link
Member Author

There's not a really great way to document this in gitlab-shell. Should we put something in GitLab docs instead?

@dblessing dblessing force-pushed the feature/custom_hooks branch from 7f95e3f to d082978 Compare November 5, 2014 12:20
@dblessing
Copy link
Member Author

@randx Fixed return values

@jkbzh
Copy link
Contributor

jkbzh commented Nov 5, 2014

@dblessing forked and look at it right now. Could you tell me where are the arguments you're not sure you're passing to and in which files? If we could irc that would save time.

@dblessing
Copy link
Member Author

@jkbzh I'll be on #gitlab IRC in about 45 min. (dblessing). I'm interested in whether I have the right args in the right order for the diff hook types. For example, system(*hook, ref_name, old_value, new_value) for update hooks. As best I can tell based on git hook docs I do have them right but I'd love some validation.

@jkbzh
Copy link
Contributor

jkbzh commented Nov 5, 2014

@dblessing comparing against a stand-alone git setting, the hooks expect to be feed the changes line thru stdin, not as cli arguments. I'll shortly send a PR with a modified gitlab_custom_hook.rb that shows how to do it.

@dblessing dblessing force-pushed the feature/custom_hooks branch from d082978 to ce73915 Compare November 5, 2014 21:00

def receive(type, refs, repo_path)
unless type == 'pre-receive' || type == 'post-receive'
puts "GitLab: An unexpected error occurred " \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer single-quoted strings when you don't need string interpolation or special symbols.

@dblessing dblessing force-pushed the feature/custom_hooks branch from ce73915 to ac6338c Compare November 5, 2014 21:00
@dblessing
Copy link
Member Author

@jkbzh I updated this PR so the pre-receive now should receive all stdin. Post-receive already supported this. Update hook is called once per branch pushed so it does not need this type of support.

@dblessing dblessing force-pushed the feature/custom_hooks branch from ac6338c to 3ef7cdf Compare November 5, 2014 21:16
hook_file = "#{hook_path}/#{hook_type}"
hook_file if File.exist?(hook_file)
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra empty line detected at body end.

@dblessing dblessing force-pushed the feature/custom_hooks branch from 786c378 to 668e583 Compare November 6, 2014 14:48
@dblessing
Copy link
Member Author

Ok, we're really ready for review now, @randx. Thanks to help from @jkbzh we have a nice working implementation.

private

def call_receive_hook(hook, changes)
require 'open3'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont like require inside method

- Reset G_ID if the custom pre-receive hook fails
- Use a pipe to feed stdin to the custom pre- and post-receive
  hooks, in the same way that the standalone git works
@dblessing dblessing force-pushed the feature/custom_hooks branch from 668e583 to b6d84f6 Compare November 6, 2014 19:26
dzaporozhets added a commit that referenced this pull request Nov 7, 2014
@dzaporozhets dzaporozhets merged commit ff9808c into gitlabhq:master Nov 7, 2014
@dzaporozhets
Copy link
Contributor

Looks good! Thank you @dblessing and @jkbzh

@dzaporozhets
Copy link
Contributor

One thing I forgot to ask is to update CHANGELOG. Can you please submit PR for this?

@dblessing
Copy link
Member Author

@randx Which version should this be under? v2.1.0 is already released, correct? What will the next version be?

@dzaporozhets
Copy link
Contributor

2.2.0

@dosire
Copy link
Member

dosire commented Nov 9, 2014

@dblessing Would you be so kind to add documentation for this in the doc directory? I think it can be linked from the administrator documentation http://doc.gitlab.com/ce/

@dosire
Copy link
Member

dosire commented Nov 9, 2014

@dblessing Just noticed you already made https://github.com/gitlabhq/gitlabhq/pull/8276/files Awesome!

@coveralls
Copy link

coveralls commented Apr 14, 2016

Coverage Status

Coverage decreased (-0.07%) to 98.01% when pulling 72e21a4 on dblessing:feature/custom_hooks into cc193ea on gitlabhq:master.

@coveralls
Copy link

coveralls commented Apr 14, 2016

Coverage Status

Coverage decreased (-1.3%) to 96.823% when pulling 72e21a4 on dblessing:feature/custom_hooks into cc193ea on gitlabhq:master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

6 participants