2008-11-25 11:01:42 +00:00
package Hydra::Controller::Root ;
2008-10-28 10:19:31 +00:00
2016-10-24 16:08:19 +02:00
use utf8 ;
2008-10-28 10:19:31 +00:00
use strict ;
use warnings ;
2009-03-04 10:59:14 +00:00
use base 'Hydra::Base::Controller::ListBuilds' ;
2008-11-25 11:01:42 +00:00
use Hydra::Helper::Nix ;
2009-02-25 12:03:13 +00:00
use Hydra::Helper::CatalystUtils ;
2010-12-03 09:40:25 +00:00
use Digest::SHA1 qw( sha1_hex ) ;
2011-12-01 20:46:02 -05:00
use Nix::Store ;
2012-07-30 20:26:34 +00:00
use Nix::Config ;
2013-10-03 17:20:00 +02:00
use Encode ;
2015-09-09 16:51:20 +02:00
use JSON ;
2009-02-25 10:52:41 +00:00
# Put this controller at top-level.
2008-10-28 10:19:31 +00:00
__PACKAGE__ - > config - > { namespace } = '' ;
2016-01-13 17:32:52 +01:00
2014-01-10 11:04:28 +01:00
sub noLoginNeeded {
my ( $ c ) = @ _ ;
2016-10-20 14:14:04 +02:00
return $ c - > request - > path eq "google-login" ||
2014-01-10 11:04:28 +01:00
$ c - > request - > path eq "login" ||
$ c - > request - > path eq "logo" ||
$ c - > request - > path =~ /^static\// ;
}
2008-10-28 10:19:31 +00:00
2014-08-23 16:39:16 +02:00
2008-11-13 09:25:38 +00:00
sub begin :Private {
2010-08-31 15:27:46 +00:00
my ( $ self , $ c , @ args ) = @ _ ;
2014-01-10 11:04:28 +01:00
2008-11-13 09:48:10 +00:00
$ c - > stash - > { curUri } = $ c - > request - > uri ;
2009-03-23 13:52:24 +00:00
$ c - > stash - > { version } = $ ENV { "HYDRA_RELEASE" } || "<devel>" ;
2011-04-01 07:40:06 +00:00
$ c - > stash - > { nixVersion } = $ ENV { "NIX_RELEASE" } || "<devel>" ;
2010-08-31 15:27:46 +00:00
$ c - > stash - > { curTime } = time ;
2015-07-01 11:34:19 +02:00
$ c - > stash - > { logo } = defined $ c - > config - > { hydra_logo } ? "/logo" : "" ;
2013-02-27 18:33:47 +01:00
$ c - > stash - > { tracker } = $ ENV { "HYDRA_TRACKER" } ;
$ c - > stash - > { flashMsg } = $ c - > flash - > { flashMsg } ;
$ c - > stash - > { successMsg } = $ c - > flash - > { successMsg } ;
2011-04-19 12:00:54 +00:00
2014-01-10 11:04:28 +01:00
$ c - > stash - > { isPrivateHydra } = $ c - > config - > { private } // "0" ne "0" ;
if ( $ c - > stash - > { isPrivateHydra } && ! noLoginNeeded ( $ c ) ) {
requireUser ( $ c ) ;
}
2010-08-31 15:37:50 +00:00
if ( scalar ( @ args ) == 0 || $ args [ 0 ] ne "static" ) {
2016-03-16 15:19:18 +01:00
$ c - > stash - > { nrRunningBuilds } = dbh ( $ c ) - > selectrow_array (
2016-03-16 13:41:43 +01:00
"select count(distinct build) from buildsteps where busy = 1" ) ;
2013-01-22 14:09:37 +01:00
$ c - > stash - > { nrQueuedBuilds } = $ c - > model ( 'DB::Builds' ) - > search ( { finished = > 0 } ) - > count ( ) ;
2010-08-31 15:27:46 +00:00
}
2013-05-25 15:36:58 -04:00
# Gather the supported input types.
$ c - > stash - > { inputTypes } = {
'string' = > 'String value' ,
'boolean' = > 'Boolean' ,
2013-09-30 12:03:25 +02:00
'nix' = > 'Nix expression' ,
2013-11-11 21:36:26 +00:00
'build' = > 'Previous Hydra build' ,
'sysbuild' = > 'Previous Hydra build (same system)' ,
2013-11-11 21:17:22 +00:00
'eval' = > 'Previous Hydra evaluation'
2013-05-25 15:36:58 -04:00
} ;
$ _ - > supportedInputTypes ( $ c - > stash - > { inputTypes } ) foreach @ { $ c - > hydra_plugins } ;
2013-06-17 12:34:21 -04:00
2016-10-20 16:11:33 +02:00
# XSRF protection: require POST requests to have the same origin.
if ( $ c - > req - > method eq "POST" ) {
my $ referer = $ c - > req - > header ( 'Origin' ) ;
$ referer // = $ c - > req - > header ( 'Referer' ) ;
my $ base = $ c - > req - > base ;
2016-10-24 16:08:19 +02:00
error ( $ c , "POST requests should come from ‘ $base’ ." )
2016-10-21 17:56:34 +02:00
unless defined $ referer && substr ( $ referer , 0 , length $ base ) eq $ base ;
2016-10-20 16:11:33 +02:00
}
2013-06-17 12:34:21 -04:00
$ c - > forward ( 'deserialize' ) ;
$ c - > stash - > { params } = $ c - > request - > data or $ c - > request - > params ;
unless ( defined $ c - > stash - > { params } and % { $ c - > stash - > { params } } ) {
$ c - > stash - > { params } = $ c - > request - > params ;
}
2016-03-25 14:48:12 +01:00
# Set the Vary header to "Accept" to ensure that browsers don't
# mix up HTML and JSON responses.
$ c - > response - > headers - > header ( 'Vary' , 'Accept' ) ;
2008-11-13 09:25:38 +00:00
}
2016-01-13 17:32:52 +01:00
2013-06-17 12:34:21 -04:00
sub deserialize :ActionClass('Deserialize') { }
2008-11-13 09:25:38 +00:00
2008-10-28 10:19:31 +00:00
sub index :Path :Args(0) {
2008-11-26 17:43:45 +00:00
my ( $ self , $ c ) = @ _ ;
2009-04-02 16:15:57 +00:00
$ c - > stash - > { template } = 'overview.tt' ;
2010-06-04 14:43:28 +00:00
$ c - > stash - > { projects } = [ $ c - > model ( 'DB::Projects' ) - > search ( isAdmin ( $ c ) ? { } : { hidden = > 0 } , { order_by = > 'name' } ) ] ;
2010-04-27 13:29:08 +00:00
$ c - > stash - > { newsItems } = [ $ c - > model ( 'DB::NewsItems' ) - > search ( { } , { order_by = > [ 'createtime DESC' ] , rows = > 5 } ) ] ;
2013-10-03 14:50:56 +02:00
$ self - > status_ok ( $ c ,
2013-10-24 16:12:36 -04:00
entity = > $ c - > stash - > { projects }
2013-06-17 12:34:21 -04:00
) ;
2008-10-28 10:19:31 +00:00
}
2013-06-17 12:34:21 -04:00
sub queue :Local :Args(0) :ActionClass('REST') { }
sub queue_GET {
2008-11-26 19:48:04 +00:00
my ( $ self , $ c ) = @ _ ;
2008-11-26 17:43:45 +00:00
$ c - > stash - > { template } = 'queue.tt' ;
2013-02-27 18:33:47 +01:00
$ c - > stash - > { flashMsg } // = $ c - > flash - > { buildMsg } ;
2013-06-17 12:34:21 -04:00
$ self - > status_ok (
$ c ,
2015-10-27 15:37:17 +01:00
entity = > [ $ c - > model ( 'DB::Builds' ) - > search (
{ finished = > 0 } ,
{ order_by = > [ "globalpriority desc" , "id" ] ,
, columns = > [ @ buildListColumns ]
} ) ]
2013-06-17 12:34:21 -04:00
) ;
2008-11-26 17:43:45 +00:00
}
2010-08-31 15:27:46 +00:00
2016-03-08 19:44:51 +01:00
sub queue_summary :Local :Path('queue-summary') :Args(0) {
my ( $ self , $ c ) = @ _ ;
$ c - > stash - > { template } = 'queue-summary.tt' ;
2016-03-16 15:19:18 +01:00
$ c - > stash - > { queued } = dbh ( $ c ) - > selectall_arrayref (
2016-03-08 19:44:51 +01:00
"select project, jobset, count(*) as queued, min(timestamp) as oldest, max(timestamp) as newest from Builds " .
"where finished = 0 group by project, jobset order by queued desc" ,
{ Slice = > { } } ) ;
2016-03-22 17:03:26 +01:00
$ c - > stash - > { systems } = dbh ( $ c ) - > selectall_arrayref (
"select system, count(*) as c from Builds where finished = 0 group by system order by c desc" ,
{ Slice = > { } } ) ;
2016-03-08 19:44:51 +01:00
}
2013-06-17 12:34:21 -04:00
sub status :Local :Args(0) :ActionClass('REST') { }
sub status_GET {
2010-08-31 15:27:46 +00:00
my ( $ self , $ c ) = @ _ ;
2013-06-17 12:34:21 -04:00
$ self - > status_ok (
$ c ,
2015-10-27 15:37:17 +01:00
entity = > [ $ c - > model ( 'DB::Builds' ) - > search (
2016-03-16 15:19:18 +01:00
{ "buildsteps.busy" = > 1 } ,
2015-10-27 15:37:17 +01:00
{ order_by = > [ "globalpriority DESC" , "id" ] ,
join = > "buildsteps" ,
columns = > [ @ buildListColumns ]
} ) ]
2013-06-17 12:34:21 -04:00
) ;
2010-08-31 15:27:46 +00:00
}
2016-02-18 17:11:46 +01:00
sub queue_runner_status :Local :Path('queue-runner-status') :Args(0) :ActionClass('REST') { }
sub queue_runner_status_GET {
my ( $ self , $ c ) = @ _ ;
#my $status = from_json($c->model('DB::SystemStatus')->find('queue-runner')->status);
my $ status = from_json ( `hydra-queue-runner --status` ) ;
if ( $? ) { $ status - > { status } = "unknown" ; }
my $ json = JSON - > new - > pretty ( ) - > canonical ( ) ;
$ c - > stash - > { template } = 'queue-runner-status.tt' ;
$ c - > stash - > { status } = $ json - > encode ( $ status ) ;
$ self - > status_ok ( $ c , entity = > $ status ) ;
}
2013-02-20 16:40:09 +01:00
sub machines :Local Args(0) {
my ( $ self , $ c ) = @ _ ;
2013-03-04 15:37:20 -05:00
my $ machines = getMachines ;
2013-04-23 15:20:24 +02:00
# Add entry for localhost.
2015-09-09 16:51:20 +02:00
$ machines - > { '' } // = { } ;
delete $ machines - > { 'localhost' } ;
my $ status = $ c - > model ( 'DB::SystemStatus' ) - > find ( "queue-runner" ) ;
if ( $ status ) {
my $ ms = decode_json ( $ status - > status ) - > { "machines" } ;
foreach my $ name ( keys % { $ ms } ) {
$ name = "" if $ name eq "localhost" ;
$ machines - > { $ name } // = { disabled = > 1 } ;
$ machines - > { $ name } - > { nrStepsDone } = $ ms - > { $ name } - > { nrStepsDone } ;
$ machines - > { $ name } - > { avgStepBuildTime } = $ ms - > { $ name } - > { avgStepBuildTime } // 0 ;
}
}
2013-04-23 15:20:24 +02:00
2013-03-04 15:37:20 -05:00
$ c - > stash - > { machines } = $ machines ;
2016-03-16 15:19:18 +01:00
$ c - > stash - > { steps } = dbh ( $ c ) - > selectall_arrayref (
"select build, stepnr, s.system as system, s.drvpath as drvpath, machine, s.starttime as starttime, project, jobset, job " .
"from BuildSteps s join Builds b on s.build = b.id " .
"where busy = 1 order by machine, stepnr" ,
{ Slice = > { } } ) ;
2013-02-20 16:40:09 +01:00
$ c - > stash - > { template } = 'machine-status.tt' ;
}
2009-03-04 10:59:14 +00:00
# Hydra::Base::Controller::ListBuilds needs this.
sub get_builds : Chained('/') PathPart('') CaptureArgs(0) {
my ( $ self , $ c ) = @ _ ;
$ c - > stash - > { allBuilds } = $ c - > model ( 'DB::Builds' ) ;
2009-04-03 15:37:21 +00:00
$ c - > stash - > { latestSucceeded } = $ c - > model ( 'DB' ) - > resultset ( 'LatestSucceeded' ) ;
2009-03-04 16:36:23 +00:00
$ c - > stash - > { channelBaseName } = "everything" ;
2013-08-12 20:11:34 +02:00
$ c - > stash - > { total } = $ c - > model ( 'DB::NrBuilds' ) - > find ( 'finished' ) - > count ;
2009-03-04 10:59:14 +00:00
}
2009-03-31 13:48:03 +00:00
sub robots_txt : Path('robots.txt') {
my ( $ self , $ c ) = @ _ ;
2009-03-31 14:14:45 +00:00
sub uri_for {
2013-01-23 12:41:57 +00:00
my ( $ c , $ controller , $ action , @ args ) = @ _ ;
2009-03-31 14:14:45 +00:00
return $ c - > uri_for ( $ c - > controller ( $ controller ) - > action_for ( $ action ) , @ args ) - > path ;
}
sub channelUris {
2013-01-23 12:41:57 +00:00
my ( $ c , $ controller , $ bindings ) = @ _ ;
2009-03-31 14:14:45 +00:00
return
2013-01-23 12:41:57 +00:00
( uri_for ( $ c , $ controller , 'closure' , $ bindings , "*" )
, uri_for ( $ c , $ controller , 'manifest' , $ bindings )
, uri_for ( $ c , $ controller , 'pkg' , $ bindings , "*" )
, uri_for ( $ c , $ controller , 'nixexprs' , $ bindings )
, uri_for ( $ c , $ controller , 'channel_contents' , $ bindings )
2009-03-31 14:14:45 +00:00
) ;
}
2009-03-31 13:48:03 +00:00
# Put actions that are expensive or not useful for indexing in
# robots.txt. Note: wildcards are not universally supported in
# robots.txt, but apparently Google supports them.
my @ rules =
2015-01-13 13:45:39 +01:00
( uri_for ( $ c , 'Build' , 'build' , [ "*" ] )
2013-01-23 12:41:57 +00:00
, uri_for ( $ c , 'Root' , 'nar' , [] , "*" )
, uri_for ( $ c , 'Root' , 'status' , [] )
, uri_for ( $ c , 'Root' , 'all' , [] )
2015-01-13 13:50:13 +01:00
, uri_for ( $ c , 'Root' , 'queue' , [] )
2013-01-23 12:41:57 +00:00
, uri_for ( $ c , 'API' , 'scmdiff' , [] )
, uri_for ( $ c , 'API' , 'logdiff' , [] , "*" , "*" )
, uri_for ( $ c , 'Project' , 'all' , [ "*" ] )
2015-01-13 13:50:13 +01:00
, uri_for ( $ c , 'Jobset' , 'all' , [ "*" , "*" ] )
, uri_for ( $ c , 'Job' , 'all' , [ "*" , "*" , "*" ] )
2013-01-23 12:41:57 +00:00
, channelUris ( $ c , 'Root' , [ "*" ] )
, channelUris ( $ c , 'Project' , [ "*" , "*" ] )
, channelUris ( $ c , 'Jobset' , [ "*" , "*" , "*" ] )
, channelUris ( $ c , 'Job' , [ "*" , "*" , "*" , "*" ] )
2009-03-31 13:48:03 +00:00
) ;
2011-04-01 07:40:06 +00:00
2009-03-31 14:55:47 +00:00
$ c - > stash - > { 'plain' } = { data = > "User-agent: *\n" . join ( '' , map { "Disallow: $_\n" } @ rules ) } ;
2009-03-31 13:48:03 +00:00
$ c - > forward ( 'Hydra::View::Plain' ) ;
}
2011-04-01 07:40:06 +00:00
2008-10-28 10:19:31 +00:00
sub default :Path {
2008-11-26 17:43:45 +00:00
my ( $ self , $ c ) = @ _ ;
2009-02-25 14:34:29 +00:00
notFound ( $ c , "Page not found." ) ;
2009-02-13 17:35:54 +00:00
}
2009-02-25 10:52:41 +00:00
sub end : ActionClass('RenderView') {
my ( $ self , $ c ) = @ _ ;
2013-03-04 15:25:23 +01:00
if ( defined $ c - > stash - > { json } ) {
2014-08-23 16:39:16 +02:00
if ( scalar @ { $ c - > error } ) {
# FIXME: dunno why we need to do decode_utf8 here.
$ c - > stash - > { json } - > { error } = join "\n" , map { decode_utf8 ( $ _ ) ; } @ { $ c - > error } ;
2013-03-04 15:25:23 +01:00
$ c - > clear_errors ;
}
$ c - > forward ( 'View::JSON' ) ;
}
2013-10-03 14:45:23 +02:00
elsif ( scalar @ { $ c - > error } ) {
$ c - > stash - > { resource } = { error = > join "\n" , @ { $ c - > error } } ;
2009-02-25 10:52:41 +00:00
$ c - > stash - > { template } = 'error.tt' ;
2014-08-23 16:39:16 +02:00
$ c - > stash - > { errors } = $ c - > error ;
2013-02-22 14:27:38 +01:00
$ c - > response - > status ( 500 ) if $ c - > response - > status == 200 ;
2009-02-25 16:29:54 +00:00
if ( $ c - > response - > status >= 300 ) {
$ c - > stash - > { httpStatus } =
$ c - > response - > status . " " . HTTP::Status:: status_message ( $ c - > response - > status ) ;
}
2009-02-25 10:52:41 +00:00
$ c - > clear_errors ;
}
2013-06-17 12:34:21 -04:00
2013-07-26 12:04:27 -04:00
$ c - > forward ( 'serialize' ) if defined $ c - > stash - > { resource } ;
2009-02-25 10:52:41 +00:00
}
2008-10-28 10:19:31 +00:00
2013-10-03 14:45:23 +02:00
2013-06-17 12:34:21 -04:00
sub serialize : ActionClass('Serialize') { }
2008-10-28 10:19:31 +00:00
2010-06-22 12:00:19 +00:00
sub nar :Local :Args(1) {
my ( $ self , $ c , $ path ) = @ _ ;
2016-02-26 17:27:30 +01:00
die if $ path =~ /\// ;
2010-06-22 12:00:19 +00:00
2016-02-26 17:27:30 +01:00
my $ storeMode = $ c - > config - > { store_mode } // "direct" ;
2010-06-22 12:00:19 +00:00
2016-02-26 17:27:30 +01:00
if ( $ storeMode eq "s3-binary-cache" ) {
notFound ( $ c , "There is no binary cache here." ) ;
}
elsif ( $ storeMode eq "local-binary-cache" ) {
my $ dir = $ c - > config - > { binary_cache_dir } ;
$ c - > serve_static_file ( $ dir . "/nar/" . $ path ) ;
}
else {
$ path = $ Nix:: Config:: storeDir . "/$path" ;
gone ( $ c , "Path " . $ path . " is no longer available." ) unless isValidPath ( $ path ) ;
$ c - > stash - > { current_view } = 'NixNAR' ;
$ c - > stash - > { storePath } = $ path ;
}
2010-06-22 12:00:19 +00:00
}
2012-07-02 15:18:30 +00:00
2012-07-30 20:26:34 +00:00
sub nix_cache_info :Path('nix-cache-info') :Args(0) {
my ( $ self , $ c ) = @ _ ;
2016-02-26 17:27:30 +01:00
my $ storeMode = $ c - > config - > { store_mode } // "direct" ;
if ( $ storeMode eq "s3-binary-cache" ) {
notFound ( $ c , "There is no binary cache here." ) ;
}
elsif ( $ storeMode eq "local-binary-cache" ) {
my $ dir = $ c - > config - > { binary_cache_dir } ;
$ c - > serve_static_file ( $ dir . "/nix-cache-info" ) ;
}
else {
$ c - > response - > content_type ( 'text/plain' ) ;
$ c - > stash - > { plain } - > { data } =
"StoreDir: $Nix::Config::storeDir\n" .
"WantMassQuery: 0\n" .
# Give Hydra binary caches a very low priority (lower than the
# static binary cache http://nixos.org/binary-cache).
"Priority: 100\n" ;
setCacheHeaders ( $ c , 24 * 60 * 60 ) ;
$ c - > forward ( 'Hydra::View::Plain' ) ;
}
2012-07-30 20:26:34 +00:00
}
2012-07-02 20:09:45 +02:00
sub narinfo :LocalRegex('^([a-z0-9]+).narinfo$') :Args(0) {
2012-07-02 15:18:30 +00:00
my ( $ self , $ c ) = @ _ ;
2013-04-23 15:33:58 +02:00
2016-02-26 17:27:30 +01:00
my $ storeMode = $ c - > config - > { store_mode } // "direct" ;
2013-04-23 15:33:58 +02:00
2016-02-26 17:27:30 +01:00
if ( $ storeMode eq "s3-binary-cache" ) {
notFound ( $ c , "There is no binary cache here." ) ;
2013-04-23 15:33:58 +02:00
}
2013-04-30 16:23:19 +02:00
2016-02-26 17:27:30 +01:00
elsif ( $ storeMode eq "local-binary-cache" ) {
my $ dir = $ c - > config - > { binary_cache_dir } ;
$ c - > serve_static_file ( $ dir . "/" . $ c - > req - > captures - > [ 0 ] . ".narinfo" ) ;
}
else {
my $ hash = $ c - > req - > captures - > [ 0 ] ;
die if length ( $ hash ) != 32 ;
my $ path = queryPathFromHashPart ( $ hash ) ;
if ( ! $ path ) {
$ c - > response - > status ( 404 ) ;
$ c - > response - > content_type ( 'text/plain' ) ;
$ c - > stash - > { plain } - > { data } = "does not exist\n" ;
$ c - > forward ( 'Hydra::View::Plain' ) ;
setCacheHeaders ( $ c , 60 * 60 ) ;
return ;
}
$ c - > stash - > { storePath } = $ path ;
$ c - > forward ( 'Hydra::View::NARInfo' ) ;
}
2012-07-02 15:18:30 +00:00
}
2011-04-18 08:21:27 +00:00
sub logo :Local {
my ( $ self , $ c ) = @ _ ;
2015-07-01 11:34:19 +02:00
my $ path = $ c - > config - > { hydra_logo } // die ( "Logo not set!" ) ;
2011-04-18 08:21:27 +00:00
$ c - > serve_static_file ( $ path ) ;
}
2013-02-21 17:27:17 +01:00
sub evals :Local Args(0) {
my ( $ self , $ c ) = @ _ ;
$ c - > stash - > { template } = 'evals.tt' ;
my $ page = int ( $ c - > req - > param ( 'page' ) || "1" ) || 1 ;
my $ resultsPerPage = 20 ;
my $ evals = $ c - > model ( 'DB::JobsetEvals' ) ;
$ c - > stash - > { page } = $ page ;
$ c - > stash - > { resultsPerPage } = $ resultsPerPage ;
$ c - > stash - > { total } = $ evals - > search ( { hasnewbuilds = > 1 } ) - > count ;
$ c - > stash - > { evals } = getEvals ( $ self , $ c , $ evals , ( $ page - 1 ) * $ resultsPerPage , $ resultsPerPage )
}
2015-07-10 15:08:34 +02:00
sub steps :Local Args(0) {
my ( $ self , $ c ) = @ _ ;
$ c - > stash - > { template } = 'steps.tt' ;
my $ page = int ( $ c - > req - > param ( 'page' ) || "1" ) || 1 ;
my $ resultsPerPage = 20 ;
$ c - > stash - > { page } = $ page ;
$ c - > stash - > { resultsPerPage } = $ resultsPerPage ;
$ c - > stash - > { steps } = [ $ c - > model ( 'DB::BuildSteps' ) - > search (
{ starttime = > { '!=' , undef } ,
stoptime = > { '!=' , undef }
} ,
{ order_by = > [ "stoptime desc" ] ,
rows = > $ resultsPerPage ,
offset = > ( $ page - 1 ) * $ resultsPerPage
} ) ] ;
$ c - > stash - > { total } = approxTableSize ( $ c , "IndexBuildStepsOnStopTime" ) ;
}
2013-02-22 15:45:10 +01:00
sub search :Local Args(0) {
my ( $ self , $ c ) = @ _ ;
$ c - > stash - > { template } = 'search.tt' ;
my $ query = trim $ c - > request - > params - > { "query" } ;
error ( $ c , "Query is empty." ) if $ query eq "" ;
error ( $ c , "Invalid character in query." )
2013-04-25 09:57:30 -04:00
unless $ query =~ /^[a-zA-Z0-9_\-\/.]+$/ ;
2013-02-22 15:45:10 +01:00
2013-02-22 16:41:42 +01:00
$ c - > stash - > { limit } = 500 ;
2013-02-22 15:45:10 +01:00
$ c - > stash - > { projects } = [ $ c - > model ( 'DB::Projects' ) - > search (
2013-02-22 15:56:29 +01:00
{ - and = >
[ { - or = > [ name = > { ilike = > "%$query%" } , displayName = > { ilike = > "%$query%" } , description = > { ilike = > "%$query%" } ] }
, { hidden = > 0 }
]
} ,
2013-02-22 15:45:10 +01:00
{ order_by = > [ "name" ] } ) ] ;
$ c - > stash - > { jobsets } = [ $ c - > model ( 'DB::Jobsets' ) - > search (
2013-02-22 15:56:29 +01:00
{ - and = >
[ { - or = > [ "me.name" = > { ilike = > "%$query%" } , "me.description" = > { ilike = > "%$query%" } ] }
, { "project.hidden" = > 0 , "me.hidden" = > 0 }
]
} ,
{ order_by = > [ "project" , "name" ] , join = > [ "project" ] } ) ] ;
2013-02-22 15:45:10 +01:00
$ c - > stash - > { jobs } = [ $ c - > model ( 'DB::Jobs' ) - > search (
2013-02-22 15:56:29 +01:00
{ "me.name" = > { ilike = > "%$query%" }
, "project.hidden" = > 0
, "jobset.hidden" = > 0
} ,
2013-02-22 16:21:50 +01:00
{ order_by = > [ "enabled_ desc" , "project" , "jobset" , "name" ] , join = > [ "project" , "jobset" ]
2013-04-01 20:18:00 -04:00
, "+select" = > [ \ "(project.enabled = 1 and jobset.enabled = 1 and exists (select 1 from Builds where project = project.name and jobset = jobset.name and job = me.name and iscurrent = 1)) as enabled_" ]
2013-02-22 16:21:50 +01:00
, "+as" = > [ "enabled" ]
2013-02-22 16:41:42 +01:00
, rows = > $ c - > stash - > { limit } + 1
2013-02-22 16:21:50 +01:00
} ) ] ;
2013-04-25 09:57:30 -04:00
2013-04-26 08:51:49 -04:00
# Perform build search in separate queries to prevent seq scan on buildoutputs table.
2013-04-25 09:57:30 -04:00
$ c - > stash - > { builds } = [ $ c - > model ( 'DB::Builds' ) - > search (
2013-04-26 08:51:49 -04:00
{ "buildoutputs.path" = > trim ( $ query ) } ,
2013-04-25 09:57:30 -04:00
{ order_by = > [ "id desc" ] , join = > [ "buildoutputs" ] } ) ] ;
2013-04-26 08:51:49 -04:00
$ c - > stash - > { buildsdrv } = [ $ c - > model ( 'DB::Builds' ) - > search (
{ "drvpath" = > trim ( $ query ) } ,
{ order_by = > [ "id desc" ] } ) ] ;
2013-02-22 15:45:10 +01:00
}
2015-07-10 15:08:34 +02:00
2014-02-19 10:21:59 +00:00
sub log :Local :Args(1) {
my ( $ self , $ c , $ path ) = @ _ ;
$ path = ( $ ENV { NIX_STORE_DIR } || "/nix/store" ) . "/$path" ;
my @ outpaths = ( $ path ) ;
my $ logPath = findLog ( $ c , $ path , @ outpaths ) ;
notFound ( $ c , "The build log of $path is not available." ) unless defined $ logPath ;
2015-07-08 19:04:08 +02:00
$ c - > stash - > { logPath } = $ logPath ;
$ c - > forward ( 'Hydra::View::NixLog' ) ;
2014-02-19 10:21:59 +00:00
}
2013-02-22 15:45:10 +01:00
2008-10-28 10:19:31 +00:00
1 ;