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

    View Slide

  2. Dependency Hell,
    Composer and PHIVE
    Photo by JJ Ying on Unsplash
    https://unsplash.com/photos/YTtDxJPflqk

    View Slide

  3. Dependency Hell 1:
    Symfony vs. ops tool

    View Slide

  4. Dependency Hell 1:
    Symfony vs. ops tool

    View Slide

  5. Dependency Hell 2:
    Ops tool vs. ops tool (in 2 steps)

    View Slide

  6. Dependency Hell 2:
    Ops tool vs. ops tool (in 2 steps)

    View Slide

  7. Dependency Hell 2:
    Ops tool vs. ops tool (in 2 steps)

    View Slide

  8. Dependency Hell 2:
    Ops tool vs. ops tool (in 2 steps)

    View Slide

  9. Dependency Hell 2:
    Ops tool vs. ops tool (in 2 steps)

    View Slide

  10. Dependency Hell 2:
    Ops tool vs. ops tool (in 1 step)

    View Slide

  11. Dependency Hell 2:
    Ops tool vs. ops tool (in 1 step)

    View Slide

  12. But, why?

    View Slide

  13. 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
    [email protected]
    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

    View Slide

  14. 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
    [email protected]
    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

    View Slide

  15. 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.

    View Slide

  16. 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

    View Slide

  17. View Slide

  18. 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)

    View Slide

  19. PHIVE
    to the rescue!

    View Slide

  20. Installing a tool with PHIVE

    View Slide

  21. Installing a tool with PHIVE

    View Slide

  22. Installing a tool with PHIVE

    View Slide

  23. Installing a tool with PHIVE
    a bit like a combination
    of composer.json
    and composer.lock

    View Slide

  24. Installing a tool with PHIVE

    View Slide

  25. Updating all PHIVE-installed tools

    View Slide

  26. Downloading all installed tools

    View Slide

  27. Automating a PHIVE installation

    View Slide

  28. Automating a PHIVE installation

    View Slide

  29. Automating a PHIVE installation
    cache this folder
    in Docker and
    in the pipeline

    View Slide

  30. Photo by Daniel Tuttle on Unsplash
    https://unsplash.com/photos/BPGPk_n7rkc

    View Slide


  31. 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

    View Slide

  32. 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

    View Slide