diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2017-04-26 21:26:54 +0100 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2017-04-26 21:26:54 +0100 |
commit | 246d0c03f0bf498f9a2ed86c29433d1ee9e17055 (patch) | |
tree | a30be1574af91b17f41afa529f6f5ce49402d0e8 /doc | |
parent | d2d522da024c59bd592d7c24d07b1272511766d4 (diff) | |
parent | 17f73b454311ef232c29e85d9eacde7941dd8097 (diff) | |
download | gitano-246d0c03f0bf498f9a2ed86c29433d1ee9e17055.tar.gz |
Merge remote-tracking branch 'origin/richardmaw/githookdoc'
(slight tweaks as per review)
Diffstat (limited to 'doc')
-rw-r--r-- | doc/admin/000.mdwn | 139 |
1 files changed, 138 insertions, 1 deletions
diff --git a/doc/admin/000.mdwn b/doc/admin/000.mdwn index 770bac8..8f36ec9 100644 --- a/doc/admin/000.mdwn +++ b/doc/admin/000.mdwn @@ -419,7 +419,7 @@ follows: * Otherwise, without the global prefix, it is included from the per-project rules - (`refs/gitano-admin` branch of the repository being operated on). + (`refs/gitano/admin` branch of the repository being operated on). Include statements can be made conditional by adding a predicate after the path, so you can split up your rules: @@ -433,6 +433,143 @@ so you can split up your rules: # Branches must not be tags deny "Branches may only be commits" [ref prefix refs/heads/] [newtype exact commit] +# Git Hook scripts + +Gitano administrators may create, or delegate creation of, +[Lua][lua] scripts to take action or provide further authentication +when content is pushed to a repository. + +These [Lua][lua] scripts are sandboxed using [Supple][supple], +to make it safer to run user-defined code. + +## How to add a hook + +Hooks are stored in the `gitano-admin.git` repository +and the `refs/gitano/admin` branch of each other repository, +so that there can be traceability of who is responsible for each hook. + +Global hooks in `gitano-admin.git` are loaded +from the `global-hooks` subdirectory. +Per-repository hooks in the `refs/gitano/admin` branch +are loaded from the `hooks` subdirectory. + +In both cases hooks are loaded from a file named after the hook +as defined by [githooks(5)][] suffixed with `.lua`. + +Currently the only hooks that are supported are: + +1. pre-receive +2. update +3. post-receive + +So a global pre-receive hook would be in the file `global-hooks/pre-receive.lua` +and a per-repository post-receive hook would be in `hooks/post-receive.lua`. + +## APIs available to hooks + +1. `log.$level(...)` to emit text at that log level. + $level can be one of: + + 1. `state` + 2. `crit` or `critical` + 3. `err` or `error` + 4. `warn` or `warning` + 5. `chat` + 6. `info` + 7. `debug` + 8. `ddebug` or `deepdebug` + +2. `fetch(url, headers, body, content_type)` during post-receive hooks. + +3. A `repo` object as the first parameter to per-repository hooks, + with the following methods: + + ------------------------------------ ---------------------------------------------------------------------------- + `:get(sha1ish)` Get the contents of a git object from anything matching [gitrevisions(7)][]. + `:get_config(confname)` Get the value confname from the repo config if it is a single value + `:get_config_list(confname)` Get the value confname from the repo config if it is a list value + `:check_signature(obj, keyringname)` Check whether `obj` is an object signed by a key in keyring `keyringname`. + ------------------------------------ ---------------------------------------------------------------------------- + + Objects returned from `get` are [gall][] objects. + Refer to [gall's API documentation][gall-api] for details. + +4. An `actor` table in the global environment, + containing the following indices: + + -------- -------------------------------------------------------------- + username Gitano username of user doing the push. + keytag Name of the ssh key the user is pushing with. + source "ssh", "http" or "git" depending on the protocol used to push. + realname Real name of user from user configuration. + email E-Mail of user from user configuration. + -------- -------------------------------------------------------------- + +5. The `refname`, `oldsha` and `newsha` as the second to fourth parameters + during per-repository update hooks, as described in [githooks(5)][]. + + Checking whether the master ref is deleted would be accomplished by: + + local _, refname, oldsha, newsha = ... + if refname == "refs/heads/master" and newsha == ("0"):rep(40) then + log.state("Master deleted") + end + +6. For pre-receive or post-receive per-repository hooks as the second parameter, + a table indexed by the `refnames` being modified + containing tables of the `oldsha` and `newsha` indexed + either at positional indices `1` and `2`, + or by name `oldsha` and `newsha`. + Checking whether the master ref is deleted would be accomplished by: + + local _, updates = ... + if (updates["refs/heads/master"] or {}).newsha == ("0"):rep(40) then + log.state("Master deleted") + end + +7. Global hooks work the same as per-repository hooks, + except they are passed a callable function first, followed by the + positional parameters as described above. The callable will run the + per-repository hook when called, + so global hooks may either replace or augment per-repository hooks. + + To unconditionally run some global hook code and then call a local hook + your global hook would be structured something like: + + -- Example global-hooks/update.lua + local hookf, repo, refname, oldsha, newsha = ... + -- Do stuff with repo/refname/oldsha/newsha here + -- + -- And finally (optionally) tail-chain through to the per-repo hook + return hookf(repo, refname, oldsha, newsha) + + To unconditionally ignore update hooks and log why: + + -- Example global-hooks/update.lua + local hookf, repo, refname, oldsha, newsha = ... + local treeish = repo:get("refs/gitano/admin").sha + if repo:get(treeish..":hooks/update.lua") then + log.state("Update hooks are disabled") + end + + To provide a default if a hook is not defined: + + -- Example global-hooks/update.lua + local hookf, repo, refname, oldsha, newsha = ... + local treeish = repo:get("refs/gitano/admin").sha + if repo:get(treeish..":hooks/update.lua") then + return hookf(repo, refname, oldsha, newsha) + end + -- Do stuff with repo/refname/oldsha/newsha here + + +[lua]: https://www.lua.org/ +[supple]: https://www.gitano.org.uk/supple/ +[githooks(5)]: https://git-scm.com/docs/githooks +[gitrevisions(7)]: https://git-scm.com/docs/gitrevisions +[gall]: https://www.gitano.org.uk/gall/ +[gall-api]: file:///usr/share/doc/lua-gall-doc/html/index.html + # Backup and restore of a Gitano instance When gitano-setup is run, the admin needs to specify a Unix user in |