From 6e662082746507eadd10ec8bcd870a770c777134 Mon Sep 17 00:00:00 2001 From: franck cuny Date: Sun, 13 Feb 2011 15:54:10 +0100 Subject: add configuration option to skip some branches; add tests for the Hook --- lib/jitterbug/Hook.pm | 111 +++++++++++++++++++++++--------- t/003_hook_route.t | 171 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 209 insertions(+), 73 deletions(-) diff --git a/lib/jitterbug/Hook.pm b/lib/jitterbug/Hook.pm index 87cfba2..bf483d5 100644 --- a/lib/jitterbug/Hook.pm +++ b/lib/jitterbug/Hook.pm @@ -19,45 +19,91 @@ post '/' => sub { $payload = from_json($payload); my $repo = $payload->{repository}->{name}; + my $ref = $payload->{ref}; + + my $authorized = _authorized_branch( $repo, $ref ); + if ( !$authorized ) { + debug("this branch is not authorized"); + status 200; + return; + } my $project = schema->resultset('Project')->find( { name => $repo } ); - if ( !$project ) { - debug("need to create a new project"); - try { - schema->txn_do( - sub { - $project = schema->resultset('Project')->create( - { - name => $repo, - url => $payload->{repository}->{url}, - description => - $payload->{repository}->{description}, - owner => to_json($payload->{repository}->{owner}), - } - ); - } - ); - } - catch { - error($_); - }; - } + $project = _create_new_project($repo, $payload) if !$project; my $last_commit = pop @{ $payload->{commits} }; $last_commit->{compare} = $payload->{compare}; $last_commit->{pusher} = $payload->{pushed}; $last_commit->{ref} = $payload->{ref}; + _insert_commit($last_commit, $project); + _insert_new_task( $last_commit, $project ); + + debug("hook accepted"); + + { updated => $repo }; +}; + +sub _authorized_branch { + my ($repo, $ref) = @_; + my $jtbg_conf = setting 'jitterbug'; + my $branches_conf = $jtbg_conf->{branches}; + + foreach my $name ($repo, 'jt_global') { + if ( defined $branches_conf->{$name} ) { + return 0 if _should_skip( $ref, $branches_conf->{$name} ); + } + } + return 1; +} + +sub _should_skip { + my ( $ref, $conf ) = @_; + foreach my $br_name (@$conf) { + return 1 if $ref =~ m!^refs/heads/$br_name!; + } + return 0; +} + +sub _create_new_project { + my ($repo, $payload) = @_; + + debug("need to create a new project"); + + my $project; + try { + schema->txn_do( + sub { + $project = schema->resultset('Project')->create( + { + name => $repo, + url => $payload->{repository}->{url}, + description => $payload->{repository}->{description}, + owner => to_json( $payload->{repository}->{owner} ), + } + ); + } + ); + } + catch { + error($_); + }; + return $project; +} + +sub _insert_commit { + my ($commit, $project) = @_; + try { schema->txn_do( sub { schema->resultset('Commit')->create( { - sha256 => $last_commit->{id}, - content => to_json($last_commit), + sha256 => $commit->{id}, + content => to_json($commit), projectid => $project->projectid, - timestamp => $last_commit->{timestamp}, + timestamp => $commit->{timestamp}, } ); } @@ -66,22 +112,25 @@ post '/' => sub { catch { error($_); }; +} +sub _insert_new_task { + my ( $commit, $project ) = @_; try { schema->txn_do( sub { schema->resultset('Task')->create( - {sha256 => $last_commit->{id}, projectid => $project->projectid} + { + sha256 => $commit->{id}, + projectid => $project->projectid + } ); } ); - }catch{ + } + catch { error($_); }; - - debug("hook accepted"); - - { updated => $repo }; -}; +} 1; diff --git a/t/003_hook_route.t b/t/003_hook_route.t index 72a841f..8327755 100644 --- a/t/003_hook_route.t +++ b/t/003_hook_route.t @@ -1,44 +1,131 @@ -use Test::More tests => 1; +use Test::More tests => 11; use strict; use warnings; -ok 1; -#use jitterbug; -#use JSON; -#use YAML qw/LoadFile/; -#use Dancer::Test; -#use Dancer::Config qw/setting/; - -#my $content = LoadFile('t/data/test.yaml'); - -#setting jitterbug => { namespace => 'jitterbug_test' }; - -#route_exists [ POST => '/hook/' ], 'a route handle is defined for /'; - -#my $response; - -#{ - #$response = dancer_response( POST => '/hook', ); - #is $response->{status}, 200, '200 with empty post'; -#} - -#{ - #my $payload = "payload=" . JSON::encode_json($content); - ##open my $in, '<', \$payload; - - ##$ENV{'CONTENT_LENGTH'} = length($payload); - ##$ENV{'CONTENT_TYPE'} = 'application/x-www-form-urlencoded'; - ##$ENV{'psgi.input'} = $in; - - #$response = dancer_response( - #POST => '/hook/', - #{ - #headers => - #[ 'Content-Type' => 'application/x-www-form-urlencoded' ], - #body => $payload - #} - #); -##use YAML::Syck; warn Dump $response; - #is $response->{status}, 200; - #is_deeply JSON::decode_json( $response->{content} ), - #{ updated => 'Dancer' }; -#} + +use jitterbug; +use jitterbug::Schema; + +use JSON; +use YAML qw/LoadFile Dump/; + +use File::Spec; +use File::Temp qw/tempdir/; + +use Dancer::Test; +use Dancer::Config qw/setting/; + +my $content = LoadFile('t/data/test.yaml'); + +my $db_dir = tempdir( CLEANUP => 1 ); +my $db_file = File::Spec->catfile( $db_dir, 'jitterbug.db' ); +my $dsn = 'dbi:SQLite:dbname=' . $db_file; +my $schema = jitterbug::Schema->connect($dsn); +$schema->deploy; + +setting plugins => { + DBIC => { + schema => { + skip_automake => 1, + pckg => "jitterbug::Schema", + connect_info => [$dsn] + } + } +}; + +route_exists [ POST => '/hook/' ], 'a route handle is defined for /'; + +my $response; + +{ + $response = dancer_response( POST => '/hook', ); + is $response->{status}, 200, '200 with empty post'; +} + +{ + my $rs = $schema->resultset('Project')->find( { name => 'Dancer' } ); + ok !defined $rs, 'no project dancer yet'; + + $response = dancer_response( + POST => '/hook/', + { + headers => + [ 'Content-Type' => 'application/x-www-form-urlencoded' ], + body => _generate_post_request($content), + } + ); + + is $response->{status}, 200, 'status OK with payload'; + is_deeply JSON::decode_json( $response->{content} ), + { updated => 'Dancer' }, 'response OK with payload'; + + $rs = $schema->resultset('Project')->find( { name => 'Dancer' } ); + ok $rs, 'project exists in DB'; + is $rs->name, 'Dancer', 'project\'s name is good'; + + is $schema->resultset('Task')->search()->count(), 1, 'one task created'; +} + +{ + $schema->resultset('Project')->search()->delete(); + $schema->resultset('Task')->search()->delete(); + + # testing with invalid global branch + setting jitterbug => { branches => { jt_global => ['foo'], }, }; + $content->{ref} = 'refs/heads/foo'; + $response = dancer_response( + POST => '/hook/', + { + headers => + [ 'Content-Type' => 'application/x-www-form-urlencoded' ], + body => _generate_post_request($content), + } + ); + is $schema->resultset('Task')->search()->count(), 0, 'no task created since this branch is forbiden'; +} + +{ + $schema->resultset('Project')->search()->delete(); + $schema->resultset('Task')->search()->delete(); + + # testing with invalid global branch + setting jitterbug => { branches => { Dancer => ['foo'], }, }; + $content->{ref} = 'refs/heads/foo'; + $response = dancer_response( + POST => '/hook/', + { + headers => + [ 'Content-Type' => 'application/x-www-form-urlencoded' ], + body => _generate_post_request($content), + } + ); + is $schema->resultset('Task')->search()->count(), 0, 'no task created since this branch is forbiden'; +} + +{ + $schema->resultset('Project')->search()->delete(); + $schema->resultset('Task')->search()->delete(); + + # this branch is forbiden for another project + setting jitterbug => { branches => { jitterbug => ['foo'], }, }; + $content->{ref} = 'refs/heads/foo'; + $response = dancer_response( + POST => '/hook/', + { + headers => + [ 'Content-Type' => 'application/x-www-form-urlencoded' ], + body => _generate_post_request($content), + } + ); + is $schema->resultset('Task')->search()->count(), 1, 'one task created since this branch is authorized for this project'; +} + +sub _generate_post_request { + my $content = shift; + my $payload = "payload=" . JSON::encode_json($content); + open my $in, '<', \$payload; + + $ENV{'CONTENT_LENGTH'} = length($payload); + $ENV{'CONTENT_TYPE'} = 'application/x-www-form-urlencoded'; + $ENV{'psgi.input'} = $in; + return $payload; +} -- cgit 1.4.1