Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Latest
* [#331](https://github.com/cleverage/process-bundle/issues/331) `ProcessManager`: the iterable tasks that produced items and the blocking tasks waiting for `proceed()` are tracked by task configuration instead of task code, and forgotten when their process ends. A task of a sub-process (`process_executor`) with the same code as a task of the parent no longer makes the parent lose the output of its blocking task (without error) or skip the flush at the end of its iteration (merged batches), and a failed sub-process no longer leaves its tasks to its next execution. Add tests.
* [#333](https://github.com/cleverage/process-bundle/issues/333) `ProcessManager`: restore the previous task configuration (`getTaskConfiguration()`, read by the log processors for `task_code` and `task_service`) when a task, an initialization, a finalization or a sub-process ends. The logs of an iterable task no longer lose their task after its first item, and the logs of a parent process are no longer attributed to a task of its sub-process; the failing task is kept for the logs of the process failure. Add tests.
* [#335](https://github.com/cleverage/process-bundle/issues/335) `LineReaderTask` (`line_reader`) and `InputLineReaderTask` (`input_line_reader`): the last line of a file that does not end with a line break is no longer lost. Add tests.
* [#345](https://github.com/cleverage/process-bundle/issues/345) `YamlWriterTask` (`yaml_writer`): a write failure throws a `RuntimeException` instead of a PHP warning (an exception in debug mode only: in production, the path was output as if the file had been written), and the parent directory is created if needed, as for the other writers. Update documentation, add tests.

v5.4.1
-----
Expand Down
3 changes: 2 additions & 1 deletion docs/reference/tasks/yaml_writer_task.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Options

| Code | Type | Required | Default | Description |
|-------------|----------|:--------:|---------|------------------------------------------------------------------------|
| `file_path` | `string` | **X** | | Path of the file to write to. Its parent directory must exist |
| `file_path` | `string` | **X** | | Path of the file to write to. Its parent directory is created if needed |
| `inline` | `int` | | `4` | Level at which the dumper switches to inline YAML (see `Yaml::dump()`) |

Examples
Expand All @@ -44,3 +44,4 @@ Notes

* This task is not blocking: when receiving several inputs, each one overwrites the file. Aggregate the data first
(e.g. with [AggregateIterableTask](aggregate_iterable_task.md)) if needed.
* When the file cannot be written (e.g. not writable directory), the task fails with a `RuntimeException`.
14 changes: 12 additions & 2 deletions src/Task/File/Yaml/YamlWriterTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace CleverAge\ProcessBundle\Task\File\Yaml;

use CleverAge\ProcessBundle\Exception\RuntimeException;
use CleverAge\ProcessBundle\Model\AbstractConfigurableTask;
use CleverAge\ProcessBundle\Model\ProcessState;
use Symfony\Component\OptionsResolver\OptionsResolver;
Expand All @@ -28,8 +29,17 @@ class YamlWriterTask extends AbstractConfigurableTask
public function execute(ProcessState $state): void
{
$options = $this->getOptions($state);
file_put_contents($options['file_path'], Yaml::dump($state->getInput(), $options['inline']));
$state->setOutput($options['file_path']);
$filePath = $options['file_path'];
// Same as the other writers: the parent directory is created if needed
$dirname = \dirname($filePath);
if (!@mkdir($dirname, 0o755, true) && !is_dir($dirname)) {
throw new RuntimeException(\sprintf('Directory "%s" was not created', $dirname));
}
// The PHP warning is replaced by the exception below, also outside of the debug mode
if (false === @file_put_contents($filePath, Yaml::dump($state->getInput(), $options['inline']))) {
throw new RuntimeException(\sprintf('Unable to write file "%s": %s', $filePath, error_get_last()['message'] ?? 'unknown error'));
}
$state->setOutput($filePath);
}

protected function configureOptions(OptionsResolver $resolver): void
Expand Down
18 changes: 18 additions & 0 deletions tests/Task/File/Yaml/YamlWriterTaskTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use CleverAge\ProcessBundle\Configuration\ProcessConfiguration;
use CleverAge\ProcessBundle\Configuration\TaskConfiguration;
use CleverAge\ProcessBundle\Context\ContextualOptionResolver;
use CleverAge\ProcessBundle\Exception\RuntimeException;
use CleverAge\ProcessBundle\Model\AbstractConfigurableTask;
use CleverAge\ProcessBundle\Model\ProcessHistory;
use CleverAge\ProcessBundle\Model\ProcessState;
Expand Down Expand Up @@ -100,6 +101,23 @@ public function testEachExecutionOverwritesTheFile(): void
self::assertSame("second: 2\n", file_get_contents($filePath));
}

public function testTheParentDirectoryIsCreated(): void
{
$filePath = $this->tmpDir.'/sub/dir/file.yaml';
$this->execute(['file_path' => $filePath], self::DATA);

self::assertSame(self::DATA, Yaml::parseFile($filePath));
}

public function testAWriteFailureThrows(): void
{
// A directory cannot be written as a file
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage(\sprintf('Unable to write file "%s": ', $this->tmpDir));

$this->execute(['file_path' => $this->tmpDir], self::DATA);
}

public function testScalarInputIsDumped(): void
{
$filePath = $this->tmpDir.'/file.yaml';
Expand Down
Loading