User:AnomieBOT/source/tools-updatebot.pl

#!/usr/bin/perl -w

# This script should be run from a post-receive hook on the bare repo, e.g. as
# something like
# /usr/bin/sudo -niu tools.anomiebot /data/project/anomiebot/bot/tools-updatebot.pl update

use strict;
use Cwd;
use File::Basename;
use IPC::Run;

my $base;
BEGIN {
    $base = File::Basename::dirname( Cwd::realpath( __FILE__ ) );
    chdir( $base );
}
use lib $base;
use AnomieBOT::API;

chdir($AnomieBOT::API::basedir);

$| = 1;

my $cmd = shift // '';
if ( $cmd eq 'update' ) {
    print( "Updating git repo...\n" );

    my $t = IPC::Run::timeout( 30 );
    $t->exception( 'git pull timed out' );
    IPC::Run::run( [qw(git pull -q --ff-only)], $t ) or die "Git pull failed with code $?\n";

    print( "Fetching hash...\n" );

    my $hash = undef;
    $t->start( 5 );
    $t->exception( 'git rev-parse timed out' );
    IPC::Run::run( [qw(git rev-parse HEAD)], '>', \$hash, $t ) or die "Git rev-parse failed with code $?\n";
    chomp $hash;

    print( "New hash is $hash\n" );

    print( "Finding jobs...\n" );

    my $api = AnomieBOT::API->new("conf.ini", 1, { db => 0 });
    my $tasks = $api->cache->get( 'joblist' );
    die "No joblist\n" unless ref($tasks) eq 'ARRAY';

    my %botnums = ();
    for my $task (@$tasks) {
        my $status = $api->cache->get( "status:$task" );
        next unless $status;
        next unless $status->{'hostname'} and $status->{'botnum'};
        $botnums{$status->{'botnum'}} = 1;
    }
    die "No jobs found\n" unless %botnums;

    print( "Signaling jobs...\n" );
    for my $botnum (sort { $a <=> $b } keys %botnums) {
        eval {
            my $api = AnomieBOT::API->new("conf.ini", $botnum, { db => 0 });
            my $file = $api->{'commandfile'};
            $api->send_command( $file, "restart-hash $hash" );
            print( "Signaled $botnum...\n" );
        };
        warn "Signal of $botnum failed: $@\n" if $@;
    }

    exit( 0 );
} else {
    die "USAGE: $0 update\n";
}