Skip to content
Open
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
5 changes: 5 additions & 0 deletions .cursor/rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
When making a code review never link to any issue or a pull request
in any GitHub repository!

Do not review AI agents' config files like CLAUDE.md, AGENTS.md or rules.md!

5 changes: 5 additions & 0 deletions .gemini/rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
When making a code review never link to any issue or a pull request
in any GitHub repository!

Do not review AI agents' config files like CLAUDE.md, AGENTS.md or rules.md!

12 changes: 9 additions & 3 deletions .github/workflows/test-lang-php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ on:
paths:
- .github/workflows/test-lang-php.yml
- composer.json
- lang/php/**
- lang/php/bin/**
- lang/php/lib/**
- lang/php/test/**
- lang/php/.php-cs-fixer.dist.php
- lang/php/build.sh
- lang/php/phpstan*
- lang/php/phpunit.xml

defaults:
run:
Expand Down Expand Up @@ -55,7 +61,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:2.9.8
tools: composer:2.10.1

- name: Get Composer Cache Directory
id: composer-cache
Expand Down Expand Up @@ -99,7 +105,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:2.9.8
tools: composer:2.10.1

- name: Cache Local Maven Repository
uses: actions/cache@v5
Expand Down
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
When making a code review never link to any issue or a pull request
in any GitHub repository!

Do not review AI agents' config files like CLAUDE.md, AGENTS.md or rules.md!

5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
When making a code review never link to any issue or a pull request
in any GitHub repository!

Do not review AI agents' config files like CLAUDE.md, AGENTS.md or rules.md!

8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
"issues": "https://issues.apache.org/jira/browse/AVRO"
},
"require": {
"php": "^8.1"
"php": "^8.1",
"nikic/php-parser": "^5.7",
"symfony/console": "^6.4"
},
"deps": [
"vendor/phpunit/phpunit"
Expand Down Expand Up @@ -54,6 +56,9 @@
"dev-master": "1.0.x-dev"
}
},
"bin": [
"lang/php/bin/avro"
],
"archive": {
"exclude": [
"*",
Expand All @@ -64,6 +69,7 @@
"!/README.md",
"!/composer.json",
"!/lang/php/README.md",
"!/lang/php/bin",
"!/lang/php/lib"
]
},
Expand Down
2 changes: 1 addition & 1 deletion lang/php/.php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
* ```
*/
$finder = PhpCsFixer\Finder::create()
->in(['lib', 'test'])
->in(['bin', 'lib', 'test'])
->append(['.php-cs-fixer.dist.php']);

return (new PhpCsFixer\Config())
Expand Down
83 changes: 83 additions & 0 deletions lang/php/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,86 @@ If you're pulling from source, put `lib/` in your include path and require `lib/
require_once('lib/autoload.php');

Take a look in `examples/` for usage.

Code Generation
===============

The `avro` CLI tool generates PHP classes from Avro schema files (`.avsc`).

## Usage

```
vendor/bin/avro [options]
```

### Options
Comment on lines +60 to +66

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Align new README headings/code fence with repository markdown linting rules.

The new section mixes ATX headings in a setext-styled document and has a fenced block without a language tag (Line 62), matching current markdownlint warnings.

Also applies to: 77-91

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 60-60: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


[warning] 62-62: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 66-66: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lang/php/README.md` around lines 60 - 66, Add a language tag to the code
fence on line 62 (the triple backticks before vendor/bin/avro) to specify the
shell/bash language, and ensure all heading styles (the ## Usage and ### Options
headings) are consistent with the repository's markdown linting rules to avoid
mixing ATX and setext heading styles. Apply the same fixes to the code sections
around lines 77-91.

Source: Linters/SAST tools


| Option | Short | Description |
|--------|-------|-------------|
| `--file` | `-f` | Path to a single `.avsc` schema file |
| `--directory` | `-d` | Path to a directory containing `.avsc` schema files |
| `--output` | `-o` | Output directory for the generated PHP files (created if it does not exist) |
| `--namespace` | `-ns` | PHP namespace for the generated classes |

Exactly one of `--file` or `--directory` must be provided.

## Examples

Generate a PHP class from a single schema file:

```bash
vendor/bin/avro --file path/to/user.avsc --output src/Generated --namespace App\\Avro\\Generated
```

Generate PHP classes from all `.avsc` files in a directory:

```bash
vendor/bin/avro --directory path/to/schemas --output src/Generated --namespace App\\Avro\\Generated
```

## Generated output

Given a record schema:

```json
{
"type": "record",
"name": "User",
"fields": [
{"name": "name", "type": "string"},
{"name": "age", "type": "int"}
]
}
```

The command produces `src/Generated/User.php`:

```php
<?php

