Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dependency Hell, Composer and PHIVE

Dependency Hell, Composer and PHIVE

- What is does dependency hell with Composer look like?
- What causes dependency hell?
- How can we avoid dependency hell with Composer and PHIVE?

Oliver Klee

August 18, 2021
Tweet

More Decks by Oliver Klee

Other Decks in Programming

Transcript

  1. Welcome to Dependency Hell Photo by JJ Ying on Unsplash

    https://unsplash.com/photos/YTtDxJPflqk 2021-08-18 | Oliver Klee | @oliklee
  2. Dependency Hell, Composer and PHIVE Photo by JJ Ying on

    Unsplash https://unsplash.com/photos/YTtDxJPflqk
  3. Exihibit 1: dependency tree of cachetool __root gordalina/cachetool: 6.5.0 ^6.5

    consolidation/self-update: 1.2.0 ^1.2.0 php ^7.3|^8.0 symfony/console: v5.3.2 ^4.0|^5.0 hollodotme/fast-cgi-client: v3.1.5 ^3.0 monolog/monolog: 2.3.0 ^1.0|^2.0 psr/container: 1.0.0 1.0.0 psr/log: 1.1.4 ^1.0 symfony/dependency-injection: v5.2.11 ^4.0|^5.0 symfony/finder: v5.3.0 ^4.0|^5.0 symfony/http-client: v5.3.3 ^4.0|^5.0 symfony/http-foundation: v5.3.3 ^4.0|^5.0 symfony/process: v5.3.2 ^4.0|^5.0 symfony/yaml: v5.3.3 ^4.0|^5.0 phpunit/phpunit ^8.0|^9.0 >=5.5.0 ^2.8|^3|^4|^5 symfony/filesystem: v5.3.3 ^2.5|^3|^4|^5 >=7.2.5 ~1.0 ^4.4|^5.0 ^4.4|^5.0 symfony/deprecation-contracts: v2.4.0 ^2.1 symfony/polyfill-mbstring: v1.23.0 ~1.0 symfony/polyfill-php73: v1.23.0 ^1.8 symfony/polyfill-php80: v1.23.0 ^1.15 symfony/service-contracts: v2.2.0 ^1.1|^2 symfony/string: v5.3.3 ^5.1 symfony/config ^4.4|^5.0 symfony/event-dispatcher ^4.4|^5.0 symfony/lock ^4.4|^5.0 symfony/var-dumper ^4.4|^5.0 >=7.2.5 symfony/polyfill-ctype: v1.23.0 ~1.8 >=7.1 ext-json * ext-xdebug >=2.6.0 tm/tooly-composer-script ^1.4.1 >=7.2 ^1.0.1 ^8.5 aws/aws-sdk-php ^2.4.9 || ^3.0 doctrine/couchdb ~1.0@dev elasticsearch/elasticsearch ^7 graylog2/gelf-php ^1.4.2 mongodb/mongodb ^1.8 php-amqplib/php-amqplib ~2.4 php-console/php-console ^3.1.3 phpspec/prophecy ^1.6.1 phpstan/phpstan ^0.12.91 predis/predis ^1.1 rollbar/rollbar ^1.3 ruflin/elastica >=0.90 <7.0.1 swiftmailer/swiftmailer ^5.3|^6.0 >=5.3.0 >=5.3.0 >=7.2.5 ^1.0 ^4.4|^5.0 ^2.1 ^1.15 ^1.1.6|^2 ^5.1 symfony/expression-language ^4.4|^5.0 >=7.2.5 >=7.2.5 ^1.0 ^4.4|^5.0 ^4.4|^5.0 ^2.1 ^1.11 ^1.15 ^1.0|^2 symfony/http-client-contracts: v2.4.0 ^2.4 amphp/amp ^2.5 amphp/http-client ^4.2.1 amphp/http-tunnel ^1.0 amphp/socket ^1.1 guzzlehttp/promises ^1.4 nyholm/psr7 ^1.0 php-http/httplug ^1.0|^2.0 psr/http-client ^1.0 symfony/http-kernel ^4.4.13|^5.1.5 symfony/stopwatch ^4.4|^5.0 >=7.2.5 ~1.0 ^2.1 ~1.1 ^1.15 ^4.4|^5.0 symfony/cache ^4.4|^5.0 symfony/mime ^4.4|^5.0 >=7.2.5 ^1.15 >=7.2.5 ^4.4|^5.0 ^2.1 ~1.8 >=7.1 >=7.1 >=7.1 >=7.1 >=7.2.5 ^1.0 >=7.2.5 ^4.4|^5.0 ~1.0 ~1.15 ~1.8 symfony/polyfill-intl-grapheme: v1.23.0 ~1.0 symfony/polyfill-intl-normalizer: v1.23.0 ~1.0 symfony/error-handler ^4.4|^5.0 symfony/translation-contracts ^1.1|^2 symfony/var-exporter ^4.4|^5.0 >=7.1 >=7.2.5 >=7.1 >=7.1
  4. Exihibit 2: dependency tree of deployer __root deployer/deployer: v4.3.4 ^4.3

    elfet/pure: v3.0.0 ~2.0|~3.0 monolog/monolog: 1.26.1 ^1.21 php >=5.6.0 phpseclib/phpseclib: 2.0.32 ~2.0 pimple/pimple: v3.4.0 ~3.0 symfony/console: v3.4.47 ~2.6|~3.0 symfony/process: v3.4.47 ~2.6|~3.0 symfony/yaml: v3.4.47 ~2.6|~3.0 deployer/phar-update ~2.0 phpunit/phpunit ~5.7 symfony/finder ~2.6|~3.0 ~2.6 || ~3.0 || ~4.0 ~2.6 || ~3.0 || ~4.0 ~4.4 ~2.6 || ~3.0 || ~4.0 react/react: v0.4.2 ~0.4 symfony/debug: v4.4.25 ~2.6 || ~3.0 || ~4.0 symfony/expression-language: v4.4.25 ~2.6 || ~3.0 || ~4.0 >=5.3.0 ~4.5 psr/log: 1.1.4 ~1.0 aws/aws-sdk-php ^2.4.9 || ^3.0 doctrine/couchdb ~1.0@dev graylog2/gelf-php ~1.0 php-amqplib/php-amqplib ~2.4 php-console/php-console ^3.1.3 phpstan/phpstan ^0.12.59 ruflin/elastica >=0.90 <3.0 sentry/sentry ^0.13 swiftmailer/swiftmailer ^5.3|^6.0 >=5.3.3 ^4.8.35|^5.7|^6.0|^9.4 phing/phing ~2.7 squizlabs/php_codesniffer ~2.0 >=7.2.5 psr/container: 1.1.1 ^1.1 symfony/phpunit-bridge ^5.0 ^5.5.9|>=7.0.8 ~3.3|~4.0 ~2.8|~3.0|~4.0 ~1.0 symfony/config ~3.3|~4.0 symfony/dependency-injection ~3.4|~4.0 symfony/polyfill-mbstring: v1.23.0 ~1.0 symfony/event-dispatcher ~2.8|~3.0|~4.0 symfony/lock ~3.4|~4.0 ^5.5.9|>=7.0.8 ^5.5.9|>=7.0.8 ~3.4|~4.0 symfony/polyfill-ctype: v1.23.0 ~1.8 >=5.4.0 ~4.0 react/cache: v0.4.2 0.4.* react/promise: v2.8.0 ~2.1 react/child-process: v0.4.3 0.4.* react/event-loop: v0.4.3 0.4.* react/stream: v0.4.6 0.4.* react/dns: v0.4.17 0.4.* react/http: v0.4.4 0.4.* react/socket: v0.4.6 0.4.* react/http-client: v0.4.17 0.4.* react/socket-client: v0.4.6 0.4.* >=7.1.3 ~1.0 symfony/polyfill-php80: v1.23.0 ^1.15 symfony/http-kernel ^3.4|^4.0|^5.0 >=7.1.3 symfony/cache: v5.3.3 ^3.4|^4.0|^5.0 symfony/service-contracts: v2.4.0 ^1.1|^2 evenement/evenement: v2.1.0 >=5.4.0 ^6.0||^5.7||^4.8.35 guzzlehttp/psr7: 1.8.2 >=5.4.0 ~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10 psr/http-message: 1.0.1 ~1.0 ralouphie/getallheaders: 3.0.3 ^2.0.5 || ^3.0.0 ext-zlib * >=5.3.0 >=5.6 ^5 || ^6.5 php-coveralls/php-coveralls ^2.1 >=5.3.0 >=7.2.0 psr/cache: 2.0.0 >=8.0.0 >=5.3.0 ^6.4 || ^5.7 || ^4.8.35 ~2.0|~1.1 >=5.4.0 ^7.0 || ^6.5 || ^5.7 || ^4.8.36 >=5.3.0 ^5.0 || ^4.8.10 ^2.0 || ^1.0 ^0.4 || ^0.3 ^0.5 || ^0.4.4 sebastian/environment ~1.0 >=5.4.0 ~4.8 >=5.3.8 ^2.0|^1.0 ^2.0|^1.0 ^0.4|^0.3 clue/stream-filter ~1.2 >=5.3.0 ^7.0 || ^6.4 || ^5.7 || ^4.8.35 ^1.0 || ^0.6 || ^0.5 || ^0.4 || ^0.3 ^2.1 || ^1.2.1 ^1.0 || ^0.5 || ^0.4 || ^0.3.5 ^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4.5 react/promise-timer: v1.6.0 ^1.2 clue/block-react ^1.2 >=5.3 ^9.0 || ^5.7 || ^4.8.35 ^3.0 || ^2.7.0 || ^1.2.1 ^1.0 || ^0.5 || ^0.4 || ^0.3.5 >=5.3.0 ^4.8.10||^5.0 ^2.0 || ^1.0 ^0.4.4 ^0.4 ringcentral/psr7: 1.3.0 ^1.2 >=5.3.0 ~4.8 ~2.0|~1.0 ^2.0 || ^1.1 0.4.*|0.3.* ^0.4.5 ^1.1 ^0.5.1 >=5.3 ~4.0 ~1.0 >=5.4.0 ^5.0 || ^4.8.10 ~2.0 ^1.0 ~2.2 0.4.* 0.4.* 0.4.* ^0.5 || ^0.4 || ^0.3 >=5.4.0 ~2.0 0.4.* 0.4.* 0.4.* >=7.2.5 ^1.1 ^1.0|^2.0 symfony/cache-contracts: v2.4.0 ^1.1.7|^2 symfony/deprecation-contracts: v2.4.0 ^2.1 ^1.15 ^1.1|^2 symfony/var-exporter: v5.3.3 ^4.4|^5.0 cache/integration-tests dev-master doctrine/cache ^1.6|^2.0 doctrine/dbal ^2.10|^3.0 predis/predis ^1.1 psr/simple-cache ^1.0 ^4.4|^5.0 ^4.4|^5.0 symfony/filesystem ^4.4|^5.0 ^4.4|^5.0 symfony/messenger ^4.4|^5.0 symfony/var-dumper ^4.4|^5.0 >=7.2.5 ^1.0|^2.0|^3.0 >=7.1 >=7.1 >=7.2.5 ^1.1 >=7.2.5 ^1.15 ^4.4.9|^5.0.9 >=7.1 >=7.1
  5. What are the causes?  Composer can install only one

    version of each package at a time.  All packages share the same „box“.  Tools tend to have more specific dependencies.
  6. What could we do?  Allow installation of multiple versions

    in parallel (npm)  2 „boxes“: install the tools globally: composer global require …  solves conflicts between code libraries and tools  does not solve conflicts between tools  2 „boxes“: separate directory for tools  solves conflicts between code libraries and tools  does not solve conflicts between tools
  7. What could we do?  one „box“ per tool: one

    separate directory and one composer.json for each tool  solves all inter-tool dependency problems  Who would be willing to maintain this?  one „box“ per tool: one PHAR for each tool  solves all inter-tool dependency problems  easy to maintain and update with the right tool  does not (easily) allow extending tools with other Composer packages (e.g. PHPStan)
  8. Installing a tool with PHIVE a bit like a combination

    of composer.json and composer.lock
  9.  How to get PHIVE?  download + cache, version-control,

    or have it in the image  plan automating update of PHARS/tools that are not (yet) PHIVE-controlled  Symfony security checker, Deployer, CacheTool  use Composer for tools that need extensions Things to plan for automation
  10. 1. Start with using Composer for everything. (This keeps things

    simple as long as possible.) 2. Then the first dependency conflict happens. 3. Move all tools to PHIVE. 4. Keep using Composer for tools that a) are not available via PHIVE b) need other Composer-installed libraries (e.g., PHPStan) Recommendation for an approach