Skip to content

Commit

Permalink
Set up basic build group Eloquent relationships (#2394)
Browse files Browse the repository at this point in the history
This PR is incremental progress towards an entirely Eloquent-based query
system, and ultimately an introduction of build groups to the GraphQL
API. In addition to setting up Eloquent relationships between build
group-related models, this PR also adds additional constraints and
indexes for better performance and data integrity.
  • Loading branch information
williamjallen authored Sep 4, 2024
1 parent 0439c98 commit ddf49ce
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 1 deletion.
8 changes: 8 additions & 0 deletions app/Models/Build.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,12 @@ public function comments(): HasMany
{
return $this->hasMany(Comment::class, 'buildid');
}

/**
* @return BelongsToMany<BuildGroup>
*/
public function buildGroups(): BelongsToMany
{
return $this->belongsToMany(BuildGroup::class, 'build2group', 'groupid', 'buildid');
}
}
21 changes: 21 additions & 0 deletions app/Models/BuildGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace App\Models;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
Expand Down Expand Up @@ -59,4 +61,23 @@ public function project(): BelongsTo
{
return $this->belongsTo(Project::class, 'id', 'projectid');
}

/**
* @return BelongsToMany<Build>
*/
public function builds(): BelongsToMany
{
return $this->belongsToMany(Build::class, 'build2group', 'buildid', 'groupid');
}

/**
* All the positions this group has ever been in. Most users probably want to use a scoped
* version of this relationship instead.
*
* @return HasMany<BuildGroupPosition>
*/
public function positions(): HasMany
{
return $this->hasMany(BuildGroupPosition::class, 'buildgroupid');
}
}
46 changes: 46 additions & 0 deletions app/Models/BuildGroupPosition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

/**
* @property int $id
* @property int $buildgroupid
* @property int $position
* @property Carbon $starttime
* @property Carbon $endtime
*
* @mixin Builder<BuildGroupPosition>
*/
class BuildGroupPosition extends Model
{
protected $table = 'buildgroup';

public $timestamps = false;

protected $fillable = [
'position',
'starttime',
'endtime',
];

protected $casts = [
'id' => 'integer',
'buildgroupid' => 'integer',
'position' => 'integer',
'starttime' => 'datetime',
'endtime' => 'datetime',
];

/**
* @return BelongsTo<BuildGroup,self>
*/
public function buildGroup(): BelongsTo
{
return $this->belongsTo(BuildGroup::class, 'buildgroupid');
}
}
8 changes: 8 additions & 0 deletions app/cdash/tests/case/CDash/MultipleSubprojectsEmailTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use CDash\Test\UseCase\UseCase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Str;

class MultipleSubprojectsEmailTest extends CDashUseCaseTestCase
{
Expand Down Expand Up @@ -118,6 +119,13 @@ public function setUp() : void
'uuid' => 'TestBuild' . $i,
]);
}

// Do the same for build groups
DB::table('buildgroup')->insertOrIgnore([
'id' => 0,
'projectid' => self::$projectid,
'description' => 'MultipleSubprojectsEmailTest-' . Str::uuid()->toString(),
]);
}
}

Expand Down
11 changes: 10 additions & 1 deletion app/cdash/tests/test_buildmodel.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use CDash\Model\Build;
use CDash\Model\BuildError;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class BuildModelTestCase extends KWWebTestCase
{
Expand All @@ -29,7 +30,15 @@ public function __construct()
$this->testDataFiles = ['build1.xml', 'build2.xml', 'build3.xml', 'build4.xml',
'build5.xml', 'configure1.xml'];

DB::insert("INSERT INTO project (name) VALUES ('BuildModel')");
$project = \App\Models\Project::create([
'name' => 'BuildModel',
]);

DB::table('buildgroup')->insertOrIgnore([
'id' => 0,
'projectid' => $project->id,
'description' => 'MultipleSubprojectsEmailTest-' . Str::uuid()->toString(),
]);

foreach ($this->testDataFiles as $testDataFile) {
if (!$this->submission('BuildModel', $this->testDataDir . '/' . $testDataFile)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
public function up(): void
{
$num_deleted = DB::delete('
DELETE FROM build2group
WHERE groupid NOT IN (
SELECT id FROM buildgroup
)
');

if ($num_deleted > 0) {
echo "Deleted $num_deleted invalid build2group rows.";
}

Schema::table('build2group', function (Blueprint $table) {
$table->dropForeign(['buildid']); // Drop the foreign key so we can drop the primary key (MySQL is particular about this)
$table->dropPrimary();
$table->foreign('buildid')->references('id')->on('build')->cascadeOnDelete();
$table->unique(['buildid', 'groupid']);
$table->unique(['groupid', 'buildid']);
$table->foreign('groupid')->references('id')->on('buildgroup')->cascadeOnDelete();
});
}

public function down(): void
{
Schema::table('build2group', function (Blueprint $table) {
$table->primary(['buildid']);
$table->dropUnique(['buildid', 'groupid']);
$table->dropUnique(['groupid', 'buildid']);
$table->dropForeign(['groupid']);
});
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
public function up(): void
{
$num_deleted = DB::delete('
DELETE FROM buildgroupposition
WHERE buildgroupid NOT IN (
SELECT id
FROM buildgroup
)
');

if ($num_deleted > 0) {
echo "Deleted $num_deleted invalid buildgroupposition rows.";
}

Schema::table('buildgroupposition', function (Blueprint $table) {
$table->increments('id');
$table->foreign('buildgroupid')
->references('id')
->on('buildgroup')
->cascadeOnDelete();
});
}

public function down(): void
{
Schema::table('buildgroupposition', function (Blueprint $table) {
$table->dropColumn('id');
$table->dropForeign(['buildgroupid']);
});
}
};

0 comments on commit ddf49ce

Please sign in to comment.