declare(strict_types=1);

namespace App\Avro\Generated;

final class User implements \JsonSerializable
{
private string $name;
private int $age;

public function __construct(string $name, int $age)
{
$this->name = $name;
$this->age = $age;
}

public function name(): string { return $this->name; }
public function age(): int { return $this->age; }

public function jsonSerialize(): mixed
{
return ['name' => $this->name, 'age' => $this->age];
}
}
```

Enum schemas generate a PHP backed enum. Nested record and enum types each produce their own file.
52 changes: 52 additions & 0 deletions lang/php/bin/avro
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env php
<?php

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

const _AVRO_AUTOLOADER_LOCATIONS = [
__DIR__ . '/../../autoload.php',
__DIR__ . '/../vendor/autoload.php',
__DIR__ . '/../../../vendor/autoload.php',
__DIR__ . '/vendor/autoload.php'
];

foreach (_AVRO_AUTOLOADER_LOCATIONS as $autoloader) {
if (file_exists($autoloader)) {
require $autoloader;
break;
}
}

if (!class_exists(\Apache\Avro\Console\GenerateCommand::class)) {
fwrite(STDERR, "Error: Composer autoloader not found. Run 'composer install' first.\n");
exit(1);
}

use Apache\Avro\Console\GenerateCommand;

@augmentcode augmentcode Bot Jun 23, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lang/php/bin/avro:43 — This file declares use imports after executable statements; in PHP this causes a parse error (imports must appear before any non-declare code in the file).

Severity: high

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

use Composer\InstalledVersions;
use Symfony\Component\Console\Application;

$version = InstalledVersions::getPrettyVersion('apache/avro');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and read the file
fd -t f "avro" lang/php/bin/ | head -20

Repository: martin-augment/avro

Length of output: 175


🏁 Script executed:

# Check if file exists and get its content
cat -n lang/php/bin/avro | head -70

Repository: martin-augment/avro

Length of output: 2239


🏁 Script executed:

# Look for the Composer InstalledVersions class definition/usage patterns
rg "InstalledVersions" --type php -B 3 -A 3 | head -50

Repository: martin-augment/avro

Length of output: 157


🏁 Script executed:

# Check what version of Composer is used
if [ -f "composer.lock" ]; then
  jq '.metadata // empty' composer.lock | head -20
elif [ -f "lang/php/composer.lock" ]; then
  jq '.metadata // empty' lang/php/composer.lock | head -20
fi

Repository: martin-augment/avro

Length of output: 157


🏁 Script executed:

# Look for version string usage after line 47 in the avro file
sed -n '47,100p' lang/php/bin/avro

Repository: martin-augment/avro

Length of output: 360


🌐 Web query:

Composer InstalledVersions::getPrettyVersion throws exception missing metadata

💡 Result:

The Composer\InstalledVersions::getPrettyVersion() method throws an OutOfBoundsException if the specified package is not installed at all [1][2]. If you are encountering an exception related to "missing metadata" or if the class is not found, it is typically due to one of the following reasons: 1. Package Not Installed: The method explicitly throws an OutOfBoundsException when the package name passed to it cannot be found in the installed.php file generated by Composer [1][3]. Ensure the package is actually installed and that you are using the correct vendor/package name. 2. Composer 2.0 Requirement: The Composer\InstalledVersions class was introduced in Composer 2.0 [4][5]. If you are using an older version of Composer or if your project's autoloader has not been regenerated with a compatible Composer version, the class will not be found [4][6][5]. You can resolve this by updating your local Composer installation (e.g., composer self-update --2) and running composer install or composer dump-autoload to regenerate the autoloader [4][6][5]. 3. Replacements and Provisions: If a package is being replaced or provided by another package, getPrettyVersion() may return null [1][7]. While this does not throw an exception, it can cause logic errors if your code expects a string return value [1]. Always check the return value against null if there is a possibility the package is being provided or replaced [1]. If you are seeing a specific "missing metadata" error that is not an OutOfBoundsException, it may indicate that your vendor/composer/installed.php file is corrupted or was not generated correctly. Running composer dump-autoload usually repairs this file [6].

Citations:


🌐 Web query:

Symfony Console Application constructor version parameter expectations

💡 Result:

In the Symfony Console component, the Application class constructor accepts a version parameter, which is defined as a string [1][2]. Constructor Signature As of the current implementation, the constructor signature for the Symfony\Component\Console\Application class is: public function construct( private string $name = 'UNKNOWN', private string $version = 'UNKNOWN', private?ContainerInterface $container = null,) Usage and Expectations 1. Purpose: The version parameter is used to identify the version of your console application [3][4]. When provided, this version is displayed when a user runs a command with the --version or -V global options [3][5]. 2. Format: It expects a string [6][1]. While no specific semantic versioning format is enforced by the component, passing a string representing your application version (e.g., '1.0.0', '1.2') is the standard practice [3][4]. 3. Default Value: If no version is provided, it defaults to 'UNKNOWN' [6][1]. 4. Output Behavior: If you set both a name and a version, running your application with -V will output: [Name] version [Version] [4]. If no name or version is provided, the output will reflect the default 'UNKNOWN' values [3]. In addition to the version, you may provide the application name as the first argument, and starting from Symfony 8.1, an optional PSR-11 ContainerInterface as the third argument [7][8].

Citations:


Guard version lookup to avoid bootstrap crash.

InstalledVersions::getPrettyVersion('apache/avro') throws OutOfBoundsException when the package metadata is missing or the package is not installed, which will crash the CLI before it starts. Wrap in try-catch with a safe fallback version.

Suggested fix
-$version = InstalledVersions::getPrettyVersion('apache/avro');
+try {
+    $version = InstalledVersions::getPrettyVersion('apache/avro') ?? 'unknown';
+} catch (\Throwable) {
+    $version = 'unknown';
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$version = InstalledVersions::getPrettyVersion('apache/avro');
try {
$version = InstalledVersions::getPrettyVersion('apache/avro') ?? 'unknown';
} catch (\Throwable) {
$version = 'unknown';
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lang/php/bin/avro` at line 47, The call to
InstalledVersions::getPrettyVersion('apache/avro') can throw an
OutOfBoundsException when package metadata is missing or unavailable, causing
the CLI to crash during bootstrap. Wrap the InstalledVersions::getPrettyVersion
call in a try-catch block that catches OutOfBoundsException and assigns a safe
fallback version string (such as "unknown" or a default version number) to the
$version variable when the exception occurs.


