epsilon-devel
[Top][All Lists]
Advanced

[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".

Attachment: send-through-irker
Description: send-through-irker

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]