about summary refs log tree commit diff
path: root/lib/jitterbug/Builder.pm
blob: 9eebe8b4d84ec9068e30c69a5403213d4be500b0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package jitterbug::Builder;

use strict;
use warnings;

use YAML qw/LoadFile Dump/;
use JSON;
use File::Path qw/rmtree/;
use Path::Class;
use Getopt::Long qw/:config no_ignore_case/;
use File::Basename;
use Git::Repository;
use jitterbug::Schema;

local $| = 1;

sub new {
    my $self = bless {} => shift;

    GetOptions(
        'C|cron'         => \$self->{'cron'},
        'c|configfile=s' => \$self->{'configfile'},
        's|sleep=i'      => \$self->{'sleep'},
    ) or die "Cannot get options\n";

    $self->{'configfile'}
        or die qq{missing config.yml, use "-c config.yml" to help us find it\n};

    return $self;
}

sub run {
    my $self      = shift || die "Must call run() from object\n";
    my $conf      = $self->{'conf'} = LoadFile( $self->{'configfile'} );
    my $dbix_conf = $conf->{'plugins'}{'DBIC'}{'schema'};

    $self->{'schema'}   = jitterbug::Schema->connect( @{ $dbix_conf->{'connect_info'} } );
    $self->{'interval'} = $self->{'sleep'}                         ||
                          $conf->{'jitterbug'}{'builder'}{'sleep'} ||
                          30;

    return $self->build;
}

sub build {
    my $self  = shift;
    my @tasks = $self->{'schema'}->resultset('Task')->all();

    while (1) {
        foreach my $task (@tasks) {
            $task ? $self->run_task($task) : sleep $self->{'interval'};
        }

        $self->{'cron'} and return 0;

        warn "done\n";
        sleep 5;
    }

    return 1;
}

sub run_task {
    my $self   = shift;
    my ($task) = @_;
    my $desc   = JSON::decode_json( $task->commit->content );
    my $conf   = $self->{'conf'};

    $desc->{'build'}{'start_time'} = time();

    my $report_path = dir(
        $conf->{'jitterbug'}{'reports'}{'dir'},
        $task->project->name,
        $task->commit->sha256,
    );

    my $build_dir = dir(
        $conf->{'jitterbug'}{'build'}{'dir'},
        $task->project->name,
    );

    my $repo    = $task->project->url . '.git';
    my $r       = Git::Repository->create( clone => $repo => $build_dir );
    $r->run( 'checkout', $task->commit->sha256 );

    my $builder = $conf->{'jitterbug'}{'build_process'}{'builder'};
    my $res     = `$builder $build_dir $report_path`;

    rmtree($build_dir);

    $desc->{'build'}{'end_time'} = time();

    my @versions = glob( $report_path . '/*' );
    foreach my $version (@versions) {
        open my $fh, '<', $version;
        my ($result, $lines);
        while (<$fh>){
            $lines .= $_;
        }
        ($result) = $lines =~ /Result:\s(\w+)/;
        my ( $name, ) = basename($version);
        $name =~ s/\.txt//;
        if ( !$result || ($result && $result !~ /PASS/ )) {
            # mail author of the commit
            $result = "FAIL";
            my $message  = $desc->{'message'};
            my $commiter = $desc->{'author'}{'email'};
            my $output   = "Build failed";
            my $sha      = $desc->{'id'};
            my $on_failure =
                $conf->{'jitterbug'}{'build_process'}{'on_failure'};
            `$on_failure $commiter $message $output $sha`;
        }
        $desc->{'build'}{'version'}{$name} = $result;
        close $fh;
    }

    $task->commit->update( {
        content => JSON::encode_json($desc),
    } );

    $task->delete();
}