Remove support for views

[?]
Apr 23, 2014, 9:21 PM
YU6CND7C726EDVGK53HYDLVJNKP2WJHC6X2N2ZSEXPUSBO2GZIJAC

Dependencies

  • [2] H3J4HW33 * Don't show the job menu.
  • [3] J4B6EM5R * Allow dots in job names in views.
  • [4] POZRGZOU * Only include the system type in URLs if there are multiple jobs with
  • [5] 4LBNSOFK Propagate URI parameters
  • [6] TV6DJXBP Remove the link for creating views since they're deprecated
  • [7] VG4QG336 Remove tablesorter
  • [8] CJKPW2G7 Hide the views tab for project that don't have them
  • [9] GS4SFHCP templates: Use uri_for to reference static paths.
  • [10] AWMM5OGV Use delete instead of delete_all
  • [11] BXHG3HYL When renaming a jobset, add a redirect from the old name
  • [12] 2VBQRQ2Q Fix some XML well-formedness problems
  • [13] S5PV6IIM * Represent jobs explicitly in the DB.
  • [14] OZ5UBJEK
  • [15] G2WXEQHE Remove the Errors page
  • [16] FV2M6MOT hydra: use autoconf/-make
  • [17] E6IC7YIK * Release sets: need to include the jobset name to disambiguate
  • [18] JTHWA6AM Rename aggregate members to constituents
  • [19] TP3PFR5K
  • [20] EFWN7JBV * Added a status page that shows all the currently executing build steps.
  • [21] BVOPAMLS
  • [22] HZWUT4YN Allow users to reproduce builds on their own systems
  • [23] 64IV56HI Replace bootstrap tarball
  • [24] VCG6KNUX Remove the "clone build" feature
  • [25] G6HJY2V4
  • [26] KU33KNG3 Add a redirect to the evaluation page of a view result
  • [27] NDL67SQT * XHTML validity.
  • [28] ZB3JV52W Add a "My jobsets" tab to the dashboard
  • [29] RU7AQO7U * Role-based access control. Only admins can create projects. Only
  • [30] 4D4U5IPY * Allow jobsets to be disabled.
  • [31] IGNQFFV7 * Put the release sets in the navbar.
  • [32] T2232OBS * Add some DB indices to make the /releases page much faster.
  • [33] BIVZGPUT Optimise clickable rows
  • [34] QTFVCDIF added hide feature for project/jobset
  • [35] JOVVHIJX Remove all entry points to modify machines
  • [36] NEQ4BISO Add bootstrap.zip
  • [37] JD7AWXQG Remove now-unused SystemTypes table
  • [38] 2YXO5ZGQ Hydra/28: Rename "scheduler" to "evaluator"
  • [39] VH5ZABDR Add a page to show the latest evaluations for the entire server
  • [40] KPZNJ33U * In views, support selecting a job that doesn't depend on the
  • [41] Y6AHH4TH Remove the logfile and logSize columns from the database
  • [42] 2G63HKCH Fix some wellformedness issues
  • [43] VBWHG272 Re-add the history tab (store size and build time), now as lazy-loaded tab on build page.
  • [44] AKAZKCR6 * At top-level and for each project, provide two channels: "latest"
  • [45] 3PNG7NIB Remove trailing whitespace
  • [46] UWVMQIAC * Refactoring.
  • [47] X27GNHDV * Basic job info in the database.
  • [48] LQ5QEDVV
  • [49] P5X4P6VK * Renaming "release sets" to "views" (not finished yet). Having
  • [50] FLXJYCRB
  • [51] XJRJ4J7M Add user registration
  • [52] JLDUSNUO * Unify rendering of finished and scheduled builds.
  • [53] LFVXESGI Remove already disabled jobstatus code
  • [54] BHZXGT2H * Channels: provide an index page that lists all the packages in the
  • [55] ZCTGG25S Add a redirect to the latest view result for which the underlying evaluation has finished completely
  • [56] FTPCV25M Store aggregate members in the database
  • [57] D7X6XTKQ Integrate the "Job status" and "All jobs" tabs
  • [58] ODNCGFQ5 * Improved the navigation bar: don't include all projects (since that
  • [59] QQ4STW3S missing file
  • [60] KKJNJHO5 Update bootstrap to 2.0.3
  • [61] S66BOMVU * Added authentication.
  • [62] S6OISBQ3 * Mark the "current" builds in a jobset, i.e. those corresponding to
  • [63] MJ4RWQ3T Add links to the project/jobset edit pages in the logical place
  • [64] 6FRLEP4P first try for timeline of last 24 hours in hydra
  • [65] VJHIHMEH * Store the meta.longDescription and meta.license attributes in the
  • [66] 37R34XJO * Negative caching: don't perform a build if a dependency already
  • [67] 5DSDXORD hydra: missing plain.tt
  • [68] HPEG2RHV Merge the BuildResultInfo table into the Builds table
  • [69] SMCOU72F hydra: add some admin for adding/enabling/etc build machines
  • [70] SZYDW2DG hydra: added some user admin
  • [71] G2T4WAHI Store the inputs of each evaluation in the database
  • [72] PZL3SZM3 Give every page a consistent title
  • [73] R2PON6R7 Allow non-admin users to see the machine status page
  • [74] FD76WVTQ missing file
  • [75] WDKFN4B2 Make sign in a modal dialog box rather than a separate page
  • [76] OX6NYJDV Split viewing and editing a jobset
  • [77] NABL63FI * hydra: project members can do stuff that the owner can do
  • [78] 4BXTDMSA * I should test before committing.
  • [79] ZWCTAZGL added newsitems, added some admin options to clear various caches.
  • [80] UICHT2PS Add a search feature
  • [81] TRDGNILT Remove unused file
  • [82] AK2UZDS2 Jobset page: Add a new tab to show job status in a matrix
  • [83] 3E6IP3R3 * Add the name of the jobset to ReleaseSetJobs, otherwise we can't
  • [84] 4HPT4SDD Revert "Remove now-unused SystemTypes table"
  • [85] 6GEU36HW Remove obsolete CSS classes
  • [86] E7FID72S Remove the BuildMachines and BuildMachinesSystemTypes tables
  • [87] 7Z3YOKCV * PROCESS -> INCLUDE in most cases. INCLUDE does proper scoping of
  • [88] JJT5QG3K remove revision from cached cvs inputs, and added missing files
  • [89] LCKWLQW3 * In Sqlite "release" is now a keyword, so use "release_" instead.
  • [90] LSZLZHJY Allow users to edit their own settings
  • [91] JTRG7RDQ add support for git as jobinput
  • [92] Q5HZWFCY Add support for darcs repositories.
  • [93] WRIU3S5E * UI for cloning builds (not functional yet).
  • [94] 2BUX775I * More release -> view.
  • [95] MWU6FF4K
  • [96] 5QE3TIHP hydra: add status icon per jobset on project page
  • [97] JFZNAYJX * Showing releases.
  • [98] SJN2QPWH * Big speed-up of the job status page and the channel generation (such
  • [99] QL55ECJ6 - adapted ui for hydra, more in line with nixos.org website
  • [100] PKPWUHUX * Idem.
  • [101] D3DIBMOK * For products that are directories (like manuals), allow a default
  • [102] 3HZY24CX * Make jobsets viewable under
  • [103] RI4S7SYT * Job status: show the active jobs.
  • [104] RSEGBU6C Hydra/20: Jobset clone feature
  • [105] JY7BXXOP Split viewing and editing a project
  • [106] YTSIRIMK * Separate job status and all builds pages.
  • [107] QTC3SYBM Jobset page: Load the jobs and status tabs on demand
  • [108] OW6XV2YS * Allow a view result to be saved as a release.
  • [109] US27ZTX5 * HydraFrontend -> Hydra.
  • [110] AKAXJDMW * Disable the statistics on the project, jobset and job pages for now
  • [111] QU5I5GCL
  • [112] FANTYCR7 Materialize the number of finished builds
  • [113] 5IK6NYKF
  • [114] EYNG4EL4 * Regenerate the bindings from a clean sqlite database.
  • [115] DHMTPGST * Ran update-dbix.
  • [116] 3HCBU2FA
  • [117] FPK5LF53 * Put the project-related actions in a separate controller. Put the
  • [118] AS2OXLRM * Editing releases.
  • [119] D5QIOJGP * Move everything up one directory.
  • [120] 6KIJX24R Get rid of unnecessary [%- and -%] tags
  • [121] ECBA3GQO * Make the schema class names match the case of the SQL table names.
  • [122] SHBLLAVH * More global substitution.
  • [123] L2E6EVE2 * Merged the Build and Job tables.
  • [124] 3Y7AFJSS * Support linking to the latest job in a view for a specific platform, e.g.
  • [125] AHTEIK7G * Added a maintainers field to the Builds table.
  • [126] 225GEK4N After editing a project/jobset, redirect back to the config tab
  • [127] 5SHCWE7X * Prevent repeated evaluation of a jobset with the same inputs. This
  • [128] RFE6T5LG * Store jobset evaluations in the database explicitly. This includes
  • [129] U4TD3AIQ Add support for viewing jobset evaluations
  • [130] 36M6DGIT Show the runtime/build dependencies in the build page
  • [131] OR5SJ42Y Show releases in a tab on the project page
  • [132] GNIEG2GC * Disambiguate jobs by jobset name. I.e. jobs with the same name in
  • [133] TWVSALRL * Allow the maximum number of concurrent builds per platform to be
  • [134] V4RNHJNR * Add a link to each project's homepage. Suggested by karltk.
  • [135] SU566LI3 * Sort releases.
  • [136] FHF6IZJQ * Basic release management: releases are now dynamically computed as
  • [137] H5REHM3M
  • [138] KXGOUX7P * Creating releases.
  • [139] 3JBUMW3E forgot to commit a file
  • [140] ZFEN2MAO Simplify jobset cloning
  • [141] JM3DPYOM generated schema with new dbix class schema loader, grrrrrr
  • [142] KSBB33RE Add a dashboard
  • [143] 4X6NS66Q * Keep the most recent builds for each job.
  • [144] 75XUS62Y * Added a page to quickly see all failed builds and failed evaluations
  • [145] ZNFDFJHG * Provide a redirect to the latest successful release in a release set
  • [146] OIUIYIV2 * Give releases a timestamp.
  • [147] BKOIYITR added some json responses
  • [148] TMP2FRIW
  • [149] ZI535LI6 * hydra: 'new' UI for project/jobset/job/build
  • [150] CVWQXYKM use newer icons consistently
  • [151] LZVO64YG Merge in the first bits of the API work
  • [152] ZVTSOVHN * Support Subversion checkouts.
  • [153] W3XAFDK6 Remove obsolete/broken timeline feature
  • [154] WNQRX7QB Doh
  • [155] DEMSSSB2 * Controller for jobs which inherits all actions in ListBuilds. So
  • [156] PPJN6SDP * paging for releases page
  • [157] SB2V735V Keep track of the database schema version
  • [158] MOX7XJ2E Merge the BuildSchedulingInfo table into the Builds table
  • [159] RBNQKATL * Adding persistant releases. A release is a named set of builds.
  • [160] JARRBLZD Bootstrapify the Hydra forms (except the project and jobset edit pages)
  • [161] U72VNKRU Remove unused file
  • [162] J3RYO2CU Remove the jobs status page
  • [163] XDDCO6CH * hydra: add dependency list with links to logfiles
  • [164] OEPUOUNB Using twitter bootstrap for more consistent looks for Hydra
  • [165] 7ECJWNVX Cleanup Project model
  • [166] XBU2ODSP * More renaming.
  • [167] KN3VYE5P * Cleaned up the foreign key constraints.
  • [168] W6DC6K4I * Happy Javascript hacking.
  • [169] H3DLVNCJ * Support redirecting to some job of a release. For instance, this
  • [170] KZAP6QPO
  • [171] SMTMFEKE hydra: add missing templates
  • [172] PHJF4FUT Add missing files
  • [*] 7YBYT2LQ
  • [*] N22GPKYT * Put info about logs / build products in the DB.

Change contents

  • file deletion: View.pm (----------)
    [12.188][12.6120:6151](),[12.6151][12.404:404]()
    package Hydra::Controller::View;
    use strict;
    use warnings;
    use base 'Catalyst::Controller';
    use Hydra::Helper::Nix;
    use Hydra::Helper::CatalystUtils;
    sub getView {
    my ($c, $projectName, $viewName) = @_;
    my $project = $c->model('DB::Projects')->find($projectName);
    notFound($c, "Project $projectName doesn't exist.") if !defined $project;
    $c->stash->{project} = $project;
    (my $view) = $c->model('DB::Views')->find($projectName, $viewName);
    notFound($c, "View $viewName doesn't exist.") if !defined $view;
    $c->stash->{view} = $view;
    (my $primaryJob) = $view->viewjobs->search({isprimary => 1});
    #die "View $viewName doesn't have a primary job." if !defined $primaryJob;
    my $jobs = [$view->viewjobs->search({},
    {order_by => ["isprimary DESC", "job", "attrs"]})];
    $c->stash->{jobs} = $jobs;
    return ($project, $view, $primaryJob, $jobs);
    }
    sub updateView {
    my ($c, $view) = @_;
    my $viewName = trim $c->request->params->{name};
    error($c, "Invalid view name: $viewName")
    unless $viewName =~ /^[[:alpha:]][\w\-]*$/;
    $view->update(
    { name => $viewName
    , description => trim $c->request->params->{description} });
    $view->viewjobs->delete;
    foreach my $param (keys %{$c->request->params}) {
    next unless $param =~ /^job-(\d+)-name$/;
    my $baseName = $1;
    my $name = trim $c->request->params->{"job-$baseName-name"};
    my $description = trim $c->request->params->{"job-$baseName-description"};
    my $attrs = trim $c->request->params->{"job-$baseName-attrs"};
    $name =~ /^([\w\-]+):($jobNameRE)$/ or error($c, "Invalid job name: $name");
    my $jobsetName = $1;
    my $jobName = $2;
    error($c, "Jobset `$jobsetName' doesn't exist.")
    unless $view->project->jobsets->find({name => $jobsetName});
    # !!! We could check whether the job exists, but that would
    # require the evaluator to have seen the job, which may not be
    # the case.
    $view->viewjobs->create(
    { jobset => $jobsetName
    , job => $jobName
    , description => $description
    , attrs => $attrs
    , isprimary => $c->request->params->{"primary"} eq $baseName ? 1 : 0
    });
    }
    error($c, "There must be one primary job.")
    if $view->viewjobs->search({isprimary => 1})->count != 1;
    }
    sub view : Chained('/') PathPart('view') CaptureArgs(2) {
    my ($self, $c, $projectName, $viewName) = @_;
    my ($project, $view, $primaryJob, $jobs) = getView($c, $projectName, $viewName);
    $c->stash->{project} = $project;
    $c->stash->{view} = $view;
    $c->stash->{primaryJob} = $primaryJob;
    $c->stash->{jobs} = $jobs;
    }
    sub view_view : Chained('view') PathPart('') Args(0) {
    my ($self, $c) = @_;
    $c->stash->{template} = 'view.tt';
    my $resultsPerPage = 10;
    my $page = int($c->req->param('page') || "1") || 1;
    my @results = ();
    push @results, getViewResult($_, $c->stash->{jobs}) foreach
    getPrimaryBuildsForView($c->stash->{project}, $c->stash->{primaryJob}, $page, $resultsPerPage);
    $c->stash->{baseUri} = $c->uri_for($self->action_for("view_view"), $c->req->captures);
    $c->stash->{results} = [@results];
    $c->stash->{page} = $page;
    $c->stash->{totalResults} = getPrimaryBuildTotal($c->stash->{project}, $c->stash->{primaryJob});
    $c->stash->{resultsPerPage} = $resultsPerPage;
    }
    sub edit : Chained('view') PathPart('edit') Args(0) {
    my ($self, $c) = @_;
    requireProjectOwner($c, $c->stash->{project});
    $c->stash->{template} = 'edit-view.tt';
    }
    sub submit : Chained('view') PathPart('submit') Args(0) {
    my ($self, $c) = @_;
    requireProjectOwner($c, $c->stash->{project});
    txn_do($c->model('DB')->schema, sub {
    updateView($c, $c->stash->{view});
    });
    $c->res->redirect($c->uri_for($self->action_for("view_view"), $c->req->captures));
    }
    sub latest : Chained('view') PathPart('latest') {
    my ($self, $c, @args) = @_;
    # Redirect to the latest result in the view in which every build
    # is successful.
    my $latest = getLatestSuccessfulViewResult(
    $c->stash->{project}, $c->stash->{primaryJob}, $c->stash->{jobs}, 0);
    error($c, "This view set has no successful results yet.") if !defined $latest;
    $c->res->redirect($c->uri_for($self->action_for("view_view"), $c->req->captures, $latest->id, @args, $c->req->params));
    }
    sub latest_finished : Chained('view') PathPart('latest-finished') {
    my ($self, $c, @args) = @_;
    # Redirect to the latest result in the view in which every build
    # is successful *and* where the jobset evaluation has finished
    # completely.
    my $latest = getLatestSuccessfulViewResult(
    $c->stash->{project}, $c->stash->{primaryJob}, $c->stash->{jobs}, 1);
    error($c, "This view set has no successful results yet.") if !defined $latest;
    $c->res->redirect($c->uri_for($self->action_for("view_view"), $c->req->captures, $latest->id, @args, $c->req->params));
    }
    sub result : Chained('view') PathPart('') {
    my ($self, $c, $id, @args) = @_;
    $c->stash->{template} = 'view-result.tt';
    # Note: we don't actually check whether $id is a primary build,
    # but who cares?
    my $primaryBuild = $c->stash->{project}->builds->find($id)
    or error($c, "Build $id doesn't exist.");
    error($c, "The primary build of this view result did not provide a release name.")
    unless $result->{releasename};
    error($c, "A release named `" . $result->{releasename} . "' already exists.")
    if $c->stash->{project}->releases->find({name => $result->{releasename}});
    my $release;
    txn_do($c->model('DB')->schema, sub {
    $release = $c->stash->{project}->releases->create(
    { name => $result->{releasename}
    , timestamp => time
    });
    foreach my $job (@{$result->{jobs}}) {
    $release->releasemembers->create(
    { build => $job->{build}->id
    , description => $job->{job}->description
    });
    }
    });
    $c->res->redirect($c->uri_for($c->controller('Release')->action_for('view'),
    [$c->stash->{project}->name, $release->name]));
    }
    elsif (scalar @args >= 1 && $args[0] eq "eval") {
    my $eval = $c->stash->{result}->{eval};
    notFound($c, "This view result has no evaluation.") unless defined $eval;
    $c->res->redirect($c->uri_for($c->controller('JobsetEval')->action_for("view"),
    [$eval->id], @args[1..$#args], $c->req->params));
    }
    # Provide a redirect to the specified job of this view result
    # through `http://.../view/$project/$viewName/$viewResult/$jobName'.
    # Optionally, you can append `-$system' to the $jobName to get a
    # build for a specific platform.
    elsif (scalar @args != 0) {
    my $jobName = shift @args;
    my $system;
    if ($jobName =~ /^($jobNameRE)-($systemRE)$/) {
    $jobName = $1;
    $system = $2;
    }
    (my $build, my @others) =
    grep { $_->{job}->job eq $jobName && (!defined $system || ($_->{build} && $_->{build}->system eq $system)) }
    @{$result->{jobs}};
    notFound($c, "View doesn't have a job named ‘$jobName’" . ($system ? " for ‘$system’" : "") . ".")
    unless defined $build;
    error($c, "Job `$jobName' isn't unique.") if @others;
    return $c->res->redirect($c->uri_for($c->controller('Build')->action_for('build'),
    [$build->{build}->id], @args));
    }
    }
    1;
    my $result = getViewResult($primaryBuild, $c->stash->{jobs});
    $c->stash->{result} = $result;
    if (scalar @args == 1 && $args[0] eq "release") {
    requireProjectOwner($c, $c->stash->{project});
    my %jobNames;
    $jobNames{$_->{job}->job}++ foreach @{$result->{jobs}};
    $c->stash->{jobNames} = \%jobNames;
    if (($c->request->params->{submit} || "") eq "delete") {
    $c->stash->{view}->delete;
    $c->res->redirect($c->uri_for($c->controller('Project')->action_for('project'),
    [$c->stash->{project}->name]));
    }
  • edit in src/lib/Hydra/Controller/Project.pm at line 32
    [12.4557][12.341:402]()
    $c->stash->{views} = [$c->stash->{project}->views->all];
  • edit in src/lib/Hydra/Controller/Project.pm at line 174
    [12.2][12.2:4](),[12.4][12.20878:20968](),[12.20968][12.89:166](),[12.89][12.89:166](),[12.166][12.2244:2245](),[12.2245][12.171:219](),[12.171][12.171:219]()
    sub create_view_submit : Chained('projectChain') PathPart('create-view/submit') Args(0) {
    my ($self, $c) = @_;
    requireProjectOwner($c, $c->stash->{project});
    my $viewName = $c->request->params->{name};
  • edit in src/lib/Hydra/Controller/Project.pm at line 175
    [12.220][12.220:536]()
    my $view;
    txn_do($c->model('DB')->schema, sub {
    # Note: $viewName is validated in updateView, which will abort
    # the transaction if the name isn't valid.
    $view = $c->stash->{project}->views->create({name => $viewName});
    Hydra::Controller::View::updateView($c, $view);
    });
  • edit in src/lib/Hydra/Controller/Project.pm at line 176
    [12.537][12.537:673](),[12.673][12.9369:9371](),[12.773][12.9369:9371](),[12.1097][12.9369:9371](),[12.9369][12.9369:9371](),[12.9371][12.674:675](),[12.675][12.9371:9372](),[12.9371][12.9371:9372](),[12.9372][12.20969:21045](),[12.21045][12.747:772](),[12.747][12.747:772](),[12.772][12.9372:9373](),[12.9372][12.9372:9373](),[12.9373][12.773:898](),[12.116][12.0:4](),[12.200][12.0:4]()
    $c->res->redirect($c->uri_for($c->controller('View')->action_for('view_view'),
    [$c->stash->{project}->name, $view->name]));
    }
    sub create_view : Chained('projectChain') PathPart('create-view') Args(0) {
    my ($self, $c) = @_;
    requireProjectOwner($c, $c->stash->{project});
    $c->stash->{template} = 'edit-view.tt';
    $c->stash->{create} = 1;
    }
  • file deletion: ReleaseSetJobs.pm (----------)ReleaseSetJobs.pm (----------)Releasesetjobs.pm (----------)ViewJobs.pm (----------)
    [12.477][12.974:1015](),[12.1015][12.5076:5076](),[12.207][12.3202:3243](),[12.3243][12.5076:5076](),[12.207][12.6308:6349](),[12.6349][12.5076:5076](),[12.477][12.8761:8796](),[12.8796][12.5076:5076]()
    use utf8;
    package Hydra::Schema::ViewJobs;
    # Created by DBIx::Class::Schema::Loader
    # DO NOT MODIFY THE FIRST PART OF THIS FILE
    =head1 NAME
    Hydra::Schema::ViewJobs
    =cut
    use strict;
    use warnings;
    use base 'DBIx::Class::Core';
    =head1 COMPONENTS LOADED
    =over 4
    =item * L<Hydra::Component::ToJSON>
    =back
    =cut
    __PACKAGE__->load_components("+Hydra::Component::ToJSON");
    =head1 TABLE: C<ViewJobs>
    =cut
    __PACKAGE__->table("ViewJobs");
    =head1 ACCESSORS
    =head2 project
    data_type: 'text'
    is_foreign_key: 1
    is_nullable: 0
    =head2 view_
    data_type: 'text'
    is_foreign_key: 1
    is_nullable: 0
    =head2 job
    data_type: 'text'
    is_nullable: 0
    =head2 attrs
    data_type: 'text'
    is_nullable: 0
    =head2 isprimary
    data_type: 'integer'
    default_value: 0
    is_nullable: 0
    =head2 description
    data_type: 'text'
    is_nullable: 1
    =head2 jobset
    data_type: 'text'
    is_nullable: 0
    =head2 autorelease
    data_type: 'integer'
    default_value: 0
    is_nullable: 0
    =cut
    __PACKAGE__->add_columns(
    "project",
    { data_type => "text", is_foreign_key => 1, is_nullable => 0 },
    "view_",
    { data_type => "text", is_foreign_key => 1, is_nullable => 0 },
    "job",
    { data_type => "text", is_nullable => 0 },
    "attrs",
    { data_type => "text", is_nullable => 0 },
    "isprimary",
    { data_type => "integer", default_value => 0, is_nullable => 0 },
    "description",
    { data_type => "text", is_nullable => 1 },
    "jobset",
    { data_type => "text", is_nullable => 0 },
    "autorelease",
    { data_type => "integer", default_value => 0, is_nullable => 0 },
    );
    =head1 PRIMARY KEY
    =over 4
    =item * L</project>
    =item * L</view_>
    =item * L</job>
    =item * L</attrs>
    =back
    =cut
    __PACKAGE__->set_primary_key("project", "view_", "job", "attrs");
    =head1 RELATIONS
    =head2 project
    Type: belongs_to
    Related object: L<Hydra::Schema::Projects>
    =cut
    __PACKAGE__->belongs_to(
    "project",
    "Hydra::Schema::Projects",
    { name => "project" },
    { is_deferrable => 0, on_delete => "CASCADE", on_update => "CASCADE" },
    );
    =head2 view
    Type: belongs_to
    Related object: L<Hydra::Schema::Views>
    =cut
    __PACKAGE__->belongs_to(
    "view",
    "Hydra::Schema::Views",
    { name => "view_", project => "project" },
    { is_deferrable => 0, on_delete => "CASCADE", on_update => "CASCADE" },
    );
    # Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-06-13 01:54:50
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hz912vBfYw0rHslBPqJW2w
    1;
  • file deletion: ReleaseSets.pm (----------)ReleaseSets.pm (----------)Releasesets.pm (----------)Views.pm (----------)
    [12.477][12.1015:1053](),[12.1053][12.6351:6351](),[12.207][12.3459:3497](),[12.3497][12.6351:6351](),[12.207][12.7380:7418](),[12.7418][12.6351:6351](),[12.477][12.9271:9303](),[12.9303][12.6351:6351]()
    use utf8;
    package Hydra::Schema::Views;
    # Created by DBIx::Class::Schema::Loader
    # DO NOT MODIFY THE FIRST PART OF THIS FILE
    =head1 NAME
    Hydra::Schema::Views
    =cut
    use strict;
    use warnings;
    use base 'DBIx::Class::Core';
    =head1 COMPONENTS LOADED
    =over 4
    =item * L<Hydra::Component::ToJSON>
    =back
    =cut
    __PACKAGE__->load_components("+Hydra::Component::ToJSON");
    =head1 TABLE: C<Views>
    =cut
    __PACKAGE__->table("Views");
    =head1 ACCESSORS
    =head2 project
    data_type: 'text'
    is_foreign_key: 1
    is_nullable: 0
    =head2 name
    data_type: 'text'
    is_nullable: 0
    =head2 description
    data_type: 'text'
    is_nullable: 1
    =head2 keep
    data_type: 'integer'
    default_value: 0
    is_nullable: 0
    =cut
    __PACKAGE__->add_columns(
    "project",
    { data_type => "text", is_foreign_key => 1, is_nullable => 0 },
    "name",
    { data_type => "text", is_nullable => 0 },
    "description",
    { data_type => "text", is_nullable => 1 },
    "keep",
    { data_type => "integer", default_value => 0, is_nullable => 0 },
    );
    =head1 PRIMARY KEY
    =over 4
    =item * L</project>
    =item * L</name>
    =back
    =cut
    __PACKAGE__->set_primary_key("project", "name");
    =head1 RELATIONS
    =head2 project
    Type: belongs_to
    Related object: L<Hydra::Schema::Projects>
    =cut
    __PACKAGE__->belongs_to(
    "project",
    "Hydra::Schema::Projects",
    { name => "project" },
    { is_deferrable => 0, on_delete => "CASCADE", on_update => "CASCADE" },
    );
    =head2 viewjobs
    Type: has_many
    Related object: L<Hydra::Schema::ViewJobs>
    =cut
    __PACKAGE__->has_many(
    "viewjobs",
    "Hydra::Schema::ViewJobs",
    { "foreign.project" => "self.project", "foreign.view_" => "self.name" },
    undef,
    );
    # Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-06-13 01:54:50
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:U23GZ3k5KZk2go6j2LYLHA
    1;
  • edit in src/lib/Hydra/Schema/Projects.pm at line 255
    [12.2269][12.2269:2322](),[12.2322][12.25357:25373](),[12.21131][12.25357:25373](),[12.25373][12.21153:21170](),[12.21153][12.21153:21170](),[12.21170][12.25374:25417](),[12.25417][12.21219:21226](),[12.21219][12.21219:21226](),[12.21226][12.2375:2398](),[12.2375][12.2375:2398](),[12.2398][12.25418:25461](),[12.2453][12.2341:2381](),[12.3058][12.2341:2381](),[12.3585][12.2341:2381](),[12.4931][12.2341:2381](),[12.8176][12.2341:2381](),[12.25461][12.2341:2381](),[12.3640][12.2341:2381](),[12.2381][12.7124:7133](),[12.7133][12.2381:2384](),[12.25468][12.2381:2384](),[12.2381][12.2381:2384](),[12.2384][12.21227:21228](),[12.21228][12.25469:25482](),[12.5159][12.21253:21270](),[12.25482][12.21253:21270](),[12.21253][12.21253:21270](),[12.21270][12.25483:25523](),[12.5206][12.21322:21329](),[12.25523][12.21322:21329](),[12.21322][12.21322:21329](),[12.21329][12.1739:1762](),[12.2384][12.1739:1762](),[12.1762][12.25524:25561]()
    { "foreign.project" => "self.name" },
    undef,
    );
    =head2 viewjobs
    Type: has_many
    Related object: L<Hydra::Schema::ViewJobs>
    =cut
    __PACKAGE__->has_many(
    "viewjobs",
    "Hydra::Schema::ViewJobs",
    { "foreign.project" => "self.name" },
    undef,
    );
    =head2 views
    Type: has_many
    Related object: L<Hydra::Schema::Views>
    =cut
    __PACKAGE__->has_many(
    "views",
    "Hydra::Schema::Views",
  • replacement in src/lib/Hydra/Schema/Projects.pm at line 270
    [12.7308][11.3219:3361]()
    # Created by DBIx::Class::Schema::Loader v0.07033 @ 2014-04-23 22:48:21
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:l8eN9UAavdqnL7Sjv4rmFw
    [12.7308]
    [12.171]
    # Created by DBIx::Class::Schema::Loader v0.07033 @ 2014-04-23 23:13:08
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:fkd9ruEoVSBGIktmAj4u4g
  • file deletion: release.tt (----------)view-result.tt (----------)release.tt (----------)
    [12.1486][12.1983:2017](),[12.2017][12.7246:7246](),[12.1486][12.3086:3124](),[12.3124][12.7246:7246](),[12.857][12.8294:8328](),[12.8328][12.7246:7246]()
    [% releaseName = (result.releasename || "(No name)") %]
    [% WRAPPER layout.tt title="View $releaseName" %]
    [% PROCESS common.tt %]
    [% PROCESS "product-list.tt" %]
    [% USE HTML %]
    <p><em>Finished building on [% INCLUDE renderDateTime timestamp = result.timestamp %].</em></p>
    [% IF result.status == 1 %]
    <p class="error">Note: One or more of the jobs in the view did not build correctly. See below for details.</p>
    [% ELSIF result.status == 2 %]
    <p class="error">Note: One or more of the jobs in the view have not been built (yet). See below for details.</p>
    [% END %]
    [% FOREACH j IN result.jobs %]
    <h2>
    [% IF j.build %]<a href="[% c.uri_for('/build' j.build.id) %]">[% END %]
    [% INCLUDE renderViewJobName job=j.job %]
    [% IF j.build %]</a>[% END %]
    </h2>
    [% IF j.build %]
    [% IF j.build.buildstatus == 0 %]
    [% IF j.build.buildproducts %]
    [% p = jobNames.${j.job.job} > 1 ? "-${j.build.system}" : "";
    INCLUDE renderProductList build=j.build latestRoot=['/view' project.name view.name 'latest' "${j.job.job}${p}"]
    %]
    [% ELSE %]
    <p><em>Succeeded.</em></p>
    [% END %]
    [% ELSE %]
    <p class="error">Build failed</p>
    [% END %]
    [% ELSE %]
    <p class="error">Build not (yet) performed.</p>
    [% END %]
    <br />
    [% END %]
    [% END %]
    [% IF c.user_exists %]
    <p>
    <a class="btn" href="[% c.uri_for('/view' project.name view.name result.id 'release') %]">Release</a>
    </p>
    [% END %]
  • file deletion: edit-releaseset.tt (----------)edit-releaseset.tt (----------)edit-view.tt (----------)
    [12.1486][12.1641:1683](),[12.1683][12.1873:1873](),[12.857][12.2739:2781](),[12.2781][12.1873:1873](),[12.1486][12.9775:9811](),[12.9811][12.1873:1873]()
    [% WRAPPER layout.tt title=(create ? "New view" : "View $project.name:$view.name") %]
    [% PROCESS common.tt %]
    [% USE HTML %]
    [% BLOCK renderJob %]
    <tr id="[% id %]" >
    <td>
    <button type="button" class="btn btn-warning" onclick='$(this).parents("tr").remove()'>
    <i class="icon-trash icon-white"></i>
    </button>
    </td>
    <td><input type="radio" id="[% "$baseName-primary" %]" name="primary" [% IF job.isprimary %]
    checked="checked" [% END %] [% HTML.attributes(value => "$n") %] /></td>
    <td><input type="text" class="string" [% HTML.attributes(id => "$baseName-name", name => "$baseName-name", value => "$job.jobset:$job.job") %] /></td>
    <td><input type="text" class="string" [% HTML.attributes(id => "$baseName-description", name => "$baseName-description", value => job.description) %] /></td>
    <td><input type="text" class="string" [% HTML.attributes(id => "$baseName-attrs", name => "$baseName-attrs", value => job.attrs) %] /></td>
    </tr>
    [% END %]
    <form class="form-horizontal" action="[% IF create %][% c.uri_for('/project' project.name 'create-view/submit') %][% ELSE %][% c.uri_for('/view' project.name view.name 'submit') %][% END %]" method="post">
    <fieldset>
    <div class="control-group">
    <label class="control-label">Identifier</label>
    <div class="controls">
    <input type="text" class="span3" name="name" [% HTML.attributes(value => view.name) %]/>
    </div>
    </div>
    <div class="control-group">
    <label class="control-label">Description</label>
    <div class="controls">
    <input type="text" class="span3" name="description" [% HTML.attributes(value => view.description) %]/>
    </div>
    </div>
    <table class="table table-condensed table-striped">
    <thead>
    <tr>
    <th></th>
    <th>Primary job</th>
    <th>Job name</th>
    <th>Description</th>
    <th>Constraint</th>
    </tr>
    </thead>
    <tbody>
    [% n = 0 %]
    [% FOREACH j IN jobs %]
    [% INCLUDE renderJob baseName="job-$n" job=j %]
    [% n = n + 1 %]
    [% END %]
    </tbody>
    </table>
    <div class="form-actions">
    <button type="submit" class="btn btn-primary">
    <i class="icon-ok icon-white"></i>
    [%IF create %]Create[% ELSE %]Apply changes[% END %]
    </button>
    [% IF !create %]
    <button id="delete-view" type="submit" class="btn btn-danger" name="submit" value="delete">
    <i class="icon-trash icon-white"></i>
    Delete this view
    </button>
    <script type="text/javascript">
    $("#delete-view").click(function() {
    return confirm("Are you sure you want to delete this view?");
    });
    </script>
    [% END %]
    </div>
    </form>
    <table class="template"> <!-- dummy wrapper needed because “hidden” trs are visible anyway -->
    [% INCLUDE renderJob job="" id="job-template" baseName="job-template" %]
    </table>
    <script type="text/javascript">
    $(document).ready(function() {
    var id = [% n %];
    $(".add-job").click(function() {
    var newnr = id++;
    var newid = "job-" + newnr;
    var x = $("#job-template").clone(true).attr("id", "").insertBefore($(this).parents("tr")).show();
    $("#job-template-name", x).attr("name", newid + "-name");
    $("#job-template-description", x).attr("name", newid + "-description");
    $("#job-template-attrs", x).attr("name", newid + "-attrs");
    $("#job-template-primary", x).attr("value", newnr);
    return false;
    });
    });
    </script>
    [% END %]
    <tr>
    <td colspan="5" style="text-align: center;"><button type="button" class="add-job btn btn-success"><i class="icon-plus icon-white"></i> Add a job</button></td>
    </tr>
  • file deletion: releases.tt (----------)releases.tt (----------)view.tt (----------)
    [12.1486][12.2017:2052](),[12.2052][12.8435:8435](),[12.857][12.10063:10098](),[12.10098][12.8435:8435](),[12.1486][12.11158:11189](),[12.11189][12.8435:8435]()
    [% WRAPPER layout.tt title="View $view.project.name:$view.name" %]
    [% PROCESS common.tt %]
    [% USE HTML %]
    <p>
    <a class="btn" href="[% c.uri_for('/view' project.name view.name "edit") %]"><i class="icon-edit"></i> Edit</a>
    <a class="btn" href="[% c.uri_for('/view' project.name view.name "latest") %]"><i class="icon-share-alt"></i> Latest</a>
    </p>
    <p>Showing results [% (page - 1) * resultsPerPage + 1 %] - [% (page - 1) * resultsPerPage + results.size %] out of [% totalResults %].</p>
    <table class="table table-condensed table-striped clickable-rows">
    <thead>
    <tr>
    <th></th>
    <th>#</th>
    <th>Name</th>
    <th>Date</th>
    [% FOREACH j IN jobs %]
    <th class="releaseSetJobName">[% INCLUDE renderViewJobName job=j %]</th>
    [% END %]
    </tr>
    </thead>
    <tbody>
    [% FOREACH result IN results %]
    <tr>
    <td>
    [% IF result.status == 0 %]
    <img src="[% c.uri_for("/static/images/checkmark_16.png") %]" />
    [% ELSIF result.status == 1 %]
    <img src="[% c.uri_for("/static/images/error_16.png") %]" />
    [% ELSIF result.status == 2 %]
    <img src="[% c.uri_for("/static/images/help_16.png") %]" />
    [% END %]
    </td>
    <td><a class="row-link" href="[% c.uri_for('/view' project.name view.name result.id) %]">[% result.id %]</a></td>
    <td>
    [% IF result.releasename %]
    <tt>[% result.releasename %]</tt>
    [% ELSE %]
    <em>No name</em>
    [% END %]
    </td>
    <td>[% INCLUDE renderDateTime timestamp=result.timestamp %]</td>
    [% FOREACH j IN result.jobs %]
    <td class="centered">
    [% IF j.build %]
    <a href="[% c.uri_for('/build' j.build.id) %]">
    [% IF j.build.get_column('buildstatus') == 0 %]
    <img src="[% c.uri_for("/static/images/checkmark_16.png") %]" />
    [% ELSE %]
    <img src="[% c.uri_for("/static/images/error_16.png") %]" />
    [% END %]
    </a>
    [% END %]
    </td>
    [% END %]
    </tr>
    [% END %]
    </tbody>
    </table>
    [% END %]
    <ul class="pager">
    [% IF page > 1 %]
    <li class="previous"><a href="[% "$baseUri?page="; (page - 1) %]">Prev</a></li>
    [% END %]
    [% IF page * resultsPerPage < totalResults %]
    <li class="next"><a href="[% "$baseUri?page="; (page + 1) %]">Next</a></li>
    [% END %]
    </ul>
    <!--
    [<a href="[% "$baseUri?page=1" %]">First</a>]
    [% IF page > 1 %]
    [<a href="[% "$baseUri?page="; (page - 1) %]">Prev</a>]
    [% END %]
    [% IF page * resultsPerPage < totalResults %]
    [<a href="[% "$baseUri?page="; (page + 1) %]">Next</a>]
    [% END %]
    [<a href="[% "$baseUri?page="; (totalResults - 1) div resultsPerPage + 1 %]">Last</a>]
    </p>
    -->
    <p>
  • edit in src/root/project.tt at line 23
    [12.270][8.0:101]()
    [% IF views.size > 0 %]
    <li><a href="#tabs-views" data-toggle="tab">Views</a></li>
    [% END %]
  • edit in src/root/project.tt at line 98
    [12.1285][12.1285:1286](),[12.1286][12.6555:6596](),[12.3197][12.6555:6596](),[12.6596][12.35872:35873](),[12.35872][12.35872:35873](),[12.35873][12.6597:6625](),[12.6625][12.35951:35952](),[12.35951][12.35951:35952](),[12.35952][12.6626:6700]()
    <div id="tabs-views" class="tab-pane">
    [% IF views.size > 0 %]
    <p>Project <tt>[% project.name %]</tt> has the following views:</p>
  • edit in src/root/project.tt at line 99
    [12.36041][12.6701:6862](),[12.6969][12.6969:7015](),[12.7015][12.36133:36134](),[12.36133][12.36133:36134](),[12.36134][12.7016:7031](),[12.7031][12.36468:36469](),[12.36468][12.36468:36469](),[12.36469][12.7032:7095](),[12.7095][12.36504:36505](),[12.36504][12.36504:36505](),[12.36505][12.7096:7110](),[12.7110][12.36586:36587](),[12.36586][12.36586:36587](),[12.36587][6.0:9](),[6.9][12.7111:7259](),[12.36587][12.7111:7259](),[12.7259][6.10:18](),[6.18][12.36621:36622](),[12.7259][12.36621:36622](),[12.36621][12.36621:36622](),[12.36622][12.7260:7269](),[12.7269][12.36728:36729](),[12.15789][12.36728:36729]()
    <ul>
    [% FOREACH view IN views %]
    <li>
    <a href="[% c.uri_for('/view' project.name view.name) %]"><tt>[% view.name %]</tt></a>
    </li>
    [% END %]
    </ul>
    [% ELSE %]
    <p>Project <tt>[% project.name %]</tt> has no views.</p>
    [% END %]
    <!--
    <p>
    <a class="btn" href="[% c.uri_for('/project' project.name 'create-view') %]"><i class="icon-plus"></i> Create a new view</a>
    </p>
    -->
    </div>
  • edit in src/sql/hydra.sql at line 372
    [12.1226][12.5737:5742](),[12.5737][12.5737:5742](),[12.11276][12.12568:12983](),[12.12983][12.12110:12176](),[12.12110][12.12110:12176](),[12.12176][12.37625:37626](),[12.37626][12.12181:12206](),[12.12181][12.12181:12206](),[12.12206][12.12984:13052](),[12.13052][12.37627:37673](),[12.37673][12.12352:12388](),[12.12352][12.12352:12388](),[12.12388][12.8350:8440]()
    );
    -- Views are a mechanism to automatically group related builds
    -- together. A view definition consists of a build of some "primary"
    -- job, plus all builds of the other jobs named in ViewJobs that have
    -- that build as an input. If there are multiple builds matching a
    -- ViewJob, then we take the oldest successful build, or the oldest
    -- unsuccessful build if there is no successful build.
    create table Views (
    project text not null,
    name text not null,
    description text,
    -- If true, don't garbage-collect builds included in this view.
    keep integer not null default 0,
    primary key (project, name),
    foreign key (project) references Projects(name) on delete cascade on update cascade
  • edit in src/sql/hydra.sql at line 375
    [12.3211][12.13340:13364](),[12.13364][12.12702:12735](),[12.12702][12.12702:12735](),[12.12735][12.13365:13398](),[12.3218][12.12768:13012](),[12.13398][12.12768:13012](),[12.12768][12.12768:13012](),[12.13012][12.13399:13501](),[12.13501][12.13125:13171](),[12.13125][12.13125:13171](),[12.13171][12.37674:37675](),[12.37675][12.13223:13247](),[12.13223][12.13223:13247](),[12.13247][12.37676:37677](),[12.37677][12.6014:6047](),[12.13252][12.6014:6047](),[12.6047][12.13502:13761](),[12.13761][12.37678:37679](),[12.37679][12.13762:13810](),[12.6052][12.13762:13810](),[12.13810][12.8441:8635](),[12.3386][12.13510:13513](),[12.6163][12.13510:13513](),[12.8635][12.13510:13513](),[12.13510][12.13510:13513](),[12.13513][12.4185:4187]()
    create table ViewJobs (
    project text not null,
    view_ text not null,
    job text not null,
    -- A constraint on the job consisting of `name=value' pairs,
    -- e.g. "system=i686-linux officialRelease=true". Should really
    -- be a separate table but I'm lazy.
    attrs text not null,
    -- If set, this is the primary job for the view. There can be
    -- only one such job per view.
    isPrimary integer not null default 0,
    description text,
    jobset text not null,
    -- If set, once there is a successful build for every job
    -- associated with a build of the view's primary job, that set of
    -- builds is automatically added as a release to the Releases
    -- table.
    autoRelease integer not null default 0,
    primary key (project, view_, job, attrs),
    foreign key (project) references Projects(name) on delete cascade on update cascade,
    foreign key (project, view_) references Views(project, name) on delete cascade on update cascade
    );
  • file addition: upgrade-27.sql (----------)
    [12.3004]
    drop table ViewJobs;
    drop table Views;