fix: throw RuntimeException for unresolved response models in spec generation

Spec generation silently produced a fatal error when a response model
string could not be resolved to a registered model object. Now throws a
clear RuntimeException in both Swagger2 and OpenAPI3 formats, for both
single and array model responses.

Also adds a CI job to run spec generation on every PR so unresolved
models are caught before merge.
This commit is contained in:
Chirag Aggarwal
2026-04-08 10:41:43 +05:30
parent f71a98a527
commit dd4a43b78c
4 changed files with 50 additions and 1 deletions
+20
View File
@@ -161,6 +161,26 @@ jobs:
- name: Run PHPStan
run: composer analyze -- --no-progress
specs:
name: Checks / Specs
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer:v2
coverage: none
- name: Install dependencies
run: composer install --prefer-dist --no-progress --ignore-platform-reqs
- name: Generate specs
run: _APP_STORAGE_LIMIT=5368709120 php app/cli.php specs --version=latest --git=no
locale:
name: Checks / Locale
runs-on: ubuntu-latest
+6 -1
View File
@@ -482,7 +482,12 @@ class Specs extends Action
? $specsDir . '/' . $format . '-mocks-' . $platform . '.json'
: $specsDir . '/' . $format . '-' . $version . '-' . $platform . '.json';
$parsedSpecs = $specs->parse();
try {
$parsedSpecs = $specs->parse();
} catch (\RuntimeException $e) {
throw new \RuntimeException("Spec generation failed for {$platform} ({$format}): " . $e->getMessage(), 0, $e);
}
$encodedSpecs = \json_encode($parsedSpecs, JSON_PRETTY_PRINT);
unset($parsedSpecs);
@@ -278,6 +278,18 @@ class OpenAPI3 extends Format
}
}
if (\is_string($model)) {
throw new \RuntimeException("Unresolved response model '{$model}' for method '{$sdk->getNamespace()}.{$sdk->getMethodName()}'. Ensure the model is registered.");
}
if (\is_array($model)) {
foreach ($model as $m) {
if (\is_string($m)) {
throw new \RuntimeException("Unresolved response model '{$m}' for method '{$sdk->getNamespace()}.{$sdk->getMethodName()}'. Ensure the model is registered.");
}
}
}
if (!(\is_array($model)) && $model->isNone()) {
$temp['responses'][(string)$response->getCode() ?? '500'] = [
'description' => in_array($produces, [
@@ -285,6 +285,18 @@ class Swagger2 extends Format
}
}
if (\is_string($model)) {
throw new \RuntimeException("Unresolved response model '{$model}' for method '{$sdk->getNamespace()}.{$sdk->getMethodName()}'. Ensure the model is registered.");
}
if (\is_array($model)) {
foreach ($model as $m) {
if (\is_string($m)) {
throw new \RuntimeException("Unresolved response model '{$m}' for method '{$sdk->getNamespace()}.{$sdk->getMethodName()}'. Ensure the model is registered.");
}
}
}
if (!(\is_array($model)) && $model->isNone()) {
$temp['responses'][(string)$response->getCode() ?? '500'] = [
'description' => in_array($produces, [