mirror of
https://github.com/tiennm99/coolify.git
synced 2026-04-17 21:20:29 +00:00
feat: add validation for YAML parsing, integer parameters, and Docker Compose custom fields
This commit adds comprehensive validation improvements and DRY principles for handling Coolify's custom Docker Compose extensions. ## Changes ### 1. Created Reusable stripCoolifyCustomFields() Function - Added shared helper in bootstrap/helpers/docker.php - Removes all Coolify custom fields (exclude_from_hc, content, isDirectory, is_directory) - Handles both long syntax (arrays) and short syntax (strings) for volumes - Well-documented with comprehensive docblock - Follows DRY principle for consistent field stripping ### 2. Fixed Docker Compose Modal Validation - Updated validateComposeFile() to use stripCoolifyCustomFields() - Now removes ALL custom fields before Docker validation (previously only removed content) - Fixes validation errors when using templates with custom fields (e.g., traccar.yaml) - Users can now validate compose files with Coolify extensions in UI ### 3. Enhanced YAML Validation in CalculatesExcludedStatus - Added proper exception handling with ParseException vs generic Exception - Added structure validation (checks if parsed result and services are arrays) - Comprehensive logging with context (error message, line number, snippet) - Maintains safe fallback behavior (returns empty collection on error) ### 4. Added Integer Validation to ContainerStatusAggregator - Validates maxRestartCount parameter in both aggregateFromStrings() and aggregateFromContainers() - Corrects negative values to 0 with warning log - Logs warnings for suspiciously high values (> 1000) - Prevents logic errors in crash loop detection ### 5. Comprehensive Unit Tests - tests/Unit/StripCoolifyCustomFieldsTest.php (NEW) - 9 tests, 43 assertions - tests/Unit/ContainerStatusAggregatorTest.php - Added 6 tests for integer validation - tests/Unit/ExcludeFromHealthCheckTest.php - Added 4 tests for YAML validation - All tests passing with proper Log facade mocking ### 6. Documentation - Added comprehensive Docker Compose extensions documentation to .ai/core/deployment-architecture.md - Documents all custom fields: exclude_from_hc, content, isDirectory/is_directory - Includes examples, use cases, implementation details, and test references - Updated .ai/README.md with navigation links to new documentation ## Benefits - Better UX: Users can validate compose files with custom fields - Better Debugging: Comprehensive logging for errors - Better Code Quality: DRY principle with reusable validation - Better Reliability: Prevents logic errors from invalid parameters - Better Maintainability: Easy to add new custom fields in future 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -104,3 +104,51 @@ it('ensures UI handles excluded status in service heading buttons', function ()
|
||||
->toContain('str($service->status)->contains(\'degraded\')')
|
||||
->toContain('str($service->status)->contains(\'exited\')');
|
||||
});
|
||||
|
||||
/**
|
||||
* Unit tests for YAML validation in CalculatesExcludedStatus trait
|
||||
*/
|
||||
it('ensures YAML validation has proper exception handling for parse errors', function () {
|
||||
$traitFile = file_get_contents(__DIR__.'/../../app/Traits/CalculatesExcludedStatus.php');
|
||||
|
||||
// Verify that ParseException is imported and caught separately from generic Exception
|
||||
expect($traitFile)
|
||||
->toContain('use Symfony\Component\Yaml\Exception\ParseException')
|
||||
->toContain('use Illuminate\Support\Facades\Log')
|
||||
->toContain('} catch (ParseException $e) {')
|
||||
->toContain('} catch (\Exception $e) {');
|
||||
});
|
||||
|
||||
it('ensures YAML validation logs parse errors with context', function () {
|
||||
$traitFile = file_get_contents(__DIR__.'/../../app/Traits/CalculatesExcludedStatus.php');
|
||||
|
||||
// Verify that parse errors are logged with useful context (error message, line, snippet)
|
||||
expect($traitFile)
|
||||
->toContain('Log::warning(\'Failed to parse Docker Compose YAML for health check exclusions\'')
|
||||
->toContain('\'error\' => $e->getMessage()')
|
||||
->toContain('\'line\' => $e->getParsedLine()')
|
||||
->toContain('\'snippet\' => $e->getSnippet()');
|
||||
});
|
||||
|
||||
it('ensures YAML validation logs unexpected errors', function () {
|
||||
$traitFile = file_get_contents(__DIR__.'/../../app/Traits/CalculatesExcludedStatus.php');
|
||||
|
||||
// Verify that unexpected errors are logged with error level
|
||||
expect($traitFile)
|
||||
->toContain('Log::error(\'Unexpected error parsing Docker Compose YAML\'')
|
||||
->toContain('\'trace\' => $e->getTraceAsString()');
|
||||
});
|
||||
|
||||
it('ensures YAML validation checks structure after parsing', function () {
|
||||
$traitFile = file_get_contents(__DIR__.'/../../app/Traits/CalculatesExcludedStatus.php');
|
||||
|
||||
// Verify that parsed result is validated to be an array
|
||||
expect($traitFile)
|
||||
->toContain('if (! is_array($dockerCompose)) {')
|
||||
->toContain('Log::warning(\'Docker Compose YAML did not parse to array\'');
|
||||
|
||||
// Verify that services is validated to be an array
|
||||
expect($traitFile)
|
||||
->toContain('if (! is_array($services)) {')
|
||||
->toContain('Log::warning(\'Docker Compose services is not an array\'');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user