[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Automatic IRC notifications of git repository updates
From: |
Luca Saiu |
Subject: |
Automatic IRC notifications of git repository updates |
Date: |
Tue, 04 May 2021 20:29:49 +0200 |
User-agent: |
Gnus (Gnus v5.13), GNU Emacs 27.0.50, x86_64-pc-linux-gnu |
Hello.
As José knows I have recently set up a script sending IRC notifications
after a git repository is updated on git.ageinghacker.net .
The idea is that, after somebody commits a change to the server, the
relevant IRC channel prints an automatic notification such as:
--8<---------------cut here---------------start------------->8---
<irker832> Jose E. Marchesi on pokology refs/heads/master: New page videos.org
http://git.ageinghacker.net/pokology/commit/?id=e282971f6b98b638ea8c5931718272ecb71d4dd5
--8<---------------cut here---------------end--------------->8---
This functionality is currently enabled for Jitter and for pokology, a
repository now hosted on ageinghacker.net holding the articles on José's
«Applied pokology» blog at
http://jemarch.net/pokology.html
.
The infrastructure is general enough to be easily generalised later;
ideally it would be nice to provide the same services on GNU machines.
José will talk to the Savannah people and maybe show them this message.
In this message I am quickly describing my configuration, hoping that
this short writeup may be useful to others, mostly for the archives.
Disclaimer: I am definitely not a git expert, and this solution is less
clean that I would have liked; in fact I became annoyed by the
complexity and unreliability of some suggested solutions, and ended up
reimplementing some hook logic from scratch.
Requirements:
* gitolite 3 https://gitolite.com
* cgit, mostly irrelevant here https://git.zx2c4.com/cgit/about/
* irker by Eric Raymond http://www.catb.org/esr/irker
* my own custom Bash script as a git hook attached to this message
* git, netcat, GNU coreutils, any Awk, as used by the script
On ageinghacker.net I use Gitolite 3 to administer multiple Git
repositories, including the jitter repository. Gitolite introduces some
complexity and some specific problems which will be irrelevant on GNU
machines, even if I anticipate that the Savannah scripts to create and
destroy repositories will present some similarities as well.
I tried to follow
http://laurent.bachelier.name/2012/12/using-irker-cia-replacement-and-gitolite/
which has good ideas but is outdated. I use gitolite3, like everybody
else probably does nowadays -- the first release of gitolite3 was
published back in 2012.
On the server, install irkerd from the debian package. We will use the
irkerd executable, which does a very fine job, but we will ignore the
git hooks provided as examples. The client connecting to irkerd is
the shell script attached here.
On the server I need to make sure that each repo can set its own
variables. In /etc/gitolite3/gitolite.rc (or, if you have it as a
different file, .gitolite.rc ) make sure that you have
GIT_CONFIG_KEYS => '.*',
in the %RC structure. (Notice that old documentation speaks of a variable
named $GL_GIT_CONFIG_KEYS. That has since changed.)
Again within %RC, in the same file, set this binding:
LOCAL_CODE => "$ENV{HOME}/local",
(I had to uncomment it.)
Now, let us make a new nice repo in gitolite.conf:
repo pokology
RW+ = admin @jose
RW = @egeyar @luca @mohammad
config cgit.owner = "José Marchesi"
config cgit.section = "8 - Projects by friends"
config gitweb.description = "Applied Pokology
http://jemarch.net/pokology.html"
config irker.project = pokology
config irker.repo = pokology
config irker.channels = "irc://chat.freenode.net/_HASH_poke"
The «irker.» variables constitute the repository-specific configuration
for IRC notifications.
Notice that the character '#' needs to be escaped (this ugly «_HASH_»
syntax I introduced at least makes it easy to just use sed), because of
limitations of the gitolite.conf syntax -- that could be circumvented by
redefining some regular expression, at the cost of other problems.
Towards the end, let us add this in order to execute the hook in
send-through-irker
on *every* repository:
repo @all
config irker.urlprefix = "http://git.ageinghacker.net/%GL_REPO/commit/?id="
- VREF/send-through-irker = @all
An alternative for the last line: add this one line to each repository
for which the hook is to be used:
- VREF/send-through-irker = @all
Now, the «urlprefix» serves to compose a URL in the IRC message,
pointing to the web interface describing the commit. For example
http://git.ageinghacker.net/pokology/commit/?id=e282971f6b98b638ea8c5931718272ecb71d4dd5
What we need is an update hook on the git server. Unfortunately
gitolite uses update hooks for its own purposes; its documentation
recommends «VREFs» for definint user update hooks, which is what I
defined here.
https://gitolite.com/gitolite/non-core.html#vrefs
(Search for «Gitolite reserves the update hook», and what follows.)
(Apparently it was also possibly in the past to easily "chain"
multiple update hooks.)
(The irker documentation suggests editing ~/.gitconfig for the gitolite
user, with settings like:
[irker]
color = mIRC
cialike = 60
Those would apply to every repo. I have not done that but might want to
do that in the future for my installation.)
Let us implement our «VREF». The same script will work for every
repository or only for those which use the functionality, as per
gitolite.conf . In any case the file to be edited is only one.
As the gitolite3 user:
$ mkdir -p ~gitolite3/local/VREF/
$ emacs -nw ~gitolite3/local/VREF/send-through-irker
$ chmod +x ~gitolite3/local/VREF/send-through-irker
I am attaching a copy of my current send-through-irker to this message.
In order to make the hook visible to every repo execute, again as
gitolite3:
$ gitolite setup
Updating the gitolite configuration by pushing a modified gitolite.conf
also seems to work.
For ease of consultation on web-based mailing list archives I am also
including a copy of the script here in the message body.
--8<---------------cut here---------------start------------->8---
#!/bin/bash
# This shell script was writen in 2021 by Luca Saiu
# <positron@gnu.org>, who disclaims every copyright interest and
# places this work into the public domain.
# set -x
# Configuration
#####################################################################################
irkerdhost=localhost
irkerdport=6659
# Command line
#####################################################################################
refname="$1"
old="$2"
new="$3"
# Global definitions
#####################################################################################
urlprefix=$(git config irker.urlprefix)
repo=$(git config irker.repo || git config irker.project || echo 'unknown-repo')
nickname=${repo}-commit
project=$(git config irker.project || echo ${repo})
ircurls=$(git config irker.channels | sed 's/_HASH_/#/g')
# irkerhook --refname=${refname} $(git rev-list --reverse ${old}..${new})
# exit 0
# Extracting information from the repo
#####################################################################################
# Given an sha, write the commit author / committer to stdout in a
# format suitable for the message.
last_commit_author ()
{
sha="$1"
LC_ALL=C
git show ${sha} --pretty=fuller --summary \
| grep '^\(Author\|Commit\): ' \
| sed 's/^[^:]*: //' \
| uniq \
| tr '\n' ' ' \
| sed 's/[^@ \t<>()]\+@[^@ \t<>()]\+//g' \
| sed 's/[<>()]//g' \
| sed 's/^ \+//;s/ \+$//' \
| sed 's/^ \+//;s/ \+$//' \
| sed 's/[ \t]\+/ /g'
}
# Sending one notification
#####################################################################################
send ()
{
ircurl="$1"
message="$2"
# set -x
echo "Notifying ${ircurl}: ${message}"
# irkerd \
# --immediate "${ircurl}" \
# --nick "${nickname}" \
# "${message}"
json="{\"to\":\"${ircurl}\", \"privmsg\":\"${message}\"}"
# echo "JSON: $json"
echo "${json}" \
| netcat -q0 ${irkerdhost} ${irkerdport} > /dev/null \
|| echo "Failed sending an IRC notification"
}
# Finding the relevant SHAs
#####################################################################################
refprefix=''
if test "${old}" = '0000000000000000000000000000000000000000' \
&& test "${new}" != '0000000000000000000000000000000000000000'; then
shas="${new}"
refprefix='(new branch) '
elif test "${old}" != '0000000000000000000000000000000000000000' \
&& test "${new}" = '0000000000000000000000000000000000000000'; then
shas="${old}"
refprefix='(delete branch) '
elif test "${new}" = '0000000000000000000000000000000000000000' \
&& test "${new}" = '0000000000000000000000000000000000000000'; then
shas="HEAD"
elif test "${old}" = "${new}"; then
shas="${new}"
refprefix='(forced update) '
else
shas=$(git log --pretty=oneline ${old}..${new} | awk '{print $1}' | tac)
fi
# Debugging
#####################################################################################
if false; then
echo "OLD >$old<"
echo "NEW >$new<"
echo "SHAS >$shas<"
fi
# Main routine
#####################################################################################
for ircurl in ${ircurls}; do
for sha in ${shas}; do
author=$(last_commit_author ${sha})
firstline=$(git show --pretty=oneline ${sha} 2> /dev/null | head
--lines=1 | sed "s/^${sha} //")
message="${author} on ${project} ${refprefix}${refname}: ${firstline}
${urlprefix}${sha}"
send "${ircurl}" "${message}"
done
done
--8<---------------cut here---------------end--------------->8---
--
Luca Saiu
* My personal web site: http://ageinghacker.net
* Jitter: http://ageinghacker.net/projects/jitter
* GNU epsilon: http://www.gnu.org/software/epsilon
I support everyone's freedom of mocking any opinion or belief, no
matter how deeply held, with open disrespect and the same unrelented
enthusiasm of a toddler who has just learned the word "poo".
send-through-irker
Description: send-through-irker
signature.asc
Description: PGP signature
- Automatic IRC notifications of git repository updates,
Luca Saiu <=