multiple commands

This commit is contained in:
2024-08-24 18:51:36 +03:00
parent d9e2c4954a
commit 1505aaa909
10 changed files with 100 additions and 50 deletions
+8 -9
View File
@@ -1,22 +1,23 @@
<script> <script>
import {getContext, onMount} from "svelte"; import {getContext, onMount} from "svelte";
import axios from "axios";
const channel = getContext("channel"); const channel = getContext("channel");
export let title; export let title;
export let command;
$: date = ""; $: date = "";
$: logs = ""; $: logs = "";
let inProgress = false; let inProgress = false;
function connect() { function connect() {
const eventSource = new EventSource(channel.lucentUrl + "/build-report-source"); const eventSource = new EventSource(channel.lucentUrl + "/command-report-source/" + command.signature );
eventSource.onmessage = function (event) { eventSource.onmessage = function (event) {
inProgress = true; inProgress = true;
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
date = data.date; date = data.date;
logs = data.logs; logs = data.logs;
} }
eventSource.onerror = (e) => { eventSource.onerror = (e) => {
console.log(e) console.log(e)
@@ -28,8 +29,7 @@
function buildWebsite(e) { function buildWebsite(e) {
e.preventDefault(); e.preventDefault();
inProgress = true; inProgress = true;
axios.post(channel.lucentUrl + "/command/" + command.signature).then(response => {
axios.post(channel.lucentUrl + "/build").then(response => {
connect() connect()
}) })
@@ -46,20 +46,19 @@
<h3 class="header-small mb-5">{title}</h3> <h3 class="header-small mb-5">{title}</h3>
<button on:click={buildWebsite} class="button primary mb-3" disabled={inProgress}>Start Build <button on:click={buildWebsite} class="button primary mb-3" disabled={inProgress}>Start
</button> </button>
<div class="mb-3"> <div class="mb-3">
{#if inProgress} {#if inProgress}
<span class="badge text-bg-warning"> <span class="badge text-bg-warning">
Build in progress Action in progress
</span> </span>
{/if} {/if}
{#if !inProgress && logs} {#if !inProgress && logs}
<span class="badge text-bg-info"> <span class="badge text-bg-info">
Build completed Action completed
</span> </span>
{/if} {/if}
@@ -61,7 +61,6 @@
if (!filter.isReference) { if (!filter.isReference) {
return null; return null;
} }
console.log(graph)
return graph.records.find(r => r.id === value); return graph.records.find(r => r.id === value);
} }
+10 -2
View File
@@ -1,17 +1,25 @@
<script> <script>
import Avatar from "../account/Avatar.svelte"; import Avatar from "../account/Avatar.svelte";
import {getContext} from "svelte"; import {getContext} from "svelte";
import Dropdown from "../common/Dropdown.svelte";
const channel = getContext("channel"); const channel = getContext("channel");
const user = getContext("user"); const user = getContext("user");
console.log( channel.commands)
</script> </script>
<div class="top-nav "> <div class="top-nav ">
<a class="top-nav-item" href="{channel.lucentUrl}/members">Members</a> <a class="top-nav-item" href="{channel.lucentUrl}/members">Members</a>
{#if channel.generateCommand} {#if channel.commands}
<a href="{channel.lucentUrl}/build-report" class="top-nav-item">Build website</a> <Dropdown>
<div slot="button">Actions</div>
{#each channel.commands as command}
<a href="{channel.lucentUrl}/command-report/{command.signature}" class="top-nav-item">{command.name}</a>
{/each}
</Dropdown>
{/if} {/if}
<!-- <div>--> <!-- <div>-->
<!-- <form method="GET">--> <!-- <form method="GET">-->
+3 -1
View File
@@ -2,6 +2,7 @@
namespace Lucent\Channel; namespace Lucent\Channel;
use Lucent\Channel\Data\UserCommand;
use Lucent\Primitive\Collection; use Lucent\Primitive\Collection;
use Lucent\Schema\Schema; use Lucent\Schema\Schema;
@@ -13,12 +14,13 @@ final class Channel
/** /**
* @param Collection<Schema> $schemas * @param Collection<Schema> $schemas
* @param Collection<UserCommand> $commands
*/ */
function __construct( function __construct(
public string $name, public string $name,
public string $url, public string $url,
public string $previewTarget, public string $previewTarget,
public string $generateCommand, public Collection $commands,
public Collection $schemas, public Collection $schemas,
public array $imageFilters, public array $imageFilters,
public array $roles, public array $roles,
+7 -2
View File
@@ -3,7 +3,7 @@
namespace Lucent\Channel; namespace Lucent\Channel;
use Lucent\File\FileService; use Lucent\Channel\Data\UserCommand;
use Lucent\Primitive\Collection; use Lucent\Primitive\Collection;
use Lucent\Schema\Schema; use Lucent\Schema\Schema;
use Lucent\Schema\SchemaService; use Lucent\Schema\SchemaService;
@@ -30,11 +30,16 @@ final class ChannelService
$schemaService = new SchemaService(); $schemaService = new SchemaService();
$schemasCollection = (new Collection($schemasArray["schemas"] ?? []))->map([$schemaService, 'fromArray']); $schemasCollection = (new Collection($schemasArray["schemas"] ?? []))->map([$schemaService, 'fromArray']);
$userCommands = [];
foreach (config("lucent.commands") as $signature => $desc) {
$userCommands[] = new UserCommand($desc, $signature);
}
$channel = new Channel( $channel = new Channel(
name: config("lucent.name") ?? "", name: config("lucent.name") ?? "",
url: rtrim(config("lucent.url") ?? "", "/"), url: rtrim(config("lucent.url") ?? "", "/"),
previewTarget: rtrim(config("lucent.previewTarget") ?? "", "/"), previewTarget: rtrim(config("lucent.previewTarget") ?? "", "/"),
generateCommand: config("lucent.generateCommand") ?? "", commands: Collection::make($userCommands),
schemas: $schemasCollection, schemas: $schemasCollection,
imageFilters: config("lucent.imageFilters") ?? [], imageFilters: config("lucent.imageFilters") ?? [],
roles: $schemasArray["roles"] ?? [] roles: $schemasArray["roles"] ?? []
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace Lucent\Channel\Data;
class UserCommand
{
public function __construct(
public string $name,
public string $signature,
)
{
}
}
+2 -2
View File
@@ -3,11 +3,11 @@
return [ return [
"env" => env("LUCENT_ENV", "production"), "env" => env("LUCENT_ENV", "production"),
"schemas_path" => env("LUCENT_SCHEMAS_PATH", "app/Lucent"), "schemas_path" => env("LUCENT_SCHEMAS_PATH", "app/Lucent"),
"database" => env('LUCENT_DB_CONNECTION', env('DB_CONNECTION',"sqlite")), "database" => env('LUCENT_DB_CONNECTION', env('DB_CONNECTION', "sqlite")),
"name" => env("LUCENT_NAME", "Lucent"), "name" => env("LUCENT_NAME", "Lucent"),
"url" => env("LUCENT_URL", env('APP_URL')), "url" => env("LUCENT_URL", env('APP_URL')),
"previewTarget" => env("LUCENT_PREVIEW_TARGET", "previewTarget"), "previewTarget" => env("LUCENT_PREVIEW_TARGET", "previewTarget"),
"generateCommand" => env("LUCENT_GENERATE_COMMAND", "generate:static"), "commands" => [],
"imageFilters" => [], "imageFilters" => [],
"canInvite" => ["admin"], "canInvite" => ["admin"],
"canBuild" => ["admin"], "canBuild" => ["admin"],
+42 -20
View File
@@ -5,11 +5,8 @@ namespace Lucent\Http\Controller;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Artisan;
use Lucent\Channel\ChannelService; use Lucent\Channel\ChannelService;
use Lucent\Svelte\Svelte; use Lucent\Svelte\Svelte;
use function Lucent\Response\ok;
class BuildController extends Controller class BuildController extends Controller
{ {
@@ -20,49 +17,66 @@ class BuildController extends Controller
{ {
} }
public function build() public function build(Request $request)
{ {
$commandSignature = $request->route("signature");
$buildLogFile = storage_path("lucent/build.log"); $buildLogFile = $this->getLogFile($commandSignature);
if(file_exists($buildLogFile)){ $pidFile = $this->getPidFile($commandSignature);
if (file_exists($buildLogFile)) {
unlink($buildLogFile); unlink($buildLogFile);
} }
if (file_exists($pidFile)) {
exec("cd " . base_path() . " && php8.3 artisan {$this->channelService->channel->generateCommand} > " . $buildLogFile . " 2>&1 & echo $!", $op); unlink($pidFile);
$pid = (int)$op[0];
return redirect($this->channelService->channel->lucentUrl . "/build-report");
} }
public function report(): View exec("cd " . base_path() . " && php8.3 artisan {$commandSignature} > " . $buildLogFile . " 2>&1 & echo $!", $op);
$pid = (int)$op[0];
file_put_contents($pidFile, $pid);
return redirect($this->channelService->channel->lucentUrl . "/command-report/" . $commandSignature);
}
public function report(Request $request): View
{ {
$commandSignature = $request->route("signature");
$command = $this->channelService->channel->commands->firstWhere("signature", $commandSignature);
return $this->svelte->render( return $this->svelte->render(
layout: "channel", layout: "channel",
view: "buildReport", view: "buildReport",
title: "Build Report", title: $command->name,
data: [
"command" => $command,
]
); );
} }
public function reportSource() public function reportSource(Request $request)
{ {
return response()->stream(function () { $commandSignature = $request->route("signature");
return response()->stream(function () use ($commandSignature) {
while (true) { while (true) {
// sleep(1); // 50ms
$data["date"] = date("Y-m-d H:i:s"); $data["date"] = date("Y-m-d H:i:s");
$data["logs"] = file_get_contents(storage_path("lucent/build.log")); $data["logs"] = file_get_contents($this->getLogFile($commandSignature));
// $lines = explode("\n",$data["logs"]); // $lines = explode("\n",$data["logs"]);
echo 'data: ' .json_encode($data); echo 'data: ' . json_encode($data);
echo "\n\n"; echo "\n\n";
ob_flush(); ob_flush();
flush(); flush();
if(str_contains($data["logs"],"Finito")){ $pidFile = $this->getPidFile($commandSignature);
if (file_exists($pidFile)) {
$pid = file_get_contents($pidFile);
} else {
break; break;
} }
if(str_contains($data["logs"],"Exception")){ if (empty($pid)) {
break;
}
if (!file_exists("/proc/$pid")) {
break; break;
} }
@@ -79,5 +93,13 @@ class BuildController extends Controller
]); ]);
} }
private function getLogFile(string $signature): string
{
return storage_path("lucent/$signature.log");
}
private function getPidFile(string $signature): string
{
return storage_path("lucent/$signature.pid.log");
}
} }
+3 -3
View File
@@ -33,9 +33,9 @@ Route::group([
Route::get('/profile', [AccountController::class, 'profile']); Route::get('/profile', [AccountController::class, 'profile']);
Route::post('/account/update-name', [AccountController::class, 'updateName']); Route::post('/account/update-name', [AccountController::class, 'updateName']);
Route::post('/account/update-email', [AccountController::class, 'updateEmail']); Route::post('/account/update-email', [AccountController::class, 'updateEmail']);
Route::get('/build-report', [BuildController::class, 'report']); Route::get('/command-report/{signature}', [BuildController::class, 'report']);
Route::get('/build-report-source', [BuildController::class, 'reportSource']); Route::get('/command-report-source/{signature}', [BuildController::class, 'reportSource']);
Route::post('/build', [BuildController::class, 'build']); Route::post('/command/{signature}', [BuildController::class, 'build']);
}); });
+2 -2
View File
@@ -27,11 +27,11 @@ class StaticGenerator
try { try {
$callback($this->writer); $callback($this->writer);
}catch (Throwable $th){ }catch (Throwable $th){
echo "Finito with errors".Carbon::now()->format("Y-m-d H:i:s")." ".$th->getMessage().PHP_EOL; echo "Finished with errors".Carbon::now()->format("Y-m-d H:i:s")." ".$th->getMessage().PHP_EOL;
} }
$this->copyBuildDirectory(); $this->copyBuildDirectory();
echo "Finito ".Carbon::now()->format("Y-m-d H:i:s").PHP_EOL; echo "Finished ".Carbon::now()->format("Y-m-d H:i:s").PHP_EOL;
} }
private function removeBuildDirectory() :void{ private function removeBuildDirectory() :void{