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; }