From 9f0191bc49eb1a5ad12cdf1e31b37f8a93745b7b Mon Sep 17 00:00:00 2001
From: sebprt <sebastien@kiboko.fr>
Date: Tue, 24 Oct 2023 17:17:55 +0200
Subject: [PATCH] Added workflow management

---
 .../Workflow/RemoveWorkflowCommand.php        |  15 ++
 src/Cloud/CommandBus.php                      |   1 +
 src/Cloud/Console/Command/CreateCommand.php   |  37 ++++-
 src/Cloud/DTO/ReferencedWorkflow.php          |  53 +++++++
 src/Cloud/DTO/Workflow.php                    |  53 +++++++
 src/Cloud/DTO/Workflow/JobInterface.php       |   1 -
 src/Cloud/DTO/WorkflowInterface.php           |  22 +++
 .../DeclareWorkflowCommandHandler.php         |  70 ++++-----
 .../Workflow/RemoveWorkflowCommandHandler.php |  20 +++
 src/Cloud/Workflow.php                        | 145 +++++++++++-------
 src/Cloud/WorkflowInterface.php               |  12 +-
 11 files changed, 317 insertions(+), 112 deletions(-)
 create mode 100644 src/Cloud/Command/Workflow/RemoveWorkflowCommand.php
 create mode 100644 src/Cloud/DTO/ReferencedWorkflow.php
 create mode 100644 src/Cloud/DTO/Workflow.php
 create mode 100644 src/Cloud/DTO/WorkflowInterface.php
 create mode 100644 src/Cloud/Handler/Workflow/RemoveWorkflowCommandHandler.php

diff --git a/src/Cloud/Command/Workflow/RemoveWorkflowCommand.php b/src/Cloud/Command/Workflow/RemoveWorkflowCommand.php
new file mode 100644
index 00000000..c4e00bba
--- /dev/null
+++ b/src/Cloud/Command/Workflow/RemoveWorkflowCommand.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Kiboko\Component\Satellite\Cloud\Command\Workflow;
+
+use Kiboko\Component\Satellite\Cloud\Command\Command;
+use Kiboko\Component\Satellite\Cloud\DTO\WorkflowId;
+
+final class RemoveWorkflowCommand implements Command
+{
+    public function __construct(
+        public WorkflowId $workflow,
+    ) {}
+}
diff --git a/src/Cloud/CommandBus.php b/src/Cloud/CommandBus.php
index fbe1a53d..9011c091 100644
--- a/src/Cloud/CommandBus.php
+++ b/src/Cloud/CommandBus.php
@@ -30,6 +30,7 @@ public static function withStandardHandlers(Client $client): self
             Satellite\Cloud\Command\Pipeline\ReplacePipelineStepCommand::class => new Satellite\Cloud\Handler\Pipeline\ReplacePipelineStepCommandHandler($client),
             Satellite\Cloud\Command\Pipeline\RemovePipelineStepCommand::class => new Satellite\Cloud\Handler\Pipeline\RemovePipelineStepCommandHandler($client),
             Satellite\Cloud\Command\Workflow\DeclareWorkflowCommand::class => new Satellite\Cloud\Handler\Workflow\DeclareWorkflowCommandHandler($client),
+            Satellite\Cloud\Command\Workflow\RemoveWorkflowCommand::class => new Satellite\Cloud\Handler\Workflow\RemoveWorkflowCommandHandler($client),
         ]);
     }
 
diff --git a/src/Cloud/Console/Command/CreateCommand.php b/src/Cloud/Console/Command/CreateCommand.php
index 834c6ae9..180e8287 100644
--- a/src/Cloud/Console/Command/CreateCommand.php
+++ b/src/Cloud/Console/Command/CreateCommand.php
@@ -23,6 +23,7 @@ protected function configure(): void
         $this->addOption('beta', mode: Console\Input\InputOption::VALUE_NONE, description: 'Shortcut to set the cloud instance to https://beta.gyroscops.com');
         $this->addOption('ssl', mode: Console\Input\InputOption::VALUE_NEGATABLE, description: 'Enable or disable SSL');
         $this->addArgument('config', Console\Input\InputArgument::REQUIRED);
