coolify/app/Models/GithubRunnerConfig.php
Andras Bacsai 576f38da1c feat(github): add self-hosted Actions runner orchestration
Implement end-to-end GitHub Actions runner support with provisioning,
tracking, and cleanup flows.

- handle `workflow_job` webhooks to provision and tear down runners
- add runner config/execution models, enum states, and relationships
- create jobs for provisioning, cleanup, and stale-runner reaping
- schedule periodic stale runner cleanup in the console kernel
- add Livewire server UI to manage runner configuration and executions
- store GitHub App runner permissions and runner group metadata
- add migrations for runner permissions, configs, executions, and group id
- update GitHub permissions URL generation for organization app settings
- include feature/unit tests for runner behavior and permission paths
2026-03-03 14:27:19 +01:00

63 lines
1.5 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class GithubRunnerConfig extends BaseModel
{
protected $guarded = [];
protected function casts(): array
{
return [
'labels' => 'array',
'is_enabled' => 'boolean',
'max_runners' => 'integer',
];
}
public function organization(): Attribute
{
return Attribute::make(
get: fn () => $this->githubApp?->organization,
);
}
public function server(): BelongsTo
{
return $this->belongsTo(Server::class);
}
public function githubApp(): BelongsTo
{
return $this->belongsTo(GithubApp::class);
}
public function executions(): HasMany
{
return $this->hasMany(GithubRunnerExecution::class);
}
public function activeRunnerCount(): int
{
return $this->executions()
->whereIn('status', ['queued', 'provisioning', 'running', 'cleaning'])
->count();
}
public function hasCapacity(): bool
{
return $this->activeRunnerCount() < $this->max_runners;
}
public function matchesLabels(array $requestedLabels): bool
{
$configLabels = collect($this->labels)->map(fn ($l) => strtolower($l));
return collect($requestedLabels)
->every(fn ($label) => $configLabels->contains(strtolower($label)));
}
}