* Renaming "release sets" to "views" (not finished yet). Having
[?]
Oct 15, 2009, 9:35 PM
P5X4P6VKS5CJOOLJRVL66GRJLDLVC3EKAVAHP2RJOXQJ7WTYAUBQCDependencies
- [2]
HKWIDRO6* I love untyped databases... - [3]
H3DLVNCJ* Support redirecting to some job of a release. For instance, this - [4]
M57TEWF5* Fixed a broken redirect when deleting a release set. - [5]
4D4U5IPY* Allow jobsets to be disabled. - [6]
PPJN6SDP* paging for releases page - [7]
EYNG4EL4* Regenerate the bindings from a clean sqlite database. - [8]
4X6NS66Q* Keep the most recent builds for each job. - [9]
67P45PY4 - [10]
L2E6EVE2* Merged the Build and Job tables. - [11]
KOTB7BKV - [12]
WYN733ST* Store build duration, handle cached builds. - [13]
BVOPAMLS - [14]
VCOSLZRP - [15]
7LKUAIGC - [16]
BD3GRK4B* Get rid of "positive failures" and separate log phases. - [17]
V4RNHJNR* Add a link to each project's homepage. Suggested by karltk. - [18]
ECBA3GQO* Make the schema class names match the case of the SQL table names. - [19]
KFFNFE4D - [20]
CMU3YKOU* Store the release name. - [21]
K5BEBWKM - [22]
FPK5LF53* Put the project-related actions in a separate controller. Put the - [23]
AFTXA575* $HYDRA_DATA environment variable. - [24]
NDL67SQT* XHTML validity. - [25]
PHX2HIVG* Store info about the build inputs in the build record. - [26]
B72GLND4 - [27]
LQ5QEDVV - [28]
QU5I5GCL - [29]
HJLYC753* Adding input value alternatives. - [30]
YTZOC7C5* Editing of jobset inputs. - [31]
OIUIYIV2* Give releases a timestamp. - [32]
ZNFDFJHG* Provide a redirect to the latest successful release in a release set - [33]
M552HLIA* Support variant builds. - [34]
A52HEFHQ* Allow builds to be restarted (if they failed with a transient error, - [35]
7Z3YOKCV* PROCESS -> INCLUDE in most cases. INCLUDE does proper scoping of - [36]
UVMFS73T* Some jQuery / CSS hackery. - [37]
J5UVLXOK* Start of a basic Catalyst web interface. - [38]
E6IC7YIK* Release sets: need to include the jobset name to disambiguate - [39]
6ULJO5NI* Urgh. `-' had special significance in HTML form parameters... - [40]
T2232OBS* Add some DB indices to make the /releases page much faster. - [41]
YAPITGB3* Boolean inputs. - [42]
LZO3C2KI* Hack around those SQLite timeouts: just retry the transaction. - [43]
SJLEZFC4check getHydraPath in stead of Envvar HYDRA_DBI directly - [44]
S6OISBQ3* Mark the "current" builds in a jobset, i.e. those corresponding to - [45]
5NO7NCKT* Refactoring. - [46]
GCHNNFZP - [47]
7ZSVXUGFsequence fix for postgresql - [48]
ZVTSOVHN* Support Subversion checkouts. - [49]
R5D7DZPE - [50]
AHTEIK7G* Added a maintainers field to the Builds table. - [51]
X27GNHDV* Basic job info in the database. - [52]
VJHIHMEH* Store the meta.longDescription and meta.license attributes in the - [53]
7YBYT2LQ - [54]
SHBLLAVH* More global substitution. - [55]
3ZCEPLNO - [56]
FHF6IZJQ* Basic release management: releases are now dynamically computed as - [57]
RU7AQO7U* Role-based access control. Only admins can create projects. Only - [58]
3E6IP3R3* Add the name of the jobset to ReleaseSetJobs, otherwise we can't - [59]
LCKWLQW3* In Sqlite "release" is now a keyword, so use "release_" instead. - [60]
BHZXGT2H* Channels: provide an index page that lists all the packages in the - [61]
S5PV6IIM* Represent jobs explicitly in the DB. - [62]
JLDUSNUO* Unify rendering of finished and scheduled builds. - [63]
D5QIOJGP* Move everything up one directory. - [64]
CLJQCY2X* Store info about all the build actions and allow them to be - [65]
37R34XJO* Negative caching: don't perform a build if a dependency already - [66]
ODNCGFQ5* Improved the navigation bar: don't include all projects (since that - [67]
YTSIRIMK* Separate job status and all builds pages. - [68]
W6DC6K4I* Happy Javascript hacking. - [69]
IK53RV4V - [70]
2AUODJBT - [71]
DVNWJXWW* Generic declaration of build products. - [72]
TWVSALRL* Allow the maximum number of concurrent builds per platform to be - [73]
IGNQFFV7* Put the release sets in the navbar. - [74]
GNIEG2GC* Disambiguate jobs by jobset name. I.e. jobs with the same name in - [75]
TLZ2SPBR - [76]
H7CNGK4O* Log evaluation errors etc. in the DB. - [77]
UWVMQIAC* Refactoring. - [78]
G6HJY2V4 - [79]
H5REHM3M - [80]
DEMSSSB2* Controller for jobs which inherits all actions in ListBuilds. So - [81]
VSVQIXAA* Allow `-' in release set names. - [82]
S66BOMVU* Added authentication. - [83]
5ZHSCNLJ - [84]
PBFZEQLZ - [85]
6BLUKEQ2* Caching of "path" inputs, and fake a revision number for those. - [86]
IN272KZW* Automatically keep all builds in the latest successful release in - [87]
ZEHSSVFG - [88]
DR4F6YUT - [89]
2AIIYGI5* Show job status and all builds for a project. - [90]
GWCV3TQV* BuildInputs table: link to dependencies, include store paths. - [91]
5IK6NYKF - [92]
NLJJZVHO* Use ->update({...}) properly. - [93]
JFZNAYJX* Showing releases. - [94]
D3DIBMOK* For products that are directories (like manuals), allow a default - [95]
75XUS62Y* Added a page to quickly see all failed builds and failed evaluations - [96]
TMP2FRIW - [97]
TQKGQ5R3 - [*]
UUGBVEGY* Development notes. - [*]
2GK5DOU7* Downloading closures. - [*]
N22GPKYT* Put info about logs / build products in the DB.
Change contents
- edit in doc/dev-notes.txt at line 99
# Releases -> Views.alter table ReleaseSets rename to Views;alter table Views rename column name to view_;alter table ReleaseSetJobs rename to ViewJobs;alter table ViewJobs rename column release_ to view_;alter table ViewJobs drop column mayFail;alter table ViewJobs add column autorelease integer not null default 0; - replacement in src/lib/Hydra/Controller/Project.pm at line 27
$c->stash->{releaseSets} = [$c->stash->{project}->releasesets->all];$c->stash->{views} = [$c->stash->{project}->views->all]; - edit in src/lib/Hydra/Controller/Root.pm at line 63[7.821]→[7.53:57](∅→∅),[7.540]→[7.0:20](∅→∅),[7.20]→[7.0:49](∅→∅),[7.49]→[7.66:71](∅→∅),[7.66]→[7.66:71](∅→∅),[7.71]→[7.540:605](∅→∅),[7.540]→[7.540:605](∅→∅),[7.605]→[7.465:543](∅→∅),[7.543]→[7.1136:1173](∅→∅),[7.140]→[7.1136:1173](∅→∅),[7.1173]→[7.727:728](∅→∅),[7.727]→[7.727:728](∅→∅),[7.728]→[7.0:90](∅→∅),[7.90]→[7.544:632](∅→∅),[7.216]→[7.904:1026](∅→∅),[7.218]→[7.904:1026](∅→∅),[7.632]→[7.904:1026](∅→∅),[7.904]→[7.904:1026](∅→∅),[7.1026]→[7.0:92](∅→∅),[7.92]→[7.305:306](∅→∅),[7.310]→[7.305:306](∅→∅),[7.305]→[7.305:306](∅→∅),[7.306]→[7.0:56](∅→∅),[7.56]→[7.371:431](∅→∅),[7.371]→[7.371:431](∅→∅),[7.484]→[7.484:485](∅→∅),[7.485]→[7.57:88](∅→∅),[7.88]→[7.0:1](∅→∅),[7.589]→[7.0:1](∅→∅),[7.1]→[7.89:145](∅→∅),[7.145]→[7.1798:1802](∅→∅),[7.1798]→[7.1798:1802](∅→∅),[7.1802]→[7.311:429](∅→∅),[7.429]→[7.633:750](∅→∅),[7.102]→[7.527:532](∅→∅),[7.750]→[7.527:532](∅→∅),[7.527]→[7.527:532](∅→∅),[7.532]→[7.314:442](∅→∅),[7.442]→[7.93:495](∅→∅),[7.668]→[7.93:495](∅→∅),[7.495]→[7.0:1](∅→∅),[7.1]→[7.103:185](∅→∅),[7.185]→[7.75:130](∅→∅),[7.75]→[7.75:130](∅→∅),[7.130]→[7.495:496](∅→∅),[7.495]→[7.495:496](∅→∅),[7.496]→[7.131:427](∅→∅),[7.427]→[7.63:72](∅→∅),[7.63]→[7.63:72](∅→∅),[7.72]→[7.496:541](∅→∅),[7.496]→[7.496:541](∅→∅),[7.541]→[7.428:494](∅→∅),[7.494]→[7.568:640](∅→∅),[7.568]→[7.568:640](∅→∅),[7.640]→[2.0:81](∅→∅),[2.81]→[7.713:736](∅→∅),[7.713]→[7.713:736](∅→∅),[7.736]→[7.751:877](∅→∅),[7.877]→[7.0:4](∅→∅),[7.847]→[7.0:4](∅→∅),[7.676]→[7.1802:1824](∅→∅),[7.1802]→[7.1802:1824](∅→∅),[7.1824]→[7.677:746](∅→∅),[7.746]→[7.1920:1921](∅→∅),[7.1920]→[7.1920:1921](∅→∅),[7.1921]→[7.146:249](∅→∅),[7.249]→[7.843:844](∅→∅),[7.843]→[7.843:844](∅→∅),[7.844]→[6.0:200](∅→∅),[6.200]→[7.927:928](∅→∅),[7.927]→[7.927:928](∅→∅),[7.928]→[7.917:960](∅→∅),[7.101]→[7.1119:1245](∅→∅),[7.960]→[7.1119:1245](∅→∅),[7.1119]→[7.1119:1245](∅→∅),[7.1245]→[7.653:654](∅→∅),[7.2014]→[7.653:654](∅→∅),[7.1228]→[7.653:654](∅→∅),[7.654]→[7.1246:1288](∅→∅),[7.1288]→[7.387:437](∅→∅),[7.437]→[7.1338:1513](∅→∅),[7.1338]→[7.1338:1513](∅→∅),[7.1513]→[7.0:42](∅→∅),[7.42]→[7.438:488](∅→∅),[7.488]→[7.92:145](∅→∅),[7.92]→[7.92:145](∅→∅),[7.145]→[4.0:116](∅→∅),[4.116]→[7.226:237](∅→∅),[7.226]→[7.226:237](∅→∅),[7.237]→[7.2089:2140](∅→∅),[7.2140]→[7.1571:1625](∅→∅),[7.1571]→[7.1571:1625](∅→∅),[7.865]→[7.1472:1496](∅→∅),[7.1472]→[7.1472:1496](∅→∅),[7.1496]→[6.201:432](∅→∅),[7.354]→[7.2079:2120](∅→∅),[6.432]→[7.2079:2120](∅→∅),[7.523]→[7.2079:2120](∅→∅),[7.1497]→[7.2079:2120](∅→∅),[7.2120]→[6.433:593](∅→∅)
}sub getReleaseSet {my ($c, $projectName, $releaseSetName) = @_;my $project = $c->model('DB::Projects')->find($projectName);notFound($c, "Project $projectName doesn't exist.") if !defined $project;$c->stash->{project} = $project;(my $releaseSet) = $c->model('DB::ReleaseSets')->find($projectName, $releaseSetName);notFound($c, "Release set $releaseSetName doesn't exist.") if !defined $releaseSet;$c->stash->{releaseSet} = $releaseSet;(my $primaryJob) = $releaseSet->releasesetjobs->search({isprimary => 1});#die "Release set $releaseSetName doesn't have a primary job." if !defined $primaryJob;my $jobs = [$releaseSet->releasesetjobs->search({},{order_by => ["isprimary DESC", "job", "attrs"]})];$c->stash->{jobs} = $jobs;return ($project, $releaseSet, $primaryJob, $jobs);}sub updateReleaseSet {my ($c, $releaseSet) = @_;my $releaseSetName = trim $c->request->params->{name};error($c, "Invalid release set name: $releaseSetName")unless $releaseSetName =~ /^[[:alpha:]][\w\-]*$/;$releaseSet->update({ name => $releaseSetName, description => trim $c->request->params->{description} });$releaseSet->releasesetjobs->delete_all;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\-]+):([\w\-]+)$/ or error($c, "Invalid job name: $name");my $jobsetName = $1;my $jobName = $2;error($c, "Jobset `$jobsetName' doesn't exist.")unless $releaseSet->project->jobsets->find({name => $jobsetName});# !!! We could check whether the job exists, but that would# require the scheduler to have seen the job, which may not be# the case.$releaseSet->releasesetjobs->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 $releaseSet->releasesetjobs->search({isprimary => 1})->count != 1;}sub releases :Local {my ($self, $c, $projectName, $releaseSetName, $subcommand) = @_;my ($project, $releaseSet, $primaryJob, $jobs) = getReleaseSet($c, $projectName, $releaseSetName);my $resultsPerPage = 10;my $page = 1;if (defined $subcommand && $subcommand =~ /^\d+$/ ) {$page = int($subcommand)}elsif (defined $subcommand && $subcommand ne "") {requireProjectOwner($c, $project);if ($subcommand eq "edit") {$c->stash->{template} = 'edit-releaseset.tt';return;}elsif ($subcommand eq "submit") {txn_do($c->model('DB')->schema, sub {updateReleaseSet($c, $releaseSet);});return $c->res->redirect($c->uri_for("/releases", $projectName, $releaseSet->name));}elsif ($subcommand eq "delete") {txn_do($c->model('DB')->schema, sub {$releaseSet->delete;});return $c->res->redirect($c->uri_for($c->controller('Project')->action_for('view'), [$project->name]));}else { error($c, "Unknown subcommand."); }}$c->stash->{template} = 'releases.tt';my @releases = ();push @releases, getRelease($_, $jobs) foreach getPrimaryBuildsForReleaseSet($project, $primaryJob, $page, $resultsPerPage);$c->stash->{baseUri} = $c->uri_for($self->action_for("releases"), $projectName, $releaseSetName);$c->stash->{releases} = [@releases];$c->stash->{page} = $page;$c->stash->{totalReleases} = getPrimaryBuildTotal($project, $primaryJob);$c->stash->{resultsPerPage} = $resultsPerPage; - edit in src/lib/Hydra/Controller/Root.pm at line 64[7.2122]→[7.1568:1569](∅→∅),[7.1568]→[7.1568:1569](∅→∅),[7.2289]→[7.2289:2290](∅→∅),[7.2290]→[7.238:387](∅→∅),[7.387]→[7.878:953](∅→∅),[7.953]→[7.1174:1211](∅→∅),[7.455]→[7.1174:1211](∅→∅)
sub create_releaseset :Local {my ($self, $c, $projectName, $subcommand) = @_;my $project = $c->model('DB::Projects')->find($projectName);error($c, "Project $projectName doesn't exist.") if !defined $project;$c->stash->{project} = $project; - edit in src/lib/Hydra/Controller/Root.pm at line 65
requireProjectOwner($c, $project); - edit in src/lib/Hydra/Controller/Root.pm at line 66[7.730]→[7.730:788](∅→∅),[7.788]→[7.2231:2289](∅→∅),[7.2289]→[7.489:535](∅→∅),[7.535]→[7.2335:2731](∅→∅),[7.2335]→[7.2335:2731](∅→∅),[7.2731]→[7.1412:1506](∅→∅),[7.1412]→[7.1412:1506](∅→∅),[7.1506]→[7.2123:2144](∅→∅),[7.2290]→[7.2123:2144](∅→∅),[7.2144]→[3.0:75](∅→∅),[3.75]→[7.2209:2252](∅→∅),[7.1694]→[7.2209:2252](∅→∅),[7.2209]→[7.2209:2252](∅→∅),[7.2252]→[7.355:458](∅→∅),[7.458]→[7.524:612](∅→∅),[7.1791]→[7.524:612](∅→∅),[7.612]→[7.459:538](∅→∅),[7.538]→[7.2732:2823](∅→∅),[7.2823]→[3.76:186](∅→∅),[3.186]→[7.1061:1067](∅→∅),[7.1061]→[7.1061:1067](∅→∅),[7.1067]→[3.187:188](∅→∅),[3.188]→[7.2346:2500](∅→∅),[7.1072]→[7.2346:2500](∅→∅),[7.2877]→[7.2346:2500](∅→∅),[7.2500]→[7.954:1174](∅→∅),[7.1174]→[7.89:90](∅→∅),[7.2902]→[7.89:90](∅→∅),[7.90]→[7.539:600](∅→∅),[7.2692]→[7.539:600](∅→∅),[7.600]→[3.189:1023](∅→∅),[7.600]→[7.821:823](∅→∅),[3.1023]→[7.821:823](∅→∅),[7.2750]→[7.821:823](∅→∅),[7.2918]→[7.821:823](∅→∅),[7.821]→[7.821:823](∅→∅),[7.96]→[7.2159:2160](∅→∅),[7.2372]→[7.2372:2373](∅→∅)
if (defined $subcommand && $subcommand eq "submit") {my $releaseSetName = $c->request->params->{name};txn_do($c->model('DB')->schema, sub {# Note: $releaseSetName is validated in updateProject,# which will abort the transaction if the name isn't# valid.my $releaseSet = $project->releasesets->create({name => $releaseSetName});updateReleaseSet($c, $releaseSet);return $c->res->redirect($c->uri_for("/releases", $projectName, $releaseSet->name));});}$c->stash->{template} = 'edit-releaseset.tt';$c->stash->{create} = 1;}sub release :Local {my ($self, $c, $projectName, $releaseSetName, $releaseId, @args) = @_;$c->stash->{template} = 'release.tt';my ($project, $releaseSet, $primaryJob, $jobs) = getReleaseSet($c, $projectName, $releaseSetName);if ($releaseId eq "latest") {# Redirect to the latest successful release.my $latest = getLatestSuccessfulRelease($project, $primaryJob, $jobs);error($c, "This release set has no successful releases yet.") if !defined $latest;return $c->res->redirect($c->uri_for("/release", $projectName, $releaseSetName, $latest->id, @args));}# Note: we don't actually check whether $releaseId is a primary# build, but who cares?my $primaryBuild = $project->builds->find($releaseId,{ join => 'resultInfo',, '+select' => ["resultInfo.releasename", "resultInfo.buildstatus"], '+as' => ["releasename", "buildstatus"] })or error($c, "Release $releaseId doesn't exist.");$c->stash->{release} = getRelease($primaryBuild, $jobs);# Provide a redirect to the specified job of this release. !!!# This isn't uniquely defined if there are multiple jobs with the# same name (e.g. builds for different platforms). However, this# mechanism is primarily to allow linking to resources of which# there is only one build, such as the manual of the latest# release.if (scalar @args != 0) {my $jobName = shift @args;(my $build, my @others) = grep { $_->{job}->job eq $jobName } @{$c->stash->{release}->{jobs}};notFound($c, "Release doesn't have a job named `$jobName'")unless defined $build;error($c, "Job `$jobName' isn't unique.") if @others;return $c->res->redirect($c->uri_for($c->controller('Build')->action_for('view_build'),[$build->{build}->id], @args));}} - file addition: View.pm[7.188]
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 updateReleaseSet {my ($c, $releaseSet) = @_;my $releaseSetName = trim $c->request->params->{name};error($c, "Invalid release set name: $releaseSetName")unless $releaseSetName =~ /^[[:alpha:]][\w\-]*$/;$releaseSet->update({ name => $releaseSetName, description => trim $c->request->params->{description} });$releaseSet->releasesetjobs->delete_all;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\-]+):([\w\-]+)$/ or error($c, "Invalid job name: $name");my $jobsetName = $1;my $jobName = $2;error($c, "Jobset `$jobsetName' doesn't exist.")unless $releaseSet->project->jobsets->find({name => $jobsetName});# !!! We could check whether the job exists, but that would# require the scheduler to have seen the job, which may not be# the case.$releaseSet->releasesetjobs->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 $releaseSet->releasesetjobs->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;my @results = ();push @results, getRelease($_, $c->stash->{jobs}) foreachgetPrimaryBuildsForReleaseSet($c->stash->{project}, $c->stash->{primaryJob}, $page, $resultsPerPage);$c->stash->{baseUri} = $c->uri_for($self->action_for("view"), $c->stash->{project}->name, $c->stash->{view}->name);$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 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 = getLatestSuccessfulRelease($c->stash->{project}, $c->stash->{primaryJob}, $c->stash->{jobs});error($c, "This view set has no successful results yet.") if !defined $latest;return $c->res->redirect($c->uri_for("/view", $c->stash->{project}->name, $c->stash->{view}->name, $latest->id, @args));}sub result : Chained('view') PathPart('') {my ($self, $c, $id, @args) = @_;$c->stash->{template} = 'release.tt';# Note: we don't actually check whether $id is a primary build,# but who cares?my $primaryBuild = $c->stash->{project}->builds->find($id,{ join => 'resultInfo',, '+select' => ["resultInfo.releasename", "resultInfo.buildstatus"], '+as' => ["releasename", "buildstatus"] })or error($c, "Build $id doesn't exist.");$c->stash->{release} = getRelease($primaryBuild, $c->stash->{jobs});# Provide a redirect to the specified job of this release. !!!# This isn't uniquely defined if there are multiple jobs with the# same name (e.g. builds for different platforms). However, this# mechanism is primarily to allow linking to resources of which# there is only one build, such as the manual of the latest# release.if (scalar @args != 0) {my $jobName = shift @args;(my $build, my @others) = grep { $_->{job}->job eq $jobName } @{$c->stash->{release}->{jobs}};notFound($c, "Release doesn't have a job named `$jobName'")unless defined $build;error($c, "Job `$jobName' isn't unique.") if @others;return $c->res->redirect($c->uri_for($c->controller('Build')->action_for('view_build'),[$build->{build}->id], @args));}}1; - replacement in src/lib/Hydra/Helper/Nix.pm at line 242[7.2741]→[7.2741:2874](∅→∅),[7.2874]→[7.1793:1860](∅→∅),[7.1860]→[7.2939:2993](∅→∅),[7.2939]→[7.2939:2993](∅→∅)
if ($job->mayfail != 1) {if (!defined $thisBuild) {$status = 2 if $status == 0; # = unfinished} elsif ($thisBuild->get_column('buildstatus') != 0) {$status = 1; # = failed}if (!defined $thisBuild) {$status = 2 if $status == 0; # = unfinished} elsif ($thisBuild->get_column('buildstatus') != 0) {$status = 1; # = failed - replacement in src/lib/Hydra/Schema/BuildInputs.pm at line 106
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:yodYRloko+NdaEVy+IL5JA# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:gtA3wQA2CLsXs4X95PfX9A - replacement in src/lib/Hydra/Schema/BuildProducts.pm at line 94
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:GdjLBqXz+LK4ewxnpIs9eQ# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ii6N3v4M1fX1tQ3YmJNFWw - replacement in src/lib/Hydra/Schema/BuildResultInfo.pm at line 89
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:KTPvLaqbXGpynWt107ISew# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:EMvF2g+MDIE84yjnJOs7og - replacement in src/lib/Hydra/Schema/BuildSchedulingInfo.pm at line 46
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:thMie1PGP25FGbo5qypE/w# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:RcdX5dHefBQnxQYbMxNF/w - replacement in src/lib/Hydra/Schema/BuildSteps.pm at line 94
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Ua+P31BMRmMKP6QFOdA89A# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:1AQCHpuv8Lqk/FYdU8JYFA - replacement in src/lib/Hydra/Schema/Builds.pm at line 166
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:luxYxoOAtLoCgl5iFTYdJA# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CcYlMej7OPRUJn6375Qlqw - replacement in src/lib/Hydra/Schema/CachedPathInputs.pm at line 50
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:DeoyeS42ddQ2FXa+8n31OQ# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mYBdemei1tFuK8Ll6eMLfQ - replacement in src/lib/Hydra/Schema/CachedSubversionInputs.pm at line 43
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CaFTGQtLjPwCISqk5W4fag# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:bE+w54cACUS2L0PJ9gPjtw - replacement in src/lib/Hydra/Schema/Jobs.pm at line 78
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:+Cb0mIbX8ddDbZY39u9feA# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:c0OEe2zPd/E4vh0PRXm4Ag - replacement in src/lib/Hydra/Schema/JobsetInputAlts.pm at line 72
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:m3a1Q6c2FePidqbqYhz5dg# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jS8pitmHFnplE8WcK0OyMQ - replacement in src/lib/Hydra/Schema/JobsetInputs.pm at line 68
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:QSYSg5xsN292LnfvbAG0Vw# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:W0rhMTOzLBZNsVShQHg5+A - replacement in src/lib/Hydra/Schema/Jobsets.pm at line 106
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:85FwtlvNxjGix7PUCJTMqA# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CB5lPsrozpvO8gLXHTyMrQ - replacement in src/lib/Hydra/Schema/Projects.pm at line 68
"releasesets","Hydra::Schema::ReleaseSets","views","Hydra::Schema::Views", - replacement in src/lib/Hydra/Schema/Projects.pm at line 73
"releasesetjobs","Hydra::Schema::ReleaseSetJobs","viewjobs","Hydra::Schema::ViewJobs", - replacement in src/lib/Hydra/Schema/Projects.pm at line 79
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Dru36PNUe9iYHEwhhHKJ3A# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:N6NPLJfc1gKM4zz6dS5PJw - replacement in src/lib/Hydra/Schema/SystemTypes.pm at line 24
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mfZTzyri5eSRhfmBmwyuFQ# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:EkpopxgwlZf8Du3EmWzTKQ - replacement in src/lib/Hydra/Schema/UserRoles.pm at line 31
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6RgJY04rmD+PumWXz5KGoQ# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:W2Q6219GlZl2IqQkBoFmFA - replacement in src/lib/Hydra/Schema/Users.pm at line 53
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZWzljXMF0IbU12wNUn+djg# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:qH+qBI3xxQgTNf3v7E3sDw - file move: ReleaseSetJobs.pm → ViewJobs.pm
- replacement in src/lib/Hydra/Schema/ViewJobs.pm at line 1
package Hydra::Schema::ReleaseSetJobs;package Hydra::Schema::ViewJobs; - replacement in src/lib/Hydra/Schema/ViewJobs.pm at line 9
__PACKAGE__->table("ReleaseSetJobs");__PACKAGE__->table("ViewJobs"); - replacement in src/lib/Hydra/Schema/ViewJobs.pm at line 19
"release_","view_", - edit in src/lib/Hydra/Schema/ViewJobs.pm at line 43
"mayfail",{ data_type => "integer", default_value => 0, is_nullable => 0, size => undef }, - edit in src/lib/Hydra/Schema/ViewJobs.pm at line 57
"autorelease",{ data_type => "integer", default_value => 0, is_nullable => 0, size => undef }, - replacement in src/lib/Hydra/Schema/ViewJobs.pm at line 60
__PACKAGE__->set_primary_key("project", "release_", "job", "attrs");__PACKAGE__->set_primary_key("project", "view_", "job", "attrs"); - replacement in src/lib/Hydra/Schema/ViewJobs.pm at line 63
"releaseset","Hydra::Schema::ReleaseSets",{ name => "release_", project => "project" },"view","Hydra::Schema::Views",{ name => "view_", project => "project" }, - replacement in src/lib/Hydra/Schema/ViewJobs.pm at line 69
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:qSQjyHzxQp0qO3CbRdcXmw# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:LkiGAkZOiLNJk6oDY0+zNw - file move: ReleaseSets.pm → Views.pm
- replacement in src/lib/Hydra/Schema/Views.pm at line 1
package Hydra::Schema::ReleaseSets;package Hydra::Schema::Views; - replacement in src/lib/Hydra/Schema/Views.pm at line 9
__PACKAGE__->table("ReleaseSets");__PACKAGE__->table("Views"); - replacement in src/lib/Hydra/Schema/Views.pm at line 39[7.6994]→[7.6994:7014](∅→∅),[7.7014]→[7.3534:3569](∅→∅),[7.3569]→[7.7049:7053](∅→∅),[7.7049]→[7.7049:7053](∅→∅),[7.7053]→[7.1993:2074](∅→∅),[7.2074]→[7.7132:7137](∅→∅),[7.7132]→[7.7132:7137](∅→∅)
"releasesetjobs","Hydra::Schema::ReleaseSetJobs",{"foreign.project" => "self.project","foreign.release_" => "self.name",},"viewjobs","Hydra::Schema::ViewJobs",{ "foreign.project" => "self.project", "foreign.view_" => "self.name" }, - replacement in src/lib/Hydra/Schema/Views.pm at line 45
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:pEjxqTAwP4ZmP/s6F4VOsg# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hV+xzi564rgcYeDvz75zCA - replacement in src/lib/Hydra/Schema.pm at line 11
# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-08 13:25:04# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:vdr83mcEie4i5Fn/Uj17Vg# Created by DBIx::Class::Schema::Loader v0.04999_06 @ 2009-10-15 23:14:39# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ODLRc6VfDQpb8MyXPKmqtg - file move: edit-releaseset.tt → edit-view.tt
- replacement in src/root/edit-view.tt at line 1
[% WRAPPER layout.tt title=(create ? "New Release Set" : "Release Set ‘$project.name:$releaseSet.name’") %][% WRAPPER layout.tt title=(create ? "New View" : "View ‘$project.name:$view.name’") %] - replacement in src/root/edit-view.tt at line 5
<h1>[% IF create %]New Release Set[% ELSE %]Release Set <tt>[% project.name %]:[% releaseSet.name %]</tt>[% END %]</h1><h1>[% IF create %]New View[% ELSE %]View <tt>[% project.name %]:[% view.name %]</tt>[% END %]</h1> - replacement in src/root/edit-view.tt at line 24
<form action="[% IF create %][% c.uri_for('/create_releaseset' project.name 'submit') %][% ELSE %][% c.uri_for('/releases' project.name releaseSet.name 'submit') %][% END %]" method="post"><form action="[% IF create %][% c.uri_for('/create-view' project.name 'submit') %][% ELSE %][% c.uri_for('/view' project.name view.name 'submit') %][% END %]" method="post"> - replacement in src/root/edit-view.tt at line 29
<td><input type="text" class="string" name="name" [% HTML.attributes(value => releaseSet.name) %] /></td><td><input type="text" class="string" name="name" [% HTML.attributes(value => view.name) %] /></td> - replacement in src/root/edit-view.tt at line 33
<td><input type="text" class="string" name="description" [% HTML.attributes(value => releaseSet.description) %] /></td><td><input type="text" class="string" name="description" [% HTML.attributes(value => view.description) %] /></td> - replacement in src/root/edit-view.tt at line 89
<form action="[% c.uri_for('/releases' project.name releaseSet.name 'delete') %]" method="post"><p><button id="delete-project" type="submit"><img src="/static/images/failure.gif" />Delete this release set</button></p><form action="[% c.uri_for('/view' project.name view.name 'delete') %]" method="post"><p><button id="delete-project" type="submit"><img src="/static/images/failure.gif" />Delete this view</button></p> - replacement in src/root/edit-view.tt at line 95
return confirm("Are you sure you want to delete this release set?");return confirm("Are you sure you want to delete this view?"); - replacement in src/root/project.tt at line 102
<h2>Releases</h2><h2>Views</h2> - replacement in src/root/project.tt at line 104
[% IF releaseSets.size > 0 %][% IF views.size > 0 %] - replacement in src/root/project.tt at line 106
<p>Project <tt>[% project.name %]</tt> has the following release sets:</p><p>Project <tt>[% project.name %]</tt> has the following views:</p> - replacement in src/root/project.tt at line 109
[% FOREACH releaseSet IN releaseSets %][% FOREACH view IN views %] - replacement in src/root/project.tt at line 111
<a href="[% c.uri_for('/releases' project.name releaseSet.name) %]"><tt>[% releaseSet.name %]</tt></a>[<a href="[% c.uri_for('/releases' project.name releaseSet.name "edit") %]">Edit</a>]<a href="[% c.uri_for('/view' project.name view.name) %]"><tt>[% view.name %]</tt></a>[<a href="[% c.uri_for('/view' project.name view.name "edit") %]">Edit</a>] - replacement in src/root/project.tt at line 119
<p>Project <tt>[% project.name %]</tt> has no release sets.</p><p>Project <tt>[% project.name %]</tt> has no views.</p> - replacement in src/root/project.tt at line 123
<p><a href="[% c.uri_for('/create_releaseset' project.name) %]">[Create a new release set]</a></p><p><a href="[% c.uri_for('/project' project.name 'create-view') %]">[Create a new view]</a></p> - file move: releases.tt → view.tt
- replacement in src/root/view.tt at line 1
[% WRAPPER layout.tt title="Release Set ‘$releaseSet.project.name:$releaseSet.name’" %][% WRAPPER layout.tt title="View ‘$view.project.name:$view.name’" %] - replacement in src/root/view.tt at line 5
<h1>Release Set <tt>[% releaseSet.project.name %]:[% releaseSet.name %]</tt></h1><h1>View <tt>[% view.project.name %]:[% view.name %]</tt></h1> - replacement in src/root/view.tt at line 8
[<a href="[% c.uri_for('/releases' project.name releaseSet.name "edit") %]">Edit</a>][<a href="[% c.uri_for('/release' project.name releaseSet.name "latest") %]">Latest</a>][<a href="[% c.uri_for('/view' project.name view.name "edit") %]">Edit</a>][<a href="[% c.uri_for('/view' project.name view.name "latest") %]">Latest</a>] - replacement in src/root/view.tt at line 12
<p>Showing releases [% (page - 1) * resultsPerPage + 1 %] - [% (page - 1) * resultsPerPage + releases.size %] out of [% totalReleases %].</p><p>Showing results [% (page - 1) * resultsPerPage + 1 %] - [% (page - 1) * resultsPerPage + results.size %] out of [% totalResults %].</p> - replacement in src/root/view.tt at line 19
<th>Release</th><th>Name</th> - replacement in src/root/view.tt at line 28
[% FOREACH release IN releases %][% link = c.uri_for('/release' releaseSet.project.name releaseSet.name release.id) %][% FOREACH result IN results %][% link = c.uri_for('/view' project.name view.name result.id) %] - replacement in src/root/view.tt at line 32
[% IF release.status == 0 %][% IF result.status == 0 %] - replacement in src/root/view.tt at line 34
[% ELSIF release.status == 1 %][% ELSIF result.status == 1 %] - replacement in src/root/view.tt at line 36
[% ELSIF release.status == 2 %][% ELSIF result.status == 2 %] - replacement in src/root/view.tt at line 40
<td><a href="[% link %]">[% release.id %]</a></td><td><a href="[% link %]">[% result.id %]</a></td> - replacement in src/root/view.tt at line 42
[% IF release.releasename %]<tt>[% release.releasename %]</tt>[% IF result.releasename %]<tt>[% result.releasename %]</tt> - replacement in src/root/view.tt at line 48
<td>[% INCLUDE renderDateTime timestamp=release.timestamp %]</td>[% FOREACH j IN release.jobs %]<td>[% INCLUDE renderDateTime timestamp=result.timestamp %]</td>[% FOREACH j IN result.jobs %] - edit in src/root/view.tt at line 67
[<a href="[% "$baseUri?page=1" %]">First</a>] - replacement in src/root/view.tt at line 69
[<a href="[% "$baseUri/"; (page - 1) %]">Prev</a>][<a href="[% "$baseUri?page="; (page - 1) %]">Prev</a>] - replacement in src/root/view.tt at line 71
[% IF page * resultsPerPage < totalReleases %][<a href="[% "$baseUri/"; (page + 1) %]">Next</a>][% IF page * resultsPerPage < totalResults %][<a href="[% "$baseUri?page="; (page + 1) %]">Next</a>] - replacement in src/root/view.tt at line 74
[<a href="[% "$baseUri/"; (totalReleases - 1) div resultsPerPage + 1 %]">Last</a>][<a href="[% "$baseUri?page="; (totalResults - 1) div resultsPerPage + 1 %]">Last</a>] - replacement in src/sql/hydra.sql at line 187
update ReleaseSets set project = new.name where project = old.name;update ReleaseSetJobs set project = new.name where project = old.name;update Views set project = new.name where project = old.name;update ViewJobs set project = new.name where project = old.name; - replacement in src/sql/hydra.sql at line 332[7.11276]→[7.11276:11598](∅→∅),[7.11598]→[7.368:652](∅→∅),[7.652]→[7.11909:12110](∅→∅),[7.11909]→[7.11909:12110](∅→∅)
-- Release sets are a mechanism to automatically group related builds-- together. A release set defines what an individual release-- consists of, namely: a release consists of a build of some-- "primary" job, plus all builds of the other jobs named in-- ReleaseSetJobs that have that build as an input. If there are-- multiple builds matching a ReleaseSetJob, then we take the oldest-- successful build, or the oldest unsuccessful build if there is no-- successful build. A release is itself considered successful if all-- builds (except those for jobs that have mayFail set) are-- successful.---- Note that individual releases aren't separately stored in the-- database, so they're really just a dynamic view on the universe of-- builds, defined by a ReleaseSet.create table ReleaseSets (-- 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 ( - replacement in src/sql/hydra.sql at line 344
-- If true, don't garbage-collect builds belonging to the releases-- defined by this row.-- If true, don't garbage-collect builds included in this view. - replacement in src/sql/hydra.sql at line 352
create trigger cascadeReleaseSetDeletebefore delete on ReleaseSetscreate trigger cascadeViewDeletebefore delete on Views - replacement in src/sql/hydra.sql at line 355
delete from ReleaseSetJobs where project = old.project and release_ = old.name;delete from ViewJobs where project = old.project and view_ = old.name; - replacement in src/sql/hydra.sql at line 359
create trigger cascadeReleaseSetUpdateupdate of name on ReleaseSetscreate trigger cascadeViewUpdateupdate of name on Views - replacement in src/sql/hydra.sql at line 362
update ReleaseSetJobs set release_ = new.name where project = old.project and release_ = old.name;update ViewJobs set view_ = new.name where project = old.project and view_ = old.name; - replacement in src/sql/hydra.sql at line 366
create table ReleaseSetJobs (create table ViewJobs ( - replacement in src/sql/hydra.sql at line 368
-- `release' is a reserved keyword in sqlite >= 3.6.8. We could-- quote them ("release") here, but since the Perl bindings don't-- do that it still wouldn't work. So use `release_' instead.release_ text not null,view_ text not null, - replacement in src/sql/hydra.sql at line 377
-- If set, this is the primary job for the release. There can be-- onlyt one such job per release set.-- If set, this is the primary job for the view. There can be-- only one such job per view. - edit in src/sql/hydra.sql at line 381
mayFail integer not null default 0, - edit in src/sql/hydra.sql at line 384
-- 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, - replacement in src/sql/hydra.sql at line 391
primary key (project, release_, job, attrs),primary key (project, view_, job, attrs), - replacement in src/sql/hydra.sql at line 393
foreign key (project, release_) references ReleaseSets(project, name) on delete cascade -- ignored by sqliteforeign key (project, view_) references Views(project, name) on delete cascade -- ignored by sqlite