+        $this->addArgument('type', Console\Input\InputArgument::REQUIRED, 'Type de configuration (pipeline ou workflow)');
     }
 
     protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output): int
@@ -62,6 +63,12 @@ protected function execute(Console\Input\InputInterface $input, Console\Output\O
             }
         }
 
+        $type = $input->getArgument('type');
+        if ($type !== 'pipeline' && $type !== 'workflow') {
+            $output->writeln('Le type doit ĂȘtre soit "pipeline" soit "workflow".');
+            return Console\Command\Command::FAILURE;
+        }
+
         for ($directory = getcwd(); '/' !== $directory; $directory = \dirname($directory)) {
             if (file_exists($directory.'/.gyro.php')) {
                 break;
@@ -121,16 +128,32 @@ protected function execute(Console\Input\InputInterface $input, Console\Output\O
         }
 
         $context = new Satellite\Cloud\Context($client, $auth, $url);
-        $pipeline = new Satellite\Cloud\Pipeline($context);
-        if (!\array_key_exists('version', $configuration)) {
-            foreach ($pipeline->create(Satellite\Cloud\Pipeline::fromLegacyConfiguration($configuration['satellite'])) as $command) {
-                $bus->push($command);
+
+        if ($type === 'pipeline') {
+            $pipeline = new Satellite\Cloud\Pipeline($context);
+            if (!\array_key_exists('version', $configuration)) {
+                foreach ($pipeline->create(Satellite\Cloud\Pipeline::fromLegacyConfiguration($configuration['satellite'])) as $command) {
+                    $bus->push($command);
+                }
+            } else {
+                foreach ($configuration['satellites'] as $satellite) {
+                    foreach ($pipeline->create(Satellite\Cloud\Pipeline::fromLegacyConfiguration($satellite)) as $command) {
+                        $bus->push($command);
+                    }
+                }
             }
-        } else {
-            foreach ($configuration['satellites'] as $satellite) {
-                foreach ($pipeline->create(Satellite\Cloud\Pipeline::fromLegacyConfiguration($satellite)) as $command) {
+        } elseif ($type === 'workflow') {
+            $workflow = new Satellite\Cloud\Workflow($context);
+            if (!\array_key_exists('version', $configuration)) {
+                foreach ($workflow->create(Satellite\Cloud\Workflow::fromLegacyConfiguration($configuration['satellite'])) as $command) {
                     $bus->push($command);
                 }
+            } else {
+                foreach ($configuration['satellites'] as $satellite) {
+                    foreach ($workflow->create(Satellite\Cloud\Workflow::fromLegacyConfiguration($satellite)) as $command) {
+                        $bus->push($command);
+                    }
+                }
             }
         }
 
diff --git a/src/Cloud/DTO/ReferencedWorkflow.php b/src/Cloud/DTO/ReferencedWorkflow.php
new file mode 100644
index 00000000..ea7e3b62
--- /dev/null
+++ b/src/Cloud/DTO/ReferencedWorkflow.php
@@ -0,0 +1,53 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Kiboko\Component\Satellite\Cloud\DTO;
+
+final class ReferencedWorkflow implements WorkflowInterface
+{
+    public function __construct(
+        private WorkflowId $id,
+        private Workflow $decorated,
+    ) {}
+
+    public function id(): WorkflowId
+    {
+        return $this->id;
+    }
+
+    public function code(): string
+    {
+        return $this->decorated->code();
+    }
+
+    public function label(): string
+    {
+        return $this->decorated->label();
+    }
+
+    public function jobs(): JobList
+    {
+        return $this->decorated->jobs();
+    }
+
+    public function autoload(): Autoload
+    {
+        return $this->decorated->autoload();
+    }
+
+    public function packages(): PackageList
+    {
+        return $this->decorated->packages();
+    }
+
+    public function repositories(): RepositoryList
+    {
+        return $this->decorated->repositories();
+    }
+
+    public function auths(): AuthList
+    {
+        return $this->decorated->auths();
+    }
+}
diff --git a/src/Cloud/DTO/Workflow.php b/src/Cloud/DTO/Workflow.php
new file mode 100644
index 00000000..8868ae43
--- /dev/null
+++ b/src/Cloud/DTO/Workflow.php
@@ -0,0 +1,53 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Kiboko\Component\Satellite\Cloud\DTO;
+
+final readonly class Workflow implements WorkflowInterface
+{
+    public function __construct(
+        private string $label,
+        private string $code,
+        private JobList $jobs,
+        private Autoload $autoload,
+        private PackageList $packages,
+        private RepositoryList $repositories,
+        private AuthList $auths,
+    ) {}
+
+    public function code(): string
+    {
+        return $this->code;
+    }
+
+    public function label(): string
+    {
+        return $this->label;
+    }
+
+    public function jobs(): JobList
+    {
+        return $this->jobs;
+    }
+
+    public function autoload(): Autoload
+    {
+        return $this->autoload;
+    }
+
+    public function packages(): PackageList
+    {
+        return $this->packages;
+    }
+
+    public function repositories(): RepositoryList
+    {
+        return $this->repositories;
+    }
+
+    public function auths(): AuthList
+    {
+        return $this->auths;
+    }
+}
diff --git a/src/Cloud/DTO/Workflow/JobInterface.php b/src/Cloud/DTO/Workflow/JobInterface.php
index 840abd8b..266feca4 100644
--- a/src/Cloud/DTO/Workflow/JobInterface.php
+++ b/src/Cloud/DTO/Workflow/JobInterface.php
@@ -8,5 +8,4 @@
 
 interface JobInterface
 {
-
 }
diff --git a/src/Cloud/DTO/WorkflowInterface.php b/src/Cloud/DTO/WorkflowInterface.php
new file mode 100644
index 00000000..62f66e10
--- /dev/null
+++ b/src/Cloud/DTO/WorkflowInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Kiboko\Component\Satellite\Cloud\DTO;
+
+interface WorkflowInterface
+{
+    public function code(): string;
+
+    public function label(): string;
+
+    public function jobs(): JobList;
+
+    public function autoload(): Autoload;
+
+    public function packages(): PackageList;
+
+    public function repositories(): RepositoryList;
+
+    public function auths(): AuthList;
+}
diff --git a/src/Cloud/Handler/Workflow/DeclareWorkflowCommandHandler.php b/src/Cloud/Handler/Workflow/DeclareWorkflowCommandHandler.php
index 1090f97c..eddf6265 100644
--- a/src/Cloud/Handler/Workflow/DeclareWorkflowCommandHandler.php
+++ b/src/Cloud/Handler/Workflow/DeclareWorkflowCommandHandler.php
@@ -6,9 +6,7 @@
 
 use Gyroscops\Api;
 use Kiboko\Component\Satellite\Cloud;
-use Kiboko\Component\Satellite\Cloud\DTO\Probe;
 use Kiboko\Component\Satellite\Cloud\DTO\PSR4AutoloadConfig;
-use Kiboko\Component\Satellite\Cloud\DTO\Step;
 
 final readonly class DeclareWorkflowCommandHandler
 {
@@ -16,53 +14,43 @@ public function __construct(
         private Api\Client $client,
     ) {}
 
-    /** TODO: update this method */
-    public function __invoke(Cloud\Command\Pipeline\DeclarePipelineCommand $command): Cloud\Event\PipelineDeclared
+    public function __invoke(Cloud\Command\Workflow\DeclareWorkflowCommand $command): Cloud\Event\Workflow\WorkflowDeclared
     {
         try {
-            /** @var \stdClass $result */
-            $result = $this->client->declarePipelinePipelineCollection(
-                (new Api\Model\PipelineDeclarePipelineCommandInput())
+            /** @var Api\Model\WorkflowDeclareWorkflowCommandJsonldRead $result */
+            $result = $this->client->declareWorkflowWorkflowCollection(
+                (new Api\Model\WorkflowDeclareWorkflowCommandInput())
                     ->setLabel($command->label)
                     ->setCode($command->code)
-                    ->setSteps($command->steps->map(
-                        fn (Step $step) => (new Api\Model\StepInput())
-                            ->setCode((string) $step->code)
-                            ->setLabel($step->label)
-                            ->setConfiguration($step->config)
-                            ->setProbes($step->probes->map(
-                                fn (Probe $probe) => (new Api\Model\Probe())->setCode($probe->code)->setLabel($probe->label))
-                            )
-                    ))
-                    ->setAutoloads($command->autoload->map(
-                        fn (PSR4AutoloadConfig $autoloadConfig) => (new Api\Model\AutoloadInput())
-                            ->setNamespace($autoloadConfig->namespace)
-                            ->setPaths($autoloadConfig->paths)
-                    ))
-                    ->setPackages($command->packages->transform())
-                    ->setAuths($command->auths->map(
-                        fn (Cloud\DTO\Auth $auth) => (new Api\Model\AddPipelineComposerAuthCommandInput())
-                            ->setUrl($auth->url)
-                            ->setToken($auth->token)
-                    ))
-                    ->setRepositories($command->repositories->map(
-                        fn (Cloud\DTO\Repository $repository) => (new Api\Model\AddPipelineComposerRepositoryCommandInput())
-                            ->setName($repository->name)
-                            ->setType($repository->type)
-                            ->setUrl($repository->url)
-                    )),
+                    ->setComposer(
+                        (new Api\Model\Composer())
+                            ->setAutoloads($command->autoload->map(
+                                fn (PSR4AutoloadConfig $autoloadConfig) => (new Api\Model\ComposerAutoload())
+                                    ->setNamespace($autoloadConfig->namespace)
+                                    ->setPaths($autoloadConfig->paths)
+                            ))
+                            ->setPackages($command->packages->transform())
+                            ->setAuthentications($command->auths->map(
+                                fn (Cloud\DTO\Auth $auth) => (new Api\Model\ComposerAuthentication())
+                                    ->setUrl($auth->url)
+                                    ->setToken($auth->token)
+                            ))
+                            ->setRepositories($command->repositories->map(
+                                fn (Cloud\DTO\Repository $repository) => (new Api\Model\ComposerRepository())
+                                    ->setName($repository->name)
+                                    ->setType($repository->type)
+                                    ->setUrl($repository->url)
+                            ))
+                    ),
             );
-        } catch (Api\Exception\DeclarePipelinePipelineCollectionBadRequestException $exception) {
+        } catch (Api\Exception\DeclareWorkflowWorkflowCollectionBadRequestException $exception) {
             throw new Cloud\DeclarePipelineFailedException('Something went wrong while declaring the pipeline. Maybe your client is not up to date, you may want to update your Gyroscops client.', previous: $exception);
-        } catch (Api\Exception\DeclarePipelinePipelineCollectionUnprocessableEntityException $exception) {
+        } catch (Api\Exception\DeclareWorkflowWorkflowCollectionUnprocessableEntityException $exception) {
             throw new Cloud\DeclarePipelineFailedException('Something went wrong while declaring the pipeline. It seems the data you sent was invalid, please check your input.', previous: $exception);
+        } catch (\Exception $exception) {
+            var_dump($exception);
         }
 
-        if (null === $result) {
-            // TODO: change the exception message, it doesn't give enough details on how to fix the issue
-            throw new Cloud\DeclarePipelineFailedException('Something went wrong while declaring the pipeline.');
-        }
-
-        return new Cloud\Event\PipelineDeclared($result->id);
+        return new Cloud\Event\Workflow\WorkflowDeclared($result->getId());
     }
 }
diff --git a/src/Cloud/Handler/Workflow/RemoveWorkflowCommandHandler.php b/src/Cloud/Handler/Workflow/RemoveWorkflowCommandHandler.php
new file mode 100644
index 00000000..81f24a60
--- /dev/null
+++ b/src/Cloud/Handler/Workflow/RemoveWorkflowCommandHandler.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Kiboko\Component\Satellite\Cloud\Handler\Workflow;
+
+use Kiboko\Component\Satellite\Cloud;
+
+final class RemoveWorkflowCommandHandler
+{
+    public function __construct(
+        \Gyroscops\Api\Client $client,
+    ) {
+    }
+
+    public function __invoke(Cloud\Command\Workflow\DeclareWorkflowCommand $command)
+    {
+
+    }
+}
diff --git a/src/Cloud/Workflow.php b/src/Cloud/Workflow.php
index 35f56e62..eb632fe5 100644
--- a/src/Cloud/Workflow.php
+++ b/src/Cloud/Workflow.php
@@ -6,49 +6,85 @@
 
 use Gyroscops\Api;
 use Kiboko\Component\Satellite\Cloud\DTO\AuthList;
+use Kiboko\Component\Satellite\Cloud\DTO\JobCode;
 use Kiboko\Component\Satellite\Cloud\DTO\Package;
 use Kiboko\Component\Satellite\Cloud\DTO\PipelineId;
 use Kiboko\Component\Satellite\Cloud\DTO\ProbeList;
 use Kiboko\Component\Satellite\Cloud\DTO\ReferencedPipeline;
+use Kiboko\Component\Satellite\Cloud\DTO\ReferencedWorkflow;
 use Kiboko\Component\Satellite\Cloud\DTO\RepositoryList;
+use Kiboko\Component\Satellite\Cloud\DTO\Step;
 use Kiboko\Component\Satellite\Cloud\DTO\StepCode;
+use Kiboko\Component\Satellite\Cloud\DTO\StepList;
+use Kiboko\Component\Satellite\Cloud\DTO\WorkflowId;
 use Symfony\Component\ExpressionLanguage\Expression;
 
-final readonly class Workflow implements PipelineInterface
+final readonly class Workflow implements WorkflowInterface
 {
     public function __construct(
         private Context $context,
     ) {}
 
-    public static function fromLegacyConfiguration(array $configuration): DTO\Pipeline
+    public static function fromLegacyConfiguration(array $configuration): DTO\Workflow
     {
         $random = bin2hex(random_bytes(4));
 
-        return new DTO\Pipeline(
-            $configuration['pipeline']['name'] ?? sprintf('Pipeline %s', $random),
-            $configuration['pipeline']['code'] ?? sprintf('pipeline_%s', $random),
-            new DTO\StepList(
-                ...array_map(function (array $stepConfig, int $order) {
-                    $name = $stepConfig['name'] ?? sprintf('step%d', $order);
-                    $code = $stepConfig['code'] ?? sprintf('step%d', $order);
-                    unset($stepConfig['name'], $stepConfig['code']);
-
-                    array_walk_recursive($stepConfig, function (&$value): void {
-                        if ($value instanceof Expression) {
-                            $value = '@='.$value;
-                        }
-                    });
+        return new DTO\Workflow(
+            $configuration['pipeline']['name'] ?? sprintf('Workflow %s', $random),
+            $configuration['pipeline']['code'] ?? sprintf('workflow_%s', $random),
+            new DTO\JobList(
+                ...array_map(
+                    function (array $config, int $order) {
+                        if (array_key_exists('pipeline', $config)) {
+                            $name = $config['pipeline']['name'] ?? sprintf('pipeline%d', $order);
+                            $code = $config['pipeline']['code'] ?? sprintf('pipeline%d', $order);
+                            unset($config['pipeline']['name'], $config['pipeline']['code']);
 
-                    return new DTO\Step(
-                        $name,
-                        new StepCode($code),
-                        $stepConfig,
-                        new ProbeList(
-                            // FIXME: add probes
-                        ),
-                        $order,
-                    );
-                }, $configuration['pipeline']['steps'], range(0, (is_countable($configuration['pipeline']['steps']) ? \count($configuration['pipeline']['steps']) : 0) - 1))
+                            array_walk_recursive($config, function (&$value): void {
+                                if ($value instanceof Expression) {
+                                    $value = '@='.$value;
+                                }
+                            });
+
+                            return new DTO\Workflow\Pipeline(
+                                $name,
+                                new JobCode($code),
+                                new StepList(
+                                    ...array_map(fn (array $step, int $order) => new Step(
+                                            $step['name'] ?? sprintf('step%d', $order),
+                                            new StepCode($step['code'] ?? sprintf('step%d', $order)),
+                                            $step,
+                                            new ProbeList(),
+                                            $order
+                                        ),
+                                        $config['pipeline']['steps'],
+                                        range(0, (is_countable($config['pipeline']['steps']) ? \count($config['pipeline']['steps']) : 0) - 1)
+                                    ),
+                                ),
+                                $order
+                            );
+                        } elseif (array_key_exists('action', $config)) {
+                            $name = $config['action']['name'] ?? sprintf('pipeline%d', $order);
+                            $code = $config['action']['code'] ?? sprintf('pipeline%d', $order);
+                            unset($config['action']['name'], $config['action']['code']);
+
+                            array_walk_recursive($config, function (&$value): void {
+                                if ($value instanceof Expression) {
+                                    $value = '@='.$value;
+                                }
+                            });
+
+                            return new DTO\Workflow\Action(
+                                $name,
+                                new JobCode($code),
+                                $config,
+                                $order,
+                            );
+                        }
+                    },
+                    $configuration['workflow']['jobs'],
+                    range(0, (is_countable($configuration['workflow']['jobs']) ? \count($configuration['workflow']['jobs']) : 0) - 1)
+                )
             ),
             new DTO\Autoload(
                 ...array_map(
@@ -62,7 +98,7 @@ public static function fromLegacyConfiguration(array $configuration): DTO\Pipeli
                     function (string $namespace) {
                         $parts = explode(':', $namespace);
 
-                        return new Package($parts[0], $parts[1]);
+                         return new Package($parts[0], $parts[1] ?? '*');
                     },
                     $configuration['composer']['require'] ?? [],
                 )
@@ -82,7 +118,7 @@ function (string $namespace) {
         );
     }
 
-    public static function fromApiWithId(Api\Client $client, PipelineId $id, array $configuration): DTO\ReferencedPipeline
+    public static function fromApiWithId(Api\Client $client, WorkflowId $id, array $configuration): DTO\ReferencedWorkflow
     {
         $item = $client->getPipelineItem($id->asString());
 
@@ -92,13 +128,13 @@ public static function fromApiWithId(Api\Client $client, PipelineId $id, array $
             throw new AccessDeniedException('Could not retrieve the pipeline.');
         }
 
-        return new ReferencedPipeline(
-            new PipelineId($item->getId()),
+        return new ReferencedWorkflow(
+            new WorkflowId($item->getId()),
             self::fromApiModel($client, $item, $configuration)
         );
     }
 
-    public static function fromApiWithCode(Api\Client $client, string $code, array $configuration): DTO\ReferencedPipeline
+    public static function fromApiWithCode(Api\Client $client, string $code, array $configuration): DTO\ReferencedWorkflow
     {
         $collection = $client->getPipelineCollection(['code' => $code]);
 
@@ -114,15 +150,15 @@ public static function fromApiWithCode(Api\Client $client, string $code, array $
             throw new \OverflowException('There seems to be several pipelines with the same code, please contact your Customer Success Manager.');
         }
 
-        return new ReferencedPipeline(
-            new PipelineId($collection[0]->getId()),
+        return new ReferencedWorkflow(
+            new WorkflowId($collection[0]->getId()),
             self::fromApiModel($client, $collection[0], $configuration)
         );
     }
 
-    private static function fromApiModel(Api\Client $client, Api\Model\PipelineRead $model, array $configuration): DTO\Pipeline
+    private static function fromApiModel(Api\Client $client, Api\Model\PipelineRead $model, array $configuration): DTO\Workflow
     {
-        $steps = $client->apiPipelineStepsProbesGetSubresourcePipelineStepSubresource($model->getId());
+        $steps = $client->add($model->getId());
 
         try {
             \assert(\is_array($steps));
@@ -130,10 +166,10 @@ private static function fromApiModel(Api\Client $client, Api\Model\PipelineRead
             throw new AccessDeniedException('Could not retrieve the pipeline steps.');
         }
 
-        return new DTO\Pipeline(
+        return new DTO\Workflow(
             $model->getLabel(),
             $model->getCode(),
-            new DTO\StepList(
+            new DTO\JobList(
                 ...array_map(function (Api\Model\PipelineStep $step, int $order) use ($client) {
                     $probes = $client->apiPipelineStepsProbesGetSubresourcePipelineStepSubresource($step->getId());
 
@@ -160,7 +196,7 @@ private static function fromApiModel(Api\Client $client, Api\Model\PipelineRead
                     function (string $namespace) {
                         $parts = explode(':', $namespace);
 
-                        return new Package($parts[0], $parts[1]);
+                        return new Package($parts[0], $parts[1] ?? '*');
                     },
                     $model->getPackages(),
                 )
@@ -180,48 +216,43 @@ function (string $namespace) {
         );
     }
 
-    public function create(DTO\PipelineInterface $pipeline): DTO\CommandBatch
+    public function create(DTO\WorkflowInterface $workflow): DTO\CommandBatch
     {
         return new DTO\CommandBatch(
-            new Command\Pipeline\DeclarePipelineCommand(
-                $pipeline->code(),
-                $pipeline->label(),
-                $pipeline->steps(),
-                $pipeline->autoload(),
-                $pipeline->packages(),
-                $pipeline->repositories(),
-                $pipeline->auths(),
+            new Command\Workflow\DeclareWorkflowCommand(
+                $workflow->code(),
+                $workflow->label(),
+                $workflow->jobs(),
+                $workflow->autoload(),
+                $workflow->packages(),
+                $workflow->repositories(),
+                $workflow->auths(),
                 $this->context->organization(),
                 $this->context->workspace(),
             )
         );
     }
 
-    public function update(DTO\ReferencedPipeline $actual, DTO\PipelineInterface $desired): DTO\CommandBatch
+    public function update(DTO\ReferencedWorkflow $actual, DTO\WorkflowInterface $desired): DTO\CommandBatch
     {
         if ($actual->code() !== $desired->code()) {
-            throw new \RuntimeException('Code does not match between actual and desired pipeline definition.');
+            throw new \RuntimeException('Code does not match between actual and desired workflow definition.');
         }
         if ($actual->label() !== $desired->label()) {
-            throw new \RuntimeException('Label does not match between actual and desired pipeline definition.');
+            throw new \RuntimeException('Label does not match between actual and desired workflow definition.');
         }
 
         // Check the changes in the list of steps
         $diff = new Diff\StepListDiff($actual->id());
         $commands = $diff->diff($actual->steps(), $desired->steps());
 
-        // Check the changes in the list of autoloads
-        if (\count($actual->autoload()) !== \count($desired->autoload())) {
-            // TODO: make diff of the autoload
-        }
-
         return new DTO\CommandBatch(...$commands);
     }
 
-    public function remove(DTO\PipelineId $id): DTO\CommandBatch
+    public function remove(DTO\WorkflowId $id): DTO\CommandBatch
     {
         return new DTO\CommandBatch(
-            new Command\Pipeline\RemovePipelineCommand($id),
+            new Command\Workflow\RemoveWorkflowCommand($id),
         );
     }
 }
diff --git a/src/Cloud/WorkflowInterface.php b/src/Cloud/WorkflowInterface.php
index 30988252..5326a3a1 100644
--- a/src/Cloud/WorkflowInterface.php
+++ b/src/Cloud/WorkflowInterface.php
@@ -5,19 +5,19 @@
 namespace Kiboko\Component\Satellite\Cloud;
 
 use Gyroscops\Api\Client;
-use Kiboko\Component\Satellite\Cloud\DTO\WorkflowId;
+use Kiboko\Component\Satellite\Cloud\DTO;
 
 interface WorkflowInterface
 {
     public static function fromLegacyConfiguration(array $configuration): DTO\Workflow;
 
-    public static function fromApiWithId(Client $client, WorkflowId $id, array $configuration): DTO\ReferencedPipeline;
+    public static function fromApiWithId(Client $client, DTO\WorkflowId $id, array $configuration): DTO\ReferencedWorkflow;
 
-    public static function fromApiWithCode(Client $client, string $code, array $configuration): DTO\ReferencedPipeline;
+    public static function fromApiWithCode(Client $client, string $code, array $configuration): DTO\ReferencedWorkflow;
 
-    public function create(DTO\PipelineInterface $pipeline): DTO\CommandBatch;
+    public function create(DTO\WorkflowInterface $workflow): DTO\CommandBatch;
 
-    public function update(DTO\ReferencedPipeline $actual, DTO\PipelineInterface $desired): DTO\CommandBatch;
+    public function update(DTO\ReferencedWorkflow $actual, DTO\WorkflowInterface $desired): DTO\CommandBatch;
 
-    public function remove(DTO\PipelineId $id): DTO\CommandBatch;
+    public function remove(DTO\WorkflowId $id): DTO\CommandBatch;
 }