[Ksummit-discuss] [CORE TOPIC] services needed from kernel.org infrastructure

James Bottomley James.Bottomley at HansenPartnership.com
Wed Jul 8 07:31:13 UTC 2015


On Tue, 2015-07-07 at 22:42 +0200, Jiri Kosina wrote:
> I think it'd be useful to have a session where maintainers could come up 
> with feature / improvement requests for kernel.org infrastructure and have 
> a subsequent discussion about whether they would be generally useful.
> 
> Let me start with my personal wish:
> 
> I personally would very welcome a facility that'd send out an e-mail if a 
> new commit is pushed to a git.kernel.org repo branch (sort of what tip-bot 
> and akpm's scripts are doing these days) to automatically notify the patch 
> author that the patch has been merged and pushed out.
> 
> Suggested attendance: Konstantin, maintainers :)

I can give you my scripts: they send email when patches are added and
dropped from the SCSI git trees.  The only problem is you need a
non-kernel.org server to run them on.  It's a simple perl script
(attached).

James

---

#!/usr/bin/perl
#
# An example hook script to mail out commit update information.
# It can also blocks tags that aren't annotated.
# Called by git-receive-pack with arguments: refname sha1-old sha1-new
#
# To enable this hook, make this file executable by "chmod +x update".
#
# Config
# ------
# hooks.mailinglist
#   This is the list that all pushes will go to; leave it blank to not send
#   emails frequently.  The log email will list every log entry in full between
#   the old ref value and the new ref value.
# hooks.announcelist
#   This is the list that all pushes of annotated tags will go to.  Leave it
#   blank to just use the mailinglist field.  The announce emails list the
#   short log summary of the changes since the last annotated tag
# hooks.allowunannotated
#   This boolean sets whether unannotated tags will be allowed into the
#   repository.  By default they won't be.
#
# Notes
# -----
# All emails have their subjects prefixed with "[SCM]" to aid filtering.
# All emails include the headers "X-Git-Refname", "X-Git-Oldrev",
# "X-Git-Newrev", and "X-Git-Reftype" to enable fine tuned filtering and info.

# --- Constants
chomp($cwd=`pwd`);
require $cwd.'/hooks/update-variables.pl' || die;

# branches which comprise the base of the tree (i.e. ones not to
# report commits in) for a push of master.  The default is 'linus'.
# 'merge-base' only gets used when the tree has to be based on a
# non-standard tree because of conflicts
%BRANCHES = (
    'merge-base' => 1,
    'linus' => 1,
);
%IGNORED_BRANCHES = (
    'for-next' => 1,
    'for-linus' => 1,
    'master' => 1,
);
@IGNOREDCC = (
    'stable at kernel.org',
    'stable at vger.kernel.org',
);

%EMAILTO = (
    'James.Bottomley at HansenPartnership.com' => 1,
);

# --- Command line
$refname = $ARGV[0];
if ($refname =~ m|^refs/tags/|) {
    $refname =~ s|^refs/tags/||;
    $tag = 1;
} else {
    $refname =~ s|^refs/heads/||;
}
$oldrev=$ARGV[1];
$newrev=$ARGV[2];

# --- Safety check
if ($ENV{'GIT_DIR'} eq '') {
	print STDERR "Don't run this script from the command line.";
	print STDERR " (if you want, you could supply GIT_DIR then run";
	print STDERR "  $0 <ref> <oldrev> <newrev>)";
	exit 1;
}

if ($refname eq '' || $oldrev eq '' || $newrev eq '') {
	print STDERR "Usage: $0 <ref> <oldrev> <newrev>";
	exit 1;
}

