* Basic release management: releases are now dynamically computed as

[?]
Nov 27, 2008, 3:16 PM
FHF6IZJQPUQHY5QWQYRPZVDBRLHREWRHGNKVQDT7F3GQKKLZXJKQC

Dependencies

Change contents

  • replacement in src/Hydra/lib/Hydra/Controller/Root.pm at line 44
    [4.1266][4.1266:1332]()
    (my $build) = $c->model('DB::Builds')->search({ id => $id });
    [4.1266]
    [4.1332]
    my $build = $c->model('DB::Builds')->find($id);
  • edit in src/Hydra/lib/Hydra/Controller/Root.pm at line 168
    [2.821]
    [2.821]
    }
    sub releasesets :Local {
    my ($self, $c, $projectName) = @_;
    $c->stash->{template} = 'releasesets.tt';
    my $project = $c->model('DB::Projects')->find($projectName);
    return error($c, "Project $projectName doesn't exist.") if !defined $project;
    $c->stash->{curProject} = $project;
    $c->stash->{releaseSets} = [$project->releasesets->all];
    }
    sub releases :Local {
    my ($self, $c, $projectName, $releaseName) = @_;
    $c->stash->{template} = 'releases.tt';
    my $project = $c->model('DB::Projects')->find($projectName);
    return error($c, "Project $projectName doesn't exist.") if !defined $project;
    $c->stash->{curProject} = $project;
    (my $releaseSet) = $c->model('DB::Releasesets')->find($projectName, $releaseName);
    return error($c, "Release set $releaseName doesn't exist.") if !defined $releaseSet;
    $c->stash->{releaseSet} = $releaseSet;
    (my $primaryJob) = $releaseSet->releasesetjobs->search({isprimary => 1});
    return error($c, "Release set $releaseName doesn't have a primary job.") if !defined $primaryJob;
    $c->stash->{jobs} = [$releaseSet->releasesetjobs->search({}, {order_by => "isprimary DESC"})];
    my @primaryBuilds = $project->builds->search(
    { attrname => $primaryJob->job, finished => 1 },
    { join => 'resultInfo', order_by => "timestamp DESC", '+select' => ["resultInfo.releasename"], '+as' => ["releasename"] });
    my @releases = ();
    foreach my $primaryBuild (@primaryBuilds) {
    my @jobs = ();
    my $status = 0; # = okay
    foreach my $job (@{$c->stash->{jobs}}) {
    my $thisBuild;
    if ($job->isprimary == 1) {
    $thisBuild = $primaryBuild;
    } else {
    # Find a build of this job that had the primary build
    # as input. If there are multiple, prefer successful
    # ones, and then oldest. !!! order_by buildstatus is hacky
    ($thisBuild) = $primaryBuild->dependentBuilds->search(
    { attrname => $job->job, finished => 1 },
    { join => 'resultInfo', rows => 1
    , order_by => ["buildstatus", "timestamp"] });
    }
    if ($job->mayfail != 1) {
    if (!defined $thisBuild) {
    $status = 2 if $status == 0; # = unfinished
    } elsif ($thisBuild->resultInfo->buildstatus != 0) {
    $status = 1; # = failed
    }
    }
    push @jobs, { build => $thisBuild };
    }
    push @releases,
    { id => $primaryBuild->id
    , releasename => $primaryBuild->get_column('releasename')
    , jobs => [@jobs]
    , status => $status
    };
    }
    $c->stash->{releases} = [@releases];
  • replacement in src/Hydra/lib/Hydra/Controller/Root.pm at line 377
    [4.5][4.108:189](),[4.108][4.108:189]()
    (my $project) = $c->model('DB::Projects')->search({ name => $projectName });
    [4.5]
    [4.1146]
    my $project = $c->model('DB::Projects')->find($projectName);
  • replacement in src/Hydra/lib/Hydra/Controller/Root.pm at line 467
    [4.2160][4.2160:2241]()
    (my $project) = $c->model('DB::Projects')->search({ name => $projectName });
    [4.2160]
    [4.1323]
    my $project = $c->model('DB::Projects')->find($projectName);
  • replacement in src/Hydra/lib/Hydra/Schema/Buildinputs.pm at line 39
    [4.782][3.0:142]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uaNcxZMTbF9WDLgf2G1Klw
    [4.782]
    [4.924]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:R1F2JbVygktvK55xmY8mcg
  • replacement in src/Hydra/lib/Hydra/Schema/Buildproducts.pm at line 36
    [4.4922][3.143:285]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:btk6BJGE0Hj9qTO4qChpfw
    [4.4922]
    [4.5064]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:aZuZd+oUAO1c8GvSbgn7Fw
  • replacement in src/Hydra/lib/Hydra/Schema/Buildresultinfo.pm at line 32
    [4.2382][3.286:428]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Cn7vCpqfbTiq1/JF48BG2Q
    [4.2382]
    [4.2524]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:QahlwGdZKC7mL7fvwNxWjA
  • replacement in src/Hydra/lib/Hydra/Schema/Builds.pm at line 73
    [4.6194][3.429:571]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:p67v2RE44sAk2yGFoTpPww
    [4.6194]
    [4.3377]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uRSa4YkaRG0K6vK/qhGI9w
  • edit in src/Hydra/lib/Hydra/Schema/Builds.pm at line 78
    [4.1]
    [4.1978]
    __PACKAGE__->many_to_many(dependentBuilds => 'dependents', 'build');
  • replacement in src/Hydra/lib/Hydra/Schema/Buildschedulinginfo.pm at line 28
    [4.4473][3.651:793]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hdFMzqZ1IIdypz+/KLoCIw
    [4.4473]
    [4.4615]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:xBocoeipFdRsWDhvtoXImA
  • replacement in src/Hydra/lib/Hydra/Schema/Buildsteps.pm at line 38
    [4.2816][3.794:936]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:zFljaYEbDkYbHuCmcIJhOA
    [4.2816]
    [4.2958]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:04BankpQ6xo6T/ioMTdWkQ
  • replacement in src/Hydra/lib/Hydra/Schema/Cachedpathinputs.pm at line 25
    [4.1497][3.937:1079]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:E9++anIBM/+OIi2UdhIZKA
    [4.1497]
    [4.1639]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Nq3TpcRmpSRWNL4Q1hGGrA
  • replacement in src/Hydra/lib/Hydra/Schema/Cachedsubversioninputs.pm at line 23
    [4.2342][3.1080:1222]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:eKcfAgBW789dI2VFGh4baw
    [4.2342]
    [4.2484]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CCbHomM+8BTBqHBeGOGcuA
  • replacement in src/Hydra/lib/Hydra/Schema/Jobsetinputalts.pm at line 36
    [4.1831][3.1223:1365]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:vEw8HtMT848S/GEL1Y1MUg
    [4.1831]
    [4.1973]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JPf4ozBKK6NQPJT2few40g
  • replacement in src/Hydra/lib/Hydra/Schema/Jobsetinputs.pm at line 46
    [4.1681][3.1366:1508]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JVmtu+NXI6P/GD5q7+YTDA
    [4.1681]
    [4.1823]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:S8z1W0kjUX9VN5HPjyGAzA
  • replacement in src/Hydra/lib/Hydra/Schema/Jobsets.pm at line 53
    [4.2992][3.1509:1651]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:e1BZx0WYj1b6iIov6KvCqA
    [4.2992]
    [4.3134]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ebblUCTW7I1wGhVlPfNd3Q
  • edit in src/Hydra/lib/Hydra/Schema/Projects.pm at line 31
    [4.3585]
    [4.2341]
    { "foreign.project" => "self.name" },
    );
    __PACKAGE__->has_many(
    "releasesets",
    "Hydra::Schema::Releasesets",
    { "foreign.project" => "self.name" },
    );
    __PACKAGE__->has_many(
    "releasesetjobs",
    "Hydra::Schema::Releasesetjobs",
  • replacement in src/Hydra/lib/Hydra/Schema/Projects.pm at line 45
    [4.3685][3.1652:1794]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BHYbrizctvmbAJyTKSu89g
    [4.3685]
    [4.3827]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:70/Br6966ZZ+p8n6lF1hcw
  • file addition: Releasesetjobs.pm (----------)
    [47.207]
    package Hydra::Schema::Releasesetjobs;
    use strict;
    use warnings;
    use base 'DBIx::Class';
    __PACKAGE__->load_components("Core");
    __PACKAGE__->table("ReleaseSetJobs");
    __PACKAGE__->add_columns(
    "project",
    { data_type => "text", is_nullable => 0, size => undef },
    "release",
    { data_type => "text", is_nullable => 0, size => undef },
    "job",
    { data_type => "text", is_nullable => 0, size => undef },
    "attrs",
    { data_type => "text", is_nullable => 0, size => undef },
    "isprimary",
    { data_type => "integer", is_nullable => 0, size => undef },
    "mayfail",
    { data_type => "integer", is_nullable => 0, size => undef },
    "description",
    { data_type => "text", is_nullable => 0, size => undef },
    );
    __PACKAGE__->set_primary_key("project", "release", "job", "attrs");
    __PACKAGE__->belongs_to("project", "Hydra::Schema::Projects", { name => "project" });
    __PACKAGE__->belongs_to(
    "releaseset",
    "Hydra::Schema::Releasesets",
    { name => "release", project => "project" },
    );
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:t2ZI1kBn/GsKlY0e4+Wspg
    # You can replace this text with custom content, and it will be preserved on regeneration
    1;
  • file addition: Releasesets.pm (----------)
    [47.207]
    package Hydra::Schema::Releasesets;
    use strict;
    use warnings;
    use base 'DBIx::Class';
    __PACKAGE__->load_components("Core");
    __PACKAGE__->table("ReleaseSets");
    __PACKAGE__->add_columns(
    "project",
    { data_type => "text", is_nullable => 0, size => undef },
    "name",
    { data_type => "text", is_nullable => 0, size => undef },
    "description",
    { data_type => "text", is_nullable => 0, size => undef },
    "keep",
    { data_type => "integer", is_nullable => 0, size => undef },
    );
    __PACKAGE__->set_primary_key("project", "name");
    __PACKAGE__->belongs_to("project", "Hydra::Schema::Projects", { name => "project" });
    __PACKAGE__->has_many(
    "releasesetjobs",
    "Hydra::Schema::Releasesetjobs",
    {
    "foreign.project" => "self.project",
    "foreign.release" => "self.name",
    },
    );
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:pNqwNlXuENM/SsZ/utKhWw
    # You can replace this text with custom content, and it will be preserved on regeneration
    1;
  • replacement in src/Hydra/lib/Hydra/Schema/Systemtypes.pm at line 19
    [4.2105][3.1795:1937]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:90X5M27CbmJcZ7YnciHVMA
    [4.2105]
    [4.2247]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:WeoKp84cptljEdtD+5l7Ug
  • replacement in src/Hydra/lib/Hydra/Schema/Userroles.pm at line 20
    [4.3736][3.1938:2080]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:g2EVNE74pSi9teIFqIA92Q
    [4.3736]
    [4.3878]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:WxjgPLWPvXpQ3nmxmlU7Dw
  • replacement in src/Hydra/lib/Hydra/Schema/Users.pm at line 28
    [4.3782][3.2081:2223]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:gmqkPkkET+452wBlILgOsQ
    [4.3782]
    [4.3924]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:s+M14nuDVIMoRSgXodj3dw
  • replacement in src/Hydra/lib/Hydra/Schema.pm at line 11
    [4.6498][3.2224:2366]()
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:yXQEjv8/1aoKNW095xSR/Q
    [4.6498]
    [4.6640]
    # Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jJnmW70e1RDsSt5ClahomQ
  • replacement in src/Hydra/programs/Build.pl at line 279
    [4.6958][4.7959:8026]()
    ($build) = $db->resultset('Builds')->search({id => $buildId});
    [4.6958]
    [4.8026]
    $build = $db->resultset('Builds')->find($buildId);
  • replacement in src/Hydra/root/jobstatus.tt at line 4
    [4.1976][2.1557:1647]()
    <h1>Job Status[% IF curProject %] in Project <tt>[% curProject.name %]</tt>[% END %]</h1>
    [4.1976]
    [4.1996]
    <h1>Job Status[% IF curProject %] of Project <tt>[% curProject.name %]</tt>[% END %]</h1>
  • edit in src/Hydra/root/layout.tt at line 102
    [4.1643][4.2830:2938]()
    [% INCLUDE makeLink uri = c.uri_for('/project' project.name 'edit') title = "Edit" %]
  • edit in src/Hydra/root/layout.tt at line 104
    [4.1868]
    [4.1868]
    [% INCLUDE makeLink uri = c.uri_for('/project' project.name 'edit') title = "Edit" %]
  • replacement in src/Hydra/root/project.tt at line 99
    [4.2196][4.2196:2270]()
    [% PROCESS renderDateTime timestamp = jobset.lastcheckedtime %]
    [4.2196]
    [4.2270]
    [% IF jobset.lastcheckedtime %]
    [% PROCESS renderDateTime timestamp = jobset.lastcheckedtime %]
    [% ELSE %]
    <em>never</em>
    [% END %]
  • file addition: releases.tt (----------)
    [48.857]
    [% WRAPPER layout.tt title="Releases" %]
    [% PROCESS common.tt %]
    [% USE HTML %]
    <h1>Releases</h1>
    <!-- <p>Description: [% releaseSet.description %]</p> -->
    <table class="tablesorter">
    <thead>
    <tr>
    <th></th>
    <th>#</th>
    <th>Release</th>
    [% FOREACH job IN jobs %]
    <th>[% IF job.description; HTML.escape(job.description); ELSE %]<tt>[% job.job %]</tt> ([% job.attrs %])[% END %]</th>
    [% END %]
    </tr>
    </thead>
    <tbody>
    [% FOREACH release IN releases %]
    <tr>
    <td>
    [% IF release.status == 0 %]
    <img src="/static/images/success.gif" />
    [% ELSIF release.status == 1 %]
    <img src="/static/images/failure.gif" />
    [% ELSIF release.status == 2 %]
    <img src="/static/images/question-mark.png" />
    [% END %]
    </td>
    <td>[% release.id %]</td>
    <td>
    [% IF release.releasename %]
    <tt>[% release.releasename %]</tt>
    [% ELSE %]
    <em>No name</em>
    [% END %]
    </td>
    [% FOREACH job IN release.jobs %]
    <td>
    [% IF job.build %]
    <a href="[% c.uri_for('/build' job.build.id) %]">
    [% IF job.build.resultInfo.buildstatus == 0 %]
    <img src="/static/images/success.gif" />
    [% ELSE %]
    <img src="/static/images/failure.gif" />
    [% END %]
    [% job.build.id %]
    </a>
    [% END %]
    </td>
    [% END %]
    </tr>
    [% END %]
    </tbody>
    </table>
    [% END %]
  • file addition: releasesets.tt (----------)
    [48.857]
    [% WRAPPER layout.tt title="Release Sets" %]
    [% PROCESS common.tt %]
    <h1>Release Sets</h1>
    <p>Project <tt>[% curProject.name %]</tt> has the following release sets:</p>
    <ul>
    [% FOREACH releaseSet IN releaseSets %]
    <li><a href="[% c.uri_for('/releases' curProject.name releaseSet.name) %]"><tt>[% releaseSet.name %]</tt></a></li>
    [% END %]
    </ul>
    [% END %]
  • file addition: question-mark.png (----------)
    [48.1279]
  • edit in src/hydra.sql at line 171
    [50.878]
    [50.878]
    update ReleaseSets set project = new.name where project = old.name;
    update ReleaseSetJobs set project = new.name where project = old.name;
  • edit in src/hydra.sql at line 293
    [4.5885]
    -- 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 (for release stability), or the *newest*
    -- unsuccessful build if there is no succesful 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 (
    project text not null,
    name text not null,
    description text,
    -- If true, don't garbage-collect builds belonging to the releases
    -- defined by this row.
    keep integer not null default 0,
    primary key (project, name),
    foreign key (project) references Projects(name) on delete cascade -- ignored by sqlite
    );
    create trigger cascadeReleaseSetDelete
    before delete on ReleaseSets
    for each row begin
    delete from ReleaseSetJobs where project = old.project and release = old.release;
    end;
    create table ReleaseSetJobs (
    project text not null,
    release 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 release. There can be
    -- onlyt one such job per release set.
    isPrimary integer not null default 0,
    mayFail integer not null default 0,
    description text,
    primary key (project, release, job, attrs),
    foreign key (project) references Projects(name) on delete cascade, -- ignored by sqlite
    foreign key (project, release) references ReleaseSets(project, name) on delete cascade -- ignored by sqlite
    );