about summary refs log tree commit diff
path: root/lib/jitterbug/Builder.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/jitterbug/Builder.pm')
-rw-r--r--lib/jitterbug/Builder.pm176
1 files changed, 108 insertions, 68 deletions
diff --git a/lib/jitterbug/Builder.pm b/lib/jitterbug/Builder.pm
index 1f9bd3d..ab96251 100644
--- a/lib/jitterbug/Builder.pm
+++ b/lib/jitterbug/Builder.pm
@@ -10,7 +10,7 @@ use File::Path qw/rmtree/;
 use Path::Class;
 use Getopt::Long qw/:config no_ignore_case/;
 use File::Basename;
-use Git::Repository;
+use File::Spec::Functions;
 use jitterbug::Schema;
 use Cwd;
 #use Data::Dumper;
@@ -81,75 +81,87 @@ sub sleep {
     sleep $interval;
 }
 
-sub run_task {
-    my ($self,$task)   = @_;
+sub _clone_into {
+    my ($repo, $dir) = @_;
+    my $pwd = getcwd;
+    chdir $dir;
 
-    my $desc    = JSON::decode_json( $task->commit->content );
-    my $conf    = $self->{'conf'};
-    my $buildconf = $conf->{'jitterbug'}{'build_process'};
-    my $project = $task->project;
+    debug("cloning $repo into $dir");
+    system("git clone $repo $dir");
 
-    my $dt = DateTime->now();
-    $task->update({started_when => $dt});
-    $desc->{'build'}{'start_time'} = $dt->epoch;
-    debug("Build Start");
+    chdir $pwd;
+}
 
-    my $report_path = dir(
-        $conf->{'jitterbug'}{'reports'}{'dir'},
-        $project->name,
-        $task->commit->sha256,
-    );
-    my $dir = $conf->{'jitterbug'}{'build'}{'dir'};
-    mkdir $dir unless -d $dir;
+sub _prepare_git_repo {
+    my ($self, $task, $buildconf, $build_dir, $cached_repo_dir) = @_;
 
-    my $build_dir = dir($dir, $project->name);
+    my $repo    = $task->project->url;
+    my $name    = $task->project->name;
 
-    my $r;
-    my $repo    = $task->project->url . '.git';
+    debug("Removing $build_dir");
+    rmtree($build_dir, { error => \my $err } );
+    warn @$err if @$err;
+
+    # If we aren't reusing/caching git repos, clone from remote into the build dir
     unless ($buildconf->{reuse_repo}) {
-        debug("Removing $build_dir");
-        rmtree($build_dir, { error => \my $err } );
-        warn @$err if @$err;
-        $r       = Git::Repository->create( clone => $repo => $build_dir );
+        _clone_into($repo, $build_dir);
     } else {
-        # If this is the first time, the repo won't exist yet
+        # We are caching git repos, so we clone a new repo from our local
+        # cached git repo, then checkout the correct sha1
+
         debug("build_dir = $build_dir");
-        if( -d $build_dir ){
-            my $pwd = getcwd;
-            chdir $build_dir;
-            # TODO: Error Checking
-            debug("Cleaning git repo");
-            system("git clean -dfx");
-            debug("Fetching new commits into $repo");
-            system("git fetch");
-            debug("Checking out correct commit");
-            system("git checkout " . $task->commit->sha256 );
-            chdir $pwd;
-        } else {
-            debug("Creating new repo");
-            my $pwd = getcwd;
-            debug("pwd=$pwd");
-            chdir $build_dir;
-            system("git clone $repo $build_dir");
-            chdir $pwd;
+        mkdir $cached_repo_dir unless -d $cached_repo_dir;
+        my $cached_repo = catfile($cached_repo_dir,$name);
+
+        unless ( -d $cached_repo ) {
+            # If this is the first time, the repo won't exist yet
+            # Clone it into our cached repo directory
+            _clone_into($repo, $cached_repo);
         }
+        my $pwd = getcwd;
+
+        chdir $cached_repo;
+        # TODO: Error Checking
+
+        debug("Fetching new commits into $cached_repo");
+        system("git fetch --prune");
+
+        $self->sleep(1); # avoid race conditions
+
+        debug("Cloning from cached repo $cached_repo_dir/$name into $build_dir");
+        _clone_into(catdir($cached_repo_dir,$name), $build_dir);
+        chdir $build_dir;
+
+        $self->sleep(1); # avoid race conditions
+
+        # TODO: this may fail on non-unixy systems
+        debug("checking out " . $task->commit->sha256);
+        system("git checkout " . $task->commit->sha256 . "&>/dev/null" );
+
+        chdir $pwd;
     }
-    $self->sleep(1); # avoid race conditions
+}
 
-    debug("Checking out " . $task->commit->sha256 . " from $repo into $build_dir\n");
-    # $r->run( 'checkout', $task->commit->sha256 );
-    my $pwd = getcwd;
-    chdir $build_dir;
-    system("git checkout " . $task->commit->sha256 );
-    chdir $pwd;
+sub build_task {
+    my ($self, $conf, $project, $task, $report_path) = @_;
+
+    my $buildconf = $conf->{'jitterbug'}{'build_process'};
+    my $dir       = $conf->{'jitterbug'}{'build'}{'dir'};
+
+    mkdir $dir unless -d $dir;
+
+    my $build_dir = dir($dir, $project->name);
+    my $cached_repo_dir = dir($dir, 'cached');
+
+    mkdir $cached_repo_dir unless -d $cached_repo_dir;
+
+    $self->_prepare_git_repo($task, $buildconf, $build_dir, $cached_repo_dir);
 
     my $builder       =    $conf->{'jitterbug'}{'projects'}{$project->name}{'builder'}
                         || $conf->{'jitterbug'}{'build_process'}{'builder'};
 
     my $perlbrew      = $conf->{'jitterbug'}{'options'}{'perlbrew'};
-    my $email_on_pass = $conf->{'jitterbug'}{'options'}{'email_on_pass'};
 
-    debug("email_on_pass = $email_on_pass");
     debug("perlbrew      = $perlbrew");
 
     # If the project has custom builder variables, use those. Otherwise, use the global setting
@@ -161,9 +173,47 @@ sub run_task {
     debug("Going to run builder : $builder_command");
     my $res             = `$builder_command`;
     debug($res);
+    return $res;
+}
+
+sub run_task {
+    my ($self,$task)   = @_;
+
+    my $desc    = JSON::decode_json( $task->commit->content );
+    my $conf    = $self->{'conf'};
+    my $project = $task->project;
+    my $report_path = dir(
+        $conf->{'jitterbug'}{'reports'}{'dir'},
+        $project->name,
+        $task->commit->sha256,
+    );
+
+    my $dt = DateTime->now();
+    $task->update({started_when => $dt});
+    $desc->{'build'}{'start_time'} = $dt->epoch;
+    debug("Build Start");
+
+    $self->build_task($conf, $project, $task, $report_path);
 
     $desc->{'build'}{'end_time'} = time();
 
+    $self->_parse_results($report_path, $conf, $task, $desc);
+
+    $task->commit->update( {
+        content => JSON::encode_json($desc),
+    } );
+    debug("Task completed for " . $task->commit->sha256 . "\n");
+
+    $task->delete();
+
+    debug("Task removed from " . $task->project->name . "\n");
+}
+
+sub _parse_results {
+    my ($self, $report_path, $conf, $task, $desc) = @_;
+    my $email_on_pass = $conf->{'jitterbug'}{'options'}{'email_on_pass'};
+    debug("email_on_pass = $email_on_pass");
+
     my @versions = glob( $report_path . '/*' );
     foreach my $version (@versions) {
         open my $fh, '<', $version;
@@ -193,15 +243,15 @@ sub run_task {
             my $on_failure_cc_email = $conf->{'jitterbug'}{'build_process'}{'on_failure_cc_email'};
 
             $message  =~ s/'/\\'/g; $commiter =~ s/'/\\'/g; $output =~ s/'/\\'/g;
-            my $failure_cmd = sprintf("%s '%s' %s '%s' '%s' %s %s", $on_failure, $commiter, $task->project->name, $message, $output, $sha, $on_failure_cc_email);
-            debug("Running failure command: $failure_cmd");
-
             # does it look like a module name?
             if ($on_failure =~ /::/) {
                 # we should do some error checking here
                 eval "require $on_failure";
                 $on_failure->new($conf,$task,$output,'failure')->run;
             } else {
+                my $failure_cmd = sprintf("%s '%s' %s '%s' '%s' %s %s", $on_failure, $commiter, $task->project->name, $message, $output, $sha, $on_failure_cc_email);
+                debug("Running failure command: $failure_cmd");
+
                 system($failure_cmd);
             }
         } elsif ($email_on_pass) {
@@ -215,8 +265,6 @@ sub run_task {
             my $on_pass_cc_email = $conf->{'jitterbug'}{'build_process'}{'on_pass_cc_email'};
 
             $message  =~ s/'/\\'/g; $commiter =~ s/'/\\'/g; $output =~ s/'/\\'/g;
-            my $pass_cmd = sprintf("%s '%s' %s '%s' '%s' %s %s", $on_pass, $commiter, $task->project->name, $message, $output, $sha, $on_pass_cc_email);
-            debug("Running pass command: $pass_cmd");
 
             # does it look like a module name?
             if ($on_pass =~ /::/) {
@@ -224,20 +272,12 @@ sub run_task {
                 eval "require $on_pass";
                 $on_pass->new($conf,$task,$output, 'pass')->run;
             } else {
+                my $pass_cmd = sprintf("%s '%s' %s '%s' '%s' %s %s", $on_pass, $commiter, $task->project->name, $message, $output, $sha, $on_pass_cc_email);
+                debug("Running pass command: $pass_cmd");
                 system($pass_cmd);
             }
         }
         $desc->{'build'}{'version'}{$name} = $result;
         close $fh;
     }
-
-    $task->commit->update( {
-        content => JSON::encode_json($desc),
-    } );
-    debug("Task completed for " . $task->commit->sha256 . "\n");
-
-    $task->delete();
-
-    debug("Task removed from " . $task->project->name . "\n");
 }
-