Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Junit Merger Cli Laravel Package

sweetchuck/junit-merger-cli

CLI tool to merge multiple JUnit XML reports into a single file. Reads file paths from stdin or arguments, outputs to stdout or a specified file. Supports DOM-based and fast substring handlers, with an option to recalculate testsuite counts.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Laravel/PHP Ecosystem Synergy: The package is natively PHP-based and integrates seamlessly with Laravel’s testing stack (PHPUnit, Pest, or Laravel’s built-in testing utilities). It addresses a critical gap in parallelized test execution workflows, where fragmented JUnit XML reports need consolidation for CI/CD tools (e.g., SonarQube, GitHub Actions).
  • Modular and Non-Invasive: The CLI tool operates outside Laravel’s core, making it a low-risk addition. It can be invoked via Artisan commands, CI scripts, or even embedded in custom logic without modifying Laravel’s architecture.
  • Standardized Output: Generates valid JUnit XML, which is a universal format for test reporting. This ensures compatibility with Laravel’s existing integrations (e.g., spatie/laravel-test-failures, third-party analytics, or custom dashboards).

Integration Feasibility

  • PHP Native with Zero Dependencies: Uses \DOMDocument and standard PHP libraries, ensuring no conflicts with Laravel’s dependencies or runtime.
  • Flexible Input/Output: Supports stdin/stdout piping (ideal for CI/CD) and file arguments, making it adaptable to Laravel’s file-based workflows (e.g., storing test reports in storage/logs/junit/).
  • Handler-Based Customization: Offers three merging strategies (dom_read_write, dom_read, substr), allowing trade-offs between:
    • Accuracy (recalculates test suite stats like tests, failures, time).
    • Performance (string concatenation for speed).
    • Simplicity (substring matching for identical-format files).

Technical Risk

  • XML Schema Robustness:
    • Risk: Input files from custom PHPUnit extensions or third-party tools may violate JUnit schema, leading to malformed merged XML.
    • Mitigation:
      • Pre-validate files using SimpleXML or DOMDocument before merging.
      • Use dom_read_write handler for strict schema compliance.
      • Add a pre-merge hook in Laravel to filter/reject invalid files.
  • Performance Bottlenecks:
    • Risk: dom_read_write recalculates attributes, which could slow down large test suites (e.g., 1000+ files).
    • Mitigation:
      • Benchmark with Laravel’s test suite size.
      • Default to substr handler for identical-format files (common in parallel PHPUnit runs).
      • Implement chunked merging for very large datasets.
  • CLI Dependency:
    • Risk: Requires shell access or exec() calls, which may be restricted in serverless/Laravel Octane environments.
    • Mitigation:
      • Wrap the CLI in a custom Artisan command with embedded logic (e.g., using the underlying junit-merger library directly).
      • For Octane, use Laravel’s Process facade to execute the CLI in a background job.
  • Lack of Laravel-Specific Features:
    • Risk: No native integration with Laravel’s service container, events, or testing utilities (e.g., Pest’s parallelization).
    • Mitigation:
      • Build a thin Laravel wrapper (e.g., a service provider or event listener) to bridge the gap.
      • Example: Listen to TestsWorked events and auto-merge reports.

Key Questions

  1. Pipeline Placement:
    • Should merging occur post-test execution (aggregating parallel runs) or pre-submission (consolidating dev/test reports)?
    • Laravel-specific: Tie to tests:unit/tests:feature Artisan commands or CI hooks.
  2. Handler Strategy:
    • Does the use case require stat recalculation (dom_read_write) for accurate reporting, or can raw speed (substr) suffice?
    • Trade-off: Recalculation ensures correct time/failures stats but adds overhead.
  3. Error Handling:
    • How should failures (e.g., invalid XML, missing files) be handled?
      • Exit codes for CI.
      • Laravel notifications for dev environments.
      • Custom exceptions for programmatic use.
  4. Scalability Limits:
    • What’s the maximum expected file count per merge?
    • Test with Laravel’s largest test suite (e.g., 500+ files) to validate performance.
  5. Alternatives:
    • Could Laravel’s events or queues replace this for simpler cases (e.g., merging a fixed set of files)?
    • Example: Use TestsWorked event to auto-collect and merge reports in memory.
  6. Long-Term Maintenance:
    • Should the package be forked and maintained as a Laravel-specific version (e.g., spatie/junit-merger)?
    • Add Laravel config for handler defaults, input paths, and output destinations.

