evilstudio / composer-parser
Compare Composer dependencies across repositories and export consolidated reports
Package info
github.com/evilprophet/composer-parser
Type:project
pkg:composer/evilstudio/composer-parser
Requires
- php: >=8.4
- ext-gd: *
- ext-json: *
- ext-zip: *
- czproject/git-php: ^4.6
- daniel-ness/ansible-vault: ^0.0.3
- google/apiclient: ^2.18
- mikehaertl/php-shellcommand: ^1.7
- monolog/monolog: ^3.9
- php-curl-class/php-curl-class: ^12.0.4
- phpoffice/phpspreadsheet: ^5.4.0
- symfony/config: ^7.4
- symfony/console: ^7.4
- symfony/dependency-injection: ^7.4
- symfony/expression-language: ^7.4
- symfony/filesystem: ^7.4
- symfony/yaml: ^7.4
Requires (Dev)
- phpunit/phpunit: ^12.4
- squizlabs/php_codesniffer: ^4.0
This package is auto-updated.
Last update: 2026-07-20 14:49:26 UTC
README
Introduction
Composer Parser is a Symfony Console application for comparing Composer dependencies across multiple repositories and publishing one consolidated report.
It loads repositories through Git or the GitLab API, reads composer.json and optionally composer.lock, groups packages by configurable rules, and writes the result to XLSX, JSON, HTML, or Google Sheets.
โจ Key Features
- Multiple repository sources: use a local Git checkout flow or download files and archives through the GitLab API.
- Three parser modes: compare declared constraints, installed versions, or the latest available versions reported by Composer.
- Four report formats: generate XLSX, JSON, HTML, or Google Sheets output from the same normalized data.
- Configurable package groups: match
require,require-dev,replace,patchset, and explicitly observed packages with regular expressions. - Configurable report styling: apply version- and package-based colors to XLSX, HTML, and Google Sheets reports.
- Complete report snapshots: repository and parser failures stop the run before the writer replaces the previous complete report.
๐ Project Structure
.
โโโ bin/ # CLI entrypoint
โโโ config/ # Parameters template and service configuration
โโโ src/ # Application source code
โ โโโ Api/ # Public contracts
โ โโโ Command/ # Console commands
โ โโโ Exception/ # Domain exceptions
โ โโโ Model/ # Configuration and report models
โ โโโ Service/ # Providers, parsers, writers, validation, and application services
โโโ tests/ # Unit and integration tests
โโโ var/ # Generated repositories, reports, and logs
โโโ composer.json # PHP dependencies and project scripts
โโโ phpunit.xml # PHPUnit suites and strict failure rules
๐ ๏ธ Requirements
- PHP
8.4+ - Composer
2+ - PHP extensions required by the locked dependencies, including
ext-curl,ext-gd,ext-json, andext-zip - Git available in
PATHwhen usinggitRepository - Composer available in
PATHwhen usingcomposerFull - GitLab URL and API token when using a GitLab provider
- Google Cloud service account JSON when using
googleSheets
๐ Quick Start
Clone the repository, install dependencies, and create the local parameters file:
git clone https://github.com/evilprophet/composer-parser.git
cd composer-parser
composer install
cp config/parameters.yaml.template config/parameters.yaml
Update config/parameters.yaml for your repositories and selected provider, parser, and writer. The template provides the supported values and a complete example configuration.
Run cleanup before every report generation so providers work with fresh repository data:
# Remove repositories downloaded by the previous run. bin/console app:cleanup # Download repositories, parse dependencies, and write the report. bin/console app:run
Use a different parameters file without changing the default configuration:
bin/console app:cleanup -p config/parameters.custom.yaml bin/console app:run -p config/parameters.custom.yaml
-p, --parameters-file <path>, and --parameters-file=<path> are equivalent. Relative paths are resolved from the current working directory.
โ๏ธ Configuration
config/parameters.yaml.template is the configuration reference. Every report run requires these base keys:
app.config.timezoneapp.config.providerTypeapp.config.parserTypeapp.config.writerTypepackage.config.includeInstalledVersionpackage.config.installedVersionDisplayedInpackage.config.packageGroupsrepository.config.repositoryListwriter.config.local.fileNamewriter.config.local.fileDirectorywriter.config.shared.sheetName
Providers
gitRepositoryclones the configured remote or reuses an existing checkout, then checks out the configured branch without runningfetchorpull.gitlabApiFilesdownloadscomposer.jsonand the optionalcomposer.lockdirectly from GitLab.gitlabApiArchivedownloads a GitLab repository archive and optionally decryptsauth.json.encryptedwithapp.config.ansibleVaultPassword.
Parsers
composerJsonreadsrequire,require-dev,replace, andextra.patchsetdata fromcomposer.json.composerJsonAndLockalso reads installed versions from bothpackagesandpackages-devincomposer.lock.composerFulladditionally runscomposer outdated --no-plugins --no-scripts --format=jsoninside each downloaded repository to collect latest available versions.
composer.lock is optional. Without it, lock-aware parsers still report declared constraints but cannot add installed or observed package versions.
Writers
xlsxwrites a styled workbook towriter.config.local.fileDirectory.jsonwrites a structured local report without styling.htmlwrites a standalone styled report.googleSheetsclears and rewrites the configured sheet through the Google Sheets API.
Styling is required for xlsx, html, and googleSheets. An XLSX sheet name cannot contain *, :, /, \, ?, [ or ].
Package groups
groupTypeacceptsrequire,require-dev,replace,patchset, orobserved.- Higher
parserPriorityclaims matchingrequire,require-dev, andreplacepackages first.observedandpatchsetentries are added to every matching group. - Lower
writerOrderis displayed first; equal values preserve configuration order. - An
observedgroup requirescomposerJsonAndLockorcomposerFull,includeInstalledVersion: true, and at least one package inobservedPackages.
Repository entries
- Every entry requires
name,directory,remote, andbranch; onlynameanddirectorymust be unique. directorymust be a normalized relative child ofvar/repositories/without.or..segments or a trailing slash.remotemust use SCP-style SSH or an HTTP, HTTPS, or SSH URL. GitLab API providers extract thenamespace/projectpath from this value.- Report columns are sorted alphabetically by repository name, independently of configuration order.
- Standard dependency and observed package rows are sorted alphabetically; patch rows preserve their source order.
Google Sheets
- Enable the Google Sheets API in a Google Cloud project.
- Create a service account and download its JSON key outside the repository.
- Share the target spreadsheet with the service account email as
Editor. - Set
writer.config.googleSheets.spreadsheetIdandwriter.config.googleSheets.serviceAccountJsonPath. - Never commit API tokens, vault passwords, or service account files.
๐ Report Flow
app:cleanupremoves only the configured working directories belowvar/repositories/.- The selected provider loads every configured repository into its local working directory.
- The selected parser builds one package matrix across all repositories.
- The selected writer publishes the report only after every repository has been processed successfully.
- A repository, parser, or validation failure returns a non-zero exit code and leaves the previous complete report untouched.
๐ป Commands Overview
| Command | Description |
|---|---|
bin/console app:cleanup |
Remove configured local repository working directories. |
bin/console app:run |
Load repositories, parse dependencies, and publish one report. |
bin/console list |
List available commands without initializing unused integrations. |
Command exit codes:
0- command completed successfully.1- configuration, provider, parser, writer, or cleanup failed at runtime.2- CLI bootstrap failed, for example because the parameters file does not exist.
๐งช Testing & Quality
Run the complete PHPUnit suite and the same PHP_CodeSniffer rules used by CI:
composer test
vendor/bin/phpcs --standard=PSR12 --extensions=php --warning-severity=0 src tests
GitLab CI runs the Unit and Integration PHPUnit suites separately on PHP 8.4 and rejects warnings, notices, deprecations, risky tests, and unexpected test output.
๐งญ Notes
- Local report names use
writer.config.local.fileName;{date}is replaced with the current date inY-m-dformat and the writer appends the extension. - Relative local output and service account paths are resolved from the current working directory.
- Local output directories are created automatically, and existing files with the same generated name are overwritten.
- Runtime errors handled by
app:cleanupandapp:runare logged tovar/log/error.log; bootstrap errors are written directly to STDERR. app:rundoes not perform cleanup automatically; the supported operational sequence is alwaysapp:cleanupfollowed byapp:run.- Run cleanup and report generation sequentially. Concurrent executions against the same working directories are not supported.
- Google Sheets output is updated in place; an API failure during the writer step can leave the target sheet empty or partially updated.