mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
feat(github-runners): add ephemeral self-hosted runners on build servers (#12054)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
03a056709d
commit
fd85b740f5
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\GithubRunnerStatus;
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -35,6 +36,10 @@ class GithubApp extends BaseModel
|
||||
'metadata',
|
||||
'pull_requests',
|
||||
'administration',
|
||||
'organization_self_hosted_runners',
|
||||
'actions',
|
||||
'webhook_events',
|
||||
'runner_group_id',
|
||||
];
|
||||
|
||||
protected $appends = ['type'];
|
||||
@@ -43,6 +48,8 @@ class GithubApp extends BaseModel
|
||||
'is_public' => 'boolean',
|
||||
'is_system_wide' => 'boolean',
|
||||
'type' => 'string',
|
||||
'webhook_events' => 'array',
|
||||
'runner_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
@@ -58,6 +65,15 @@ class GithubApp extends BaseModel
|
||||
throw new \Exception('You cannot delete this GitHub App because it is in use by '.$applications_count.' application(s). Delete them first.');
|
||||
}
|
||||
|
||||
// Runner rows cascade with the App, so live runner containers would lose their cleanup and keep taking jobs.
|
||||
$hasLiveRunners = $github_app->runnerConfigs()->where('is_enabled', true)->exists()
|
||||
|| GithubRunnerExecution::where('github_app_id', $github_app->id)
|
||||
->whereIn('status', GithubRunnerStatus::occupying())
|
||||
->exists();
|
||||
if ($hasLiveRunners) {
|
||||
throw new \Exception('You cannot delete this GitHub App because servers use it for GitHub Actions runners. Disable the runners on these servers and wait for running jobs to finish first.');
|
||||
}
|
||||
|
||||
$privateKey = $github_app->privateKey;
|
||||
if ($privateKey) {
|
||||
// Check if key is used by anything EXCEPT this GitHub app
|
||||
@@ -97,6 +113,35 @@ class GithubApp extends BaseModel
|
||||
return $this->belongsTo(PrivateKey::class);
|
||||
}
|
||||
|
||||
public function runnerConfigs()
|
||||
{
|
||||
return $this->hasMany(GithubRunnerConfig::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permissions and webhook events that GitHub Actions runners need but the App does not have.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function missingRunnerRequirements(): array
|
||||
{
|
||||
$missing = [];
|
||||
if (blank($this->organization)) {
|
||||
$missing[] = 'An organization (runners are registered at organization level)';
|
||||
}
|
||||
if ($this->organization_self_hosted_runners !== 'write') {
|
||||
$missing[] = 'Organization permission "Self-hosted runners": write';
|
||||
}
|
||||
if (! in_array($this->actions, ['read', 'write'], true)) {
|
||||
$missing[] = 'Repository permission "Actions": read';
|
||||
}
|
||||
if (! in_array('workflow_job', $this->webhook_events ?? [], true)) {
|
||||
$missing[] = 'Webhook event "Workflow job"';
|
||||
}
|
||||
|
||||
return $missing;
|
||||
}
|
||||
|
||||
public function type(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
|
||||
Reference in New Issue
Block a user