site-josuah

/usr/josuah
Log | Files | Refs

commit 49fefb88ae08d6f319d0ad5f1ce29f487914c53e
parent f197ae3c6f6434748b67b6e60497b800f2480125
Author: Josuah Demangeon <me@josuah.net>
Date:   Fri, 17 Apr 2020 22:52:16 +0200

fix the git-hooks-* scripts

Diffstat:
D.githooks/.post-update.swp | 0
Mindex.md | 13++++++++-----
Dwiki/git-hooks/index.md | 98-------------------------------------------------------------------------------
Awiki/githooks/index.md | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mwiki/supervisor/index.md | 49+++++++++++++++++++++----------------------------
5 files changed, 118 insertions(+), 131 deletions(-)

diff --git a/.githooks/.post-update.swp b/.githooks/.post-update.swp diff --git a/index.md b/index.md @@ -3,17 +3,20 @@ Welcome to my publication tool, [[josuah.net]]. You can find documentation about my software projects: * The [[NotWiki]] project, a website/gophersite generation tool. + * My [[githooks]] scripts, that regenerate my NotWiki sites. - * My [[githooks]] scripts, tiny alternative to [[githooks.com]]'s setups. +[notwiki]: //code.z0.is/notwiki/ +[githooks]: //josuah.net/wiki/githooks/ As well as documentation on other people's software: -And finally, [[ASCII]] Art and a soon-to-disappear [[blog]]. + * Use of [[awk]], the command/language. + +[awk]: //josuah.net/wiki/awk/ + +And finally, [[ASCII]] Art. -[notwiki]: //code.z0.is/notwiki/ -[githooks]: //josuah.net/wiki/git-hooks/ [ascii]: /ascii/ -[blog]: /blog/ You can access to this server through tor: diff --git a/wiki/git-hooks/index.md b/wiki/git-hooks/index.md @@ -1,98 +0,0 @@ -Minimal Git Hooks configuration to get started -============================================== - -Git [[hooks]] permit to run commands on a range of git events, mainly: a git -commit. - -I use 3 shell scripts of roughly 10 lines each to configure git hooks, calling -scripts from within the repository itself: .githooks/<hookname> - -[hooks]: https://githooks.com/ - -git-hooks-run -------------- -This is what runs on every event, to put on /bare-repo.git/hook/<hookname>. -There is no point in running it by hand. - - #!/bin/sh -e - - hookname=$1 ref=$2 - - [ "$(git ls-tree "$ref" ".git$hookname")" ] || exit 0 - - echo "${0##*/}: running '$1' on '$ref'" - git cat-file blob "$ref:.git$hookname" | { - IFS='! ' read -r _ cmd args - exec "$cmd" "$args" "/dev/stdin" "$ref" - } - -It checks if there is a file called .githooks/<hookname> (git ls-tree "$ref" -...), and if so, extract this file from git (git cat-file blob ...), read the -shebang, and execute the rest with the command of the shebang ("| { ... }"). - - -git-hooks-install ------------------ -This setups the command above for a bare git repository: - - #!/bin/sh -e - # setup git hooks to run .githook from the inside of the repo - - for x; do - for hook in pre-commit pre-receive post-commit post-receive; do - echo "#!/usr/bin/env git-hooks-run" >"$x/hooks/$hook" - chmod +x "$x/hooks/$hook" - done - done - -It replace selected hooks at repo.git/hooks/<hookname> with only this shebang: - - #!/usr/bin/env git-hooks-run - -This has the effect of calling the git-hooks-run from above with -hook/<hookname> as argument, along with the extra arguments providedd by git, -which is all we need for our hooks. - - -git-hooks-workdir ------------------ -With only git-hooks-run, we lack a way to use the content of the repository -to interact with the hooks (it is not always needed to use the content). - -In case this is needed, this command extract the workdir of the commit pushed -into a new directory in /var/cache/git (that it delete in case of failure), -and print it out so that the hook script can use it: - - #!/bin/sh -e - # utility to run from hooks to create a temporary working directory - - ref=$1 - commit=$(git rev-parse "$ref") - workdir="/var/cache/git/$commit" - - mkdir -p "$workdir" - trap 'rm -rf "$workdir"' INT EXIT TERM HUP - git archive --prefix="$workdir/" --format="tar" "$ref" | (cd / && tar -xf -) - exec echo "$workdir" - -To use it from within the hook, to catch the workdir and make sure there is -no remaining file even in case of failure, thanks to the trap internal shell -command: - - #!/bin/sh -ex - tmp=$(git-hooks-workdir "$@") - trap 'rm -rf "$tmp"' INT TERM EXIT HUP - cd "$tmp" - -This might be the top of your hook script. - -The (optional) -x flags in the shebang, which will print every command as it is -executed. It will be printed on commiter side as "remote: $line". - -The (optional) -e flag is there to die if any command fails, such as the initial -cd to the "$tmp" directory. - -At that point, we will be in a workind directory containing the content of the -state at the commit pushed, and we can run commands, such as running unit test -(make test), send an email or anything we need. - diff --git a/wiki/githooks/index.md b/wiki/githooks/index.md @@ -0,0 +1,89 @@ +Minimal Git Hooks configuration +=============================== + +Git [[hooks]] permit to run commands on a range of git events, mainly: a git +commit. + +I use 3 shell scripts of roughly 10 lines each to configure git hooks, calling +scripts from within the repository itself: .githooks/<hookname> + +[hooks]: https://githooks.com/ + +git-hooks-run +------------- +This is what runs on every event, to put on /bare-repo.git/hook/<hookname>. +There is no point in running it by hand. + + #!/bin/sh -e + hookname=$1 ref=${2:-master} + + echo "${0##*/}: running '$1' on '$ref'" + git cat-file blob "$ref:.git$hookname" | { + IFS='! ' read -r _ cmd args + exec "$cmd" "$args" "/dev/stdin" "$ref" + } + +It checks if there is a file called .githooks/<hookname> (git ls-tree "$ref" +...), and if so, extract this file from git (git cat-file blob ...), read the +shebang, and execute the rest with the command of the shebang ("| { ... }"). + + +git-hooks-install +----------------- +This setups the command above for a bare git repository: + + #!/bin/sh -e + for x; do + echo "#!/usr/bin/env git-hooks-run" >"$x/hooks/post-upate" + chmod +x "$x/hooks/post-update" + done + +It replace selected hooks at repo.git/hooks/post-update with only this shebang: + + #!/usr/bin/env git-hooks-run + +This has the effect of calling the git-hooks-run from above with +hook/post-update as argument, along with the extra arguments providedd by git, +which is all we need for our hook. + + +git-hooks-workdir +----------------- +With only git-hooks-run, we lack a way to use the content of the repository +to interact with the hooks (it is not always needed to use the content). + +In case this is needed, this command extract the workdir of the commit pushed +into a new directory in /var/cache/git (that it delete in case of failure), +and print it out so that the hook script can use it: + + #!/bin/sh -e + ref=$1 + commit=$(git rev-parse "$ref") + workdir="/var/cache/git/$commit" + + mkdir -p "$workdir" + trap 'rm -rf "$workdir"' INT EXIT TERM HUP + git archive --prefix="$workdir/" --format="tar" "$ref" | (cd / && tar -xf -) + exec echo "$workdir" + +To use it from within the hook, to catch the workdir and make sure there is +no remaining file even in case of failure, thanks to the trap internal shell +command: + + #!/bin/sh -ex + tmp=$(git-hooks-workdir "$@") + trap 'rm -rf "$tmp"' INT TERM EXIT HUP + cd "$tmp" + +This might be the top of your hook script. + +The (optional) -x flags in the shebang, which will print every command as it is +executed. It will be printed on commiter side as "remote: $line". + +The (optional) -e flag is there to die if any command fails, such as the initial +cd to the "$tmp" directory. + +At that point, we will be in a workind directory containing the content of the +state at the commit pushed, and we can run commands, such as running unit test +(make test), send an email or anything we need. + diff --git a/wiki/supervisor/index.md b/wiki/supervisor/index.md @@ -10,7 +10,7 @@ A simple problem, a simple solution: make the process double-fork so the user sitting at the terminal is free to keep going. pgrep and ps are your friends now. -This is one simple approach, but lead to that problem how to run the same +This is one simple approach, but lead to that problem how to run the same daemon twice? Knee-jerk reaction: "Why would one want to do that?" @@ -22,32 +22,25 @@ Knee-jerk reaction: "Why would one want to do that?" * Different agetty with one per TTY, * ... -The solution often encountered is handling the variety of roles -from the inside of the daemon instead of starting one dedicated -daemon per role: with configuration blocks that lets you handle -each different roles in a different way (per vhost, per network -interface, per tty, per tcp port...). +The solution often encountered is handling the variety of roles from the inside +of the daemon instead of starting one dedicated daemon per role: with +configuration blocks that lets you handle each different roles in a different +way (per vhost, per network interface, per tty, per tcp port...). -That makes each and every daemon much more complex. They all need -a complex configuration file parser and have a much more complex -internal design. - -Why not one daemon per configuration block? Because when a daemon -puts itself to the background (through forking), we loose its PID -(Process ID) and then we cannot distinguish two identical daemons. -How do we know which one to restart then? +That makes each and every daemon much more complex. They all need a complex +configuration file parser and have a much more complex internal design. Solutions? - * Writing the PID into a file is not good, as if a daemon gets killed while - getting out of memory, the PID file remains, and another daemon could get + * Writing the PID into a file is not good, as if a daemon gets killed while + getting out of memory, the PID file remains, and another daemon could get the PID of its parent (SysV-style). - * Having a ${daemon}ctl command that talks to the daemon through a socket - works, but then each daemon needs to support it while a simple signal handling + * Having a ${daemon}ctl command that talks to the daemon through a socket + works, but then each daemon needs to support it while a simple signal handling would solve all use cases (*BSD-style). - * Matching the command line the daemon was started with with pgrep works but + * Matching the command line the daemon was started with with pgrep works but it requires to adapt it to each daemon (also *BSD-style). * Use Linux-specific APIs to work around the issues lead by the diversity of @@ -60,22 +53,22 @@ control back to the terminal was convenient for running programs from a shell, but causes problems on other sides. need to get the control back to the terminal after starting the program... -Then use one process to launch all the others: A "supervisor" that starts the -daemons, and keeps each daemon as a child proces. The supervisor knows their +Then use one process to launch all the others: A "supervisor" that starts the +daemons, and keeps each daemon as a child proces. The supervisor knows their PID without pidfile or socket. That is how fork(2) works: it returns the PID to the parent so that it can wait(2) for it, send it signals... -How to organize daemons then? A trivial approach is to have one run script per +How to organize daemons then? A trivial approach is to have one run script per daemon to launch, that exec(2) into the daemon which stays at the foreground. -Once the supervisor is is triggered, it can start each of these ./$daemon/run -scripts, keep them as child, and watch for more to come, with some -./$daemon/sock for listenning for commands such as "restart", "stop", "alarm" +Once the supervisor is is triggered, it can start each of these ./$daemon/run +scripts, keep them as child, and watch for more to come, with some +./$daemon/sock for listenning for commands such as "restart", "stop", "alarm" to send signals to the daemon. -The supervision system was complex to implement right and half baked inside of -each daemon with ${daemon}ctl, it is now done reliably once for all daemons in +The supervision system was complex to implement right and half baked inside of +each daemon with ${daemon}ctl, it is now done reliably once for all daemons in a dedicated program: the supervisor. -Running this/these extra processes does not consume much more memory (one +Running this/these extra processes does not consume much more memory (one megabyte?) and makes each daemon smaller, compensating for the lost bytes.