diff options
Diffstat (limited to '')
-rw-r--r-- | Build.PL | 1 | ||||
-rw-r--r-- | README | 43 | ||||
-rw-r--r-- | README.md | 49 | ||||
-rw-r--r-- | config.yml | 1 | ||||
-rw-r--r-- | example.yml | 53 | ||||
-rw-r--r-- | lib/jitterbug/Builder.pm | 74 | ||||
-rw-r--r-- | public/js/common.js | 2 | ||||
-rw-r--r-- | scripts/build_rakudo_and_spectest.sh | 10 | ||||
-rwxr-xr-x | scripts/capsule.sh | 2 | ||||
-rw-r--r-- | t/004_project.t | 7 | ||||
-rw-r--r-- | t/lib/jitterbug/Test.pm | 7 |
11 files changed, 180 insertions, 69 deletions
diff --git a/Build.PL b/Build.PL index 926267d..10991a6 100644 --- a/Build.PL +++ b/Build.PL @@ -24,6 +24,7 @@ my $builder = Module::Build->new( 'Dancer::Template::Xslate' => 0, 'Dancer::Plugin::DBIC' => 0, 'DBIx::Class' => 0, + 'DateTime::Format::SQLite' => 0, 'SQL::Translator' => 0, 'Digest::MD5' => 0, 'App::perlbrew' => 0, diff --git a/README b/README deleted file mode 100644 index 8ce74fd..0000000 --- a/README +++ /dev/null @@ -1,43 +0,0 @@ -Jitterbug : A continuous integration system built on Dancer and git hooks - -Jitterbug is written in Perl 5 and depends on various CPAN modules, such -as Dancer, DBIx::Class and Git::Repository. - -Installing Jitterbug -=================== - -perl Build.PL - -# You can also use Makefile.PL, but you will then have to manually -# install dependencies -# perl Makefile.PL - -# install missing dependencies -./Build installdeps - -# start the jitterbug Dancer app, which by default binds to port 3000 -perl jitterbug.pl - -# If you need to start it on a different port use -p -# perl jitterbug.pl -p 3001 - -In another terminal, deploy a DBIx::Class schema ( which is SQLite by default, -change the values in config.yml to tweak) : - -perl scripts/jitterbug_db --config config.yml --deploy - -Now add a post-receive hook to your github project that hits the /hook/ URL -on the server that the jitterbug Dancer app is running on, i.e. - - http://example.com:3001/hook/ - -Now you must start the builder, which actually clones a new git repo for -each task (this could be network-intensive) and actually runs the build -and test commands for each project. - - perl scripts/builder.pl -c config.yml - -Now, when you commit to a project that has a Jitterbug post-receive hook, -the builder check every 30 seconds for a new task and build and test your -projects! - diff --git a/README.md b/README.md new file mode 100644 index 0000000..c42076a --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +## Jitterbug : Cross Language Continuous integration for Git + + +### What is Jitterbug? + +Jitterbug is written in Perl 5 and depends on various CPAN modules, such +as Moose, Dancer, DBIx::Class and others. + +### Installing Jitterbug + + # You can also use Makefile.PL, but you will then have to manually + perl Build.PL + # perl Makefile.PL + + # install missing dependencies + ./Build installdeps + + # you can also use cpanm + # cpanm --installdeps . + + # Look at config.yaml or example.yaml for how to configure your Jitterbug instance + $EDITOR config.yaml + + # start the jitterbug Dancer app, which by default binds to port 3000 + perl jitterbug.pl + + # If you need to start it on a different port use -p + perl jitterbug.pl -p 3001 + +In another terminal, deploy a DBIx::Class schema ( which is SQLite by default, +change the values in config.yml to tweak) : + + perl scripts/jitterbug_db --config config.yml --deploy + +Now add a post-receive hook to your github project that hits the /hook/ URL +on the server that the jitterbug Dancer app is running on, i.e. + + http://example.com:3001/hook/ + +Now you must start the builder, which actually clones a new git repo for +each task (this could be network-intensive) and actually runs the build +and test commands for each project. + + perl scripts/builder.pl -c config.yml + +Now, when you commit to a project that has a Jitterbug post-receive hook, +the builder check periodically for a new task and build and test your +projects! + diff --git a/config.yml b/config.yml index 47f4f42..53a50c1 100644 --- a/config.yml +++ b/config.yml @@ -32,6 +32,7 @@ jitterbug: on_pass_from_email: donotreply@example.com on_pass_header: on_pass_footer: + reuse_repo: 1 options: perlbrew: 1 email_on_pass: 0 diff --git a/example.yml b/example.yml new file mode 100644 index 0000000..fc3f72e --- /dev/null +++ b/example.yml @@ -0,0 +1,53 @@ +layout: "main" +logger: "file" +appname: "jitterbug" + +builds_per_feed: 5 +template: "xslate" +engines: + xslate: + path: / + type: text + cache: 0 + +jitterbug: + reports: + dir: /tmp/jitterbug + build: + dir: /tmp/build + build_process: + builder: ./scripts/capsule.sh + builder_variables: "" + on_failure: "jitterbug::Emailer" + on_failure_to_email: jonathan@leto.net + on_failure_cc_email: + on_failure_from_email: jitterbug@leto.net + on_failure_subject_prefix: "[jitterbug] FAIL " + on_failure_header: "Jitterbug Web Interace : http://new.leto.net:3000\n%%PROJECT%% : http://new.leto.net:8090/project/%%PROJECT%%\nFailing Commit Diff: https://github.com/parrot/%%PROJECT%%/commit/%%SHA1%%\n\n%%SUMMARY%%\n\n" + on_failure_footer: "Sorry, but your Princess is in another castle!" + on_pass: "jitterbug::Emailer" + on_pass_to_email: + on_pass_cc_email: jonathan@leto.net + on_pass_subject_prefix: "[jitterbug] PASS " + on_pass_from_email: jitterbug@leto.net + on_pass_footer: "Amazingly, everything WORKED!" + on_pass_header: "Great job!" + reuse_repo: 1 + options: + perlbrew: 1 + email_on_pass: 0 + branches: + parrot: master|smoke-me + projects: + rakudo: + builder: ./scripts/build_rakudo_and_spectest.sh + +plugins: + DBIC: + schema: + skip_automake: 1 + pckg: "jitterbug::Schema" + connect_info: + - dbi:SQLite:dbname=jitterbug.db + + diff --git a/lib/jitterbug/Builder.pm b/lib/jitterbug/Builder.pm index f6fb41e..366878f 100644 --- a/lib/jitterbug/Builder.pm +++ b/lib/jitterbug/Builder.pm @@ -12,10 +12,11 @@ use Getopt::Long qw/:config no_ignore_case/; use File::Basename; use Git::Repository; use jitterbug::Schema; +use Cwd; #use Data::Dumper; local $| = 1; -use constant DEBUG => 0; +use constant DEBUG => $ENV{DEBUG} || 0; sub new { my $self = bless {} => shift; @@ -81,10 +82,12 @@ sub sleep { } sub run_task { - my $self = shift; - my ($task) = @_; - my $desc = JSON::decode_json( $task->commit->content ); - my $conf = $self->{'conf'}; + my ($self,$task) = @_; + + my $desc = JSON::decode_json( $task->commit->content ); + my $conf = $self->{'conf'}; + my $buildconf = $conf->{'jitterbug'}{'build_process'}; + my $project = $task->project; my $dt = DateTime->now(); $task->update({started_when => $dt}); @@ -93,28 +96,55 @@ sub run_task { my $report_path = dir( $conf->{'jitterbug'}{'reports'}{'dir'}, - $task->project->name, + $project->name, $task->commit->sha256, ); + my $dir = $conf->{'jitterbug'}{'build'}{'dir'}; + mkdir $dir unless -d $dir; - my $build_dir = dir( - $conf->{'jitterbug'}{'build'}{'dir'}, - $task->project->name, - ); - - debug("Removing $build_dir"); - rmtree($build_dir, { error => \my $err } ); - warn @$err if @$err; - - $self->sleep(1); # avoid race conditions + my $build_dir = dir($dir, $project->name); + my $r; my $repo = $task->project->url . '.git'; - my $r = Git::Repository->create( clone => $repo => $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 ); + } else { + # If this is the first time, the repo won't exist yet + 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; + } + } + $self->sleep(1); # avoid race conditions debug("Checking out " . $task->commit->sha256 . " from $repo into $build_dir\n"); - $r->run( 'checkout', $task->commit->sha256 ); + # $r->run( 'checkout', $task->commit->sha256 ); + my $pwd = getcwd; + chdir $build_dir; + system("git checkout " . $task->commit->sha256 ); + chdir $pwd; - my $builder = $conf->{'jitterbug'}{'build_process'}{'builder'}; + 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'}; @@ -122,7 +152,9 @@ sub run_task { debug("email_on_pass = $email_on_pass"); debug("perlbrew = $perlbrew"); - my $builder_variables = $conf->{'jitterbug'}{'build_process'}{'builder_variables'}; + # If the project has custom builder variables, use those. Otherwise, use the global setting + my $builder_variables = $conf->{'jitterbug'}{'projects'}{$project->name}{'builder_variables'} + || $conf->{'jitterbug'}{'build_process'}{'builder_variables'} || ''; my $builder_command = "$builder_variables $builder $build_dir $report_path $perlbrew"; @@ -139,6 +171,8 @@ sub run_task { while (<$fh>){ $lines .= $_; } + # if $result is undefined, either there was a build failure + # or the test output is not from a TAP harness ($result) = $lines =~ /Result:\s(\w+)/; my ( $name, ) = basename($version); $name =~ s/\.txt//; diff --git a/public/js/common.js b/public/js/common.js index 646f80e..93c080a 100644 --- a/public/js/common.js +++ b/public/js/common.js @@ -4,6 +4,7 @@ $(document).ready(function() { var class = "#commits-day-" + day; $(class).toggle(); }); + /* This times out on large test outputs $('.builds a').click(function() { var url = $(this).attr("href"); var id = $(this).parents('.commit').attr('id'); @@ -12,4 +13,5 @@ $(document).ready(function() { }); return false; }) + */ }) diff --git a/scripts/build_rakudo_and_spectest.sh b/scripts/build_rakudo_and_spectest.sh new file mode 100644 index 0000000..423b8b5 --- /dev/null +++ b/scripts/build_rakudo_and_spectest.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# This serves as an example of a custom build script, which builds +# Rakudo Perl 6 and times a spectest run + +make realclean +perl Configure.pl --gen-parrot +make +make t/spec +time make spectest diff --git a/scripts/capsule.sh b/scripts/capsule.sh index 30c3877..9fca79e 100755 --- a/scripts/capsule.sh +++ b/scripts/capsule.sh @@ -20,6 +20,8 @@ function jitterbug_build () { perl Build.PL >> $logfile 2>&1 # ./Build installdeps is not available in older Module::Build's cpanm --installdeps . >> $logfile 2>&1 + # Run this again in case our Build is out of date (suboptimal) + perl Build.PL >> $logfile 2>&1 HARNESS_VERBOSE=1 ./Build test --verbose >> $logfile 2>&1 elif [ -f 'Makefile.PL' ]; then echo "Found Makefile.PL" diff --git a/t/004_project.t b/t/004_project.t index 4d00338..568ffc0 100644 --- a/t/004_project.t +++ b/t/004_project.t @@ -10,9 +10,10 @@ use Dancer::Test; jitterbug::Test->init(); -my $response; +my $r; { - $response = dancer_response(GET => '/project/Dancer'); - is $response->status, 404; + local $TODO = "non-existent project gives a 500 instead of a 404"; + $r = dancer_response(GET => '/project/Dancer'); + is $r->status, 404 or diag $r->content; } diff --git a/t/lib/jitterbug/Test.pm b/t/lib/jitterbug/Test.pm index ee6a13d..2326e83 100644 --- a/t/lib/jitterbug/Test.pm +++ b/t/lib/jitterbug/Test.pm @@ -10,12 +10,13 @@ use File::Spec; use File::Temp qw/tempdir/; sub init { - my $db_dir = tempdir( CLEANUP => 1 ); - my $db_file = File::Spec->catfile( $db_dir, 'jitterbug.db' ); + #my $db_dir = tempdir( CLEANUP => 1 ); + # TODO: this should be pulled from the config file + my $db_file = File::Spec->catfile( qw/t data jitterbug.db/ ); my $dsn = 'dbi:SQLite:dbname=' . $db_file; my $schema = jitterbug::Schema->connect($dsn); _setting($dsn); - $schema->deploy; + $schema->deploy unless -s $db_file; } sub _setting { |