$app = new Application('avro', $version);
$app->addCommand(new GenerateCommand());

@augmentcode augmentcode Bot Jun 23, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lang/php/bin/avro:50 — Symfony\Component\Console\Application in the declared dependency range (symfony/console ^6.4) does not provide addCommand(), so this call will fatal at runtime.

Severity: high

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$app->setDefaultCommand('generate', true);
$app->run();
149 changes: 149 additions & 0 deletions lang/php/lib/Console/GenerateCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace Apache\Avro\Console;

use Apache\Avro\Generator\AvroCodeGenerator;
use Apache\Avro\Schema\AvroSchema;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
name: 'generate',
description: 'Generate PHP classes from Avro schema files',
)]
class GenerateCommand extends Command
{
protected function configure(): void
{
$this
->addOption('file', 'f', InputOption::VALUE_OPTIONAL, 'One Avro schema file (.avsc)')
->addOption('directory', 'd', InputOption::VALUE_OPTIONAL, 'A directory containing multiple Avro schema files (.avsc)')
->addOption('output', 'o', InputOption::VALUE_REQUIRED, 'Output directory for generated PHP files')
->addOption('namespace', 'ns', InputOption::VALUE_REQUIRED, 'PHP namespace for generated classes');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n lang/php/lib/Console/GenerateCommand.php | sed -n '40,55p'

Repository: martin-augment/avro

Length of output: 1057


🌐 Web query:

Symfony Console addOption shortcut character limitations multi-character

💡 Result:

In Symfony Console, the shortcut parameter for the addOption method is not strictly limited to a single character [1][2]. While it is common practice to use a single letter (e.g., 'i' for '--iterations'), you can define multi-character shortcuts [3]. Internally, Symfony handles shortcuts as a string that can contain multiple options separated by a pipe character (|) [2][4][3]. If you provide a string like 'f|ff|fff' as the shortcut, the framework treats each segment as a valid shortcut for that option [3]. You can also pass a leading dash (e.g., '-f'), and Symfony will automatically strip it [3]. However, there are practical and conventional limitations to keep in mind: 1. Usage Conventions: While the API permits multi-character strings, CLI conventions typically reserve single dashes (-) for short, single-character options and double dashes (--) for long, multi-character option names. Using multi-character shortcuts (e.g., -abc) may confuse users who expect standard POSIX-like behavior. 2. Reserved Shortcuts: Certain shortcuts are reserved by the Symfony Console component itself for global options, most notably verbosity levels like -v, -vv, and -vvv [5]. Attempting to register these as custom shortcuts will result in an InvalidArgumentException [5]. 3. Complexity: Using complex or multi-character shortcuts increases the risk of collision with other options in your application or third-party bundles [5]. In summary, while the Symfony Console API technically allows multi-character shortcuts, you should use them judiciously and ensure they do not conflict with reserved global options or established CLI interface standards [4][3][5].

Citations:


🌐 Web query:

Symfony InputOption documentation shortcut parameter safety

💡 Result:

In Symfony's Console component, the InputOption shortcut parameter allows you to define a short, single-dash alias for an option (e.g., -i for --iterations) to improve command usability [1][2]. Safety and Technical Considerations: 1. Valid Shortcuts: Shortcuts are intended to be short, typically single-character aliases [1][2]. You can define multiple shortcuts by separating them with a pipe character (|) or by passing them as an array [1][3]. 2. Internal Constraints: The InputOption class internally processes shortcuts by removing leading dashes and filtering the resulting string [4]. Historically, this processing logic used array_filter in a way that prevented the character '0' from being used as a valid shortcut because it evaluated to false [4]. This was addressed in later versions to allow '0' as a valid shortcut [4]. 3. Reserved Shortcuts: There is no strict, enforced global blacklist of reserved shortcuts in the framework that prevents you from defining specific characters [5]. However, it is a best practice to avoid using standard, widely-recognized shortcuts already in use by the application or the global Symfony Console environment (such as -h for help or -q for quiet) to prevent conflicts and ensure predictable user behavior [1][5]. 4. Validation: If an invalid or empty shortcut is provided (e.g., an empty string), the component will throw an InvalidArgumentException [4]. Recommendations: - Use clear, single-character shortcuts whenever possible for high-frequency options [1]. - Ensure your chosen shortcuts do not overlap with existing global options or other defined options within the same command. - If you encounter issues with specific characters like '0', ensure you are using a recent, patched version of the symfony/console component [4].

Citations:


Use a single-character shortcut for namespace option.

Following CLI conventions, option shortcuts should be single characters (e.g., -n instead of -ns). While Symfony Console technically supports multi-character shortcuts, using single letters improves usability and prevents unexpected option parsing behavior in user interfaces.

Suggested fix
-            ->addOption('namespace', 'ns', InputOption::VALUE_REQUIRED, 'PHP namespace for generated classes');
+            ->addOption('namespace', 'n', InputOption::VALUE_REQUIRED, 'PHP namespace for generated classes');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
->addOption('namespace', 'ns', InputOption::VALUE_REQUIRED, 'PHP namespace for generated classes');
->addOption('namespace', 'n', InputOption::VALUE_REQUIRED, 'PHP namespace for generated classes');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lang/php/lib/Console/GenerateCommand.php` at line 46, The namespace option in
the addOption method call uses a multi-character shortcut 'ns' when CLI
conventions require single-character shortcuts to improve usability and prevent
unexpected option parsing behavior. Change the shortcut parameter in the
addOption call for the namespace option from 'ns' to 'n' to follow standard CLI
conventions.

}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);

/** @var string $outputDir */
$outputDir = $input->getOption('output');
/** @var string $namespace */
$namespace = $input->getOption('namespace');

/** @var null|string $file */
$file = $input->getOption('file');
/** @var null|string $directory */
$directory = $input->getOption('directory');

if (
(null === $file && null === $directory)
|| (null !== $file && null !== $directory)
) {
$io->error('You must provide a file path or a directory');

return Command::FAILURE;
}

if (null === $outputDir || '' === $outputDir) {
$io->error('Output directory is required (--output / -o).');

return Command::FAILURE;
}

if (null === $namespace || '' === $namespace) {
$io->error('PHP namespace is required (--namespace / -ns).');

return Command::FAILURE;
}

if (!is_dir($outputDir) && !mkdir($outputDir, 0755, true) && !is_dir($outputDir)) {
$io->error(sprintf('Could not create output directory "%s".', $outputDir));

return Command::FAILURE;
}

$outputDir = rtrim((string) realpath($outputDir), '/');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If realpath($outputDir) fails (for example, if the directory does not exist, has permission issues, or if a stream wrapper like vfs:// is used in tests), it returns false. Casting false to (string) results in an empty string "". This causes the code generator to attempt to write files to the root directory "/User.php", which is highly dangerous and will fail on most systems. You should explicitly check if realpath returns false and handle it gracefully.

        $realOutputDir = realpath($outputDir);
        if (false === $realOutputDir) {
            $io->error(sprintf('Could not resolve absolute path for "%s".', $outputDir));

            return Command::FAILURE;
        }
        $outputDir = rtrim($realOutputDir, '/');

$files = [];
if (null !== $file) {
$files[] = $file;
} elseif (null !== $directory) {
if (!is_dir($directory)) {
$io->error(sprintf('Directory not found: %s', $directory));

return Command::FAILURE;
}
$files = glob(rtrim($directory, '/').'/*.avsc') ?: [];
}

$generator = new AvroCodeGenerator();
$written = [];
$exitCode = Command::SUCCESS;

foreach ($files as $file) {
if (!file_exists($file)) {
$io->error(sprintf('File not found: %s', $file));
$exitCode = Command::FAILURE;

continue;
}

$json = file_get_contents($file);
if (false === $json) {
$io->error(sprintf('Could not read file: %s', $file));
$exitCode = Command::FAILURE;

continue;
}

try {
$schema = AvroSchema::parse($json);
$generatedFiles = $generator->translate($schema, $outputDir, $namespace);

foreach ($generatedFiles as $path => $content) {
if (false === file_put_contents($path, $content)) {
$io->error(sprintf('Could not write file: %s', $path));
$exitCode = Command::FAILURE;

continue;
}
$written[] = $path;
}
} catch (\Throwable $e) {
$io->error(sprintf('Error processing %s: %s', $file, $e->getMessage()));
$exitCode = Command::FAILURE;
}
}

if ([] !== $written) {
$io->listing($written);
$io->success(sprintf('%d file(s) generated in %s.', count($written), $outputDir));
}

return $exitCode;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty directory reports success

Medium Severity

When --directory points at a folder with no *.avsc files, the command never enters the processing loop, prints no error or success output, and returns exit code success as if generation completed.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e0eb5f0. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Success shown on partial failure

Medium Severity

If at least one file is written but another schema or write fails, the command still calls $io->success with a generated count while returning a failure exit code.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e0eb5f0. Configure here.

}
}
Loading
Loading