if ($tag) {
    chomp(@t = `git cat-file tag $newrev`);
    foreach (@t) {
	if (/^tagger (.*>)/) {
	    $recipients = $1;
	    break;
	}
    }

    if (!$recipients) {
	print STDERR "Can't find a tagger in $refname\n";
	exit 1;
    }

    if (%EMAILTO) {
	$EMAILTO{$recipients} = 1;

	$recipients = join(', ', keys(%EMAILTO));
    }

    chomp(@_ = `git merge-base $newrev master`);

    $oldrev = $_[0];

    chomp(@commitlist = `git rev-list $newrev ^$oldrev`);

    @commitlog = ();
    foreach $commit (@commitlist) {
	chomp(@_ = `git show --oneline $commit`);
	push @commitlog, $_[0];
    }
    @email = (
# Generate header
	"From: James Bottomley <jejb\@kernel.org>",
	"To: $recipients",
	"Subject: Tag $revname added to tree ${TREE}",
	"X-Git-Oldrev: $oldrev",
	"X-Git-Newrev: $newrev",
	"X-Git-Tree: $TREEHDR",
	"",
	"Your tag $refname",
	"",
	"Containing:",
	);
    push @email, @commitlog;
    push @email, (
	"",
	"has been added to the $TREETYPE $TREE tree",
	"",
	"You can find it here:",
	"",
	"http://git.kernel.org/?p=linux/kernel/git/jejb/${TREE}.git;a=tag;h=$newrev",
	"",
	$WHENPUSH,
	"",
	"James Bottomley",
	"",
	"P.S. If you find this email unwanted, set up a procmail rule junking on",
	"the header:",
	"",
	"X-Git-Tree: $TREEHDR",
	"",
    );
    open(EMAIL, "| /usr/sbin/sendmail -t") || die;
    print EMAIL join("\n", @email);
    close(EMAIL);
    #print STDERR join("\n", @email);
    print STDERR "Email sent to: $recipients\n";
    exit 0;
}

if ($IGNORED_BRANCHES{$refname}) {
    print STDERR "Branch $refname ignored, not generating email\n";
    exit 0;
}
if ($refname =~ m/-base$/ || $BRANCHES{$refname}) {
    print STDERR "Updating base branch\n";
    exit 0;
}

$branch = '';
chomp(@branches = `git branch`);

if ($refname eq 'master') {
    foreach $b (keys(%BRANCHES)) {
	next if (!grep(/^..$b/, at branches));
	$branch = $b;
	last;
    }
} elsif (grep(/^..${refname}-base/, at branches)) {
    $branch = $refname.'-base';
}

if (!$branch) {
    print STDERR 'Upstream head has no needed bases: '.join(" ", @BRANCHES)." or ${refname}-base\n";
    exit 1;
}

if ($oldrev eq '0000000000000000000000000000000000000000' ) {
    print STDERR "Creating new branch $refname\n";
    exit 0;
}

@commitlist = ();
chomp(@revlist = `git rev-list $newrev ^$oldrev ^$branch`);
chomp(@cherrylist = `git cherry $refname $newrev`);

# don't annoy Linus guard: check that all of the cherrylist is actually mine
foreach $commit (@revlist) {
    # - prefix means the commit from $newrev is already in $branch
    next if (grep(/^- $commit/, @cherrylist));
    push @commitlist, $commit;
    $_ = `git log --pretty='format:%cn' $commit^..$commit`;
    next if (/^James Bottomley/);
    next if (/^Christoph Hellwig/);
    print STDERR "ERROR: commit $commit is not yours\n";
    print STDERR "ERROR: $_\n";
    exit 1;
}

$WHENPUSH = $WHENPUSHED{$refname};
if (!$WHENPUSH) {
    $WHENPUSH = $WHENPUSHED{'default'};
}
$NEEDACKS = $NEEDACKS{$refname};

#find the deleted commits and add them to the commit list
chomp(@deletelist = `git cherry $newrev $refname $branch`);
foreach $_ (@deletelist) {
    next if (!m/^\+ /);
    # found a delete; add it to the email list keeping the + prefix
    push @commitlist, $_;
}

