[Bps-public-commit] smokingit branch, master, updated. 15caa61b1d4413396c558a3c2d36ac21b97f9709
Alex Vandiver
alexmv at bestpractical.com
Sun Nov 4 23:49:15 EST 2012
The branch, master has been updated
via 15caa61b1d4413396c558a3c2d36ac21b97f9709 (commit)
via fe9344b9cefae3976631be1618e7d024a1f6a7d3 (commit)
via 37651f7b11e6a734614b3b77a240bad63bd19700 (commit)
via 568040e26f76fe89362ca54f32a2c1a5dec0e388 (commit)
via 598e7fef6563decb0443e1db941837c7702f894e (commit)
via ae3378f7b943e92ac3d3860161db95542e37df11 (commit)
via dbca24044f519ab9db1579970f02e524dcc5d615 (commit)
via f9b55c47d3a12a4fc633024b92eed9c21a442474 (commit)
via 6c9cf864d032587279dbf25acf0f03012b2af94c (commit)
via 7b905dae939d95e963b135508a2c921bbee07638 (commit)
via f4b92237f6433490681acfa90d82da229d6b5062 (commit)
via 546527a9572621314d4b4dc77773f52f9707b604 (commit)
via 7535959ee0789cd54094c1c8cb12f023b4d830a7 (commit)
via dd06a6c6b5840565462c26a4950a67ad12fbff88 (commit)
via 1f3fc27b6987c3e01b5ab2132fa6cfad2700298e (commit)
via e2e24641907698901acd75d136e13a7e14e3795e (commit)
via ee4701f0481e9a7a809eb8931aaf8986d7c5a849 (commit)
via be74911c5d9f26b21733fbfe8a83aa904b06b849 (commit)
via 1f8c7071063e76464af8518bb68d44e68efa81d5 (commit)
via 0088b3e98644f1154f326367295010e7f9679b7d (commit)
via fd618b071d52175f8637bbbad7558093731bbf26 (commit)
from d3de530f504643e1cafab64c125a235fe068e7ef (commit)
Summary of changes:
Makefile.PL | 1 -
bin/local_updates | 146 +++++++++-----------
bin/rpc | 23 ++++
bin/start-gearmand | 9 --
bin/update-user | 13 ++
etc/config.yml | 14 +-
lib/Smokingit.pm | 33 ++---
lib/Smokingit/Action/Test.pm | 168 ++++++++++++++++++++++++
lib/Smokingit/Model/Branch.pm | 50 +++++--
lib/Smokingit/Model/Commit.pm | 42 +++---
lib/Smokingit/Model/Configuration.pm | 18 ++-
lib/Smokingit/Model/Project.pm | 28 +++-
lib/Smokingit/Model/SmokeResult.pm | 88 ++++++++-----
lib/Smokingit/Model/User.pm | 36 +++++
lib/Smokingit/Status.pm | 93 +++++++++++++
lib/Smokingit/View.pm | 3 +
lib/Smokingit/View/Branch.pm | 25 +++-
lib/Smokingit/View/Configuration.pm | 9 ++
lib/Smokingit/View/GitHub.pm | 5 +-
lib/Smokingit/View/Page.pm | 52 ++++++++
lib/Smokingit/View/Project.pm | 114 ++++++++++++----
share/web/static/css/app-late.css | 22 +++-
share/web/static/css/login.css | 64 +++++++++
share/web/static/css/main.css | 3 +
share/web/static/images/silk/control_play.png | Bin 0 -> 592 bytes
share/web/static/images/silk/control_repeat.png | Bin 0 -> 422 bytes
share/web/static/js/app-late.js | 30 +++++
27 files changed, 859 insertions(+), 230 deletions(-)
create mode 100755 bin/rpc
delete mode 100755 bin/start-gearmand
create mode 100755 bin/update-user
create mode 100644 lib/Smokingit/Action/Test.pm
create mode 100644 lib/Smokingit/Model/User.pm
create mode 100644 lib/Smokingit/Status.pm
create mode 100644 share/web/static/css/login.css
create mode 100644 share/web/static/images/silk/control_play.png
create mode 100644 share/web/static/images/silk/control_repeat.png
create mode 100644 share/web/static/js/app-late.js
- Log -----------------------------------------------------------------
commit fd618b071d52175f8637bbbad7558093731bbf26
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Thu Mar 15 03:31:44 2012 -0400
Add a simple username-only model to hang auth off of
diff --git a/bin/update-user b/bin/update-user
new file mode 100755
index 0000000..ae53d68
--- /dev/null
+++ b/bin/update-user
@@ -0,0 +1,13 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Jifty;
+BEGIN { Jifty-> new };
+
+my ($username, $password) = @ARGV;
+
+my $user = Smokingit::Model::User->new( current_user => Smokingit::CurrentUser->superuser );
+$user->load_or_create( name => $username );
+$user->set_password( $password );
+
diff --git a/etc/config.yml b/etc/config.yml
index da58a75..6c35058 100644
--- a/etc/config.yml
+++ b/etc/config.yml
@@ -11,7 +11,7 @@ framework:
Host: localhost
Password: ''
User: postgres
- Version: 0.0.5
+ Version: 0.0.6
DevelMode: 1
LogLevel: INFO
Mailer: Sendmail
@@ -20,6 +20,10 @@ framework:
- CompressedCSSandJS: {}
- ErrorTemplates: {}
- REST: {}
+ - Authentication::Password:
+ login_by: username
+ nav_menu: 0
+ signup: 0
SkipAccessControl: 1
Web:
BaseURL: http://localhost
diff --git a/lib/Smokingit/Model/User.pm b/lib/Smokingit/Model/User.pm
new file mode 100644
index 0000000..9590d79
--- /dev/null
+++ b/lib/Smokingit/Model/User.pm
@@ -0,0 +1,36 @@
+use strict;
+use warnings;
+
+package Smokingit::Model::User;
+use Jifty::DBI::Schema;
+
+use Smokingit::Record schema {};
+
+use Jifty::Plugin::User::Mixin::Model::User;
+use Jifty::Plugin::Authentication::Password::Mixin::Model::User;
+
+sub is_protected {1}
+
+sub since { '0.0.6' }
+
+sub create {
+ my $self = shift;
+ my (%args) = @_;
+ $args{email} ||= $args{name} . '@bestpractical.com';
+ $args{email_confirmed} = 1;
+ $self->SUPER::create(%args);
+}
+
+sub current_user_can {
+ my $self = shift;
+ my $right = shift;
+ my %args = (@_);
+
+ return 1 if $right eq "read";
+ return 1 if $right eq "update"
+ and $self->current_user->id == $self->id;
+
+ return $self->SUPER::current_user_can( $right, %args );
+}
+
+1;
commit 0088b3e98644f1154f326367295010e7f9679b7d
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Fri Mar 23 04:31:48 2012 -0400
Login and logout
diff --git a/lib/Smokingit/View/Page.pm b/lib/Smokingit/View/Page.pm
index 6ecc5fb..047e6f4 100644
--- a/lib/Smokingit/View/Page.pm
+++ b/lib/Smokingit/View/Page.pm
@@ -9,6 +9,58 @@ use Jifty::View::Declare::Helpers;
sub render_page {
my $self = shift;
my $title = shift;
+
+ div {
+ { id is 'authbox' };
+ if (Jifty->web->current_user->id) {
+ div {
+ { class is 'username' };
+ js_handlers {
+ onclick => "jQuery('#authbox .logout').toggle()" };
+ outs(Jifty->web->current_user->username);
+ div {
+ { class is 'logout' };
+ form {
+ my $logout = new_action(
+ class => "Logout",
+ moniker => "logout"
+ );
+ form_submit( submit => $logout, label => "Log out" );
+ }
+ }
+ }
+ } else {
+ div {
+ { class is 'prompt' };
+ js_handlers {
+ onclick => [
+ "jQuery('#authbox .prompt').hide()",
+ "jQuery('#authbox .loginform').show()",
+ "jQuery('.loginform input.argument-username').focus()",
+ ],
+ };
+ "Login";
+ };
+ div {
+ { class is 'loginform' };
+ form {
+ my $login = new_action(
+ class => "Login",
+ moniker => "login",
+ );
+ render_param( $login => $_ )
+ for qw/username password token hashed_password/;
+ render_param(
+ $login => "remember",
+ render_as => 'hidden',
+ default_value => 1
+ );
+ form_submit( label => "Login", onclick => "return getPasswordToken('login');" );
+ };
+ }
+ }
+ }
+
div {
{ id is 'content' };
$self->instrument_content;
diff --git a/share/web/static/css/login.css b/share/web/static/css/login.css
new file mode 100644
index 0000000..697900a
--- /dev/null
+++ b/share/web/static/css/login.css
@@ -0,0 +1,64 @@
+#authbox {
+ width: 7em;
+ padding: 0 0.5em;
+ position: absolute;
+ background: #ccc;
+ -webkit-border-radius: 1em;
+ -moz-border-radius: 1em;
+ z-index: 5;
+ margin-top: -0.5em;
+ margin-left: -0.5em;
+}
+
+#authbox .prompt, #authbox .username {
+ text-align: center;
+ padding: 0.3em;
+ font-weight: bold;
+ cursor: pointer;
+}
+
+#authbox .loginform {
+ display: none;
+ padding: 0.5em 0;
+}
+
+#authbox .form_field {
+ padding-top: 0;
+}
+
+#authbox label {
+ width: inherit;
+ display: block;
+ text-align: center;
+ float: none;
+}
+
+#authbox input[type="text"], #authbox input[type="password"] {
+ width: 7em;
+}
+
+#authbox .submit_button {
+ text-align: center;
+}
+
+#authbox .submit_button input {
+ margin: 0;
+}
+
+#authbox .logout {
+ display: none;
+ padding-top: 0.5em;
+}
+
+#authbox div.form_field .error {
+ width: 14em;
+ background-color: #CBB;
+ -webkit-border-radius: 0.5em;
+ -moz-border-radius: 0.5em;
+ opacity: 0.80;
+ margin-right: -4em;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ margin-bottom: 0.5em;
+ border: 1px solid #A00000;
+}
\ No newline at end of file
diff --git a/share/web/static/css/main.css b/share/web/static/css/main.css
index 3b88cd0..34c7031 100644
--- a/share/web/static/css/main.css
+++ b/share/web/static/css/main.css
@@ -8,4 +8,7 @@
@import "jquery.autocomplete.css";
@import "jquery.jgrowl.css";
@import "facebox.css";
+
+ at import "login.css";
+
@import "app-late.css";
commit 1f8c7071063e76464af8518bb68d44e68efa81d5
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Thu Mar 15 03:29:38 2012 -0400
Add ACLs to objects
diff --git a/etc/config.yml b/etc/config.yml
index 6c35058..e89a8fd 100644
--- a/etc/config.yml
+++ b/etc/config.yml
@@ -24,7 +24,7 @@ framework:
login_by: username
nav_menu: 0
signup: 0
- SkipAccessControl: 1
+ SkipAccessControl: 0
Web:
BaseURL: http://localhost
DataDir: var/mason
diff --git a/lib/Smokingit/Model/Branch.pm b/lib/Smokingit/Model/Branch.pm
index 6a5289a..bcb0f38 100644
--- a/lib/Smokingit/Model/Branch.pm
+++ b/lib/Smokingit/Model/Branch.pm
@@ -6,7 +6,8 @@ use Jifty::DBI::Schema;
use Smokingit::Record schema {
column project_id =>
- references Smokingit::Model::Project;
+ references Smokingit::Model::Project,
+ is protected;
column name =>
type is 'text',
@@ -14,16 +15,20 @@ use Smokingit::Record schema {
label is _("Branch name");
column first_commit_id =>
- references Smokingit::Model::Commit;
+ references Smokingit::Model::Commit,
+ is protected;
column current_commit_id =>
- references Smokingit::Model::Commit;
+ references Smokingit::Model::Commit,
+ is protected;
column tested_commit_id =>
- references Smokingit::Model::Commit;
+ references Smokingit::Model::Commit,
+ is protected;
column last_status_update =>
- references Smokingit::Model::Commit;
+ references Smokingit::Model::Commit,
+ is protected;
column status =>
type is 'text',
@@ -54,7 +59,8 @@ use Smokingit::Record schema {
column current_actor =>
type is 'text',
- since '0.0.3';
+ since '0.0.3',
+ is protected;
};
sub create {
@@ -286,5 +292,16 @@ sub format_user {
}
+sub current_user_can {
+ my $self = shift;
+ my $right = shift;
+ my %args = (@_);
+
+ return 1 if $right eq 'read';
+ return 1 if $right eq 'update' and $self->current_user->id;
+
+ return $self->SUPER::current_user_can($right => %args);
+}
+
1;
diff --git a/lib/Smokingit/Model/Commit.pm b/lib/Smokingit/Model/Commit.pm
index f971566..4dba40f 100644
--- a/lib/Smokingit/Model/Commit.pm
+++ b/lib/Smokingit/Model/Commit.pm
@@ -36,6 +36,7 @@ use Smokingit::Record schema {
column body =>
type is 'text';
};
+sub is_protected {1}
sub create {
my $self = shift;
@@ -230,5 +231,15 @@ sub status_cache_key {
return "status-" . $self->sha;
}
+sub current_user_can {
+ my $self = shift;
+ my $right = shift;
+ my %args = (@_);
+
+ return 1 if $right eq 'read';
+
+ return $self->SUPER::current_user_can($right => %args);
+}
+
1;
diff --git a/lib/Smokingit/Model/Configuration.pm b/lib/Smokingit/Model/Configuration.pm
index 42b5f11..e48738c 100644
--- a/lib/Smokingit/Model/Configuration.pm
+++ b/lib/Smokingit/Model/Configuration.pm
@@ -47,5 +47,18 @@ sub create {
return ($ok, $msg);
}
+sub current_user_can {
+ my $self = shift;
+ my $right = shift;
+ my %args = (@_);
+
+ return 1 if $right eq 'create' and $self->current_user->id;
+ return 1 if $right eq 'read';
+ return 1 if $right eq 'update' and $self->current_user->id;
+ return 1 if $right eq 'delete' and $self->current_user->id;
+
+ return $self->SUPER::current_user_can($right => %args);
+}
+
1;
diff --git a/lib/Smokingit/Model/Project.pm b/lib/Smokingit/Model/Project.pm
index e7cb530..1404a9a 100644
--- a/lib/Smokingit/Model/Project.pm
+++ b/lib/Smokingit/Model/Project.pm
@@ -266,5 +266,18 @@ sub schedule_tests {
return $smokes;
}
+sub current_user_can {
+ my $self = shift;
+ my $right = shift;
+ my %args = (@_);
+
+ return 1 if $right eq 'create' and $self->current_user->id;
+ return 1 if $right eq 'read';
+ return 1 if $right eq 'update' and $self->current_user->id;
+ return 1 if $right eq 'delete' and $self->current_user->id;
+
+ return $self->SUPER::current_user_can($right => %args);
+}
+
1;
diff --git a/lib/Smokingit/Model/SmokeResult.pm b/lib/Smokingit/Model/SmokeResult.pm
index 846171a..3d79d96 100644
--- a/lib/Smokingit/Model/SmokeResult.pm
+++ b/lib/Smokingit/Model/SmokeResult.pm
@@ -60,6 +60,7 @@ use Smokingit::Record schema {
column elapsed => type is 'integer';
};
+sub is_protected {1}
sub short_error {
my $self = shift;
@@ -190,5 +191,16 @@ sub post_result {
.": ".($self->is_ok ? "OK" : "NOT OK"));
}
+
+sub current_user_can {
+ my $self = shift;
+ my $right = shift;
+ my %args = (@_);
+
+ return 1 if $right eq 'read';
+
+ return $self->SUPER::current_user_can($right => %args);
+}
+
1;
commit be74911c5d9f26b21733fbfe8a83aa904b06b849
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Thu Mar 15 03:30:12 2012 -0400
Promote some tasks to running as the superuser for rights reasons
diff --git a/bin/local_updates b/bin/local_updates
index ed9b1cf..dda017f 100755
--- a/bin/local_updates
+++ b/bin/local_updates
@@ -53,8 +53,8 @@ $worker->register_function(
$smoke->load_by_cols( %lookup );
if ($smoke->id) {
$msg->("Re-testing $summary\n");
- $smoke->set_submitted_at(undef);
- $smoke->set_gearman_process(undef);
+ $smoke->as_superuser->set_submitted_at(undef);
+ $smoke->as_superuser->set_gearman_process(undef);
$tests += $smoke->run_smoke;
} else {
# Guess which branch
@@ -82,7 +82,9 @@ $worker->register_function(
my $job = shift;
my $project_name = $job->arg;
- my $project = Smokingit::Model::Project->new;
+ my $project = Smokingit::Model::Project->new(
+ current_user => Smokingit::CurrentUser->superuser,
+ );
$project->load_by_cols( name => $project_name );
return "No such project: $project_name\n"
unless $project->id;
@@ -96,7 +98,9 @@ $worker->register_function(
$worker->register_function(
post_results => sub {
my $job = shift;
- my $smoke = Smokingit::Model::SmokeResult->new;
+ my $smoke = Smokingit::Model::SmokeResult->new(
+ current_user => Smokingit::CurrentUser->superuser,
+ );
my ($ok, $msg) = $smoke->post_result($job->arg);
warn "$msg\n";
return $ok;
@@ -109,7 +113,9 @@ $worker->register_function(
my $job = shift;
my $project_name = $job->arg;
- my $projects = Smokingit::Model::ProjectCollection->new;
+ my $projects = Smokingit::Model::ProjectCollection->new(
+ current_user => Smokingit::CurrentUser->superuser,
+ );
if ($project_name) {
$projects->limit( column => "name", value => $project_name );
} else {
diff --git a/lib/Smokingit/Model/Commit.pm b/lib/Smokingit/Model/Commit.pm
index 4dba40f..933ad35 100644
--- a/lib/Smokingit/Model/Commit.pm
+++ b/lib/Smokingit/Model/Commit.pm
@@ -77,7 +77,9 @@ sub run_smoke {
configuration_id => $config->id,
commit_id => $self->id,
);
- my $smoke = Smokingit::Model::SmokeResult->new;
+ my $smoke = Smokingit::Model::SmokeResult->new(
+ current_user => Smokingit::CurrentUser->superuser,
+ );
$smoke->load_by_cols( %lookup );
return 0 if $smoke->id;
diff --git a/lib/Smokingit/Model/Project.pm b/lib/Smokingit/Model/Project.pm
index 1404a9a..d700a27 100644
--- a/lib/Smokingit/Model/Project.pm
+++ b/lib/Smokingit/Model/Project.pm
@@ -60,7 +60,11 @@ sub sha {
my $sha = shift;
local $ENV{GIT_DIR} = $self->repository_path;
my $commit = Smokingit::Model::Commit->new;
- $commit->load_or_create( project_id => $self->id, sha => $sha );
+ $commit->load_by_cols( project_id => $self->id, sha => $sha );
+ return $commit if $commit->id;
+
+ $commit->as_superuser->create( project_id => $self->id, sha => $sha );
+ $commit->load_by_cols( project_id => $self->id, sha => $sha );
return $commit;
}
diff --git a/lib/Smokingit/Model/SmokeResult.pm b/lib/Smokingit/Model/SmokeResult.pm
index 3d79d96..b064642 100644
--- a/lib/Smokingit/Model/SmokeResult.pm
+++ b/lib/Smokingit/Model/SmokeResult.pm
@@ -112,8 +112,8 @@ sub run_smoke {
{ uniq => $self->id },
);
warn "Unable to insert run_tests job!\n" unless $job_id;
- $self->set_gearman_process($job_id || "failed");
- $self->set_queued_at( Jifty::DateTime->now );
+ $self->as_superuser->set_gearman_process($job_id || "failed");
+ $self->as_superuser->set_queued_at( Jifty::DateTime->now );
# If we had a result for this already, we need to clean its status
# out of the memcached cache. Remove both the cache on the commit,
commit ee4701f0481e9a7a809eb8931aaf8986d7c5a849
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Thu Mar 15 03:30:37 2012 -0400
Remove create/update parts of the UI for unpriv users
diff --git a/lib/Smokingit/View.pm b/lib/Smokingit/View.pm
index 2946d21..8b30fa0 100644
--- a/lib/Smokingit/View.pm
+++ b/lib/Smokingit/View.pm
@@ -38,6 +38,9 @@ template '/index.html' => page {
};
}
+ my $project = Smokingit::Model::Project->new;
+ return unless $project->current_user_can("create");
+
div {
{ id is "create-project"; };
h2 { "Add a project" };
diff --git a/lib/Smokingit/View/Branch.pm b/lib/Smokingit/View/Branch.pm
index 88c5a62..8c83437 100644
--- a/lib/Smokingit/View/Branch.pm
+++ b/lib/Smokingit/View/Branch.pm
@@ -100,7 +100,7 @@ template '/fragments/branch/properties' => sub {
{ id is "branch-properties" };
js_handlers {
onclick => {replace_with => "/fragments/branch/edit" }
- };
+ } if $b->current_user_can("update");
row {
th { "Status" };
@@ -149,6 +149,10 @@ template '/fragments/branch/properties' => sub {
template '/fragments/branch/edit' => sub {
my $b = Smokingit::Model::Branch->new;
$b->load( get('branch_id') );
+
+ redirect "/fragments/branch/properties"
+ unless $b->current_user_can("update");
+
my $status = $b->status;
form {
my $update = $b->as_update_action( moniker => "update" );
diff --git a/lib/Smokingit/View/Configuration.pm b/lib/Smokingit/View/Configuration.pm
index f88e4fd..5d832a4 100644
--- a/lib/Smokingit/View/Configuration.pm
+++ b/lib/Smokingit/View/Configuration.pm
@@ -7,6 +7,10 @@ use Jifty::View::Declare -base;
template '/config' => page {
my $c = get('config');
redirect '/' unless $c;
+
+ redirect "/project/". $c->project->name . "/"
+ unless $c->current_user_can("update");
+
page_title is $c->name;
div {{class is "subtitle"} $c->project->name };
form {
@@ -26,6 +30,11 @@ template '/config' => page {
template '/new-configuration' => page {
redirect '/' unless get('project');
+
+ my $config = Smokingit::Model::Configuration->new;
+ redirect "/project/". get('project')->name . "/"
+ unless $config->current_user_can("create");
+
page_title is get('project')->name;
div {{class is "subtitle"} "New configuration" };
form {
diff --git a/lib/Smokingit/View/Project.pm b/lib/Smokingit/View/Project.pm
index 391fe05..ebac662 100644
--- a/lib/Smokingit/View/Project.pm
+++ b/lib/Smokingit/View/Project.pm
@@ -24,17 +24,22 @@ template '/project' => page {
ul {
while (my $c = $configs->next) {
li {
- hyperlink(
- label => $c->name,
- url => "config/" . $c->name,
- );
+ if ($c->current_user_can("update")) {
+ hyperlink(
+ label => $c->name,
+ url => "config/" . $c->name
+ );
+ } else {
+ outs $c->name;
+ }
};
}
};
+ my $config = Smokingit::Model::Configuration->new;
hyperlink(
label => "New configuration",
url => "new-configuration",
- );
+ ) if $config->current_user_can("create");
};
div {
commit e2e24641907698901acd75d136e13a7e14e3795e
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Fri Mar 23 00:58:06 2012 -0400
Slightly dimmer green on passing tests for legibility
diff --git a/share/web/static/css/app-late.css b/share/web/static/css/app-late.css
index 34b2a00..2c935e3 100644
--- a/share/web/static/css/app-late.css
+++ b/share/web/static/css/app-late.css
@@ -279,7 +279,7 @@ li {
font-size: 145%;
}
-.commitlist .commit.passing .sha { color: #1c1; }
+.commitlist .commit.passing .sha { color: #191; }
.commitlist .commit.failing .sha { color: #f11; }
.commitlist .commit.todo .sha { color: #fa0; }
.commitlist .commit.parsefail .sha { color: #f11; }
commit 1f3fc27b6987c3e01b5ab2132fa6cfad2700298e
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Fri Mar 23 00:58:30 2012 -0400
Reorder css rules for commits to a canonical order
diff --git a/share/web/static/css/app-late.css b/share/web/static/css/app-late.css
index 2c935e3..0ec6794 100644
--- a/share/web/static/css/app-late.css
+++ b/share/web/static/css/app-late.css
@@ -279,15 +279,15 @@ li {
font-size: 145%;
}
+.commitlist .commit.untested .sha { color: #555; }
.commitlist .commit.passing .sha { color: #191; }
-.commitlist .commit.failing .sha { color: #f11; }
.commitlist .commit.todo .sha { color: #fa0; }
+.commitlist .commit.failing .sha { color: #f11; }
.commitlist .commit.parsefail .sha { color: #f11; }
.commitlist .commit.errors .sha { color: #f11; }
.commitlist .commit.testing .sha { color: #11f; }
.commitlist .commit.queued .sha { color: #115; }
.commitlist .commit.broken .sha { color: #f11; }
-.commitlist .commit.untested .sha { color: #555; }
.commitlist .okbox {
float: left;
commit dd06a6c6b5840565462c26a4950a67ad12fbff88
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Fri Mar 23 04:25:20 2012 -0400
Order branches by mine first
diff --git a/lib/Smokingit/View/Project.pm b/lib/Smokingit/View/Project.pm
index ebac662..5799765 100644
--- a/lib/Smokingit/View/Project.pm
+++ b/lib/Smokingit/View/Project.pm
@@ -145,7 +145,6 @@ template '/fragments/project/branch-list' => sub {
sub branchlist {
my ($branches, %args) = @_;
- $branches->order_by( column => "name" );
if ($branches->count) {
$branches->prefetch( name => "current_commit" );
my $results = $branches->join(
@@ -169,6 +168,13 @@ sub branchlist {
error is_ok exit wait
passed failed parse_errors todo_passed/],
);
+ my @order = ({ column => "name" });
+ if (Jifty->web->current_user->id) {
+ my $actor = '%<'.Jifty->web->current_user->user_object->email.'>';
+ $actor = Jifty->handle->quote_value($actor);
+ unshift @order, { function => "main.current_actor like $actor", order => 'DESC' };
+ }
+ $branches->order_by( @order );
div { class is "hline"; }
if $args{hline};
ul {
commit 7535959ee0789cd54094c1c8cb12f023b4d830a7
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Sat Mar 24 21:05:47 2012 -0400
Missing smoke_results prefetch is is expected on new shas
When a branch on a new project is rendered, we generate new Commit
objects on demand, which will not have prefetched smoke_results. As not
having those isn't an error, merely a slight performance hit, remove the
associated warning.
diff --git a/lib/Smokingit/Model/Commit.pm b/lib/Smokingit/Model/Commit.pm
index 933ad35..faa5026 100644
--- a/lib/Smokingit/Model/Commit.pm
+++ b/lib/Smokingit/Model/Commit.pm
@@ -93,10 +93,7 @@ sub run_smoke {
sub hash_results {
my $self = shift;
my $results = shift || $self->prefetched( "smoke_results" );
- unless ($results) {
- warn "$self does not have smoke_results prefetched!\n";
- return;
- }
+ return unless $results;
$self->{results} = {};
$self->{results}{$_->configuration->id} = $_
for @{$results->items_array_ref};
commit 546527a9572621314d4b4dc77773f52f9707b604
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Wed Jun 20 01:11:49 2012 -0400
Move to Jifty::Plugin::RPC instead of Gearman
Gearman, while it has its uses, does not have guaranteed execution.
Make use of the Jifty::Plugin::RPC plugin to use AMQP for a back-end
message bus for RPC; this provides guaranteed execution as well as a
generalized message bus for other uses. Guaranteed execution obviates
the need for a check_queue call or method, but does require that the
`gearman_process` column be renamed to the more general `queue_status`
column.
This commit removes the real-time completion updates that
$status->percent provided; such functionality will be later replaced by
the message bus.
diff --git a/Makefile.PL b/Makefile.PL
index 44c4dfa..66cb8fd 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -3,7 +3,6 @@ use inc::Module::Install;
name 'Smokingit';
version '0.01';
requires 'Jifty' => '1.01209';
-requires 'Gearman::Client';
requires 'Git::PurePerl';
WriteAll;
diff --git a/bin/local_updates b/bin/local_updates
index dda017f..f39c67b 100755
--- a/bin/local_updates
+++ b/bin/local_updates
@@ -7,24 +7,14 @@ use lib 'lib';
use Jifty;
BEGIN { Jifty->new; }
-use Gearman::Worker;
-my $worker = Gearman::Worker->new(
- job_servers => Jifty->config->app('job_servers'),
-);
-
-# User task, synchronous
-$worker->register_function(
- check_queue => sub {
- my $restarted = Smokingit->check_queue;
- return "Restarted $restarted tasks\n";
- },
-);
+use AnyEvent;
# User task, synchronous
-$worker->register_function(
- retest => sub {
- my $job = shift;
- my ($sha,$configname) = $job->arg =~ /^([0-9a-fA-F]+)(?:\s*\[(.*)\])?/;
+Jifty->rpc->register(
+ name => "retest",
+ run => sub {
+ my $arg = shift;
+ my ($sha,$configname) = $arg =~ /^([0-9a-fA-F]+)(?:\s*\[(.*)\])?/;
my $commits = Smokingit::Model::CommitCollection->new;
$commits->limit( column => "sha", operator => "like", value => "$sha%" );
@@ -54,7 +44,7 @@ $worker->register_function(
if ($smoke->id) {
$msg->("Re-testing $summary\n");
$smoke->as_superuser->set_submitted_at(undef);
- $smoke->as_superuser->set_gearman_process(undef);
+ $smoke->as_superuser->set_queue_status(undef);
$tests += $smoke->run_smoke;
} else {
# Guess which branch
@@ -77,10 +67,10 @@ $worker->register_function(
);
# User or background task
-$worker->register_function(
- sync_project => sub {
- my $job = shift;
- my $project_name = $job->arg;
+Jifty->rpc->register(
+ name => "sync_project",
+ run => sub {
+ my $project_name = shift;
my $project = Smokingit::Model::Project->new(
current_user => Smokingit::CurrentUser->superuser,
@@ -95,23 +85,24 @@ $worker->register_function(
);
# Background task, from worker
-$worker->register_function(
- post_results => sub {
- my $job = shift;
+Jifty->rpc->register(
+ name => "post_results",
+ run => sub {
+ my $data = shift;
my $smoke = Smokingit::Model::SmokeResult->new(
current_user => Smokingit::CurrentUser->superuser,
);
- my ($ok, $msg) = $smoke->post_result($job->arg);
+ my ($ok, $msg) = $smoke->post_result($data);
warn "$msg\n";
return $ok;
},
);
# Background task
-$worker->register_function(
- plan_tests => sub {
- my $job = shift;
- my $project_name = $job->arg;
+Jifty->rpc->register(
+ name => "plan_tests",
+ run => sub {
+ my $project_name = shift;
my $projects = Smokingit::Model::ProjectCollection->new(
current_user => Smokingit::CurrentUser->superuser,
@@ -135,11 +126,9 @@ $worker->register_function(
);
# Schedule some basic maintenance
-Smokingit->gearman->dispatch_background( check_queue => 1 );
-
my $projects = Smokingit::Model::ProjectCollection->new;
$projects->unlimit;
-Smokingit->gearman->dispatch_background( sync_project => $_->name )
+Jifty->rpc->call( name => "sync_project", args => $_->name )
while $_ = $projects->next;
-$worker->work while 1;
+AE::cv->recv;
diff --git a/bin/rpc b/bin/rpc
new file mode 100755
index 0000000..f6f7d67
--- /dev/null
+++ b/bin/rpc
@@ -0,0 +1,23 @@
+#!/usr/bin/env perl
+
+use AnyEvent::RabbitMQ::RPC;
+
+use strict;
+use warnings;
+
+die unless @ARGV == 2;
+my ($queue, $arg) = @ARGV;
+
+my $rpc = AnyEvent::RabbitMQ::RPC->new(
+ host => 'localhost',
+ port => 5672,
+ user => 'guest',
+ pass => 'guest',
+ vhost => '/',
+ serialize => 'Storable',
+);
+
+print $rpc->call(
+ name => $queue,
+ args => $arg,
+);
diff --git a/bin/start-gearmand b/bin/start-gearmand
deleted file mode 100755
index 01d8a90..0000000
--- a/bin/start-gearmand
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-gearmand \
- --daemon\
- --verbose \
- --verbose \
- --pid-file=var/gearman.pid \
- --log-file=log/gearmand.log \
- --port=4730
diff --git a/etc/config.yml b/etc/config.yml
index e89a8fd..ffffea9 100644
--- a/etc/config.yml
+++ b/etc/config.yml
@@ -11,12 +11,13 @@ framework:
Host: localhost
Password: ''
User: postgres
- Version: 0.0.6
+ Version: 0.0.7
DevelMode: 1
LogLevel: INFO
Mailer: Sendmail
MailerArgs: []
- Plugins:
+ Plugins:
+ - RPC: {}
- CompressedCSSandJS: {}
- ErrorTemplates: {}
- REST: {}
@@ -34,7 +35,5 @@ framework:
StaticRoot: share/web/static
TemplateRoot: share/web/templates
application:
- job_servers:
- - 127.0.0.1:4730
memcached_servers:
- 127.0.0.1:11211
diff --git a/lib/Smokingit.pm b/lib/Smokingit.pm
index d2306a7..dbcfa7c 100644
--- a/lib/Smokingit.pm
+++ b/lib/Smokingit.pm
@@ -2,36 +2,15 @@ use strict;
use warnings;
package Smokingit;
-use Gearman::Client;
use Cache::Memcached;
-our( $GEARMAN, $MEMCACHED );
+our( $MEMCACHED );
sub start {
- $GEARMAN = Gearman::Client->new;
- $GEARMAN->job_servers( Jifty->config->app('job_servers') );
-
$MEMCACHED = Cache::Memcached->new(
{ servers => Jifty->config->app( 'memcached_servers' ) } );
}
-sub gearman { $GEARMAN }
sub memcached { $MEMCACHED }
-sub check_queue {
- my $job = shift;
- my $queued = Smokingit::Model::SmokeResultCollection->new;
- $queued->limit(
- column => "submitted_at",
- operator => "IS",
- value => "NULL",
- );
- my $restarted = 0;
- while (my $smoke = $queued->next) {
- next if $smoke->gearman_status->known;
- $restarted += $smoke->run_smoke;
- }
- return $restarted;
-}
-
1;
diff --git a/lib/Smokingit/Model/Branch.pm b/lib/Smokingit/Model/Branch.pm
index bcb0f38..cdd081e 100644
--- a/lib/Smokingit/Model/Branch.pm
+++ b/lib/Smokingit/Model/Branch.pm
@@ -91,8 +91,9 @@ sub create {
unless $self->project->branches->count == 1
or $self->to_merge_into->id;
- Smokingit->gearman->dispatch_background(
- plan_tests => $self->project->name,
+ Jifty->rpc->call(
+ name => "plan_tests",
+ args => $self->project->name,
) if $plan_tests;
return ($ok, $msg);
@@ -173,8 +174,9 @@ sub set_status {
# It's no longer ignored; start testing where the tip is now,
# not where it was when we first found it
$self->set_tested_commit_id( $self->current_commit->id );
- Smokingit->gearman->dispatch_background(
- plan_tests => $self->project->name,
+ Jifty->rpc->call(
+ name => "plan_tests",
+ args => $self->project->name,
);
}
@@ -239,7 +241,7 @@ sub commit_list {
name => "smoke_results",
alias => $results,
class => "Smokingit::Model::SmokeResultCollection",
- columns => [qw/id gearman_process configuration_id commit_id
+ columns => [qw/id queue_status configuration_id commit_id
error is_ok exit wait
passed failed parse_errors todo_passed/],
);
diff --git a/lib/Smokingit/Model/Commit.pm b/lib/Smokingit/Model/Commit.pm
index faa5026..3bdd262 100644
--- a/lib/Smokingit/Model/Commit.pm
+++ b/lib/Smokingit/Model/Commit.pm
@@ -129,24 +129,18 @@ sub status {
return @{$cache_value} if $cache_value;
my @return;
- if ($result->gearman_process) {
- my $status = $result->gearman_status;
- if (not $status->known) {
- return ("broken", "Unknown");
- } elsif ($status->running) {
- my $percent = defined $status->percent
- ? int($status->percent*100)."%" : undef;
- my $msg = defined $percent
- ? "$percent complete"
- : "Configuring";
- return ("testing", $msg, $percent);
- } else {
+ if (my $status = $result->queue_status) {
+ if ($status eq "queued") {
return ("queued", "Queued to test");
+ } elsif ($status eq "broken") {
+ return ("broken", "Failed to queue!");
+ } else {
+ return ("testing", $status, undef);
}
} elsif ($result->error) {
@return = ("errors", $result->short_error);
} elsif ($result->is_ok) {
- @return = ("passing", $result->passed . " OK")
+ @return = ("passing", $result->passed . " OK");
} elsif ($result->failed) {
@return = ("failing", $result->failed . " failed");
} elsif ($result->parse_errors) {
diff --git a/lib/Smokingit/Model/Configuration.pm b/lib/Smokingit/Model/Configuration.pm
index e48738c..1ea17ec 100644
--- a/lib/Smokingit/Model/Configuration.pm
+++ b/lib/Smokingit/Model/Configuration.pm
@@ -40,8 +40,9 @@ sub create {
my ($ok, $msg) = $self->SUPER::create(@_);
return ($ok, $msg) unless $ok;
- Smokingit->gearman->dispatch_background(
- plan_tests => $self->project->name,
+ Jifty->rpc->call(
+ name => "plan_tests",
+ args => $self->project->name,
);
return ($ok, $msg);
diff --git a/lib/Smokingit/Model/Project.pm b/lib/Smokingit/Model/Project.pm
index d700a27..44a84bb 100644
--- a/lib/Smokingit/Model/Project.pm
+++ b/lib/Smokingit/Model/Project.pm
@@ -36,8 +36,9 @@ sub create {
return ($ok, $msg) unless $ok;
# Kick off the clone in the background
- Smokingit->gearman->dispatch_background(
- sync_project => $self->name,
+ Jifty->rpc->call(
+ name => "sync_project",
+ args => $self->name,
);
return ($ok, $msg);
@@ -109,7 +110,7 @@ sub planned_tests {
my $self = shift;
my $tests = Smokingit::Model::SmokeResultCollection->new;
$tests->limit(
- column => "gearman_process",
+ column => "queue_status",
operator => "IS NOT",
value => "NULL"
);
@@ -126,7 +127,7 @@ sub finished_tests {
my $self = shift;
my $tests = Smokingit::Model::SmokeResultCollection->new;
$tests->limit(
- column => "gearman_process",
+ column => "queue_status",
operator => "IS",
value => "NULL"
);
diff --git a/lib/Smokingit/Model/SmokeResult.pm b/lib/Smokingit/Model/SmokeResult.pm
index b064642..292bec8 100644
--- a/lib/Smokingit/Model/SmokeResult.pm
+++ b/lib/Smokingit/Model/SmokeResult.pm
@@ -4,8 +4,6 @@ use warnings;
package Smokingit::Model::SmokeResult;
use Jifty::DBI::Schema;
-use Storable qw/nfreeze thaw/;
-
use Smokingit::Record schema {
column project_id =>
is mandatory,
@@ -29,7 +27,12 @@ use Smokingit::Record schema {
since '0.0.4';
column gearman_process =>
- type is 'text';
+ type is 'text',
+ till '0.0.7';
+
+ column queue_status =>
+ type is 'text',
+ since '0.0.7';
column queued_at =>
is timestamp,
@@ -69,18 +72,10 @@ sub short_error {
return $msg;
}
-use Gearman::JobStatus;
-sub gearman_status {
- my $self = shift;
- return Gearman::JobStatus->new(0,0) unless $self->gearman_process;
- return $self->{job_status} ||= Smokingit->gearman->get_status($self->gearman_process)
- || Gearman::JobStatus->new(0,0);
-}
-
sub run_smoke {
my $self = shift;
- if ($self->gearman_status->known) {
+ if ($self->queue_status) {
warn join( ":",
$self->project->name,
$self->configuration->name,
@@ -96,9 +91,9 @@ sub run_smoke {
$self->commit->short_sha
)."\n";
- my $job_id = Smokingit->gearman->dispatch_background(
- "run_tests",
- nfreeze( {
+ Jifty->rpc->call(
+ name => "run_tests",
+ args => {
smoke_id => $self->id,
project => $self->project->name,
@@ -108,19 +103,21 @@ sub run_smoke {
env => $self->configuration->env,
parallel => ($self->configuration->parallel ? 1 : 0),
test_glob => $self->configuration->test_glob,
- } ),
- { uniq => $self->id },
+ },
+ on_sent => sub {
+ my $ok = shift;
+ $self->as_superuser->set_queue_status($ok ? "queued" : "broken");
+ $self->as_superuser->set_queued_at( Jifty::DateTime->now );
+
+ # If we had a result for this already, we need to clean its status
+ # out of the memcached cache. Remove both the cache on the commit,
+ # as well as this smoke.
+ Smokingit->memcached->delete( $self->commit->status_cache_key );
+ Smokingit->memcached->delete( $self->status_cache_key );
+ },
);
- warn "Unable to insert run_tests job!\n" unless $job_id;
- $self->as_superuser->set_gearman_process($job_id || "failed");
- $self->as_superuser->set_queued_at( Jifty::DateTime->now );
-
- # If we had a result for this already, we need to clean its status
- # out of the memcached cache. Remove both the cache on the commit,
- # as well as this smoke.
- Smokingit->memcached->delete( $self->commit->status_cache_key );
- Smokingit->memcached->delete( $self->status_cache_key );
- return $job_id ? 1 : 0;
+
+ return 1;
}
sub status_cache_key {
@@ -132,9 +129,7 @@ sub post_result {
my $self = shift;
my ($arg) = @_;
- my %result;
- eval { %result = %{ thaw( $arg ) } };
- return (0, "Thaw failed: $@") if $@;
+ my %result = %{ $arg };
# Properties to extract from the aggregator
my @props =
@@ -168,7 +163,7 @@ sub post_result {
$self->load( $smokeid );
if (not $self->id) {
return (0, "Invalid smoke ID: $smokeid");
- } elsif (not $self->gearman_process) {
+ } elsif (not $self->queue_status) {
return (0, "Smoke report on $smokeid which wasn't being smoked? (last report at @{[$self->submitted_at]})");
}
@@ -178,7 +173,7 @@ sub post_result {
$self->$method($result{$key});
}
# Mark as no longer smoking
- $self->set_gearman_process(undef);
+ $self->set_queue_status(undef);
# And commit all of that
Jifty->handle->commit;
diff --git a/lib/Smokingit/View/GitHub.pm b/lib/Smokingit/View/GitHub.pm
index 8595f8d..e4e3a26 100644
--- a/lib/Smokingit/View/GitHub.pm
+++ b/lib/Smokingit/View/GitHub.pm
@@ -35,8 +35,9 @@ template '/github' => sub {
or return "Branch is not currently tested\n";
}
- Smokingit->gearman->dispatch_background(
- sync_project => $project->name,
+ Jifty->api->call(
+ name => "sync_project",
+ args => $project->name,
);
return undef;
};
diff --git a/lib/Smokingit/View/Project.pm b/lib/Smokingit/View/Project.pm
index 5799765..7b66d82 100644
--- a/lib/Smokingit/View/Project.pm
+++ b/lib/Smokingit/View/Project.pm
@@ -164,7 +164,7 @@ sub branchlist {
name => "smoke_results",
alias => $results,
class => "Smokingit::Model::SmokeResultCollection",
- columns => [qw/id gearman_process configuration_id
+ columns => [qw/id queue_status configuration_id
error is_ok exit wait
passed failed parse_errors todo_passed/],
);
commit f4b92237f6433490681acfa90d82da229d6b5062
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Wed Jun 20 01:43:59 2012 -0400
Subscribe to updates on the `worker_progress` topic
The worker (as of 4f044a7 in smokingit-worker.git) publishes status
updates, including what Gearman used to provide via ->progress, as
structured data on the `worker_progress` topic. Subscribe to it in the
local update thread and set the queue_status column based on it.
diff --git a/bin/local_updates b/bin/local_updates
index f39c67b..4e467a3 100755
--- a/bin/local_updates
+++ b/bin/local_updates
@@ -125,6 +125,30 @@ Jifty->rpc->register(
}
);
+my $listen = Jifty->bus->new_listener;
+$listen->subscribe( Jifty->bus->topic("worker_progress") );
+$listen->poll(
+ sub {
+ my %message = %{ shift() };
+ my $smoke = Smokingit::Model::SmokeResult->new(
+ current_user => Smokingit::CurrentUser->superuser,
+ );
+ $smoke->load( $message{smoke_id} );
+ my $status = $message{status};
+ if ($status eq "started") {
+ $smoke->set_queue_status("Processing commit");
+ } elsif ($status eq "configuring") {
+ $smoke->set_queue_status("Configuring");
+ } elsif ($status eq "testing") {
+ my $fraction = $message{complete}/($message{total} || 1);
+ $smoke->set_queue_status(
+ int($fraction*100) ."% complete");
+ } else {
+ warn "Unknown worker status: $status";
+ }
+ }
+);
+
# Schedule some basic maintenance
my $projects = Smokingit::Model::ProjectCollection->new;
$projects->unlimit;
diff --git a/etc/config.yml b/etc/config.yml
index ffffea9..1b9d03a 100644
--- a/etc/config.yml
+++ b/etc/config.yml
@@ -17,6 +17,7 @@ framework:
Mailer: Sendmail
MailerArgs: []
Plugins:
+ - PubSub: {}
- RPC: {}
- CompressedCSSandJS: {}
- ErrorTemplates: {}
diff --git a/lib/Smokingit/Model/Commit.pm b/lib/Smokingit/Model/Commit.pm
index 3bdd262..be12c67 100644
--- a/lib/Smokingit/Model/Commit.pm
+++ b/lib/Smokingit/Model/Commit.pm
@@ -130,7 +130,9 @@ sub status {
my @return;
if (my $status = $result->queue_status) {
- if ($status eq "queued") {
+ if ($status =~ /^(\d+%) complete$/) {
+ return ("testing", $status, $1);
+ } elsif ($status eq "queued") {
return ("queued", "Queued to test");
} elsif ($status eq "broken") {
return ("broken", "Failed to queue!");
commit 7b905dae939d95e963b135508a2c921bbee07638
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Wed Jun 20 02:02:30 2012 -0400
Refactor testing into an action
diff --git a/bin/local_updates b/bin/local_updates
index 4e467a3..1d6065e 100755
--- a/bin/local_updates
+++ b/bin/local_updates
@@ -5,7 +5,7 @@ use warnings;
use lib 'lib';
use Jifty;
-BEGIN { Jifty->new; }
+BEGIN { Jifty->new( no_request => 1 ); }
use AnyEvent;
@@ -13,56 +13,7 @@ use AnyEvent;
Jifty->rpc->register(
name => "retest",
run => sub {
- my $arg = shift;
- my ($sha,$configname) = $arg =~ /^([0-9a-fA-F]+)(?:\s*\[(.*)\])?/;
-
- my $commits = Smokingit::Model::CommitCollection->new;
- $commits->limit( column => "sha", operator => "like", value => "$sha%" );
- return "Unknown SHA\n" if $commits->count == 0;
- return "Ambiguous SHA\n" if $commits->count > 1;
-
- my @msgs;
- my $msg = sub { warn @_; push @msgs, @_ };
-
- my $commit = $commits->next;
-
- my $branch;
-
- my $configs = $commit->project->configurations;
- $configs->limit( column => "name", operator => "MATCHES", value => $configname )
- if defined $configname and length $configname;
- my $tests = 0;
- while (my $config = $configs->next) {
- my $summary = $commit->short_sha . "[" . $config->name ."]";
- my %lookup = (
- project_id => $commit->project->id,
- configuration_id => $config->id,
- commit_id => $commit->id,
- );
- my $smoke = Smokingit::Model::SmokeResult->new;
- $smoke->load_by_cols( %lookup );
- if ($smoke->id) {
- $msg->("Re-testing $summary\n");
- $smoke->as_superuser->set_submitted_at(undef);
- $smoke->as_superuser->set_queue_status(undef);
- $tests += $smoke->run_smoke;
- } else {
- # Guess which branch
- unless ($branch) {
- $branch = Smokingit::Model::Branch->new;
- my @branches = $commit->branches;
- $branch->load_by_cols( name => $branches[0], project_id => $commit->project->id)
- if @branches == 1;
- }
- if ($branch->id) {
- $msg->("Testing $summary\n");
- $tests += $commit->run_smoke( $config, $branch );
- } else {
- $msg->("No existing smoke for $summary found, and can't determine branch\n");
- }
- }
- }
- return join "", @msgs;
+ return Smokingit->test( @_ ) . "\n";
},
);
diff --git a/lib/Smokingit.pm b/lib/Smokingit.pm
index dbcfa7c..b1d5293 100644
--- a/lib/Smokingit.pm
+++ b/lib/Smokingit.pm
@@ -13,4 +13,19 @@ sub start {
sub memcached { $MEMCACHED }
+sub test {
+ my $self = shift;
+
+ my $arg = shift;
+ my $action = Smokingit::Action::Test->new(
+ current_user => Smokingit::CurrentUser->superuser,
+ arguments => { commit => $arg },
+ );
+ $action->validate;
+ return $action->result->field_error("commit") . "\n"
+ unless $action->result->success;
+ $action->run;
+ return ($action->result->message || $action->result->error);
+}
+
1;
diff --git a/lib/Smokingit/Action/Test.pm b/lib/Smokingit/Action/Test.pm
new file mode 100644
index 0000000..fe0e309
--- /dev/null
+++ b/lib/Smokingit/Action/Test.pm
@@ -0,0 +1,168 @@
+use strict;
+use warnings;
+
+=head1 NAME
+
+Smokingit::Action::Test
+
+=cut
+
+package Smokingit::Action::Test;
+use base qw/Smokingit::Action/;
+
+use Jifty::Param::Schema;
+use Jifty::Action schema {
+ param 'commit' =>
+ label is 'Commit to test',
+ is mandatory;
+};
+
+sub validate_commit {
+ my $self = shift;
+ my $arg = shift;
+
+ unless ($arg =~ /^([0-9a-fA-F]+)(?:\s*\[\s*(.*)\s*\])?(?:\s*\{\s*(.*)\s*\})?$/) {
+ return $self->validation_error(
+ commit => "That doesn't look like a SHA" );
+ }
+ my ($sha,$config_text, $branch_text) = ($1, $2, $3);
+
+ my $commits = Smokingit::Model::CommitCollection->new;
+ $commits->limit( column => "sha", operator => "like", value => "$sha%" );
+ return $self->validation_error(
+ commit => "Unknown SHA $sha"
+ ) if $commits->count == 0;
+ return $self->validation_error(
+ commit => "Ambiguous SHA (".$commits->count." matches)"
+ ) if $commits->count > 1;
+
+ my $commit = $commits->first;
+ $sha = $commit->sha;
+
+ if (not $config_text) {
+ # We'll do all of them
+ } elsif ($config_text =~ /^\d+$/) {
+ my $config = Smokingit::Model::Configuration->new;
+ $config->load( $config_text );
+ return $self->validation_error( commit => "Invalid configuration id" )
+ unless $config->id and $config->project->id == $commit->project->id;
+ } else {
+ my $configs = $commit->project->configurations;
+ $configs->limit( column => "name", operator => "MATCHES", value => $config_text );
+ return $self->validation_error( commit => "Invalid configuration name" )
+ unless $configs->count == 1;
+ $config_text = $configs->first->id;
+ }
+
+ my $existing = Smokingit::Model::SmokeResultCollection->new;
+ $existing->limit(
+ column => "project_id",
+ value => $commit->project->id
+ );
+ $existing->limit(
+ column => "commit_id",
+ value => $commit->id
+ );
+ $existing->limit(
+ column => "configuration_id",
+ value => $config_text
+ ) if $config_text;
+
+ if ($existing->count) {
+ # Re-testing the existing smokes
+ undef $branch_text;
+ } else {
+ my @branches = $commit->branches;
+ if ($branch_text) {
+ if ($branch_text =~ /^\d+$/) {
+ my $branch = Smokingit::Model::Branch->new;
+ $branch->load($branch_text);
+ return $self->validation_error( commit => "Invalid branch id" )
+ unless $branch->id;
+ $branch_text = $branch->name;
+ }
+ return $self->validation_error( commit => "Invalid branch name" )
+ unless grep {$_ eq $branch_text} @branches;
+ } elsif (@branches == 1) {
+ $branch_text = $branches[0];
+ } else {
+ return $self->validation_error( commit => "Can't determine which branch to test on" );
+ }
+ }
+
+ $sha .= "[$config_text]" if $config_text;
+ $sha .= "{$branch_text}" if $branch_text;
+ $self->argument_value( commit => $sha );
+ return $self->validation_ok( "commit" );
+}
+
+sub take_action {
+ my $self = shift;
+
+ my $arg = $self->argument_value("commit");
+ my ($sha, $config, $branchname) =
+ $arg =~ /^([0-9a-fA-F]+)(?:\[(\d+)\])?(?:\{(.*)\})?$/;
+
+ my $commit = Smokingit::Model::Commit->new;
+ $commit->load_by_cols( sha => $sha );
+
+ if ($branchname) {
+ # Testing new commits
+ my $branch = Smokingit::Model::Branch->new;
+ $branch->load_by_cols( name => $branchname, project_id => $commit->project->id);
+
+ my $configs = $commit->project->configurations;
+ $configs->limit( column => "id", value => $config ) if $config;
+
+ while (my $config = $configs->next) {
+ $commit->run_smoke( $config, $branch );
+ }
+ $self->result->message(
+ "Testing "
+ . $configs->count
+ . " configurations of "
+ . $commit->short_sha
+ );
+ } else {
+ # Re-testing old commits
+ my $existing = Smokingit::Model::SmokeResultCollection->new;
+ $existing->limit(
+ column => "project_id",
+ value => $commit->project->id,
+ );
+ $existing->limit(
+ column => "commit_id",
+ value => $commit->id,
+ );
+ $existing->limit(
+ column => "queue_status",
+ operator => "IS",
+ value => "NULL",
+ );
+ $existing->limit(
+ column => "configuration_id",
+ value => $config,
+ ) if $config;
+ $existing->order_by( column => 'queued_at' );
+
+ while (my $smoke = $existing->next) {
+ $smoke->as_superuser->set_submitted_at(undef);
+ $smoke->as_superuser->set_queue_status(undef);
+ $smoke->run_smoke;
+ }
+
+ if ($existing->count == 0) {
+ $self->result->message("Commits already queued for testing");
+ } else {
+ $self->result->message(
+ "Retesting "
+ . $existing->count
+ . " configurations of "
+ . $commit->short_sha
+ );
+ }
+
+ }
+}
+
+1;
commit 6c9cf864d032587279dbf25acf0f03012b2af94c
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Wed Jun 20 02:06:19 2012 -0400
Publish progress updates
diff --git a/bin/local_updates b/bin/local_updates
index 1d6065e..cffc2a1 100755
--- a/bin/local_updates
+++ b/bin/local_updates
@@ -85,18 +85,19 @@ $listen->poll(
current_user => Smokingit::CurrentUser->superuser,
);
$smoke->load( $message{smoke_id} );
- my $status = $message{status};
- if ($status eq "started") {
+ my $status = Smokingit::Status->new( $smoke );
+ if ($message{status} eq "started") {
$smoke->set_queue_status("Processing commit");
- } elsif ($status eq "configuring") {
+ } elsif ($message{status} eq "configuring") {
$smoke->set_queue_status("Configuring");
- } elsif ($status eq "testing") {
+ } elsif ($message{status} eq "testing") {
my $fraction = $message{complete}/($message{total} || 1);
$smoke->set_queue_status(
int($fraction*100) ."% complete");
} else {
- warn "Unknown worker status: $status";
+ warn "Unknown worker status: $message{status}";
}
+ $status->publish;
}
);
diff --git a/lib/Smokingit/Model/SmokeResult.pm b/lib/Smokingit/Model/SmokeResult.pm
index 292bec8..8f44910 100644
--- a/lib/Smokingit/Model/SmokeResult.pm
+++ b/lib/Smokingit/Model/SmokeResult.pm
@@ -3,6 +3,7 @@ use warnings;
package Smokingit::Model::SmokeResult;
use Jifty::DBI::Schema;
+use Smokingit::Status;
use Smokingit::Record schema {
column project_id =>
@@ -91,6 +92,7 @@ sub run_smoke {
$self->commit->short_sha
)."\n";
+ my $status = Smokingit::Status->new( $self );
Jifty->rpc->call(
name => "run_tests",
args => {
@@ -108,12 +110,15 @@ sub run_smoke {
my $ok = shift;
$self->as_superuser->set_queue_status($ok ? "queued" : "broken");
$self->as_superuser->set_queued_at( Jifty::DateTime->now );
+ $self->load($self->id);
# If we had a result for this already, we need to clean its status
# out of the memcached cache. Remove both the cache on the commit,
# as well as this smoke.
Smokingit->memcached->delete( $self->commit->status_cache_key );
Smokingit->memcached->delete( $self->status_cache_key );
+
+ $status->publish;
},
);
@@ -157,6 +162,8 @@ sub post_result {
}
$result{submitted_at} = Jifty::DateTime->now;
+ my $status = Smokingit::Status->new( $self );
+
# Find the smoke
Jifty->handle->begin_transaction;
my $smokeid = delete $result{smoke_id};
@@ -178,6 +185,8 @@ sub post_result {
# And commit all of that
Jifty->handle->commit;
+ $status->publish;
+
return (1, "Test result for "
. $self->project->name
." ". $self->commit->short_sha
diff --git a/lib/Smokingit/Status.pm b/lib/Smokingit/Status.pm
new file mode 100644
index 0000000..1a17285
--- /dev/null
+++ b/lib/Smokingit/Status.pm
@@ -0,0 +1,93 @@
+use warnings;
+use strict;
+
+package Smokingit::Status;
+
+sub new {
+ my $class = shift;
+ my ($smoke) = @_;
+ my $self = bless { smoke => $smoke }, $class;
+ $self->before;
+ return $self;
+}
+
+sub before {
+ my $self = shift;
+ my $smoke = $self->{smoke};
+ $self->{before} = [ $smoke->commit->status($smoke) ],
+}
+
+sub publish {
+ my $self = shift;
+ my $smoke = $self->{smoke};
+ my $commit = $smoke->commit;
+
+ my $before = $self->{before};
+ my ($short, $long, $percent) = $commit->status($smoke);
+
+ # Set up for next time
+ $self->before;
+
+ return unless $before->[0] ne $short
+ or $before->[1] ne $long
+ or ($before->[2]||"") ne ($percent||"");
+
+ Jifty->bus->topic("test_progress")->publish( {
+ type => "test_progress",
+ short_sha => $commit->short_sha,
+ sha => $commit->sha,
+ branch => $smoke->branch_name,
+ config_name => $smoke->configuration->name,
+ config => $smoke->configuration->id,
+ smoke_id => $smoke->id,
+ raw_status => $short,
+ status => $long,
+ percent => $percent,
+ } );
+
+ return if $before->[0] eq $short;
+
+ Jifty->bus->topic("commit_status")->publish( {
+ type => "commit_status",
+ sha => $commit->sha,
+ commit_id => $commit->id,
+ raw_status => $commit->status,
+ } );
+
+ if ($short eq "queued") {
+ Jifty->bus->topic("test_queued")->publish( {
+ type => "test_queued",
+ sha => $commit->sha,
+ config => $smoke->configuration->id,
+ smoke_id => $smoke->id,
+ } );
+ }
+
+ return unless $short =~ /^(errors|passing|failing|parsefail|todo)$/;
+ Jifty->bus->topic("test_result")->publish( {
+ type => "test_result",
+ sha => $commit->sha,
+ config => $smoke->configuration->id,
+ smoke_id => $smoke->id,
+ raw_status => $short,
+ status => $long,
+ } );
+
+ my $smoked = Smokingit::Model::SmokeResultCollection->new;
+ $smoked->limit( column => "commit_id", value => $commit->id );
+ $smoked->limit( column => "project_id", value => $smoke->project->id );
+ $smoked->limit(
+ column => "queue_status",
+ operator => "IS",
+ value => "NULL"
+ );
+ return unless $smoked->count == $smoke->project->configurations->count;
+ Jifty->bus->topic("commit_result")->publish( {
+ type => "commit_result",
+ sha => $commit->sha,
+ commit_id => $commit->id,
+ raw_status => $commit->status,
+ } );
+}
+
+1;
commit f9b55c47d3a12a4fc633024b92eed9c21a442474
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Wed Jun 20 02:07:29 2012 -0400
Push updates to planned and recent tests based on events
diff --git a/lib/Smokingit/View/Project.pm b/lib/Smokingit/View/Project.pm
index 7b66d82..e026db6 100644
--- a/lib/Smokingit/View/Project.pm
+++ b/lib/Smokingit/View/Project.pm
@@ -55,27 +55,53 @@ template '/project' => page {
};
};
- my $tests = get('project')->finished_tests;
- $tests->rows_per_page(10);
- if ($tests->count) {
- div {
- id is "recent-tests";
- class is "commitlist";
- h2 { "Recent tests" };
- test_result($_) while $_ = $tests->next;
- };
- }
+ render_region(
+ name => "finished",
+ path => "/fragments/project/finished",
+ defaults => { project_id => get('project')->id },
+ );
- my $planned = get('project')->planned_tests;
- if ($planned->count) {
- div {
- id is "planned-tests";
- class is "commitlist";
- h2 { "Planned tests" };
- test_result($_) while $_ = $planned->next;
- }
- }
+ render_region(
+ name => "planned",
+ path => "/fragments/project/planned",
+ defaults => { project_id => get('project')->id },
+ );
+ };
+};
+
+template '/fragments/project/finished' => sub {
+ my $project = Smokingit::Model::Project->new;
+ $project->load( get('project_id') );
+
+ my $tests = $project->finished_tests;
+ $tests->rows_per_page(10);
+ div {
+ id is "recent-tests";
+ h2 { "Recent tests" };
+ span {
+ class is "commitlist";
+ test_result($_) while $_ = $tests->next;
+ };
+ };
+ Jifty->subs->update_on( topic => "test_queued" );
+ Jifty->subs->update_on( topic => "test_result" );
+};
+
+template '/fragments/project/planned' => sub {
+ my $project = Smokingit::Model::Project->new;
+ $project->load( get('project_id') );
+
+ my $planned = $project->planned_tests;
+ div {
+ id is "planned-tests";
+ h2 { "Planned tests" };
+ span {
+ class is "commitlist";
+ test_result($_) while $_ = $planned->next;
+ };
};
+ Jifty->subs->update_on( topic => "test_queued" );
+ Jifty->subs->update_on( topic => "test_result" );
};
sub test_result {
commit dbca24044f519ab9db1579970f02e524dcc5d615
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Wed Jun 20 02:08:10 2012 -0400
Add more classes to allow client-side updates
diff --git a/lib/Smokingit/View/Branch.pm b/lib/Smokingit/View/Branch.pm
index 8c83437..0948596 100644
--- a/lib/Smokingit/View/Branch.pm
+++ b/lib/Smokingit/View/Branch.pm
@@ -53,17 +53,17 @@ template '/branch' => page {
my $merge = $commit->subject =~ /^Merge branch /
? "merge" : "nonmerge";
div {
- {class is "$merge commit ".$commit->status};
+ {class is $commit->sha." $merge commit ".$commit->status};
for my $config (@configs) {
my ($status, $msg, $in) = $commit->status($config);
if ($status =~ /^(untested|testing|queued)$/) {
span {
- attr { class => "okbox $status", title => $msg };
+ attr { class => "okbox $status config-".$config->id, title => $msg };
outs_raw($in ||" ")
};
} else {
hyperlink(
- class => "okbox $status",
+ class => "okbox $status config-".$config->id,
label => " ",
escape_label => 0,
url => "/test/".$commit->sha."/".$config->name,
diff --git a/lib/Smokingit/View/Project.pm b/lib/Smokingit/View/Project.pm
index e026db6..3d73bb3 100644
--- a/lib/Smokingit/View/Project.pm
+++ b/lib/Smokingit/View/Project.pm
@@ -108,10 +108,10 @@ sub test_result {
my $test = shift;
my ($status, $msg, $in) = $test->commit->status($test);
div {
- class is "commit $status";
+ class is $test->commit->sha." config-".$test->configuration->id." commit $status";
if ($status =~ /^(untested|queued|testing|broken)$/) {
span {
- attr { class => "okbox $status", title => $msg };
+ attr { class => "okbox $status config-".$test->configuration->id, title => $msg };
outs_raw($in || " ")
};
span {
@@ -207,7 +207,7 @@ sub branchlist {
while (my $b = $branches->next) {
$b->current_commit->hash_results( $b->prefetched("smoke_results") );
li {
- { class is $b->test_status; }
+ { class is $b->test_status . " " . $b->current_commit->sha; }
hyperlink(
label => $b->name . " (" . $b->format_user('current_actor') . ")",
url => "branch/" . $b->name,
commit ae3378f7b943e92ac3d3860161db95542e37df11
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Wed Jun 20 02:08:42 2012 -0400
Do client-side updates of the UI based on events
diff --git a/lib/Smokingit.pm b/lib/Smokingit.pm
index b1d5293..9873527 100644
--- a/lib/Smokingit.pm
+++ b/lib/Smokingit.pm
@@ -9,6 +9,7 @@ our( $MEMCACHED );
sub start {
$MEMCACHED = Cache::Memcached->new(
{ servers => Jifty->config->app( 'memcached_servers' ) } );
+ Jifty->web->add_javascript( "app-late.js" );
}
sub memcached { $MEMCACHED }
diff --git a/lib/Smokingit/View/Branch.pm b/lib/Smokingit/View/Branch.pm
index 0948596..129bab1 100644
--- a/lib/Smokingit/View/Branch.pm
+++ b/lib/Smokingit/View/Branch.pm
@@ -7,6 +7,10 @@ use Jifty::View::Declare -base;
template '/branch' => page {
my $b = get('branch');
redirect '/' unless $b;
+
+ Jifty->subs->add( topic => $_ )
+ for qw/ test_progress commit_status /;
+
page_title is $b->name;
div {
{ class is "subtitle" }
diff --git a/lib/Smokingit/View/Project.pm b/lib/Smokingit/View/Project.pm
index 3d73bb3..7754a3e 100644
--- a/lib/Smokingit/View/Project.pm
+++ b/lib/Smokingit/View/Project.pm
@@ -6,6 +6,10 @@ use Jifty::View::Declare -base;
template '/project' => page {
redirect '/' unless get('project');
+
+ Jifty->subs->add( topic => $_ )
+ for qw/ test_progress commit_status /;
+
page_title is get('project')->name;
div {{class is "subtitle"} get('project')->repository_url };
diff --git a/share/web/static/js/app-late.js b/share/web/static/js/app-late.js
new file mode 100644
index 0000000..bb90313
--- /dev/null
+++ b/share/web/static/js/app-late.js
@@ -0,0 +1,30 @@
+var all_statuses = "broken errors failing todo passing parsefail testing queued untested";
+jQuery(function(){
+ jQuery(pubsub).bind("message.test_progress", function (event, d) {
+ jQuery(".commit."+d.sha+" .okbox.config-"+d.config)
+ .removeClass(all_statuses)
+ .addClass(d.raw_status)
+ .attr("title",d.status)
+ .text( d.percent );
+ jQuery(".commit."+d.sha+".config-"+d.config)
+ .removeClass(all_statuses)
+ .addClass(d.raw_status);
+ jQuery(".commit."+d.sha+".config-"+d.config+" .sha")
+ .attr("title",d.status);
+ if ( d.raw_status != "testing" )
+ jQuery(".commit."+d.sha+" .okbox.config-"+d.config)
+ .html( " " );
+ });
+
+ jQuery(pubsub).bind("message.commit_status", function (event, d) {
+ jQuery(".biglist .commit."+d.sha)
+ .removeClass(all_statuses)
+ .addClass(d.raw_status);
+ jQuery("#branch-list ."+d.sha)
+ .removeClass(all_statuses)
+ .addClass(d.raw_status);
+ jQuery(".biglist .commit."+d.sha+" .testme")
+ .removeClass("testme")
+ .addClass("retestme");
+ });
+});
commit 598e7fef6563decb0443e1db941837c7702f894e
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Wed Jun 20 02:09:09 2012 -0400
(Re-)testing buttons for logged-in users
diff --git a/lib/Smokingit/View/Branch.pm b/lib/Smokingit/View/Branch.pm
index 129bab1..8a71a0d 100644
--- a/lib/Smokingit/View/Branch.pm
+++ b/lib/Smokingit/View/Branch.pm
@@ -75,6 +75,15 @@ template '/branch' => page {
);
}
}
+ span {
+ { class is ( $commit->status eq "untested" ? "testme" : "retestme" ) };
+ my $sha = $commit->sha;
+ my $branch = $b->id;
+ js_handlers {
+ onclick => "pubsub.send({type:'jifty.action',class:'Test',arguments:{commit:'$sha\{$branch}'}})"
+ };
+ outs_raw " ";
+ } if Jifty->web->current_user->id;
if ($commit->status =~ /^(untested|testing|queued)$/) {
span {
{ class is "sha" };
diff --git a/lib/Smokingit/View/Project.pm b/lib/Smokingit/View/Project.pm
index 7754a3e..0ba371e 100644
--- a/lib/Smokingit/View/Project.pm
+++ b/lib/Smokingit/View/Project.pm
@@ -115,6 +115,10 @@ sub test_result {
class is $test->commit->sha." config-".$test->configuration->id." commit $status";
if ($status =~ /^(untested|queued|testing|broken)$/) {
span {
+ attr { class => "spacer" };
+ outs_raw(" ")
+ } if Jifty->web->current_user->id;
+ span {
attr { class => "okbox $status config-".$test->configuration->id, title => $msg };
outs_raw($in || " ")
};
@@ -123,6 +127,15 @@ sub test_result {
$test->commit->short_sha
};
} else {
+ span {
+ { class is "retestme" };
+ my $sha = $test->commit->sha;
+ my $config = $test->configuration->id;
+ js_handlers {
+ onclick => "pubsub.send({type:'jifty.action',class:'Test',arguments:{commit:'$sha\[$config]'}})"
+ };
+ outs_raw " ";
+ } if Jifty->web->current_user->id;
hyperlink(
class => "okbox $status",
label => " ",
diff --git a/share/web/static/css/app-late.css b/share/web/static/css/app-late.css
index 0ec6794..3fcffa8 100644
--- a/share/web/static/css/app-late.css
+++ b/share/web/static/css/app-late.css
@@ -289,7 +289,11 @@ li {
.commitlist .commit.queued .sha { color: #115; }
.commitlist .commit.broken .sha { color: #f11; }
-.commitlist .okbox {
+.commitlist .spacer {
+ float: left;
+ width: 32px;
+}
+.commitlist .okbox, .commitlist .testme, .commitlist .retestme {
float: left;
width: 32px;
background-repeat: no-repeat;
@@ -310,6 +314,16 @@ li {
.commitlist .okbox.queued { background-image: url('/static/images/silk/hourglass.png'); }
.commitlist .okbox.broken { background-image: url('/static/images/silk/server_error.png'); }
+.commitlist .testme, .commitlist .retestme {
+ cursor: pointer;
+ opacity: 0.3;
+}
+.commitlist .testme:hover, .commitlist .retestme:hover {
+ opacity: 1;
+}
+.commitlist .testme { background-image: url('/static/images/silk/control_play.png'); }
+.commitlist .retestme { background-image: url('/static/images/silk/control_repeat.png'); }
+
.commitlist .branchpoint {
clear: both;
margin-top: 0.5em;
diff --git a/share/web/static/images/silk/control_play.png b/share/web/static/images/silk/control_play.png
new file mode 100644
index 0000000..0846555
Binary files /dev/null and b/share/web/static/images/silk/control_play.png differ
diff --git a/share/web/static/images/silk/control_repeat.png b/share/web/static/images/silk/control_repeat.png
new file mode 100644
index 0000000..1c4f57a
Binary files /dev/null and b/share/web/static/images/silk/control_repeat.png differ
commit 568040e26f76fe89362ca54f32a2c1a5dec0e388
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Sun Nov 4 01:22:58 2012 -0500
Use now() to get millisecond resolution on queued_at
diff --git a/lib/Smokingit/Model/SmokeResult.pm b/lib/Smokingit/Model/SmokeResult.pm
index 8f44910..273c301 100644
--- a/lib/Smokingit/Model/SmokeResult.pm
+++ b/lib/Smokingit/Model/SmokeResult.pm
@@ -109,7 +109,10 @@ sub run_smoke {
on_sent => sub {
my $ok = shift;
$self->as_superuser->set_queue_status($ok ? "queued" : "broken");
- $self->as_superuser->set_queued_at( Jifty::DateTime->now );
+ # Use SQL so we get millisecond accuracy in the DB. Otherwise rows
+ # inserted during the same second may not sort the same as they show
+ # up in the worker's queue.
+ $self->__set( column => 'queued_at', value => 'now()', is_sql_function => 1 );
$self->load($self->id);
# If we had a result for this already, we need to clean its status
@@ -160,7 +163,6 @@ sub post_result {
# Unset the existing data if there was a fail
$result{$_} = undef for @props, "is_ok", "elapsed";
}
- $result{submitted_at} = Jifty::DateTime->now;
my $status = Smokingit::Status->new( $self );
@@ -174,6 +176,10 @@ sub post_result {
return (0, "Smoke report on $smokeid which wasn't being smoked? (last report at @{[$self->submitted_at]})");
}
+ # Use SQL so we get millisecond accuracy in the DB. This is not as
+ # necessary as for queued_at (above), but is useful nonetheless.
+ $self->__set( column => 'submitted_at', value => 'now()', is_sql_function => 1 );
+
# Update with the new data
for my $key (keys %result) {
my $method = "set_$key";
commit 37651f7b11e6a734614b3b77a240bad63bd19700
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Sun Nov 4 02:15:24 2012 -0500
Never assign to global (non-lexical) $_, due to AnyEvent event loop
Any place wherein a postfix while assigns to $_, it is modifying the
global $_, not the lexical $_ that for and map make use of. This leads
to the possibility of action at a distance -- particularly when in an
event-driven context such as AnyEvent.
Observed failure modes of global $_ being modified when running under
Twiggy include unpredictable server hangs and spurious errors; these
were much more common under 5.16.0 than under 5.10.1, for whatever
reason.
diff --git a/bin/local_updates b/bin/local_updates
index cffc2a1..681ad31 100755
--- a/bin/local_updates
+++ b/bin/local_updates
@@ -104,7 +104,8 @@ $listen->poll(
# Schedule some basic maintenance
my $projects = Smokingit::Model::ProjectCollection->new;
$projects->unlimit;
-Jifty->rpc->call( name => "sync_project", args => $_->name )
- while $_ = $projects->next;
+while (my $project = $projects->next) {
+ Jifty->rpc->call( name => "sync_project", args => $project->name )
+}
AE::cv->recv;
diff --git a/lib/Smokingit/Model/Branch.pm b/lib/Smokingit/Model/Branch.pm
index cdd081e..a81159f 100644
--- a/lib/Smokingit/Model/Branch.pm
+++ b/lib/Smokingit/Model/Branch.pm
@@ -246,7 +246,10 @@ sub commit_list {
passed failed parse_errors todo_passed/],
);
my %commits;
- $commits{$_->sha} = $_ while $_ = $commits->next;
+ while (my $commit = $commits->next) {
+ $commits{$commit->sha} = $commit;
+ }
+
return map $commits{$_} || $self->project->sha($_), @revs;
}
diff --git a/lib/Smokingit/View/Project.pm b/lib/Smokingit/View/Project.pm
index 0ba371e..498c262 100644
--- a/lib/Smokingit/View/Project.pm
+++ b/lib/Smokingit/View/Project.pm
@@ -84,7 +84,9 @@ template '/fragments/project/finished' => sub {
h2 { "Recent tests" };
span {
class is "commitlist";
- test_result($_) while $_ = $tests->next;
+ while (my $test = $tests->next) {
+ test_result($test);
+ }
};
};
Jifty->subs->update_on( topic => "test_queued" );
@@ -101,7 +103,9 @@ template '/fragments/project/planned' => sub {
h2 { "Planned tests" };
span {
class is "commitlist";
- test_result($_) while $_ = $planned->next;
+ while (my $test = $planned->next) {
+ test_result($test);
+ }
};
};
Jifty->subs->update_on( topic => "test_queued" );
commit fe9344b9cefae3976631be1618e7d024a1f6a7d3
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Sun Nov 4 19:28:48 2012 -0500
Display undef next_actor better, with fewer warnings
diff --git a/lib/Smokingit/Model/Branch.pm b/lib/Smokingit/Model/Branch.pm
index a81159f..dc031c4 100644
--- a/lib/Smokingit/Model/Branch.pm
+++ b/lib/Smokingit/Model/Branch.pm
@@ -287,7 +287,9 @@ When we get user accounts, this will become $branch->current_actor->name
sub format_user {
my ($self, $type) = @_;
if ($self->can($type)) {
- if ( $self->$type =~ m/<(.*?)@/ ) {
+ if ( not defined $self->$type ) {
+ return "somebody";
+ } elsif ( $self->$type =~ m/<(.*?)@/ ) {
return $1;
}
} else {
commit 15caa61b1d4413396c558a3c2d36ac21b97f9709
Merge: d3de530 fe9344b
Author: Alex Vandiver <alexmv at bestpractical.com>
Date: Sun Nov 4 23:27:18 2012 -0500
Merge branch 'pubsub'
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list