Skip to content

Commit 9bb1169

Browse files
committed
Merge branch 'main' into bugfix/issue-95-changes-from-html-editor-not-built-correctly
2 parents 569069c + f470e8f commit 9bb1169

5 files changed

Lines changed: 272 additions & 0 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
/**
11+
* Auto-generated Migration: Please modify to your needs!
12+
*/
13+
final class Version20260218143103 extends AbstractMigration
14+
{
15+
public function getDescription(): string
16+
{
17+
return '';
18+
}
19+
20+
public function up(Schema $schema): void
21+
{
22+
// this up() migration is auto-generated, please modify it to your needs
23+
$this->addSql('CREATE TABLE html_editor_builds (id CHAR(36) NOT NULL, workspace_id CHAR(36) NOT NULL, source_path VARCHAR(512) NOT NULL, user_email VARCHAR(255) NOT NULL, status VARCHAR(32) NOT NULL, error_message LONGTEXT DEFAULT NULL, created_at DATETIME NOT NULL, PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci`');
24+
}
25+
26+
public function down(Schema $schema): void
27+
{
28+
// this down() migration is auto-generated, please modify it to your needs
29+
$this->addSql('DROP TABLE html_editor_builds');
30+
}
31+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\ChatBasedContentEditor\Domain\Entity;
6+
7+
use App\ChatBasedContentEditor\Domain\Enum\HtmlEditorBuildStatus;
8+
use DateTimeImmutable;
9+
use Doctrine\DBAL\Types\Types;
10+
use Doctrine\ORM\Mapping as ORM;
11+
use EnterpriseToolingForSymfony\SharedBundle\DateAndTime\Service\DateAndTimeService;
12+
use Exception;
13+
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
14+
15+
#[ORM\Entity]
16+
#[ORM\Table(name: 'html_editor_builds')]
17+
class HtmlEditorBuild
18+
{
19+
/**
20+
* @throws Exception
21+
*/
22+
public function __construct(
23+
string $workspaceId,
24+
string $sourcePath,
25+
string $userEmail
26+
) {
27+
$this->workspaceId = $workspaceId;
28+
$this->sourcePath = $sourcePath;
29+
$this->userEmail = $userEmail;
30+
$this->status = HtmlEditorBuildStatus::Pending;
31+
$this->createdAt = DateAndTimeService::getDateTimeImmutable();
32+
}
33+
34+
#[ORM\Id]
35+
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
36+
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
37+
#[ORM\Column(
38+
type: Types::GUID,
39+
unique: true
40+
)]
41+
private ?string $id = null;
42+
43+
public function getId(): ?string
44+
{
45+
return $this->id;
46+
}
47+
48+
#[ORM\Column(
49+
type: Types::GUID,
50+
nullable: false
51+
)]
52+
private readonly string $workspaceId;
53+
54+
public function getWorkspaceId(): string
55+
{
56+
return $this->workspaceId;
57+
}
58+
59+
#[ORM\Column(
60+
type: Types::STRING,
61+
length: 512,
62+
nullable: false
63+
)]
64+
private readonly string $sourcePath;
65+
66+
public function getSourcePath(): string
67+
{
68+
return $this->sourcePath;
69+
}
70+
71+
#[ORM\Column(
72+
type: Types::STRING,
73+
length: 255,
74+
nullable: false
75+
)]
76+
private readonly string $userEmail;
77+
78+
public function getUserEmail(): string
79+
{
80+
return $this->userEmail;
81+
}
82+
83+
#[ORM\Column(
84+
type: Types::STRING,
85+
length: 32,
86+
nullable: false,
87+
enumType: HtmlEditorBuildStatus::class
88+
)]
89+
private HtmlEditorBuildStatus $status;
90+
91+
public function getStatus(): HtmlEditorBuildStatus
92+
{
93+
return $this->status;
94+
}
95+
96+
public function setStatus(HtmlEditorBuildStatus $status): void
97+
{
98+
$this->status = $status;
99+
}
100+
101+
#[ORM\Column(
102+
type: Types::TEXT,
103+
nullable: true
104+
)]
105+
private ?string $errorMessage = null;
106+
107+
public function getErrorMessage(): ?string
108+
{
109+
return $this->errorMessage;
110+
}
111+
112+
public function setErrorMessage(?string $errorMessage): void
113+
{
114+
$this->errorMessage = $errorMessage;
115+
}
116+
117+
#[ORM\Column(
118+
type: Types::DATETIME_IMMUTABLE,
119+
nullable: false
120+
)]
121+
private readonly DateTimeImmutable $createdAt;
122+
123+
public function getCreatedAt(): DateTimeImmutable
124+
{
125+
return $this->createdAt;
126+
}
127+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\ChatBasedContentEditor\Domain\Enum;
6+
7+
enum HtmlEditorBuildStatus: string
8+
{
9+
case Pending = 'pending';
10+
case Running = 'running';
11+
case Completed = 'completed';
12+
case Failed = 'failed';
13+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\ChatBasedContentEditor\Infrastructure\Handler;
6+
7+
use App\ChatBasedContentEditor\Domain\Entity\HtmlEditorBuild;
8+
use App\ChatBasedContentEditor\Domain\Enum\HtmlEditorBuildStatus;
9+
use App\ChatBasedContentEditor\Infrastructure\Message\RunHtmlBuildMessage;
10+
use App\ProjectMgmt\Facade\ProjectMgmtFacadeInterface;
11+
use App\WorkspaceMgmt\Facade\WorkspaceMgmtFacadeInterface;
12+
use App\WorkspaceTooling\Facade\WorkspaceToolingServiceInterface;
13+
use Doctrine\ORM\EntityManagerInterface;
14+
use Psr\Log\LoggerInterface;
15+
use RuntimeException;
16+
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
17+
use Throwable;
18+
19+
#[AsMessageHandler]
20+
final readonly class RunHtmlBuildHandler
21+
{
22+
public function __construct(
23+
private EntityManagerInterface $entityManager,
24+
private WorkspaceMgmtFacadeInterface $workspaceMgmtFacade,
25+
private ProjectMgmtFacadeInterface $projectMgmtFacade,
26+
private WorkspaceToolingServiceInterface $workspaceToolingService,
27+
private LoggerInterface $logger,
28+
) {
29+
}
30+
31+
public function __invoke(RunHtmlBuildMessage $message): void
32+
{
33+
$build = $this->entityManager->find(HtmlEditorBuild::class, $message->buildId);
34+
35+
if ($build === null) {
36+
$this->logger->error('HtmlEditorBuild not found', ['buildId' => $message->buildId]);
37+
38+
return;
39+
}
40+
41+
$build->setStatus(HtmlEditorBuildStatus::Running);
42+
$this->entityManager->flush();
43+
44+
try {
45+
$workspace = $this->workspaceMgmtFacade->getWorkspaceById($build->getWorkspaceId());
46+
47+
if ($workspace === null) {
48+
throw new RuntimeException('Workspace not found: ' . $build->getWorkspaceId());
49+
}
50+
51+
$project = $this->projectMgmtFacade->getProjectInfo($workspace->projectId);
52+
53+
$buildOutput = $this->workspaceToolingService->runBuildInWorkspace(
54+
$workspace->workspacePath,
55+
$project->agentImage
56+
);
57+
58+
$this->logger->info('HTML editor Docker build completed', [
59+
'buildId' => $message->buildId,
60+
'workspaceId' => $build->getWorkspaceId(),
61+
'sourcePath' => $build->getSourcePath(),
62+
'buildOutput' => $buildOutput,
63+
]);
64+
65+
$this->workspaceMgmtFacade->commitAndPush(
66+
$build->getWorkspaceId(),
67+
'Manual HTML edit: ' . $build->getSourcePath(),
68+
$build->getUserEmail()
69+
);
70+
71+
$build->setStatus(HtmlEditorBuildStatus::Completed);
72+
$this->entityManager->flush();
73+
} catch (Throwable $e) {
74+
$this->logger->error('HTML editor build failed', [
75+
'buildId' => $message->buildId,
76+
'workspaceId' => $build->getWorkspaceId(),
77+
'sourcePath' => $build->getSourcePath(),
78+
'error' => $e->getMessage(),
79+
]);
80+
81+
$build->setStatus(HtmlEditorBuildStatus::Failed);
82+
$build->setErrorMessage($e->getMessage());
83+
$this->entityManager->flush();
84+
}
85+
}
86+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\ChatBasedContentEditor\Infrastructure\Message;
6+
7+
use EnterpriseToolingForSymfony\SharedBundle\WorkerSystem\SymfonyMessage\ImmediateSymfonyMessageInterface;
8+
9+
readonly class RunHtmlBuildMessage implements ImmediateSymfonyMessageInterface
10+
{
11+
public function __construct(
12+
public string $buildId,
13+
) {
14+
}
15+
}

0 commit comments

Comments
 (0)