Integration Approach

Stack Fit

  • Laravel Compatibility:
    • Zero conflicts with PHP 8.1+ (Laravel 9+) or testing tools (Pest, PHPUnit).
    • Leverages native PHP XML tools, avoiding foreign dependencies.
  • CI/CD Synergy:
    • Designed for pipeline orchestration (GitHub Actions, CircleCI, Jenkins).
    • Example workflow for Laravel:
      # .github/workflows/tests.yml
      jobs:
        test:
          runs-on: ubuntu-latest
          steps:
            - run: php artisan test --parallel --distribute
            - run: find storage/logs/junit -name '*.xml' | vendor/bin/junit-merger merge:files --handler=dom_read_write > merged-report.xml
            - uses: actions/upload-artifact@v3
              with:
                name: junit-report
                path: merged-report.xml
      
  • Artisan Integration:
    • Encapsulate the CLI in a custom command for Laravel-native usage:
      // app/Console/Commands/MergeJUnitReports.php
      class MergeJUnitReports extends Command {
          protected $signature = 'junit:merge
              {--output= : Output file path (default: storage/logs/junit/merged.xml)}
              {--handler=dom_read_write : Merge handler (dom_read_write|dom_read|substr)}';
      
          public function handle() {
              $files = glob(storage_path('logs/junit/*.xml'));
              if (empty($files)) {
                  $this->error('No JUnit files found!');
                  return 1;
              }
      
              $output = $this->option('output') ?? storage_path('logs/junit/merged.xml');
              $handler = $this->option('handler');
      
              $command = "php vendor/bin/junit-merger merge:files --handler={$handler} " . implode(' ', $files) . " > {$output}";
              $exitCode = shell_exec($command);
      
              if ($exitCode !== 0) {
                  $this->error("Merge failed with exit code {$exitCode}");
                  return $exitCode;
              }
      
              $this->info("Merged report saved to: {$output}");
              return 0;
          }
      }
      
    • Register the command in app/Console/Kernel.php:
      protected $commands = [
          Commands\MergeJUnitReports::class,
      ];
      

Migration Path

  1. Phase 1: CLI Wrapper (Minimal Viable Integration)
    • Action: Call the CLI directly in CI or scripts.
    • Pros: Zero Laravel changes, low risk.
    • Example:
      # In a CI script or Artisan command
      find storage/logs/junit -name '*.xml' | vendor/bin/junit-merger merge:files > merged.xml
      
  2. Phase 2: Artisan Command (Reusable Integration)
    • Action: Wrap the CLI in a Laravel command (as shown above).
    • Pros: Reusable across environments, configurable via options.
    • Example Usage:
      php artisan junit:merge --output=reports/ci.xml --handler=substr
      
  3. Phase 3: Library Integration (Advanced Customization)
    • Action: Fork the underlying junit-merger library and publish it as a Laravel package (e.g., spatie/junit-merger).
    • Features to Add:
      • Service provider for config/handlers.
      • Event listeners (e.g., trigger merge on TestsWorked).
      • Queueable jobs for async merging.
    • Example Package Structure:
      spatie/junit-merger/
      ├── src/
      │   ├── JUnitMergerServiceProvider.php
      │   ├── Console/MergeCommand.php
      │   ├── Events/JUnitMerged.php
      │   └── Handlers/DomReadWriteHandler.php
      ├── config/junit-merger.php
      └── README.md
      

Compatibility

  • Input Files:
    • Works with any JUnit XML, but PHPUnit/Pest outputs are assumed.
    • Validation: Add a pre-
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium