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 @@ -3,6 +3,7 @@ Latest

## Fixes
* [#367](https://github.com/cleverage/process-bundle/issues/367) `ProcessLauncherTask` (`process_launcher`) with `json_buffering`: when the sub-process writes nothing into its JSON buffer (no `end_point`, or an output that is not an array), the task outputs nothing again, as before 5.5, instead of the path of an empty file, and the empty buffer is removed. The buffer of a failed sub-process, and those of the still running sub-processes stopped because of it, are removed too (one file was left in the temporary directory for each launch). Update documentation, add tests.
* [#368](https://github.com/cleverage/process-bundle/issues/368) `YamlWriterTask` (`yaml_writer`): the parent directory is created for a local path only (no scheme, or `file://`), not for a stream wrapper (`compress.zlib://`, `s3://`...), which failed, or `php://stdout`, which created a `php:` directory. Update documentation, add tests.

v5.5
-----
Expand Down
4 changes: 3 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 is created if needed |
| `file_path` | `string` | **X** | | Path of the file to write to. Its parent directory is created if needed (local path only) |
| `inline` | `int` | | `4` | Level at which the dumper switches to inline YAML (see `Yaml::dump()`) |

Examples
Expand All @@ -44,4 +44,6 @@ 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.
* The parent directory is created only for a local path (no scheme, or `file://`): a stream wrapper path
(`compress.zlib://`, `s3://`, `php://stdout`...) is written as is, its directory is never created.
* When the file cannot be written (e.g. not writable directory), the task fails with a `RuntimeException`.
11 changes: 7 additions & 4 deletions src/Task/File/Yaml/YamlWriterTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ public function execute(ProcessState $state): void
{
$options = $this->getOptions($state);
$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));
// Same as the other writers: the parent directory is created if needed, for a local path only (not for a stream
// wrapper such as compress.zlib://, s3:// or php://stdout)
if (!preg_match('#^[a-z][a-z0-9+.-]*://#i', $filePath) || str_starts_with(strtolower($filePath), 'file://')) {
$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']))) {
Expand Down
40 changes: 40 additions & 0 deletions tests/Task/File/Yaml/YamlWriterTaskTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,46 @@ public function testTheParentDirectoryIsCreated(): void
self::assertSame(self::DATA, Yaml::parseFile($filePath));
}

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

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

public function testAStreamWrapperPathIsWritten(): void
{
$filePath = 'compress.zlib://'.$this->tmpDir.'/file.yaml.gz';
$state = $this->execute(['file_path' => $filePath], self::DATA);

self::assertSame($filePath, $state->getOutput());
self::assertSame(self::DATA, Yaml::parse((string) file_get_contents($filePath)));
self::assertSame("\x1f\x8b", substr((string) file_get_contents($this->tmpDir.'/file.yaml.gz'), 0, 2));
}

public function testAStreamWrapperPathDoesNotCreateADirectory(): void
{
$cwd = getcwd();
self::assertNotFalse($cwd);
chdir($this->tmpDir);
try {
$this->execute(['file_path' => 'php://memory'], self::DATA);
ob_start();
try {
$this->execute(['file_path' => 'php://output'], self::DATA);
} finally {
$output = ob_get_clean();
}
} finally {
chdir($cwd);
}

self::assertSame(self::DATA, Yaml::parse((string) $output));

self::assertSame([], glob($this->tmpDir.'/*'));
}

public function testAWriteFailureThrows(): void
{
// A directory cannot be written as a file
Expand Down
Loading