foreach $commit (@commitlist) {
    if ($commit =~ m/^\+ /) {
	$commit = substr($commit,2);
	$delete = 1;
	$EMAILPREFIX="Patch dropped from ${TREE}: ";
    } else {
	$delete = 0;
	$EMAILPREFIX="Patch added to ${TREE}: ";
    }
    
    @email = ();
    $author = '';
    if (%EMAILTO) {
	%recipients = %EMAILTO;
    }
    %ackrequired = ();
    $subject = '';

    outer: foreach $_ (`git log $commit^..$commit`) {
	if (/^    / && $subject eq '') {
	    chomp($subject = substr($_, 4));
	} elsif (/^Author: / && $author eq '') {
	    chomp($author = substr($_, 8));
	    $recipients{$author} = 1;
	} elsif (/^    signed-off-by: /i) {
	    chomp($a = substr($_, 19));
	    $recipients{$a} = 1;
	    delete $ackrequired{$a};
	} elsif (/^    reviewed-by: /i) {
	    chomp($a = substr($_, 16));
	    $recipients{$a} = 1;
	    delete $ackrequired{$a};
	} elsif(/^    acked-by: /i) {
	    chomp($a = substr($_, 14));
	    $recipients{$a} = 1;
	    delete $ackrequired{$a};
	} elsif(/^    tested-by: /i) {
	    chomp($a = substr($_, 15));
	    $recipients{$a} = 1;
	    delete $ackrequired{$a};
	} elsif(/^    reported-by: /i) {
	    chomp($a = substr($_, 17));
	    $recipients{$a} = 1;
	    delete $ackrequired{$a};
	} elsif (/^    cc: /i) {
	    chomp($a = substr($_, 8));
	    foreach(@IGNOREDCC) {
		if ($a =~ m/$_/) {
		    next outer;
		}
	    }
	    $recipients{$a} = 1;
	    $ackrequired{$a} = 1;
	}
    }
    # I don't want to receive email
    #delete $recipients{'James Bottomley <James.Bottomley at SteelEye.com>'};
    # --- Email (all stdout will be the email)
    $recipients = join(', ', keys(%recipients));
    #$recipients = 'James.Bottomley at HansenPartnership.com';
    
    @email = (
# Generate header
	      "From: James Bottomley <jejb\@kernel.org>",
	      "To: $recipients",
	      "Subject: ${EMAILPREFIX} $subject",
	      "X-Git-Oldrev: $oldrev",
	      "X-Git-Newrev: $newrev",
	      "X-Git-Tree: $TREEHDR",
	      "",
# body goes here
	      "Your commit:",
	      );
    chomp(@commitlog = `git log $commit^..$commit`);
    # get rid of the commit/author/date header
    shift @commitlog;
    shift @commitlog;
    shift @commitlog;
    push @email, @commitlog;
    if ($delete) {
	push @email, (
	    "",
	    "has been dropped from the $TREETYPE $TREE tree",
	    "On branch \"$refname\"",
	    "",
	);
    } else {
	push @email, (
	      "",
	      "has been added to the $TREETYPE $TREE tree",
	      "On branch \"$refname\"",
	      "You can find it here:",
	      "",
	      "http://git.kernel.org/?p=linux/kernel/git/jejb/${TREE}.git;a=commit;h=$commit",
	      "",
	      $WHENPUSH,
	);
    }
    if ($NEEDACKS && %ackrequired) {
	push @email, (
	       "",
	       "This patch is pending because it requires ACKs from:",
	       "",
	       join("\n", keys(%ackrequired)),
	       "",
	       "If those are received it may be moved into one of the upstream SCSI trees",
		      );
    }
    push @email, (
	      "",
	      "James Bottomley",
	      "",
	      "P.S. If you find this email unwanted, set up a procmail rule junking on",
	      "the header:",
	      "",
	      "X-Git-Tree: $TREEHDR",
	      "",
	      );
    open(EMAIL, "| /usr/sbin/sendmail -t") || die;
    print EMAIL join("\n", @email);
    close(EMAIL);
    #print STDERR join("\n", @email);
    print STDERR "Email sent to: $recipients\n";
}

exit 0




More information about the Ksummit-discuss mailing list