From f546548168c690599f1bc5b23d7a95ce38167a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=A4u=C3=9Fler?= Date: Thu, 18 Jun 2026 21:06:37 +0200 Subject: [PATCH] [TASK] Restructure build files and switch to reusable workflows --- .gitattributes | 6 +- .github/settings.yml | 29 ++--- .github/workflows/cgl.yaml | 62 ---------- .github/workflows/ci.yaml | 57 ++++++++++ .github/workflows/release.yaml | 26 +---- .github/workflows/tests.yaml | 107 ------------------ .gitignore | 1 - CONTRIBUTING.md | 96 ++++++++++------ README.md | 3 +- .../checks/.php-cs-fixer.php | 2 +- phpstan.php => build/checks/phpstan.php | 2 +- rector.php => build/checks/rector.php | 8 +- build/tests/.gitignore | 2 + phpunit.xml => build/tests/phpunit.xml | 14 +-- composer.json | 55 +++++---- composer.lock | 68 ++++++++++- 16 files changed, 257 insertions(+), 281 deletions(-) delete mode 100644 .github/workflows/cgl.yaml create mode 100644 .github/workflows/ci.yaml delete mode 100644 .github/workflows/tests.yaml rename .php-cs-fixer.php => build/checks/.php-cs-fixer.php (98%) rename phpstan.php => build/checks/phpstan.php (93%) rename rector.php => build/checks/rector.php (89%) create mode 100644 build/tests/.gitignore rename phpunit.xml => build/tests/phpunit.xml (54%) diff --git a/.gitattributes b/.gitattributes index b1c7f15..139dcab 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,15 +1,11 @@ * text=auto -/.build export-ignore /.github export-ignore +/build export-ignore /tests export-ignore /.editorconfig export-ignore /.gitattributes export-ignore /.gitignore export-ignore -/.php-cs-fixer.php export-ignore /CODEOWNERS export-ignore /composer.lock export-ignore /CONTRIBUTING.md export-ignore -/phpstan.php export-ignore -/phpunit.xml export-ignore -/rector.php export-ignore /renovate.json export-ignore diff --git a/.github/settings.yml b/.github/settings.yml index 4493e6a..00a2413 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -11,6 +11,7 @@ repository: allow_squash_merge: true allow_merge_commit: true allow_rebase_merge: true + allow_auto_merge: true delete_branch_on_merge: true allow_update_branch: true # This will be handled by Renovate @@ -89,33 +90,27 @@ rulesets: strict_required_status_checks_policy: true do_not_enforce_on_create: false required_status_checks: - - context: 'cgl' + - context: 'Checks / Perform Composer checks' integration_id: 15368 - - context: 'Tests (PHP 8.2 & locked dependencies)' + - context: 'Checks / Perform repository checks' integration_id: 15368 - - context: 'Tests (PHP 8.2 & highest dependencies)' + - context: 'Tests (PHP 8.2 & highest dependencies) / Run tests' integration_id: 15368 - - context: 'Tests (PHP 8.2 & lowest dependencies)' + - context: 'Tests (PHP 8.2 & lowest dependencies) / Run tests' integration_id: 15368 - - context: 'Tests (PHP 8.3 & locked dependencies)' + - context: 'Tests (PHP 8.3 & highest dependencies) / Run tests' integration_id: 15368 - - context: 'Tests (PHP 8.3 & highest dependencies)' + - context: 'Tests (PHP 8.3 & lowest dependencies) / Run tests' integration_id: 15368 - - context: 'Tests (PHP 8.3 & lowest dependencies)' + - context: 'Tests (PHP 8.4 & highest dependencies) / Run tests' integration_id: 15368 - - context: 'Tests (PHP 8.4 & locked dependencies)' + - context: 'Tests (PHP 8.4 & lowest dependencies) / Run tests' integration_id: 15368 - - context: 'Tests (PHP 8.4 & highest dependencies)' + - context: 'Tests (PHP 8.5 & highest dependencies) / Run tests' integration_id: 15368 - - context: 'Tests (PHP 8.4 & lowest dependencies)' + - context: 'Tests (PHP 8.5 & lowest dependencies) / Run tests' integration_id: 15368 - - context: 'Tests (PHP 8.5 & locked dependencies)' - integration_id: 15368 - - context: 'Tests (PHP 8.5 & highest dependencies)' - integration_id: 15368 - - context: 'Tests (PHP 8.5 & lowest dependencies)' - integration_id: 15368 - - context: 'Test coverage' + - context: 'Test coverage / Collect test coverage' integration_id: 15368 bypass_actors: - actor_id: 5 diff --git a/.github/workflows/cgl.yaml b/.github/workflows/cgl.yaml deleted file mode 100644 index 4570903..0000000 --- a/.github/workflows/cgl.yaml +++ /dev/null @@ -1,62 +0,0 @@ -name: CGL -on: - push: - branches: - - '**' - pull_request: - branches: - - main - -jobs: - prepare: - name: Prepare workflow - uses: eliashaeussler/.github/.github/workflows/pull-request.yaml@d5e6edeb05f9d931a17ab0618ae631658cbf43ec # main - - cgl: - runs-on: ubuntu-latest - needs: prepare - if: needs.prepare.outputs.continue == 'true' - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - with: - fetch-depth: 0 - - # Prepare environment - - name: Setup PHP - uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 - with: - # We use the minimum supported PHP version - php-version: 8.2 # renovate-ignore - tools: composer:v2, composer-require-checker, composer-unused, cs2pr - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # Validation - - name: Validate composer.json - run: composer validate - - # Install dependencies - - name: Install Composer dependencies - uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0 - - # Check Composer dependencies - - name: Check dependencies - run: composer-require-checker check - - name: Check for unused dependencies - run: composer-unused - - # Linting - - name: Lint composer.json - run: composer lint:composer - - name: Lint Editorconfig - run: composer lint:editorconfig - - name: Lint PHP - run: composer lint:php -- --format checkstyle | cs2pr - - # SCA - - name: SCA PHP - run: composer sca:php -- --error-format github - - # Migration - - name: Run Rector migration - run: composer migration:rector -- --dry-run diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..0447d10 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,57 @@ +name: CI + +on: + push: + branches: + - '**' + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + prepare: + name: 'Prepare workflow' + uses: eliashaeussler/gha/.github/workflows/preparation.yaml@e030eb819bbfa1ca7ac404b465ee8129ec9b2ce9 # 0.7.2 + + checks: + name: 'Checks' + + needs: [prepare] + if: ${{ needs.prepare.outputs.continue == 'true' }} + + permissions: + contents: read + security-events: write + + uses: eliashaeussler/gha/.github/workflows/checks.yaml@e030eb819bbfa1ca7ac404b465ee8129ec9b2ce9 # 0.7.2 + with: + # We use the minimum supported PHP version + php-version: 8.2 # renovate-ignore + + tests: + name: 'Tests (PHP ${{ matrix.php-version }} & ${{ matrix.dependencies }} dependencies)' + + needs: [prepare] + if: ${{ needs.prepare.outputs.continue == 'true' }} + + strategy: + fail-fast: false + matrix: + php-version: ["8.2", "8.3", "8.4", "8.5"] + dependencies: ["highest", "lowest"] + + uses: eliashaeussler/gha/.github/workflows/composer-tests.yaml@e030eb819bbfa1ca7ac404b465ee8129ec9b2ce9 # 0.7.2 + with: + php-version: ${{ matrix.php-version }} + dependencies: ${{ matrix.dependencies }} + + test-coverage: + name: 'Test coverage' + + needs: [prepare] + if: ${{ needs.prepare.outputs.continue == 'true' }} + + uses: eliashaeussler/gha/.github/workflows/composer-test-coverage.yaml@e030eb819bbfa1ca7ac404b465ee8129ec9b2ce9 # 0.7.2 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9b58e44..e48d781 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,28 +1,14 @@ name: Release + on: push: tags: - '*' +permissions: + contents: write + jobs: - # Job: Create release release: - name: Create release - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - with: - fetch-depth: 0 - - # Check if tag is valid - - name: Check tag - run: | - if ! [[ ${{ github.ref }} =~ ^refs/tags/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]; then - exit 1 - fi - - # Create release - - name: Create release - uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1 - with: - generateReleaseNotes: true + name: 'Create release' + uses: eliashaeussler/gha/.github/workflows/github-release.yaml@e030eb819bbfa1ca7ac404b465ee8129ec9b2ce9 # 0.7.2 diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml deleted file mode 100644 index 0a939e3..0000000 --- a/.github/workflows/tests.yaml +++ /dev/null @@ -1,107 +0,0 @@ -name: Tests -on: - push: - branches: - - '**' - pull_request: - branches: - - main - -jobs: - prepare: - name: Prepare workflow - uses: eliashaeussler/.github/.github/workflows/pull-request.yaml@d5e6edeb05f9d931a17ab0618ae631658cbf43ec # main - - tests: - name: Tests (PHP ${{ matrix.php-version }} & ${{ matrix.dependencies }} dependencies) - runs-on: ubuntu-latest - needs: prepare - if: needs.prepare.outputs.continue == 'true' - strategy: - fail-fast: false - matrix: - php-version: ["8.2", "8.3", "8.4", "8.5"] - dependencies: ["locked", "highest", "lowest"] - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - with: - fetch-depth: 0 - - # Prepare environment - - name: Setup PHP - uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 - with: - php-version: ${{ matrix.php-version }} - tools: composer:v2 - coverage: none - - # Install dependencies - - name: Install Composer dependencies - uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0 - with: - dependency-versions: ${{ matrix.dependencies }} - - # Run tests - - name: Run tests - run: composer test - - coverage: - name: Test coverage - runs-on: ubuntu-latest - needs: prepare - if: needs.prepare.outputs.continue == 'true' - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - with: - fetch-depth: 0 - - # Prepare environment - - name: Setup PHP - uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 - with: - php-version: 8.5 - tools: composer:v2 - coverage: pcov - - # Install dependencies - - name: Install Composer dependencies - uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0 - - # Run tests - - name: Build coverage directory - run: mkdir -p .build/coverage - - name: Run tests with coverage - run: composer test:coverage - - # Upload artifact - - name: Fix coverage path - working-directory: .build/coverage - run: sed -i 's#/home/runner/work/gitattributes/gitattributes#${{ github.workspace }}#g' clover.xml - - name: Upload coverage artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 - with: - name: coverage - path: .build/coverage/clover.xml - retention-days: 7 - - coverage-report: - name: Report test coverage - runs-on: ubuntu-latest - needs: coverage - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - with: - fetch-depth: 0 - - # Download artifact - - name: Download coverage artifact - id: download - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 - with: - name: coverage - - # Coveralls - - name: Coveralls report - uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2 - with: - file: ${{ steps.download.outputs.download-path }}/clover.xml diff --git a/.gitignore b/.gitignore index 8730576..2ca5cc8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -/.build/ /vendor/ /.php-cs-fixer.cache /.phpunit.result.cache diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6e19cf6..b1b1d8a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,9 @@ -# Contributing +# Contribution guide -Thanks for considering contributing to this project! Each contribution is -highly appreciated. In order to maintain a high code quality, please follow -all steps below. +Thanks for considering contributing to this project. Contributions of any size are highly appreciated. + +To keep the code base consistent and maintainable, please follow the workflow described below before +submitting a pull request. ## Requirements @@ -19,63 +20,88 @@ cd gitattributes composer install ``` -## Run linters +## Development workflow -```bash -# All linters -composer lint +A typical contribution workflow looks like this: + +1. Apply automatic fixes. +2. Run all checks. +3. Run the test suite. +4. Submit a pull request. + +### Apply automatic fixes -# Specific linters -composer lint:composer -composer lint:editorconfig -composer lint:php +Use the following commands to normalize and format the code base: -# Fix all CGL issues +```bash +# Apply all automatic fixes composer fix -# Fix specific CGL issues +# Apply specific fixes composer fix:composer composer fix:editorconfig composer fix:php ``` -## Run static code analysis +### Run checks + +Use `composer check` to run the full code quality pipeline locally. This command bundles dependency analysis, +static analysis, coding style checks, and Rector in dry-run mode so that potential refactorings can be reviewed +without changing files. ```bash -# All static code analyzers -composer sca +# Run all checks +composer check + +# Run specific checks +composer check:deps +composer check:refactor +composer check:static +composer check:style + +# Run specific style checks +composer check:style:composer +composer check:style:editorconfig +composer check:style:php +``` -# Specific static code analyzers -composer sca:php +### Run refactorings + +Refactorings are intentionally separated from regular checks because they may change the code base. + +```bash +# Run all configured refactorings +composer refactor + +# Run specific refactorings +composer refactor:php ``` -## Run tests +### Run tests + +Run the full test suite before opening a pull request: ```bash -# All tests +# Run tests composer test -# All tests with code coverage +# Run tests with code coverage composer test:coverage ``` -### Test reports +## Coverage reports -Code coverage reports are written to `.build/coverage`. You can open the -last HTML report like follows: +Code coverage reports are written to `build/tests/coverage`. Open the latest HTML report with: ```bash -open .build/coverage/html/index.html +open build/tests/coverage/html/index.html ``` -## Submit a pull request - -Once you have finished your work, please **submit a pull request** and describe -what you've done. Ideally, your PR references an issue describing the problem -you're trying to solve. +## Pull requests -All described code quality tools are automatically executed on each pull request -for all currently supported PHP versions. Take a look at the appropriate -[workflows][1] to get a detailed overview. +Once the changes are ready, please [submit a pull request](https://github.com/eliashaeussler/gitattributes/compare) +and describe what was changed and why. Ideally, the pull request references an issue that describes the +problem being solved. -[1]: .github/workflows +All documented code quality tools are executed automatically for pull requests across the currently +supported PHP versions. For details, refer to the [GitHub Actions workflows](.github/workflows). diff --git a/README.md b/README.md index 30e8803..46fe6b7 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,7 @@ # Object-oriented `.gitattributes` file handling [![Coverage](https://img.shields.io/coverallsCoverage/github/eliashaeussler/gitattributes?logo=coveralls)](https://coveralls.io/github/eliashaeussler/gitattributes) -[![CGL](https://img.shields.io/github/actions/workflow/status/eliashaeussler/gitattributes/cgl.yaml?label=cgl&logo=github)](https://github.com/eliashaeussler/gitattributes/actions/workflows/cgl.yaml) -[![Tests](https://img.shields.io/github/actions/workflow/status/eliashaeussler/gitattributes/tests.yaml?label=tests&logo=github)](https://github.com/eliashaeussler/gitattributes/actions/workflows/tests.yaml) +[![CI](https://img.shields.io/github/actions/workflow/status/eliashaeussler/gitattributes/ci.yaml?label=CI&logo=github)](https://github.com/eliashaeussler/gitattributes/actions/workflows/ci.yaml) [![Supported PHP Versions](https://img.shields.io/packagist/dependency-v/eliashaeussler/gitattributes/php?logo=php)](https://packagist.org/packages/eliashaeussler/gitattributes) diff --git a/.php-cs-fixer.php b/build/checks/.php-cs-fixer.php similarity index 98% rename from .php-cs-fixer.php rename to build/checks/.php-cs-fixer.php index 11d4e93..eb33dc2 100644 --- a/.php-cs-fixer.php +++ b/build/checks/.php-cs-fixer.php @@ -34,5 +34,5 @@ return PhpCsFixerConfig\Config::create() ->withRule($header) - ->withFinder(static fn (Finder\Finder $finder) => $finder->in(__DIR__)) + ->withFinder(static fn (Finder\Finder $finder) => $finder->in(dirname(__DIR__, 2))) ; diff --git a/phpstan.php b/build/checks/phpstan.php similarity index 93% rename from phpstan.php rename to build/checks/phpstan.php index 8d189c5..d5362e9 100644 --- a/phpstan.php +++ b/build/checks/phpstan.php @@ -23,7 +23,7 @@ use EliasHaeussler\PHPStanConfig; -return PHPStanConfig\Config\Config::create(__DIR__) +return PHPStanConfig\Config\Config::create(dirname(__DIR__, 2)) ->in( 'src', 'tests', diff --git a/rector.php b/build/checks/rector.php similarity index 89% rename from rector.php rename to build/checks/rector.php index 6c3595f..c0967bb 100644 --- a/rector.php +++ b/build/checks/rector.php @@ -27,14 +27,16 @@ use Rector\ValueObject\PhpVersion; return static function (RectorConfig $rectorConfig): void { + $rootPath = dirname(__DIR__, 2); + Config::create($rectorConfig, PhpVersion::PHP_82) ->in( - __DIR__.'/src', - __DIR__.'/tests', + $rootPath.'/src', + $rootPath.'/tests', ) ->withPHPUnit() ->skip(PrivatizeLocalGetterToPropertyRector::class, [ - __DIR__.'/src/Rule/Pattern/FilePattern.php', + $rootPath.'/src/Rule/Pattern/FilePattern.php', ]) ->apply() ; diff --git a/build/tests/.gitignore b/build/tests/.gitignore new file mode 100644 index 0000000..e3a1841 --- /dev/null +++ b/build/tests/.gitignore @@ -0,0 +1,2 @@ +/coverage +/.phpunit.result.cache diff --git a/phpunit.xml b/build/tests/phpunit.xml similarity index 54% rename from phpunit.xml rename to build/tests/phpunit.xml index 769933f..9ecb28e 100644 --- a/phpunit.xml +++ b/build/tests/phpunit.xml @@ -1,27 +1,27 @@ - tests/src + ../../tests/src - - + + - + - src + ../../src diff --git a/composer.json b/composer.json index e831f82..f01bf92 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ "ergebnis/composer-normalize": "^2.30", "phpstan/extension-installer": "^1.2", "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^11.4 || ^12.0 || ^13.0" + "phpunit/phpunit": "^11.4 || ^12.0 || ^13.0", + "shipmonk/composer-dependency-analyser": "^1.8" }, "autoload": { "psr-4": { @@ -44,31 +45,47 @@ "sort-packages": true }, "scripts": { + "check": [ + "@check:deps", + "@check:refactor", + "@check:static", + "@check:style" + ], + "check:deps": "composer-dependency-analyser", + "check:refactor": [ + "@check:refactor:php" + ], + "check:refactor:php": "@refactor:php --dry-run", + "check:static": "phpstan analyse -c build/checks/phpstan.php", + "check:style": [ + "@check:style:composer", + "@check:style:editorconfig", + "@check:style:php" + ], + "check:style:composer": "@fix:composer --dry-run", + "check:style:editorconfig": "ec", + "check:style:php": "@fix:php --dry-run", + "ci": [ + "@composer validate --strict", + "@composer audit", + "@check:deps", + "@check:refactor", + "@check:static --error-format github", + "@check:style" + ], "fix": [ "@fix:composer", "@fix:editorconfig", "@fix:php" ], "fix:composer": "@composer normalize", - "fix:editorconfig": "@lint:editorconfig --fix", - "fix:php": "php-cs-fixer fix", - "lint": [ - "@lint:composer", - "@lint:editorconfig", - "@lint:php" - ], - "lint:composer": "@fix:composer --dry-run", - "lint:editorconfig": "ec", - "lint:php": "@fix:php --dry-run", - "migration": [ - "@migration:rector" - ], - "migration:rector": "rector process -c rector.php", - "sca": [ - "@sca:php" + "fix:editorconfig": "@check:style:editorconfig --fix", + "fix:php": "php-cs-fixer fix --config build/checks/.php-cs-fixer.php", + "refactor": [ + "@refactor:php" ], - "sca:php": "phpstan analyse -c phpstan.php", + "refactor:php": "rector process -c build/checks/rector.php", "test": "@test:coverage --no-coverage", - "test:coverage": "phpunit -c phpunit.xml" + "test:coverage": "phpunit -c build/tests/phpunit.xml" } } diff --git a/composer.lock b/composer.lock index 5ceb477..76b1a68 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5d9233d5f663596c3574d15ebe430109", + "content-hash": "473407b5cab00f10d525e93d7b3bdcf8", "packages": [ { "name": "symfony/filesystem", @@ -4521,6 +4521,72 @@ ], "time": "2024-10-09T05:16:32+00:00" }, + { + "name": "shipmonk/composer-dependency-analyser", + "version": "1.8.4", + "source": { + "type": "git", + "url": "https://github.com/shipmonk-rnd/composer-dependency-analyser.git", + "reference": "975e5873b519d5180b1017a5dfb43d80781abd45" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shipmonk-rnd/composer-dependency-analyser/zipball/975e5873b519d5180b1017a5dfb43d80781abd45", + "reference": "975e5873b519d5180b1017a5dfb43d80781abd45", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "editorconfig-checker/editorconfig-checker": "^10.7.0", + "ergebnis/composer-normalize": "^2.19.0", + "ext-dom": "*", + "ext-libxml": "*", + "phpcompatibility/php-compatibility": "^9.3.5", + "phpstan/phpstan": "^1.12.26", + "phpstan/phpstan-phpunit": "^1.4.2", + "phpstan/phpstan-strict-rules": "^1.6.2", + "phpunit/phpunit": "^8.5.42 || ^9.6.23", + "shipmonk/name-collision-detector": "^2.1.1", + "slevomat/coding-standard": "^8.15.0" + }, + "bin": [ + "bin/composer-dependency-analyser" + ], + "type": "library", + "autoload": { + "psr-4": { + "ShipMonk\\ComposerDependencyAnalyser\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Fast detection of composer dependency issues (dead dependencies, shadow dependencies, misplaced dependencies)", + "keywords": [ + "analyser", + "composer", + "composer dependency", + "dead code", + "dead dependency", + "detector", + "dev", + "misplaced dependency", + "shadow dependency", + "static analysis", + "unused code", + "unused dependency" + ], + "support": { + "issues": "https://github.com/shipmonk-rnd/composer-dependency-analyser/issues", + "source": "https://github.com/shipmonk-rnd/composer-dependency-analyser/tree/1.8.4" + }, + "time": "2025-11-25T14:38:16+00:00" + }, { "name": "staabm/side-effects-detector", "version": "1.0.5",