summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/jitterbug/Hook.pm111
-rw-r--r--t/003_hook_route.t171
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;
+}