166 lines
4.8 KiB
PHP
166 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
use OpenApi\Attributes as OA;
|
|
|
|
#[OA\Schema(
|
|
description: 'Project model',
|
|
type: 'object',
|
|
properties: [
|
|
'id' => ['type' => 'integer'],
|
|
'application_id' => ['type' => 'string'],
|
|
'deployment_uuid' => ['type' => 'string'],
|
|
'pull_request_id' => ['type' => 'integer'],
|
|
'force_rebuild' => ['type' => 'boolean'],
|
|
'commit' => ['type' => 'string'],
|
|
'status' => ['type' => 'string'],
|
|
'is_webhook' => ['type' => 'boolean'],
|
|
'is_api' => ['type' => 'boolean'],
|
|
'created_at' => ['type' => 'string'],
|
|
'updated_at' => ['type' => 'string'],
|
|
'logs' => ['type' => 'string'],
|
|
'current_process_id' => ['type' => 'string'],
|
|
'restart_only' => ['type' => 'boolean'],
|
|
'git_type' => ['type' => 'string'],
|
|
'server_id' => ['type' => 'integer'],
|
|
'application_name' => ['type' => 'string'],
|
|
'server_name' => ['type' => 'string'],
|
|
'deployment_url' => ['type' => 'string'],
|
|
'destination_id' => ['type' => 'string'],
|
|
'only_this_server' => ['type' => 'boolean'],
|
|
'rollback' => ['type' => 'boolean'],
|
|
'commit_message' => ['type' => 'string'],
|
|
],
|
|
)]
|
|
class ApplicationDeploymentQueue extends Model
|
|
{
|
|
protected $guarded = [];
|
|
|
|
public function application(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
get: fn () => Application::find($this->application_id),
|
|
);
|
|
}
|
|
|
|
public function server(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
get: fn () => Server::find($this->server_id),
|
|
);
|
|
}
|
|
|
|
public function setStatus(string $status)
|
|
{
|
|
$this->update([
|
|
'status' => $status,
|
|
]);
|
|
}
|
|
|
|
public function getOutput($name)
|
|
{
|
|
if (! $this->logs) {
|
|
return null;
|
|
}
|
|
|
|
return collect(json_decode($this->logs))->where('name', $name)->first()?->output ?? null;
|
|
}
|
|
|
|
public function getHorizonJobStatus()
|
|
{
|
|
return getJobStatus($this->horizon_job_id);
|
|
}
|
|
|
|
public function commitMessage()
|
|
{
|
|
if (empty($this->commit_message) || is_null($this->commit_message)) {
|
|
return null;
|
|
}
|
|
|
|
return str($this->commit_message)->value();
|
|
}
|
|
|
|
private function redactSensitiveInfo($text)
|
|
{
|
|
$text = remove_iip($text);
|
|
|
|
$app = $this->application;
|
|
if (! $app) {
|
|
return $text;
|
|
}
|
|
|
|
$lockedVars = collect([]);
|
|
|
|
if ($app->environment_variables) {
|
|
$lockedVars = $lockedVars->merge(
|
|
$app->environment_variables
|
|
->where('is_shown_once', true)
|
|
->pluck('real_value', 'key')
|
|
->filter()
|
|
);
|
|
}
|
|
|
|
if ($this->pull_request_id !== 0 && $app->environment_variables_preview) {
|
|
$lockedVars = $lockedVars->merge(
|
|
$app->environment_variables_preview
|
|
->where('is_shown_once', true)
|
|
->pluck('real_value', 'key')
|
|
->filter()
|
|
);
|
|
}
|
|
|
|
foreach ($lockedVars as $key => $value) {
|
|
$escapedValue = preg_quote($value, '/');
|
|
$text = preg_replace(
|
|
'/'.$escapedValue.'/',
|
|
REDACTED,
|
|
$text
|
|
);
|
|
}
|
|
|
|
return $text;
|
|
}
|
|
|
|
public function addLogEntry(string $message, string $type = 'stdout', bool $hidden = false)
|
|
{
|
|
if ($type === 'error') {
|
|
$type = 'stderr';
|
|
}
|
|
$message = str($message)->trim();
|
|
if ($message->startsWith('╔')) {
|
|
$message = "\n".$message;
|
|
}
|
|
$newLogEntry = [
|
|
'command' => null,
|
|
'output' => $this->redactSensitiveInfo($message),
|
|
'type' => $type,
|
|
'timestamp' => Carbon::now('UTC'),
|
|
'hidden' => $hidden,
|
|
'batch' => 1,
|
|
];
|
|
|
|
// Use a transaction to ensure atomicity
|
|
DB::transaction(function () use ($newLogEntry) {
|
|
// Reload the model to get the latest logs
|
|
$this->refresh();
|
|
|
|
if ($this->logs) {
|
|
$previousLogs = json_decode($this->logs, associative: true, flags: JSON_THROW_ON_ERROR);
|
|
$newLogEntry['order'] = count($previousLogs) + 1;
|
|
$previousLogs[] = $newLogEntry;
|
|
$this->logs = json_encode($previousLogs, flags: JSON_THROW_ON_ERROR);
|
|
} else {
|
|
$this->logs = json_encode([$newLogEntry], flags: JSON_THROW_ON_ERROR);
|
|
}
|
|
|
|
// Save without triggering events to prevent potential race conditions
|
|
$this->saveQuietly();
|
|
});
|
|
}
|
|
}
|