OperationStatus::class, 'started_at' => 'datetime', 'finished_at' => 'datetime', 'secrets' => 'encrypted:array', ]; } public function operation(): BelongsTo { return $this->belongsTo(Operation::class); } public function logsExcerpt(): Attribute { return Attribute::make( get: fn () => $this->logs ? Str::afterLast($this->logs, "\n") : null, ); } public function errorLogsExcerpt(): Attribute { return Attribute::make( get: fn () => $this->error_logs ? Str::afterLast($this->error_logs, "\n") : null, ); } public function dispatchJob(): void { dispatch(new RunStep($this)); } public function scriptForExecution(): string { $script = $this->script; foreach (($this->secrets ?? []) as $key => $value) { $script = str_replace("[!{$key}!]", $value, $script); } return $script; } /** * @return array{container_id?: string, health_status?: string} */ public function capturedRuntimeState(): array { $state = []; foreach (explode("\n", (string) $this->logs) as $line) { if (str_starts_with($line, 'container_id=')) { $state['container_id'] = trim((string) str($line)->after('container_id=')); } if (str_starts_with($line, 'health_status=')) { $state['health_status'] = trim((string) str($line)->after('health_status=')); } } return array_filter($state, fn (string $value): bool => $value !== ''); } }