diff -Nru kgb-bot-1.42/Changes kgb-bot-1.48/Changes --- kgb-bot-1.42/Changes 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/Changes 2018-04-21 09:22:17.000000000 +0000 @@ -1,3 +1,69 @@ +1.48 (2018-04-21) + [ Damyan Ivanov ] + * add only_branch webhook option + * webhook: add (via ...) only when *both* user name and email differs + between author and pusher + +1.47 (2018-04-10) + [ Damyan Ivanov ] + * webhook/merge request: drop "revision" output and put the action in square + brackets + * set default params in one place + * add shorten_urls webhook parameter, defaults to 1 + + [ James Clarke ] + * webhook: + + Better tag deletion messages + + Show branch deletions (Closes: #895283) + + [ Damyan Ivanov ] + * fix warning about double "my" in 70-webhook-push.t + * fix 52-client-git.t and 53-client-git-merges.t with Git 1.17. + (Closes: 894775) + + [ Colin Finck ] + * Git client: Support an "author-via" placeholder in the message template, + which shows the author and committer name if both are different. + +1.46 (2018-03-08) + [ Damyan Ivanov ] + * webhook/push: add always_squash_branch parameter, + defaults to [ 'upstream', 'upstream/master' ] + * fix stats counting + * bot: reload URL shortening module when the config is changed + * document short_url_service in kgb.conf(5) + + [ James Clarke ] + * Use ! rather than # for GitLab merge requests + * Use iid rather than global id for merge requests and issues + + [ gregor herrmann ] + * bot: rename "signed-tags" to "signed tags", as in the client. + +1.45 (2018-03-06) + [ Damyan Ivanov ] + * point output of '/ctcp source' to salsa + * fix short url code after 97033851da793b345f5283fb96897d5f9b55b810 + * collect some stats - run time, notification counts + * react to !stats and !statsreset + * update HOWTO.release + * shorten compare URLs + +1.44 (2018-03-03) + [ Damyan Ivanov ] + * bot/webhook: shorten git hashes in URLs + (as a fallback when URL shortening has problems or is not configured) + * webhook: no heuristics when determining which params are arrays + * webhook/pipeline: add support for pipeline_only_status URL parameter + (multiple values) + (Closes: #891870) + * webhook: colorize pipeline success/failure in reverse green/red + +1.43 (2018-03-02) + [ Damyan Ivanov ] + * improve pipeline notifications + * improve commit squash handling + 1.42 (2018-02-26) [ Martín Ferrari ] * Speed-up KGB joining of channels and setup. diff -Nru kgb-bot-1.42/debian/changelog kgb-bot-1.48/debian/changelog --- kgb-bot-1.42/debian/changelog 2018-02-26 13:21:58.000000000 +0000 +++ kgb-bot-1.48/debian/changelog 2018-04-21 09:12:21.000000000 +0000 @@ -1,3 +1,100 @@ +kgb-bot (1.48-1) unstable; urgency=medium + + * add only_branch webhook option + * webhook: add (via ...) only when *both* user name and email differs + between author and pusher + + -- Damyan Ivanov Sat, 21 Apr 2018 09:12:21 +0000 + +kgb-bot (1.47-1) unstable; urgency=medium + + [ Damyan Ivanov ] + * webhook/merge request: drop "revision" output and put the action in square + brackets + * set default params in one place + * add shorten_urls webhook parameter, defaults to 1 + + [ James Clarke ] + * webhook: + + Better tag deletion messages + + Show branch deletions (Closes: #895283) + + [ Damyan Ivanov ] + * fix warning about double "my" in 70-webhook-push.t + * fix 52-client-git.t and 53-client-git-merges.t with Git 1.17. + (Closes: 894775) + + [ Colin Finck ] + * Git client: Support an "author-via" placeholder in the message template, + which shows the author and committer name if both are different. + + -- Damyan Ivanov Tue, 10 Apr 2018 13:56:20 +0000 + +kgb-bot (1.46-1) unstable; urgency=medium + + [ Damyan Ivanov ] + * webhook/push: add always_squash_branch parameter, + defaults to [ 'upstream', 'upstream/master' ] + * fix stats counting + * bot: reload shortening service when short_url_service changes in the + config + * document 'short_url_service' in kgb.conf(5) + + [ James Clarke ] + * Use ! rather than # for GitLab merge requests + * Use iid rather than global id for merge requests and issues + + [ gregor herrmann ] + * bot: rename "signed-tags" to "signed tags", as in the client. + * Add debian/gbp.conf: Turn off pristine-tar feature. + + [ James Clarke ] + * Set upstream-tree to SLOPPY since we have no upstream tags nor branch + + [ Damyan Ivanov ] + * add James Clarke to copyright statements + * update Upstream-Contact and Source fields in debian/copyright + + -- Damyan Ivanov Thu, 08 Mar 2018 05:25:11 +0000 + +kgb-bot (1.45-1) unstable; urgency=medium + + * kgb-bot.service: run ExecStartPre commands as root (creation/permissions + of log file) + * point '/ctcp source' to salsa + * fix short url code broken in 1.44 + * kgb-bot.service: set TZ=UTC + * collect some stats - run time, notification counts + * react to !stats and !statsreset + * update HOWTO.release + * fix a mispaste in t/76-webhook-pipeline.t missing a test and a double "my" + declaration + * convert debian/watch to a dummy one - there is no other upstream but us + * autopkgtest: skip smoke tests not supposed to be run with installed + package + * shorten compare URL + + -- Damyan Ivanov Tue, 06 Mar 2018 06:30:01 +0000 + +kgb-bot (1.44-1) unstable; urgency=medium + + * bot/webhook: shorten git hashes in URLs + (as a fallback when URL shortening has problems or is not configured) + * webhook: no heuristics when determining which params are arrays + * webhook/pipeline: add support for pipeline_only_status URL parameter + (multiple values) + (Closes: #891870) + * webhook: colorize pipeline success/failure in reverse green/red + + -- Damyan Ivanov Sat, 03 Mar 2018 07:45:41 +0000 + +kgb-bot (1.43-1) unstable; urgency=medium + + * improve pipeline notifications + * improve commit squash handling + + -- Damyan Ivanov Fri, 02 Mar 2018 06:17:51 +0000 + kgb-bot (1.42-1) unstable; urgency=medium [ Martín Ferrari ] @@ -588,7 +685,7 @@ [ Salvatore Bonaccorso ] * debian/control: Remove libdigest-sha1-perl from Depends for kgb-client - binary package. + binary package. * Bump Standards-Version to 3.9.2. [ gregor herrmann ] diff -Nru kgb-bot-1.42/debian/control kgb-bot-1.48/debian/control --- kgb-bot-1.42/debian/control 2018-02-26 12:57:28.000000000 +0000 +++ kgb-bot-1.48/debian/control 2018-03-02 06:19:30.000000000 +0000 @@ -59,7 +59,7 @@ lsb-base, libschedule-ratelimiter-perl, libyaml-perl, - kgb-client, + kgb-client (= ${binary:Version}), git Suggests: polygen, libfile-which-perl diff -Nru kgb-bot-1.42/debian/copyright kgb-bot-1.48/debian/copyright --- kgb-bot-1.42/debian/copyright 2018-02-06 10:09:15.000000000 +0000 +++ kgb-bot-1.48/debian/copyright 2018-04-10 15:43:57.000000000 +0000 @@ -1,13 +1,15 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: App::KGB -Upstream-Contact: Debian KGB Maintainers -Source: https://alioth.debian.org/projects/kgb +Upstream-Contact: Debian KGB Maintainers +Source: https://salsa.debian.org/kgb-team/kgb Files: * Copyright: 2008-2013, Martín Ferrari 2008-2018, Damyan Ivanov 2010-2016, gregor herrmann + 2018, James Clarke + 2018, Colin Finck License: GPL-2+ License: GPL-2+ diff -Nru kgb-bot-1.42/debian/gbp.conf kgb-bot-1.48/debian/gbp.conf --- kgb-bot-1.42/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 +++ kgb-bot-1.48/debian/gbp.conf 2018-03-08 05:19:47.000000000 +0000 @@ -0,0 +1,3 @@ +[DEFAULT] +pristine-tar = False +upstream-tree = SLOPPY diff -Nru kgb-bot-1.42/debian/kgb-bot.service kgb-bot-1.48/debian/kgb-bot.service --- kgb-bot-1.42/debian/kgb-bot.service 2018-02-07 09:37:10.000000000 +0000 +++ kgb-bot-1.48/debian/kgb-bot.service 2018-03-05 10:28:43.000000000 +0000 @@ -6,7 +6,9 @@ [Service] User=Debian-kgb Group=Debian-kgb +Environment=TZ=UTC Type=forking +PermissionsStartOnly=true PIDFile=/run/kgb-bot/kgb-bot.pid ExecStartPre=/usr/bin/touch /var/log/kgb-bot.log ExecStartPre=/bin/chown Debian-kgb:root /var/log/kgb-bot.log diff -Nru kgb-bot-1.42/debian/tests/pkg-perl/smoke-skip kgb-bot-1.48/debian/tests/pkg-perl/smoke-skip --- kgb-bot-1.42/debian/tests/pkg-perl/smoke-skip 1970-01-01 00:00:00.000000000 +0000 +++ kgb-bot-1.48/debian/tests/pkg-perl/smoke-skip 2018-03-05 19:37:19.000000000 +0000 @@ -0,0 +1,3 @@ +t/changes.t +t/00-compile_scripts.t +t/00-compile_shell_scripts.t diff -Nru kgb-bot-1.42/debian/watch kgb-bot-1.48/debian/watch --- kgb-bot-1.42/debian/watch 2013-08-07 19:18:54.000000000 +0000 +++ kgb-bot-1.48/debian/watch 2018-03-05 19:36:58.000000000 +0000 @@ -1,3 +1,2 @@ -version=3 -https://alioth.debian.org/frs/?group_id=100408 \ - .+/kgb-bot_([\d.]+)\.orig\.tar\.gz +# debian/watch is not useful for this package, because Debian packagers are +# also upstream authors diff -Nru kgb-bot-1.42/HOWTO.release kgb-bot-1.48/HOWTO.release --- kgb-bot-1.42/HOWTO.release 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/HOWTO.release 2018-04-21 09:22:17.000000000 +0000 @@ -1,13 +1,11 @@ Steps for creating new releases =============================== - * Bump version in lib/App/KGB.pm and script/kgb-bot + * Bump version in lib/App/KGB.pm * Update Changes and debian/changelog (git-dch) * `make distcheck`, update MANIFEST{,SKIP} as needed. * `make dist' * build/upload for Debian - + make orig to get a .orig.tar file. - * upload to alioth - + https://alioth.debian.org/frs/admin/qrs.php?group_id=100408 + + make orig to get a .orig.tar file in ../ * upload to CPAN - + cpan-upload -u USERID App-KGB-*.tar.gz + + cpan-upload -u USERID ../App-KGB-*.tar.gz diff -Nru kgb-bot-1.42/lib/App/KGB/Client/Git.pm kgb-bot-1.48/lib/App/KGB/Client/Git.pm --- kgb-bot-1.42/lib/App/KGB/Client/Git.pm 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/lib/App/KGB/Client/Git.pm 2018-04-21 09:22:17.000000000 +0000 @@ -2,6 +2,7 @@ # # KGB - an IRC bot helping collaboration # Copyright © 2009,2013 Damyan Ivanov +# Copyright © 2018 Colin Finck # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software @@ -431,12 +432,23 @@ my @parents; my $author_login; my $author_name; + my $author_via; while (<$fh>) { if ( /^author (.+) <([^>]+)@[^>]+>/ ) { utf8::decode( $author_name = $1 ); utf8::decode( $author_login = $2 ); next; } + if ( /^committer (.+) <([^>]+)@[^>]+>/ ) { + my $committer_name; + utf8::decode( $committer_name = $1 ); + if ($committer_name ne $author_name) { + $author_via = $author_name . ' (via ' . $committer_name . ')'; + } else { + $author_via = $author_name; + } + next; + } push( @parents, substr( $1, 0, 7 ) ), next if /^parent\s+(\S+)/; push( @log, $1 ), next if /^ (.*)/; if (s/^::?//) { # a merge commit @@ -480,6 +492,7 @@ id => substr( $new, 0, 7 ), author => $author_login, author_name => $author_name, + author_via => $author_via, log => join( "\n", @log ), changes => \@changes, parents => \@parents, diff -Nru kgb-bot-1.42/lib/App/KGB/Client.pm kgb-bot-1.48/lib/App/KGB/Client.pm --- kgb-bot-1.42/lib/App/KGB/Client.pm 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/lib/App/KGB/Client.pm 2018-04-21 09:22:17.000000000 +0000 @@ -13,6 +13,7 @@ # KGB - an IRC bot helping collaboration # Copyright © 2008 Martín Ferrari # Copyright © 2009,2010,2011,2012,2013 Damyan Ivanov +# Copyright © 2018 Colin Finck # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software @@ -231,6 +232,11 @@ The name of the commit author (e.g. "Joe Random") +=item ${author_via} + +The name of the commit author, plus the name of the committer if that is +different (e.g. "Joe Random" or "Joe Random (via Max Random)") + =item ${branch} The branch of the commit. @@ -810,12 +816,14 @@ if ($commit) { $p{author_login} = $commit->author if ($commit->author); $p{author_name} = $commit->author_name if ($commit->author_name); + $p{author_via} = $commit->author_via if ($commit->author_via); $p{branch} = $commit->branch if ($commit->branch); $p{commit_id} = $commit->id if ($commit->id); $p{log} = $commit->log if ($commit->log); } $p{author_name} ||= $p{author_login}; $p{author_login} ||= $p{author_name}; + $p{author_via} ||= $p{author_name}; if (defined($self->module)) { $p{module} = $self->module; } elsif ($commit and defined($commit->module)) { @@ -839,6 +847,9 @@ elsif ( $token eq 'author-name' ) { push @r, author => $p{author_name}; } + elsif ( $token eq 'author-via' ) { + push @r, author => $p{author_via}; + } elsif ( $token eq 'branch' ) { push @r, branch => $p{branch}; } diff -Nru kgb-bot-1.42/lib/App/KGB/Commit.pm kgb-bot-1.48/lib/App/KGB/Commit.pm --- kgb-bot-1.42/lib/App/KGB/Commit.pm 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/lib/App/KGB/Commit.pm 2018-04-21 09:22:17.000000000 +0000 @@ -72,7 +72,7 @@ =cut use base 'Class::Accessor::Fast'; -__PACKAGE__->mk_accessors( qw( id changes log author author_name branch module ) ); +__PACKAGE__->mk_accessors( qw( id changes log author author_name author_via branch module ) ); use Carp qw(confess); diff -Nru kgb-bot-1.42/lib/App/KGB.pm kgb-bot-1.48/lib/App/KGB.pm --- kgb-bot-1.42/lib/App/KGB.pm 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/lib/App/KGB.pm 2018-04-21 09:22:17.000000000 +0000 @@ -31,7 +31,7 @@ =cut -our $VERSION = '1.42'; +our $VERSION = '1.48'; =head1 DESCRIPTION diff -Nru kgb-bot-1.42/man5/kgb.conf.pod kgb-bot-1.48/man5/kgb.conf.pod --- kgb-bot-1.42/man5/kgb.conf.pod 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/man5/kgb.conf.pod 2018-04-21 09:22:17.000000000 +0000 @@ -250,6 +250,15 @@ =back +=head2 short_url_service I + +The name of a WWW::Shorten module to use for URL-shortening. The leading +C part must be omitted. + +Default: none + +Example: Debli + =head1 EXAMPLE CONFGURATION # vim: filetype=yaml @@ -322,6 +331,7 @@ # available colors: black, navy, green, red, brown, purple, orange, yellow, # lime, teal, aqua, blue, fuchsia, gray, silver, white # available modifiers: bold underline reverse + short_url_service: Debli =head1 SEE ALSO diff -Nru kgb-bot-1.42/MANIFEST kgb-bot-1.48/MANIFEST --- kgb-bot-1.42/MANIFEST 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/MANIFEST 2018-04-21 09:22:17.000000000 +0000 @@ -72,4 +72,5 @@ t/pod-coverage.t t/pod.t t/TestBot.pm +t/WWW/Shorten/DummyShortener.pm TODO diff -Nru kgb-bot-1.42/META.json kgb-bot-1.48/META.json --- kgb-bot-1.42/META.json 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/META.json 2018-04-21 09:22:17.000000000 +0000 @@ -82,6 +82,6 @@ "http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt" ] }, - "version" : "1.42", + "version" : "1.48", "x_serialization_backend" : "JSON::PP version 2.97001" } diff -Nru kgb-bot-1.42/META.yml kgb-bot-1.48/META.yml --- kgb-bot-1.42/META.yml 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/META.yml 2018-04-21 09:22:17.000000000 +0000 @@ -61,5 +61,5 @@ perl: '5.010' resources: license: http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt -version: '1.42' +version: '1.48' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff -Nru kgb-bot-1.42/script/kgb-bot kgb-bot-1.48/script/kgb-bot --- kgb-bot-1.42/script/kgb-bot 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/script/kgb-bot 2018-04-21 09:22:17.000000000 +0000 @@ -7,6 +7,7 @@ # Copyright © 2008 Martín Ferrari # Copyright © 2008,2009,2010,2011,2012,2013,2018 Damyan Ivanov # Copyright © 2010 gregor herrmann +# Copyright © 2018 James Clarke # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software @@ -105,6 +106,8 @@ our $shuttingdown = 0; our $painter; our $painter_dummy = App::KGB::Painter->new( { simulate => 1 } ); +my %stats; +my $run_time_since = time; # for JSON::XS, used for debugging sub Net::IP::TO_JSON { @@ -330,6 +333,9 @@ $conf->{colors}{prop_change} //= 'underline'; + $conf->{colors}{success} //= 'reverse green'; + $conf->{colors}{failure} //= 'reverse red'; + $KGB::debug = $conf->{debug} if exists $conf->{debug}; $conf->{pid_dir} = Cwd::realpath( $conf->{pid_dir} // '/var/run/kgb-bot' ); @@ -408,6 +414,27 @@ } } +sub count { + my ($self, $counter) = @_; + + $stats{$counter}++; +} + +sub get_stats { + return \%stats; +} + +sub get_run_seconds { + return time - $run_time_since; +} + +sub reset_stats { + %stats = (); + $run_time_since = time; +} + +1; + package KGB::POE; use strict; @@ -991,7 +1018,7 @@ version => "KGB v$App::KGB::VERSION", userinfo => "KGB v$App::KGB::VERSION", clientinfo => "VERSION USERINFO CLIENTINFO SOURCE", - source => "http://alioth.debian.org/projects/kgb", + source => "https://salsa.debian.org/kgb-team/kgb", ) ); @@ -1218,9 +1245,13 @@ if ( exists $heap->{seen_idx}{$hash} ) { KGB->debug("'$part' seen recently\n"); + KGB->count('suppressed_duplicate_notifications'); + return undef; } + KGB->count('notifications'); + my $alias = "irc_" . $KGB::config->{chanidx}{$chan}{network}; $kernel->post( $alias => $method => $chan => $_ ) foreach (@$str); if ( $KGB::debug ) { @@ -1252,6 +1283,20 @@ . $KGB::config->{networks}{$net}{nick} . " VERSION?" ); } + elsif ( $command eq 'stats' ) { + my $stats = KGB->get_stats; + my $run_time = human_duration( KGB->get_run_seconds ); + my $msg = "after $run_time: "; + $msg .= + %$stats + ? join( ', ', map( "$_:$stats->{$_}", sort keys %$stats ) ) + : 'no stats yet'; + return reply( $kernel, $net, $chan, $nick, $msg); + } + elsif ( $command eq 'statsreset' ) { + KGB->reset_stats; + return reply( $kernel, $net, $chan, $nick, 'Done' ); + } else { return reply( $kernel, $net, $chan, $nick, "command '$command' is not known to me" ); @@ -1488,6 +1533,10 @@ =cut +my @array_webhook_params = + qw( channel pipeline_only_status always_squash_branch only_branch ); +my %array_webhook_params = map( ( $_ => 1 ), @array_webhook_params ); + sub webhook_request { my ( $request, $response, $dirmatch ) = @_[ ARG0 .. ARG2 ]; @@ -1599,25 +1648,22 @@ KGB->debug('Body check passed'); # form a CGI-like param hash - my $param = {}; + my $param = { map( ( $_ => [] ), @array_webhook_params ) }; + $param->{always_squash_branch} = [qw( upstream upstream/master )]; + $param->{shorten_urls} = 1; + $param->{use_irc_notices} = 1; my $uri = URI->new( $request->url ); my @query = $request->uri->query_form; while ( my( $key, $value ) = splice( @query, 0, 2 ) ) { - next unless length $value; - - if ( exists $param->{$key} ) { - $param->{$key} = [ $param->{$key} ] unless ref $param->{$key}; - push @{ $param->{$key} }, $value; + if ( $array_webhook_params{$key} ) { + push @{ $param->{$key} }, $value if length $value; } else { $param->{$key} = $value; } } - $param->{use_irc_notices} = 1 unless exists $param->{use_irc_notices}; - - my @channels = $param->{channel} // (); - @channels = @{ $channels[0] } if ref $channels[0]; + my @channels = @{ $param->{channel} }; s/^(?!#)/#/ for @channels; push @channels, @{ $KGB::config->{broadcast_channels} } unless $param->{private}; @@ -1638,14 +1684,26 @@ return $_[KERNEL]->post( $_[SENDER], DONE => $response ); } +sub monkey_shorten_git_hashes { + my $url = shift; + + $url =~ s/\b[0-9a-f]{7}\K[0-9a-f]{33}\b//g; + + return $url; +} + my $shortener_loaded = 0; sub shorten_url { - my $service = $KGB::config->{short_url_service} or return shift; - my $url = shift; + my $opts = shift; + + return monkey_shorten_git_hashes($url) unless $opts->{shorten_urls}; + + my $service = $KGB::config->{short_url_service} + or return monkey_shorten_git_hashes($url); - unless ($shortener_loaded) { + unless ($shortener_loaded and $shortener_loaded eq $service) { my $ok = eval { require WWW::Shorten; WWW::Shorten->import( $service, ':short' ); @@ -1657,23 +1715,27 @@ return $url; } - $shortener_loaded = 1; + $shortener_loaded = $service; } my $short_url; - my $ok = eval { short_link($url); 1 }; + my $ok = eval { $short_url = short_link($url); 1 }; unless ($ok) { KGB->out( "Failure while calling URL shortening service '$service' for '$url': $@" ); - return $url; + return monkey_shorten_git_hashes($url); } - return $short_url if defined($short_url); + unless ( defined $short_url ) { + KGB->out( + "URL shortening service '$service' failed to shorten '$url'."); + return monkey_shorten_git_hashes($url); + } - KGB->out("URL shortening service '$service' failed to shorten '$url'."); - return $url; + KGB->count('URLs_shortened'); + return $short_url; } sub to_irc { @@ -1816,6 +1878,40 @@ if exists $opts->{use_color} and not $opts->{use_color}; + my $branch = $body->{ref}; + $branch =~ s{^refs/heads/}{}; + + return + if @{ $opts->{only_branch} } + and not grep { $_ eq $branch } @{ $opts->{only_branch} }; + + my $rev_prefix = $opts->{rev_prefix} // ''; + + if ( $body->{after} =~ /^0+$/ ) { + # branch deleted + my @info; + push @info, colorize( author => $body->{user_name} ) + if $body->{user_name}; + push @info, colorize( branch => $branch ) if $branch; + push @info, + "$rev_prefix" + . colorize( revision => substr( $body->{before}, 0, 7 ) ) + if $body->{before}; + push @info, colorize( module => $module ) if $module ne ''; + push @info, colorize( deletion => '.' ); + push @info, colorize( separator => '*' ), 'branch deleted'; + + to_irc( + { kernel => $kernel, + strings => [ join( ' ', @info ) ], + repository => $body->{project}{namespace}, + opts => $opts, + } + ); + + return; + } + unless ($body->{commits} and ref( $body->{commits} ) and ref( $body->{commits} ) eq 'ARRAY' @@ -1825,15 +1921,23 @@ return; } - my $branch = $body->{ref}; - $branch =~ s{^refs/heads/}{}; - - my $rev_prefix = $opts->{rev_prefix} // ''; - my $max_commits = $opts->{squash_threshold} // 20; $max_commits = 20 unless $max_commits and $max_commits =~ /^\d\d?$/; - if ( @{ $body->{commits} } > $max_commits ) { + my $commit_count = scalar @{ $body->{commits} }; + $commit_count = $body->{total_commits_count} + if $body->{total_commits_count} + and $body->{total_commits_count} > $commit_count; + + my $to_show_count = scalar @{ $body->{commits} }; + $to_show_count = $max_commits if $max_commits < $to_show_count; + + if ( grep { $_ eq $branch } @{ $opts->{always_squash_branch} } ) { + $to_show_count = 0; + } + + if ( $to_show_count != $commit_count ) { + # not all commits will be shown, prepend a summary of the push my @info; push @info, colorize( author => $body->{user_name} ) if $body->{user_name}; @@ -1844,15 +1948,19 @@ if $body->{checkout_sha}; push @info, colorize( module => $module ) if $module ne ''; push @info, colorize( separator => '*' ), - sprintf( 'pushed %d commits', scalar @{ $body->{commits} } ); + sprintf( 'pushed %d commits', $commit_count ); + push @info, sprintf( '(first %d follow)', $to_show_count ) + if $to_show_count; push @info, colorize( separator => '*' ); push @info, colorize( - web => sprintf( - '%s/compare/%s...%s', - $body->{project}{homepage}, - substr( $body->{before}, 0, 7 ), - substr( $body->{after}, 0, 7 ) + web => shorten_url( + sprintf( + '%s/compare/%s...%s', + $body->{project}{homepage}, $body->{before}, + $body->{after}, + ), + $opts ) ); @@ -1863,11 +1971,12 @@ opts => $opts, } ); - - return; } + my $shown = 0; for my $commit ( @{ $body->{commits} } ) { + last if $shown + 1 > $to_show_count; + my $path_string; my %dirs; @@ -1880,7 +1989,8 @@ if $body->{user_name} and $body->{user_email} and $commit->{author}{email} - and $body->{user_email} ne $commit->{author}{email}; + and $body->{user_email} ne $commit->{author}{email} + and $body->{user_name} ne $commit->{author}{name}; my @changes; push @changes, @@ -1932,7 +2042,7 @@ my $web_string = $commit->{url} - ? colorize( web => shorten_url( $commit->{url} ) ) + ? colorize( web => shorten_url( $commit->{url}, $opts ) ) : undef; my @log = split( /\n/, $commit->{message} ); @@ -1963,6 +2073,8 @@ opts => $opts, } ); + + $shown++; } } @@ -2000,7 +2112,8 @@ my @string = join( ' ', @info ); - my $web_string = $url ? colorize( web => shorten_url($url) ) : undef; + my $web_string = + $url ? colorize( web => shorten_url( $url, $opts ) ) : undef; my @log = split( /\n/, $body->{object_attributes}{message} // '' ); # for multi-line commit log, emit only the first line if the second one @@ -2050,27 +2163,40 @@ my $branch = 'tags'; my $message = $body->{message} // ''; - $branch = 'signed-tags' + $branch = 'signed tags' if $message =~ s/-----BEGIN PGP SIGNATURE-----.*//s; + my $rev = $body->{after}; + my $web_string; + my $action; + + if ( $rev =~ /^0+$/ ) { + $action = 'deletion'; + $message = 'tag deleted'; + $rev = $body->{before}; + } + else { + $action = 'addition'; + $web_string = $body->{project}{homepage} + ? colorize( + web => shorten_url( + sprintf( '%s/tags/%s', $body->{project}{homepage}, $tag ), $opts + ) + ) + : undef; + } + my @info; push @info, colorize( author => $body->{user_name} ); push @info, colorize( branch => $branch ); push @info, - $rev_prefix . colorize( revision => substr( $body->{after}, 0, 7 ) ); + $rev_prefix . colorize( revision => substr( $rev, 0, 7 ) ); push @info, colorize( module => $module ) if $module ne ''; - push @info, colorize( addition => $tag ) if $tag ne ''; + push @info, colorize( $action => $tag ) if $tag ne ''; my @string = join( ' ', @info ); - my $web_string = - $body->{project}{homepage} - ? colorize( web => shorten_url( - sprintf( '%s/tags/%s', $body->{project}{homepage}, $tag ) - ) ) - : undef; - my @log = split( /\n/, $message ); # for multi-line commit log, emit only the first line if the second one # is empty @@ -2129,7 +2255,7 @@ push @info, colorize( author => $body->{user}{name} ); push @info, colorize( branch => 'issues' ); push @info, colorize( module => $module ) if $module ne ''; - push @info, colorize( revision => $body->{object_attributes}{id} ); + push @info, colorize( revision => '#' . $body->{object_attributes}{iid} ); push @info, colorize( $action => $body->{object_attributes}{title} ); my @string = join( ' ', @info ); @@ -2151,7 +2277,8 @@ else { push @string, @log; } - my $web_string = $url ? colorize( web => shorten_url($url) ) : undef; + my $web_string = + $url ? colorize( web => shorten_url( $url, $opts ) ) : undef; $string[0] .= ' ' . colorize( separator => '*' ) . ' ' . $web_string if defined($web_string); @@ -2167,7 +2294,7 @@ my %note_descr = ( Commit => 'commented commit ', - MergeRequest => 'commented merge request #', + MergeRequest => 'commented merge request !', Issue => 'commented issue #', Snippet => 'commented snippet #', ); @@ -2191,14 +2318,14 @@ if $nt eq 'Commit' and $body->{commit} and $body->{commit}{id}; - $log .= $body->{merge_request}{id} + $log .= $body->{merge_request}{iid} if $nt eq 'MergeRequest' and $body->{merge_request} - and $body->{merge_request}{id}; - $log .= $body->{issue}{id} + and $body->{merge_request}{iid}; + $log .= $body->{issue}{iid} if $nt eq 'Issue' and $body->{issue} - and $body->{issue}{id}; + and $body->{issue}{iid}; $log .= $body->{snippet}{id} if $nt eq 'Snippet' and $body->{snippet} @@ -2215,7 +2342,8 @@ my @string = join( ' ', @info ); - my $web_string = $url ? colorize( web => shorten_url($url) ) : undef; + my $web_string = + $url ? colorize( web => shorten_url( $url, $opts ) ) : undef; $string[0] .= ' ' . colorize( separator => '*' ) . ' ' . $web_string if defined($web_string); @@ -2241,10 +2369,10 @@ my $url = $body->{object_attributes}{url}; - my $log = - $body->{object_attributes}{action} - . ' of merge request #' - . $body->{object_attributes}{id}; + my $action = $body->{object_attributes}{action} || 'unspecified action'; + + my $log = sprintf( '[%s] merge request !%s', + $action, $body->{object_attributes}{iid} ); my @info; @@ -2252,13 +2380,12 @@ push @info, colorize( branch => $body->{object_attributes}{target_branch} ) if $body->{object_attributes}{target_branch}; push @info, colorize( module => $module ) if $module ne ''; - push @info, colorize( revision => $body->{object_attributes}{id} ) - if $body->{object_attributes}{id}; push @info, colorize( separator => '*' ) . ' ' . $log; my @string = join( ' ', @info ); - my $web_string = $url ? colorize( web => shorten_url($url) ) : undef; + my $web_string = + $url ? colorize( web => shorten_url( $url, $opts ) ) : undef; $string[0] .= ' ' . colorize( separator => '*' ) . ' ' . $web_string if defined($web_string); @@ -2314,21 +2441,37 @@ local $KGB::painter = $KGB::painter_dummy if exists $opts->{use_color} and not $opts->{use_color}; - my $log = sprintf( - 'Pipeline #%d finished in %s. Status: %s', - $body->{object_attributes}{id}, - human_duration( $body->{object_attributes}{duration} ), - $body->{object_attributes}{status} // 'UNKNOWN' - ); + my $id = $body->{object_attributes}{id}; + my $status = $body->{object_attributes}{status}; + + return + if @{ $opts->{pipeline_only_status} } + and not grep { $_ eq $status } @{ $opts->{pipeline_only_status} }; + + $status = colorize( $status => $status ) + if $status =~ /^(?:success|failure)$/; + + my $log; + if ( my $duration = $body->{object_attributes}{duration} ) { + $log = sprintf( "[%s] %s", human_duration($duration), $status ) + } + else { + $log = $status; + } + + if ( my $builds = $body->{builds} ) { + my @build_info; + push @build_info, sprintf( '%s: %s', $_->{name}, $_->{status} ) + for @$builds; + $log .= ' (' . join( '; ', @build_info ) . ')' if @build_info; + } my @info; push @info, colorize( author => $body->{user}{name} ); - push @info, colorize( branch => $body->{object_attributes}{target_branch} ) - if $body->{object_attributes}{target_branch}; + push @info, colorize( branch => 'pipeline' ); push @info, colorize( module => $module ) if $module ne ''; - push @info, colorize( revision => $body->{object_attributes}{id} ) - if $body->{object_attributes}{id}; + push @info, colorize( revision => $id ) if $id; push @info, colorize( separator => '*' ) . ' ' . $log; my @string = join( ' ', @info ); @@ -2347,7 +2490,7 @@ my $module = $body->{project_name}; - KGB->debug("Handling webhook pipeline event for project $module"); + KGB->debug("Handling webhook build event for project $module"); local $KGB::painter = $KGB::painter_dummy if exists $opts->{use_color} and not $opts->{use_color}; diff -Nru kgb-bot-1.42/t/52-client-git.t kgb-bot-1.48/t/52-client-git.t --- kgb-bot-1.42/t/52-client-git.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/52-client-git.t 2018-04-21 09:22:17.000000000 +0000 @@ -104,8 +104,8 @@ ok( $git, 'local repository allocated' ); isa_ok( $git, 'Git' ); -$git->command( 'config', 'user.name', 'Test U. Ser' ); -$git->command( 'config', 'user.email', 'ser@example.neverland' ); +my $ign = $git->command( 'config', 'user.name', 'Test U. Ser' ); +$ign = $git->command( 'config', 'user.email', 'ser@example.neverland' ); write_tmp 'reflog', ''; @@ -133,8 +133,8 @@ write_tmp 'reflog', ''; unlink $hook_log if $hook_log and -s $hook_log; - my $ignore = $git->command( [qw( push origin --all )], { STDERR => 0 } ); - $ignore = $git->command( [qw( push origin --tags )], { STDERR => 0 } ); + my $ign = $git->command( [qw( push origin --all )], { STDERR => 0 } ); + $ign = $git->command( [qw( push origin --tags )], { STDERR => 0 } ); $c->_reset; $c->_detect_commits; @@ -144,7 +144,7 @@ my %commits; sub do_commit { - $git->command_oneline( 'commit', '-m', shift ) =~ /\[(\w+).*\s+(\w+)\]/; + my $ign = $git->command_oneline( 'commit', '-m', shift ) =~ /\[(\w+).*\s+(\w+)\]/; push @{ $commits{$1} }, $2; #diag "commit $2 in branch $1" unless $tmp_cleanup; } @@ -153,9 +153,9 @@ ###### first commit w( 'a', 'some content' ); -$git->command( 'add', '.' ); +$ign = $git->command( 'add', '.' ); do_commit('initial import'); -$git->command( 'remote', 'add', 'origin', "file://$remote" ); +$ign = $git->command( 'remote', 'add', 'origin', "file://$remote" ); push_ok; # now "$dir/reflog" shall have some refs @@ -185,7 +185,7 @@ a 'a', 'some other content'; w 'b', 'some other content'; -$git->command( 'add', '.' ); +$ign = $git->command( 'add', '.' ); do_commit('some changes'); push_ok(); @@ -207,15 +207,15 @@ . '' ); ##### remove, banch, modyfy, add, tag; batch send -$git->command( 'rm', 'a' ); +$ign = $git->command( 'rm', 'a' ); do_commit('a removed'); -$git->command( 'checkout', '-q', '-b', 'other', 'master' ); +$ign = $git->command( 'checkout', '-q', '-b', 'other', 'master' ); w 'c', 'a new file was born'; w 'b', 'new content'; -$git->command( 'add', '.' ); +$ign = $git->command( 'add', '.' ); do_commit('a change in the other branch'); -$git->command( 'tag', '1.0-beta' ); +$ign = $git->command( 'tag', '1.0-beta' ); push_ok(); my $other_branch_point = $commits{master}[0]; @@ -270,9 +270,9 @@ w( File::Spec->catfile( 'debian', 'README' ), 'You read this!? Good boy/girl.' ); -$git->command( 'add', 'debian' ); +$ign = $git->command( 'add', 'debian' ); do_commit( "add README for release\n\nas everybody knows, releases have to have READMEs\nHello, hi!" ); -$git->command( 'tag', '-a', '-m', 'Release 1.0', '1.0-release' ); +$ign = $git->command( 'tag', '-a', '-m', 'Release 1.0', '1.0-release' ); push_ok(); $c1 = $commit = $c->describe_commit; @@ -312,7 +312,7 @@ # a hollow branch -$git->command('branch', 'hollow'); +$ign = $git->command('branch', 'hollow'); push_ok(); # hollow branches are not detected for now @@ -335,7 +335,7 @@ # some UTF-8 w 'README', 'You dont read this!? Bad!'; -$git->command( 'add', '.' ); +$ign = $git->command( 'add', '.' ); do_commit( "update readme with an über cléver cómmít with cyrillics: привет" ); push_ok(); @@ -354,10 +354,10 @@ # parent-less branch write_tmp 'reflog', ''; -$git->command( [ 'checkout', '--orphan', 'allnew' ], { STDERR => 0 } ); -$git->command( 'rm', '-rf', '.' ); -$git->command( 'commit', '--allow-empty', '-m', 'created empty branch allnew' ); -$git->command( [ 'push', '-u', 'origin', 'allnew' ], { STDERR => 0 } ); +$ign = $git->command( [ 'checkout', '--orphan', 'allnew' ], { STDERR => 0 } ); +$ign = $git->command( 'rm', '-rf', '.' ); +$ign = $git->command( 'commit', '--allow-empty', '-m', 'created empty branch allnew' ); +$ign = $git->command( [ 'push', '-u', 'origin', 'allnew' ], { STDERR => 0 } ); $c->_reset; $c->_detect_commits; @@ -377,14 +377,14 @@ is( $commit, undef ); # now the same on the master branch -$git->command( [ 'checkout', '-q', 'master' ], { STDERR => 0 } ); +$ign = $git->command( [ 'checkout', '-q', 'master' ], { STDERR => 0 } ); ( my $gitversion = Git::command_oneline('version') ) =~ s/^git version\s*//; my ( $major, $minor, $patch, $ignored ) = split( /\./, $gitversion ); note "Git version $major $minor"; if ( $major > 2 or $major == 2 and $minor >= 9 ) { # 2.9.0+ - $git->command( 'merge', 'allnew', '--allow-unrelated-histories' ); + $ign = $git->command( 'merge', 'allnew', '--allow-unrelated-histories' ); } else { - $git->command( 'merge', 'allnew' ); + $ign = $git->command( 'merge', 'allnew' ); } push_ok(); $c2 = $commit = $c->describe_commit; @@ -398,14 +398,14 @@ . $c2->id . '' ); -$git->command( checkout => '-q', 'other' ); +$ign = $git->command( checkout => '-q', 'other' ); mkdir( File::Spec->catdir( $local, 'debian', 'patches' ) ); w( File::Spec->catfile( 'debian', 'patches', 'series' ), 'some.patch' ); w( File::Spec->catfile( 'debian', 'patches', 'some.patch' ), 'This is a patch' ); -$git->command( add => 'debian' ); -$git->command( commit => -m => 'A change in two files' ); +$ign = $git->command( add => 'debian' ); +$ign = $git->command( commit => -m => 'A change in two files' ); push_ok(); $commit = $c->describe_commit; diff -Nru kgb-bot-1.42/t/53-client-git-merges.t kgb-bot-1.48/t/53-client-git-merges.t --- kgb-bot-1.42/t/53-client-git-merges.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/53-client-git-merges.t 2018-04-21 09:22:17.000000000 +0000 @@ -102,8 +102,8 @@ ok( $git, 'local repository allocated' ); isa_ok( $git, 'Git' ); -$git->command( 'config', 'user.name', 'Test U. Ser' ); -$git->command( 'config', 'user.email', 'ser@example.neverland' ); +my $ign = $git->command( 'config', 'user.name', 'Test U. Ser' ); +$ign = $git->command( 'config', 'user.email', 'ser@example.neverland' ); write_tmp 'reflog', ''; @@ -142,7 +142,7 @@ my %commits; sub do_commit { - $git->command_oneline( 'commit', '-m', shift ) =~ /\[(\w+).*\s+(\w+)\]/; + my $ignore = $git->command_oneline( 'commit', '-m', shift ) =~ /\[(\w+).*\s+(\w+)\]/; push @{ $commits{$1} }, $2; diag "commit $2 in branch $1" unless $tmp_cleanup; } @@ -151,9 +151,9 @@ ###### first commit w( 'old', 'content' ); -$git->command( 'add', '.' ); +$ign = $git->command( 'add', '.' ); do_commit('import old content'); -$git->command( 'remote', 'add', 'origin', "file://$remote" ); +$ign = $git->command( 'remote', 'add', 'origin', "file://$remote" ); push_ok; $commit = $c->describe_commit; @@ -167,27 +167,27 @@ #### branch, two changes, merge. then the changes should be reported only once my $b1 = 'a-new'; -$git->command( [ 'checkout', '-b', $b1, 'master' ], +$ign = $git->command( [ 'checkout', '-b', $b1, 'master' ], { STDERR => 0 } ); w( 'new', 'content' ); -$git->command( 'add', 'new' ); -$git->command( 'commit', '-m', 'created new content' ); +$ign = $git->command( 'add', 'new' ); +$ign = $git->command( 'commit', '-m', 'created new content' ); w( 'new', 'more content' ); -$git->command( 'commit', '-a', '-m', 'updated new content' ); -$git->command( 'checkout', '-q', 'master' ); -$git->command( 'merge', '--no-ff', '-m', "merge '$b1' into master", $b1 ); +$ign = $git->command( 'commit', '-a', '-m', 'updated new content' ); +$ign = $git->command( 'checkout', '-q', 'master' ); +$ign = $git->command( 'merge', '--no-ff', '-m', "merge '$b1' into master", $b1 ); # same with a branch name sorting after 'master' my $b2 = 'new-content'; -$git->command( [ 'checkout', '-b', $b2, 'master' ], +$ign = $git->command( [ 'checkout', '-b', $b2, 'master' ], { STDERR => 0 } ); w( 'new', 'content' ); -$git->command( 'add', 'new' ); -$git->command( 'commit', '-m', 'created new content' ); +$ign = $git->command( 'add', 'new' ); +$ign = $git->command( 'commit', '-m', 'created new content' ); w( 'new', 'more content' ); -$git->command( 'commit', '-a', '-m', 'updated new content' ); -$git->command( 'checkout', '-q', 'master' ); -$git->command( 'merge', '--no-ff', '-m', "merge '$b2' into master", $b2 ); +$ign = $git->command( 'commit', '-a', '-m', 'updated new content' ); +$ign = $git->command( 'checkout', '-q', 'master' ); +$ign = $git->command( 'merge', '--no-ff', '-m', "merge '$b2' into master", $b2 ); push_ok(); $commit = $c->describe_commit; diff -Nru kgb-bot-1.42/t/70-webhook-push.t kgb-bot-1.48/t/70-webhook-push.t --- kgb-bot-1.42/t/70-webhook-push.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/70-webhook-push.t 2018-04-21 09:22:17.000000000 +0000 @@ -38,8 +38,15 @@ my $R = getcwd; my $ua = LWP::UserAgent->new(); -my $webhook_url = sprintf( 'http://%s:%d/webhook/?channel=test&network=local', - $test_bot->addr, $test_bot->port ); +my $webhook_url = sprintf( + 'http://%s:%d/webhook/?%s', + $test_bot->addr, + $test_bot->port, + join( '&', + 'channel=test', 'network=local', + 'shorten_urls=0', 'only_branch=master', + "only_branch=old_branch" ) +); sub webhook_post { my $response = $ua->post( @@ -55,6 +62,7 @@ user_name => 'Unused Test User', user_username => 'ser', project => { name => 'test-repo', }, + after => '284ffdd4c525547f6ae848d768fff92ff9a89743', commits => [ { id => 'b9b55876e288bba29d1579d308eea5758bc148ef', message => "Commit three files (add, mod, rm)", @@ -84,7 +92,7 @@ '05master b9b5587 06test-repo', '10mod-one 03file-one 04rm-one', '* Commit three files (add, mod, rm)', - '* 14http://git/b9b55876e288bba29d1579d308eea5758bc148ef' ) + '* 14http://git/b9b5587' ) ); TestBot->expect( @@ -93,9 +101,64 @@ '05master 284ffdd 06test-repo', '10(6 files)', '* Commit six files (2×(add, mod, rm))', - '* 14http://git/284ffdd4c525547f6ae848d768fff92ff9a89743' ) + '* 14http://git/284ffdd' ) ); +$resp = webhook_post( + { object_kind => 'push', + ref => 'refs/heads/old_branch', + user_name => 'Test User', + user_username => 'ser', + project => { name => 'test-repo', }, + before => '284ffdd4c525547f6ae848d768fff92ff9a89743', + after => '0000000000000000000000000000000000000000', + commits => [ ], + } +); + +is( $resp->code, 202, 'response status is 202' ) or diag $resp->as_string; + +TestBot->expect( + join( ' ', + '#test 03Test User', + '05old_branch 284ffdd 06test-repo', + '04.', + '* branch deleted' ) +); + +# a push outside the designated branch + +$resp = webhook_post( + { object_kind => 'push', + ref => 'refs/heads/random-branch', + user_name => 'Test User', + user_username => 'ser', + project => { name => 'test-repo', }, + before => '284ffdd4c525547f6ae848d768fff92ff9a89743', + after => '2189572634934075403487349534879534875349', + commits => [ + { id => 'b9b55876e288bba29d1579d308eea5758bc148ef', + message => "Commit three files (add, mod, rm)", + url => "http://git/b9b55876e288bba29d1579d308eea5758bc148ef", + author => { name => 'Test User', }, + added => [ 'file-one' ], + modified => [ 'mod-one' ], + removed => [ 'rm-one' ], + }, + { id => '284ffdd4c525547f6ae848d768fff92ff9a89743', + message => "Commit six files (2×(add, mod, rm))\n\nThese were all needed", + url => "http://git/284ffdd4c525547f6ae848d768fff92ff9a89743", + author => { name => 'Test User', }, + added => [ 'file-one', 'file-two.txt' ], + modified => [ 'mod-one', 'mod-two.txt' ], + removed => [ 'rm-one', 'rm-two.txt' ], + }, + ], + } +); + +is( $resp->code, 202, 'response status is 202' ) or diag $resp->as_string; + diag `cat t/bot/kgb-bot.log`; my $output = $test_bot->get_output; diff -Nru kgb-bot-1.42/t/71-webhook-push_tag.t kgb-bot-1.48/t/71-webhook-push_tag.t --- kgb-bot-1.42/t/71-webhook-push_tag.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/71-webhook-push_tag.t 2018-04-21 09:22:17.000000000 +0000 @@ -38,8 +38,13 @@ my $R = getcwd; my $ua = LWP::UserAgent->new(); -my $webhook_url = sprintf( 'http://%s:%d/webhook/?channel=test&network=local&use_color=0', - $test_bot->addr, $test_bot->port ); +my $webhook_url = sprintf( + 'http://%s:%d/webhook/?' + . join( '&', + 'channel=test', 'network=local', 'use_color=0', 'shorten_urls=0' ), + $test_bot->addr, + $test_bot->port +); sub webhook_post { my $response = $ua->post( @@ -86,13 +91,34 @@ TestBot->expect( join( ' ', '#test Test User', - 'signed-tags 470fc2f test-repo', + 'signed tags 470fc2f test-repo', 'v5.8-plus', '* Tagging v5.8-plus', '* http://git/project/tags/v5.8-plus', ) ); +is( $resp->code, 202, 'response status is 202' ) or diag $resp->as_string; + +$resp = webhook_post( + { object_kind => 'tag_push', + ref => 'refs/tags/v5.8-plus', + before => '470fc2f92766368cd72e2796db89360fe8e81637', + after => '0000000000000000000000000000000000000000', + user_name => 'Test User', + project => { name => 'test-repo', homepage => 'http://git/project', }, + } +); + +TestBot->expect( + join( ' ', + '#test Test User', + 'tags 470fc2f test-repo', + 'v5.8-plus', + '* tag deleted', + ) +); + is( $resp->code, 202, 'response status is 202' ) or diag $resp->as_string; diag `cat t/bot/kgb-bot.log`; diff -Nru kgb-bot-1.42/t/72-webhook-wiki_page.t kgb-bot-1.48/t/72-webhook-wiki_page.t --- kgb-bot-1.42/t/72-webhook-wiki_page.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/72-webhook-wiki_page.t 2018-04-21 09:22:17.000000000 +0000 @@ -38,8 +38,9 @@ my $R = getcwd; my $ua = LWP::UserAgent->new(); -my $webhook_url = sprintf( 'http://%s:%d/webhook/?channel=test&network=local', - $test_bot->addr, $test_bot->port ); +my $webhook_url = sprintf( 'http://%s:%d/webhook/?%s', + $test_bot->addr, $test_bot->port, + join( '&', 'channel=test', 'network=local', 'shorten_urls=0' ) ); sub webhook_post { my $response = $ua->post( diff -Nru kgb-bot-1.42/t/73-webhook-issue.t kgb-bot-1.48/t/73-webhook-issue.t --- kgb-bot-1.42/t/73-webhook-issue.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/73-webhook-issue.t 2018-04-21 09:22:17.000000000 +0000 @@ -38,8 +38,9 @@ my $R = getcwd; my $ua = LWP::UserAgent->new(); -my $webhook_url = sprintf( 'http://%s:%d/webhook/?channel=test&network=local', - $test_bot->addr, $test_bot->port ); +my $webhook_url = sprintf( 'http://%s:%d/webhook/?%s', + $test_bot->addr, $test_bot->port, + join( '&', 'channel=test', 'network=local', 'shorten_urls=0' ) ); sub webhook_post { return $ua->post( @@ -54,7 +55,8 @@ user => { name => 'Test User' }, project => { name => 'test-repo', }, object_attributes => { - id => 42, + id => 4242, + iid => 42, title => "Issue title goes here", url => 'http://git/issues/42', action => 'open', @@ -68,7 +70,7 @@ join( ' ', '#test 03Test User', '05issues 06test-repo', - '42', + '#42', '03Issue title goes here', '* 14http://git/issues/42', ) diff -Nru kgb-bot-1.42/t/74-webhook-notes.t kgb-bot-1.48/t/74-webhook-notes.t --- kgb-bot-1.42/t/74-webhook-notes.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/74-webhook-notes.t 2018-04-21 09:22:17.000000000 +0000 @@ -42,9 +42,13 @@ my $R = getcwd; my $ua = LWP::UserAgent->new(); -my $webhook_url = - sprintf( 'http://%s:%d/webhook/?channel=test&network=local&use_color=0', - $test_bot->addr, $test_bot->port ); +my $webhook_url = sprintf( + 'http://%s:%d/webhook/?%s', + $test_bot->addr, + $test_bot->port, + join( '&', + 'channel=test', 'network=local', 'use_color=0', 'shorten_urls=0' ) +); sub webhook_post { return $ua->post( @@ -92,7 +96,7 @@ noteable_type => 'MergeRequest', url => 'http://git/merge_requests/4242#note42', }, - merge_request => { id => 4242 }, + merge_request => { id => 424242, iid => 4242 }, } ); @@ -103,7 +107,7 @@ '#test Test User', 'test-repo', '42', - '* commented merge request #4242', + '* commented merge request !4242', '* http://git/merge_requests/4242#note42', ) ); @@ -118,7 +122,7 @@ noteable_type => 'Issue', url => 'http://git/issues/4242#note42', }, - issue => { id => 4242 }, + issue => { id => 424242, iid => 4242 }, } ); diff -Nru kgb-bot-1.42/t/75-webhook-merge-request.t kgb-bot-1.48/t/75-webhook-merge-request.t --- kgb-bot-1.42/t/75-webhook-merge-request.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/75-webhook-merge-request.t 2018-04-21 09:22:17.000000000 +0000 @@ -42,9 +42,13 @@ my $R = getcwd; my $ua = LWP::UserAgent->new(); -my $webhook_url = - sprintf( 'http://%s:%d/webhook/?channel=test&network=local&use_color=0', - $test_bot->addr, $test_bot->port ); +my $webhook_url = sprintf( + 'http://%s:%d/webhook/?%s', + $test_bot->addr, + $test_bot->port, + join( '&', + 'channel=test', 'network=local', 'use_color=0', 'shorten_urls=0' ) +); sub webhook_post { return $ua->post( @@ -59,7 +63,8 @@ user => { name => 'Test User' }, project => { name => 'test-repo', }, object_attributes => { - id => 42, + id => 4242, + iid => 42, target_branch => "nevermore", action => 'open', url => 'http://git/merge_requests/42', @@ -73,8 +78,7 @@ join( ' ', '#test Test User', 'nevermore test-repo', - '42', - '* open of merge request #42', + '* [open] merge request !42', '* http://git/merge_requests/42', ) ); diff -Nru kgb-bot-1.42/t/76-webhook-pipeline.t kgb-bot-1.48/t/76-webhook-pipeline.t --- kgb-bot-1.42/t/76-webhook-pipeline.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/76-webhook-pipeline.t 2018-04-21 09:22:17.000000000 +0000 @@ -42,9 +42,15 @@ my $R = getcwd; my $ua = LWP::UserAgent->new(); -my $webhook_url = - sprintf( 'http://%s:%d/webhook/?channel=test&network=local&use_color=0', - $test_bot->addr, $test_bot->port ); +my $webhook_url = sprintf( + 'http://%s:%d/webhook/?%s', + $test_bot->addr, + $test_bot->port, + join( '&', + 'channel=test', 'network=local', + 'use_color=0', 'pipeline_only_status=success', + 'pipeline_only_status=failure' ) +); sub webhook_post { return $ua->post( @@ -59,21 +65,82 @@ user => { name => 'Test User' }, project => { name => 'test-repo', }, object_attributes => + { id => 42, status => 'created' }, + } +); + +is( $resp->code, 202, 'pipeline event response status is 202' ) + or diag $resp->as_string; + +$resp = webhook_post( + { object_kind => 'pipeline', + user => { name => 'Test User' }, + project => { name => 'test-repo', }, + object_attributes => { id => 42, status => 'success', duration => 3665, }, } ); -is( $resp->code, 202, 'pipeline event response status is 202' ) or diag $resp->as_string; +is( $resp->code, 202, 'pipeline event response status is 202' ) + or diag $resp->as_string; TestBot->expect( join( ' ', '#test Test User', + 'pipeline', 'test-repo', '42', - '* Pipeline #42 finished in 1 hour, 1 minute and 5 seconds. Status: success', + '* [1 hour, 1 minute and 5 seconds] success', ) ); +$resp = webhook_post( + { object_kind => 'pipeline', + user => { name => 'Test User' }, + project => { name => 'test-rep', }, + object_attributes => + { id => 43, status => 'success', duration => 3666, }, + builds => [ + { name => 'staging', status => 'created' }, + { name => 'build-image', status => 'success' }, + ], + } +); + +is( $resp->code, 202, 'pipeline event response status is 202' ) or diag $resp->as_string; + +TestBot->expect( + join( ' ', + '#test Test User', + 'pipeline', + 'test-rep', + '43', + '* [1 hour, 1 minute and 6 seconds] success (staging: created; build-image: success)', + ) +); + +$resp = webhook_post( + { object_kind => 'pipeline', + user => { name => 'Test User' }, + project => { name => 'test-rep', }, + object_attributes => + { id => 43, status => 'failure' }, + } +); + +is( $resp->code, 202, 'pipeline event response status is 202' ) or diag $resp->as_string; + +TestBot->expect( + join( ' ', + '#test Test User', + 'pipeline', + 'test-rep', + '43', + '* failure', + ) +); + + diag `cat t/bot/kgb-bot.log`; $test_bot->stop; # make sure all output is there diff -Nru kgb-bot-1.42/t/78-webhook-push-squash.t kgb-bot-1.48/t/78-webhook-push-squash.t --- kgb-bot-1.42/t/78-webhook-push-squash.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/78-webhook-push-squash.t 2018-04-21 09:22:17.000000000 +0000 @@ -38,8 +38,14 @@ my $R = getcwd; my $ua = LWP::UserAgent->new(); -my $webhook_url = sprintf( 'http://%s:%d/webhook/?channel=test&network=local&squash_threshold=1&use_color=0', - $test_bot->addr, $test_bot->port ); +my $webhook_url = sprintf( + 'http://%s:%d/webhook/?%s', + $test_bot->addr, + $test_bot->port, + join( '&', + 'channel=test', 'network=local', 'squash_threshold=1', + 'use_color=0', 'shorten_urls=0' ), +); sub webhook_post { my $response = $ua->post( @@ -88,10 +94,117 @@ join( ' ', '#test Test User', 'master checkou test-repo', - '* pushed 2 commits', + '* pushed 2 commits (first 1 follow)', '* http://git/test/compare/before...after' ) ); +TestBot->expect( + join( ' ', + '#test Test User', + 'master b9b5587 test-repo', + 'mod-one file-one rm-one', + '* Commit three files (add, mod, rm)', + '* http://git/b9b5587' ) +); + +$resp = webhook_post( + { object_kind => 'push', + before => 'before', + after => 'after6', + ref => 'refs/heads/master', + checkout_sha => 'checkout', + user_name => 'Test User', + user_username => 'ser', + project => { + name => 'test-repo', + homepage => 'http://git/test', + }, + commits => [ + { id => 'b9b55876e288bba29d1579d308eea5758bc148ef', + message => "Commit three files (add, mod, rm)", + url => "http://git/b9b55876e288bba29d1579d308eea5758bc148ef", + author => { name => 'Test User', }, + added => [ 'file-one' ], + modified => [ 'mod-one' ], + removed => [ 'rm-one' ], + }, + { id => '284ffdd4c525547f6ae848d768fff92ff9a89743', + message => "Commit six files (2×(add, mod, rm))\n\nThese were all needed", + url => "http://git/284ffdd4c525547f6ae848d768fff92ff9a89743", + author => { name => 'Test User', }, + added => [ 'file-one', 'file-two.txt' ], + modified => [ 'mod-one', 'mod-two.txt' ], + removed => [ 'rm-one', 'rm-two.txt' ], + }, + ], + total_commits_count => 6, + } +); + +is( $resp->code, 202, 'response status is 202' ) or diag $resp->as_string; + +TestBot->expect( + join( ' ', + '#test Test User', + 'master checkou test-repo', + '* pushed 6 commits (first 1 follow)', + '* http://git/test/compare/before...after6' ) +); + +TestBot->expect( + join( ' ', + '#test Test User', + 'master b9b5587 test-repo', + 'mod-one file-one rm-one', + '* Commit three files (add, mod, rm)', + '* http://git/b9b5587' ) +); + +$resp = webhook_post( + { object_kind => 'push', + before => 'before', + after => 'after6', + ref => 'refs/heads/upstream', + checkout_sha => 'checkout', + user_name => 'Test User', + user_username => 'ser', + project => { + name => 'test-repo', + homepage => 'http://git/test', + }, + commits => [ + { id => 'b9b55876e288bba29d1579d308eea5758bc148ef', + message => "Commit three files (add, mod, rm)", + url => "http://git/b9b55876e288bba29d1579d308eea5758bc148ef", + author => { name => 'Test User', }, + added => [ 'file-one' ], + modified => [ 'mod-one' ], + removed => [ 'rm-one' ], + }, + { id => '284ffdd4c525547f6ae848d768fff92ff9a89743', + message => "Commit six files (2×(add, mod, rm))\n\nThese were all needed", + url => "http://git/284ffdd4c525547f6ae848d768fff92ff9a89743", + author => { name => 'Test User', }, + added => [ 'file-one', 'file-two.txt' ], + modified => [ 'mod-one', 'mod-two.txt' ], + removed => [ 'rm-one', 'rm-two.txt' ], + }, + ], + total_commits_count => 6, + } +); + +is( $resp->code, 202, 'response status is 202' ) or diag $resp->as_string; + +TestBot->expect( + join( ' ', + '#test Test User', + 'upstream checkou test-repo', + '* pushed 6 commits', + '* http://git/test/compare/before...after6' ) +); + + diag `cat t/bot/kgb-bot.log`; my $output = $test_bot->get_output; diff -Nru kgb-bot-1.42/t/79-webhook-push-author.t kgb-bot-1.48/t/79-webhook-push-author.t --- kgb-bot-1.42/t/79-webhook-push-author.t 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/79-webhook-push-author.t 2018-04-21 09:22:17.000000000 +0000 @@ -84,7 +84,7 @@ 'master b9b5587 test-repo', 'mod-one file-one rm-one', '* Commit three files (add, mod, rm)', - '* http://git/b9b55876e288bba29d1579d308eea5758bc148ef' ) + '* http://l.nk/0' ) ); diag `cat t/bot/kgb-bot.log`; diff -Nru kgb-bot-1.42/t/TestBot.pm kgb-bot-1.48/t/TestBot.pm --- kgb-bot-1.42/t/TestBot.pm 2018-02-26 13:23:16.000000000 +0000 +++ kgb-bot-1.48/t/TestBot.pm 2018-04-21 09:22:17.000000000 +0000 @@ -96,6 +96,7 @@ enabled: 1 allowed_networks: - $addr +short_url_service: DummyShortener EOF chmod 0600, $fh; close($fh); @@ -103,6 +104,12 @@ my $bot_script = $ENV{KGB_BOT_SCRIPT} || File::Spec->catfile( 'script', 'kgb-bot' ); + my $t_dir = File::Spec->catdir(getcwd, 't'); + my $dirs = $ENV{PERL5LIB}; + if ($dir) { $dirs .= ":$t_dir" } + else { $dirs = $t_dir } + $ENV{PERL5LIB} = $dirs; + system( $bot_script, '--config', $conf_file, '--simulate', $self->output_file, '--simulate-color' ) == 0 diff -Nru kgb-bot-1.42/t/WWW/Shorten/DummyShortener.pm kgb-bot-1.48/t/WWW/Shorten/DummyShortener.pm --- kgb-bot-1.42/t/WWW/Shorten/DummyShortener.pm 1970-01-01 00:00:00.000000000 +0000 +++ kgb-bot-1.48/t/WWW/Shorten/DummyShortener.pm 2018-04-21 09:22:17.000000000 +0000 @@ -0,0 +1,24 @@ +package WWW::Shorten::DummyShortener; + +use strict; +use warnings; + +use base qw( WWW::Shorten::generic Exporter ); +our @EXPORT = qw(makeashorterlink makealongerlink); +our $VERSION = '0.0'; + +use Carp; + +my $LINK_COUNTER = 0; +my $URL_BASE = 'http://l.nk/'; + +sub makeashorterlink { + my $url = shift or croak 'No URL passed to makeashorterlink'; + return sprintf( "%s%d", $URL_BASE, $LINK_COUNTER++ ); +} + +sub makealongerlink { + die "Not implemented. This is a dummy test module, okay?"; +} + +1;