Skip to main content

Drupal Updater: Streamlining Drupal Maintenance Updates from CLI

Drupal, a powerful content management system, relies on a multi-component ecosystem comprising Drupal modules, themes, vendor packages, and external libraries. Regular updates are essential to keep your Drupal project secure, efficient, and equipped with the latest features. However, managing these updates manually can be time-consuming and error-prone.

The update process typically involves package updates, thorough testing (both automated and manual), and ensuring stability. Automating this process can alleviate the burden of manual labor and allow teams to focus on critical tasks. Furthermore, having a standardized update procedure ensures consistency across the development team.

Additionally, in Drupal, individual modules may introduce configuration changes, making it crucial to isolate these changes in separate commits, combining package updates with the associated configuration. This practice allows for easy rollbacks and commits revert when necessary.

Drupal Updater to the Rescue

The Drupal Updater is a versatile tool compatible with any Drupal 9 and above installation. Its primary function is to detect and update outdated packages listed in the `composer.json` file, along with their associated configuration. 

More info and full documentation on GitHub

Here's how it simplifies the update process:

  • Package Detection: The tool identifies all packages listed in your `composer.json` file that have new versions available. It integrates with composer audit and Drupal Update module to detect new versions.
  • Sequential Updates: It updates packages one by one, ensuring that the associated configurations are also updated simultaneously. This guarantees that your Drupal project remains coherent and functional.
  • Full package version control: The tool respects composer version constraints, giving you complete control over your package versions. You can even freeze a package's version in your `composer.json` file if needed, that way it will never be updated. If this is the case we recommend adding a note with the Composer comments package.
  • Specific packages update: you can specify a specific list of packages to be updated also.
  • Dependency Handling: The tool also manages dependencies intelligently, ensuring that updates do not cause conflicts or compatibility issues. It relies on each component's composer requirements constraints.
  • Security Focus: You have the option to update all packages or only those with security issues, allowing you to prioritize critical updates when the time comes.
  • Version Control Integration (GIT): the tool creates a commit with the updated package information and its dependencies.
  • Multisite integration: Drupal Updater integrates with Drupal Multisites, allowing you to export the different configurations per site when a package is updated.
  • Conflict Resolution (the only manual action): In case of conflicts, the Drupal Updater allows you to focus your efforts on resolving issues saving you time on the previous processes. e.g. rerolling problematic patches or adapting custom code to new package versions. All other aspects of the update process are automated.

Real example

Find a real example of the tool running and its steps in one of your projects:

  1. Consolidating configuration:
    // 1. CONSOLIDATING CONFIGURATION //
    Running drush cr on the "@self" environment:
    Running drush cim -y on the "@self" environment:
    Consolidating @self environment
    Running drush cex -y on the "@self" environment:
  2. Checking Packages
    // 2. CHECKING PACKAGES //
    algolia/places
    aliagadev/inheritlink
    choices/choices
    ckeditor/autogrow
    ckeditor/codemirror
    ckeditor/codesnippet
    ckeditor/fakeobjects
    ckeditor/image
    ckeditor/link
    ckeditor/videodetector
    codemirror/codemirror
    components/highlightjs
    composer/installers
    cweagans/composer-patches
    d3/d3
    drupal-composer/drupal-security-advisories
    drupal/admin_toolbar
    drupal/advagg
    drupal/allowed_formats
    drupal/antibot
    drupal/behat_javascript
    drupal/block_class
    drupal/ckeditor_bootstrap_buttons
    drupal/classy_paragraphs
    drupal/codesnippet
    drupal/components
    drupal/config_filter
    drupal/config_split
    drupal/config_update
    drupal/context
    drupal/core
    drupal/core-composer-scaffold
    drupal/crop
    drupal/ctools
    drupal/datalayer
    drupal/datalayer_webform
    drupal/default_content
    drupal/devel
    drupal/draggableviews
    drupal/editor_advanced_link
    drupal/embed
    drupal/entity_reference_revisions
    drupal/entity_usage
    drupal/environment_indicator
    drupal/eu_cookie_compliance
    drupal/eu_cookie_compliance_matomo
    drupal/extlink
    drupal/extra_field_plus
    drupal/extra_field_set
    drupal/field_group
    drupal/field_group_background_image
    drupal/fontawesome
    drupal/fvm
    drupal/gin
    drupal/google_tag
    drupal/google_tag_cookies
    drupal/honeypot
    drupal/hreflang
    drupal/image_styles_generator
    drupal/image_widget_crop
    drupal/imagemagick
    drupal/inherit_link
    drupal/inline_entity_form
    drupal/jquery_ui
    drupal/jquery_ui_datepicker
    drupal/jquery_ui_tabs
    drupal/jquery_ui_tooltip
    drupal/libraries
    drupal/link_icons
    drupal/matomo
    drupal/media_library_edit
    drupal/menu_attributes
    drupal/menu_block
    drupal/menu_link_attributes
    drupal/menu_multilingual
    drupal/metatag
    drupal/migrate_default_content
    drupal/migrate_source_yaml
    drupal/nagios
    drupal/node_authlink
    drupal/paragraphs
    drupal/paragraphs_previewer
    drupal/pathauto
    drupal/rabbit_hole
    drupal/radix
    drupal/realname
    drupal/redirect
    drupal/reroute_email
    drupal/schema_metatag
    drupal/scrollama
    drupal/simple_sitemap
    drupal/sitemap
    drupal/smart_trim
    drupal/stage_file_proxy
    drupal/string_field_formatter
    drupal/styleguide
    drupal/token
    drupal/url_embed
    drupal/views_condition
    drupal/views_infinite_scroll
    drupal/viewsreference
    drupal/webform
    drupal/xray_audit
    drupal/yoast_seo
    drush/drush
    fengyuanchen/cropper
    fontawesome/fontawesome
    idiazroncero/btbutton
    jquery/chosen
    jquery/geocomplete
    jquery/hotkeys
    jquery/icheck
    jquery/image-picker
    jquery/inputmask
    jquery/intl-tel-input
    jquery/rateit
    jquery/select2
    jquery/textcounter
    jquery/timepicker
    jquery/toggles
    kenwheeler/slick
    kint-php/kint
    metadrop/drupal-artifact-builder
    metadrop/drupal-dev
    metadrop/grumphp-php-compatibility
    mglaman/phpstan-drupal
    phpcompatibility/php-compatibility
    phpro/grumphp
    progress-tracker/progress-tracker
    psr/cache
    signature_pad/signature_pad
    svg-pan-zoom/svg-pan-zoom
    symfony/deprecation-contracts
    symfony/string
    tabby/tabby
    tippyjs/5.x
    tippyjs/6.x
  3. Updating Packages
    // 3. UPDATING PACKAGES //
    [...]
    /// Updating: drupal/admin_toolbar ///
    Running drush cr on the "@self" environment:
    Running drush updb -y on the "@self" environment:
    Running drush cex -y on the "@self" environment:
    
    Updated packages:
    +----------------------+-------+-------+------------------------------------------------------------------------+
    | Production Changes   | From  | To    | Compare                                                                |
    +----------------------+-------+-------+------------------------------------------------------------------------+
    | drupal/admin_toolbar | 3.4.1 | 3.4.2 | https://git.drupalcode.org/project/admin_toolbar/compare/3.4.1...3.4.2 |
    +----------------------+-------+-------+------------------------------------------------------------------------+
    /// Updating: drupal/advagg ///
    Running drush cr on the "@self" environment:
    Running drush updb -y on the "@self" environment:
    Running drush cex -y on the "@self" environment:
    
    Updated packages:
    
    /// Updating: drupal/allowed_formats ///
    Package drupal/allowed_formats has an update available to 3.0.0 version. Due to composer.json constraints, it hasn't been updated.
    /// Updating: drupal/antibot ///
    There aren't available updates for drupal/antibot package.
    /// Updating: drupal/behat_javascript ///
    Running drush cr on the "@self" environment:
    Running drush updb -y on the "@self" environment:
    Running drush cex -y on the "@self" environment:
    
    Updated packages:
    +----------------------------------+---------+---------+-------------------------------------------------------------------------------+
    | Production Changes               | From    | To      | Compare                                                                       |
    +----------------------------------+---------+---------+-------------------------------------------------------------------------------+
    | doctrine/deprecations            | v1.1.1  | 1.1.2   | https://github.com/doctrine/deprecations/compare/v1.1.1...1.1.2               |
    | laminas/laminas-stdlib           | 3.17.0  | 3.18.0  | https://github.com/laminas/laminas-stdlib/compare/3.17.0...3.18.0             |
    | masterminds/html5                | 2.8.0   | 2.8.1   | https://github.com/Masterminds/html5-php/compare/2.8.0...2.8.1                |
    | psr/http-client                  | 1.0.2   | 1.0.3   | https://github.com/php-fig/http-client/compare/1.0.2...1.0.3                  |
    | symfony/polyfill-ctype           | v1.27.0 | v1.28.0 | https://github.com/symfony/polyfill-ctype/compare/v1.27.0...v1.28.0           |
    | symfony/polyfill-intl-idn        | v1.27.0 | v1.28.0 | https://github.com/symfony/polyfill-intl-idn/compare/v1.27.0...v1.28.0        |
    | symfony/polyfill-intl-normalizer | v1.27.0 | v1.28.0 | https://github.com/symfony/polyfill-intl-normalizer/compare/v1.27.0...v1.28.0 |
    | symfony/polyfill-mbstring        | v1.27.0 | v1.28.0 | https://github.com/symfony/polyfill-mbstring/compare/v1.27.0...v1.28.0        |
    | symfony/polyfill-php72           | v1.27.0 | v1.28.0 | https://github.com/symfony/polyfill-php72/compare/v1.27.0...v1.28.0           |
    | symfony/polyfill-php73           | v1.27.0 | v1.28.0 | https://github.com/symfony/polyfill-php73/compare/v1.27.0...v1.28.0           |
    | symfony/polyfill-php80           | v1.27.0 | v1.28.0 | https://github.com/symfony/polyfill-php80/compare/v1.27.0...v1.28.0           |
    +----------------------------------+---------+---------+-------------------------------------------------------------------------------+
    +---------------------------------+---------+---------+-------------------------------------------------------------------------+
    | Dev Changes                     | From    | To      | Compare                                                                 |
    +---------------------------------+---------+---------+-------------------------------------------------------------------------+
    | friends-of-behat/mink-extension | v2.7.2  | v2.7.4  | https://github.com/FriendsOfBehat/MinkExtension/compare/v2.7.2...v2.7.4 |
    | phpdocumentor/type-resolver     | 1.7.2   | 1.7.3   | https://github.com/phpDocumentor/TypeResolver/compare/1.7.2...1.7.3     |
    | symfony/polyfill-php81          | v1.27.0 | v1.28.0 | https://github.com/symfony/polyfill-php81/compare/v1.27.0...v1.28.0     |
    +---------------------------------+---------+---------+-------------------------------------------------------------------------+
    /// Updating: drupal/block_class ///
    There aren't available updates for drupal/block_class package.
    /// Updating: drupal/ckeditor_bootstrap_buttons ///
    Running drush cr on the "@self" environment:
    Running drush updb -y on the "@self" environment:
    Running drush cex -y on the "@self" environment:
    
    Updated packages:
    +--------------------+-------+-------+-------------------------------------------------------------------+
    | Production Changes | From  | To    | Compare                                                           |
    +--------------------+-------+-------+-------------------------------------------------------------------+
    | drupal/ckeditor    | 1.0.1 | 1.0.2 | https://git.drupalcode.org/project/ckeditor/compare/1.0.1...1.0.2 |
    +--------------------+-------+-------+-------------------------------------------------------------------+
    /// Updating: drupal/classy_paragraphs ///
    There aren't available updates for drupal/classy_paragraphs package.
    /// Updating: drupal/codesnippet ///
    Running drush cr on the "@self" environment:
    Running drush updb -y on the "@self" environment:
    Running drush cex -y on the "@self" environment:
    
    Updated packages:
    +---------------------------------------------+--------+--------+----------------------------------------------------------------------------------------+
    | Production Changes                          | From   | To     | Compare                                                                                |
    +---------------------------------------------+--------+--------+----------------------------------------------------------------------------------------+
    | drupal-ckeditor-libraries-group/codesnippet | 4.20.1 | 4.22.1 | https://github.com/drupal-ckeditor-libraries-group/codesnippet/compare/4.20.1...4.22.1 |
    +---------------------------------------------+--------+--------+----------------------------------------------------------------------------------------+
    /// Updating: drupal/components ///
    There aren't available updates for drupal/components package.
    /// Updating: drupal/config_filter ///
    There aren't available updates for drupal/config_filter package.
    /// Updating: drupal/config_split ///
    There aren't available updates for drupal/config_split package.
    /// Updating: drupal/config_update ///
    There aren't available updates for drupal/config_update package.
    /// Updating: drupal/context ///
    There aren't available updates for drupal/context package.
    /// Updating: drupal/core ///
    Running drush cr on the "@self" environment:
    Running drush updb -y on the "@self" environment:
    Running drush cex -y on the "@self" environment:
    
    Updated packages:
    +--------------------------------+---------+---------+---------------------------------------------------------------------+
    | Production Changes             | From    | To      | Compare                                                             |
    +--------------------------------+---------+---------+---------------------------------------------------------------------+
    | composer/semver                | 3.3.2   | 3.4.0   | https://github.com/composer/semver/compare/3.3.2...3.4.0            |
    | doctrine/reflection            | 1.2.3   | 1.2.4   | https://github.com/doctrine/reflection/compare/1.2.3...1.2.4        |
    | drupal/core                    | 9.5.9   | 9.5.11  | https://github.com/drupal/core/compare/9.5.9...9.5.11               |
    | laminas/laminas-feed           | 2.20.0  | 2.21.0  | https://github.com/laminas/laminas-feed/compare/2.20.0...2.21.0     |
    | laminas/laminas-servicemanager | 3.21.0  | REMOVED |                                                                     |
    | symfony/polyfill-iconv         | v1.27.0 | v1.28.0 | https://github.com/symfony/polyfill-iconv/compare/v1.27.0...v1.28.0 |
    | symfony/var-dumper             | v5.4.24 | v5.4.29 | https://github.com/symfony/var-dumper/compare/v5.4.24...v5.4.29     |
    +--------------------------------+---------+---------+---------------------------------------------------------------------+
    /// Updating: drupal/core-composer-scaffold ///
    
    Updated packages:
    +-------------------------------+-------+--------+-------------------------------------------------------------------------+
    | Production Changes            | From  | To     | Compare                                                                 |
    +-------------------------------+-------+--------+-------------------------------------------------------------------------+
    | drupal/core-composer-scaffold | 9.5.9 | 9.5.11 | https://github.com/drupal/core-composer-scaffold/compare/9.5.9...9.5.11 |
    +-------------------------------+-------+--------+-------------------------------------------------------------------------+
    /// Updating: drupal/crop ///
    There aren't available updates for drupal/crop package.
    /// Updating: drupal/ctools ///
    There aren't available updates for drupal/ctools package.
    /// Updating: drupal/datalayer ///
    Package drupal/datalayer has an update available to 2.0.1 version. Due to composer.json constraints, it hasn't been updated.
    /// Updating: drupal/datalayer_webform ///
    There aren't available updates for drupal/datalayer_webform package.
    /// Updating: drupal/default_content ///
    There aren't available updates for drupal/default_content package.
    /// Updating: drupal/devel ///
    There aren't available updates for drupal/devel package.
    /// Updating: drupal/draggableviews ///
    There aren't available updates for drupal/draggableviews package.
    /// Updating: drupal/editor_advanced_link ///
    Running drush cr on the "@self" environment:
    Running drush updb -y on the "@self" environment:
    Running drush cex -y on the "@self" environment:
    
    Updated packages:
    +-----------------------------+-------+-------+-------------------------------------------------------------------------------+
    | Production Changes          | From  | To    | Compare                                                                       |
    +-----------------------------+-------+-------+-------------------------------------------------------------------------------+
    | drupal/editor_advanced_link | 2.1.1 | 2.2.4 | https://git.drupalcode.org/project/editor_advanced_link/compare/2.1.1...2.2.4 |
    +-----------------------------+-------+-------+-------------------------------------------------------------------------------+
    [...]
  4. Reporting:
    // 4. REPORT //
    +---------------------------------------------+--------------+---------------+----------------------------------------------------------------------------------------+
    | Production Changes                          | From         | To            | Compare                                                                                |
    +---------------------------------------------+--------------+---------------+----------------------------------------------------------------------------------------+
    | composer/ca-bundle                          | 1.3.6        | 1.3.7         | https://github.com/composer/ca-bundle/compare/1.3.6...1.3.7                            |
    | composer/semver                             | 3.3.2        | 3.4.0         | https://github.com/composer/semver/compare/3.3.2...3.4.0                               |
    | consolidation/output-formatters             | 4.3.1        | 4.3.2         | https://github.com/consolidation/output-formatters/compare/4.3.1...4.3.2               |
    | doctrine/deprecations                       | v1.1.1       | 1.1.2         | https://github.com/doctrine/deprecations/compare/v1.1.1...1.1.2                        |
    | doctrine/reflection                         | 1.2.3        | 1.2.4         | https://github.com/doctrine/reflection/compare/1.2.3...1.2.4                           |
    | drupal-ckeditor-libraries-group/codesnippet | 4.20.1       | 4.22.1        | https://github.com/drupal-ckeditor-libraries-group/codesnippet/compare/4.20.1...4.22.1 |
    | drupal/admin_toolbar                        | 3.4.1        | 3.4.2         | https://git.drupalcode.org/project/admin_toolbar/compare/3.4.1...3.4.2                 |
    | drupal/ckeditor                             | 1.0.1        | 1.0.2         | https://git.drupalcode.org/project/ckeditor/compare/1.0.1...1.0.2                      |
    | drupal/core                                 | 9.5.9        | 9.5.11        | https://github.com/drupal/core/compare/9.5.9...9.5.11                                  |
    | drupal/core-composer-scaffold               | 9.5.9        | 9.5.11        | https://github.com/drupal/core-composer-scaffold/compare/9.5.9...9.5.11                |
    | drupal/editor_advanced_link                 | 2.1.1        | 2.2.4         | https://git.drupalcode.org/project/editor_advanced_link/compare/2.1.1...2.2.4          |
    | drupal/environment_indicator                | 4.0.14       | 4.0.16        | https://git.drupalcode.org/project/environment_indicator/compare/4.0.14...4.0.16       |
    | drupal/eu_cookie_compliance_matomo          | 1.0.5        | 1.0.6         | https://git.drupalcode.org/project/eu_cookie_compliance_matomo/compare/1.0.5...1.0.6   |
    | drupal/file_mdm                             | 2.5.0        | 2.6.0         | https://git.drupalcode.org/project/file_mdm/compare/2.5.0...2.6.0                      |
    | drupal/fontawesome                          | 2.25.0       | 2.26.0        | https://git.drupalcode.org/project/fontawesome/compare/2.25.0...2.26.0                 |
    | drupal/gin                                  | 3.0.0-rc3    | 3.0.0-rc6     | https://git.drupalcode.org/project/gin/compare/3.0.0-rc3...3.0.0-rc6                   |
    | drupal/gin_toolbar                          | 1.0.0-rc1    | 1.0.0-rc3     | https://git.drupalcode.org/project/gin_toolbar/compare/1.0.0-rc1...1.0.0-rc3           |
    | drupal/honeypot                             | 2.1.2        | 2.1.3         | https://git.drupalcode.org/project/honeypot/compare/2.1.2...2.1.3                      |
    | drupal/libraries                            | 4.0.3        | 4.0.4         | https://git.drupalcode.org/project/libraries/compare/4.0.3...4.0.4                     |
    | drupal/link_icons                           | 3.1.0-rc1    | 3.1.0-rc2     | https://git.drupalcode.org/project/link_icons/compare/3.1.0-rc1...3.1.0-rc2            |
    | drupal/metatag                              | 1.25.0       | 1.26.0        | https://git.drupalcode.org/project/metatag/compare/1.25.0...1.26.0                     |
    | drupal/node_authlink                        | bdfdd7d      | c2c1f6e       | https://git.drupalcode.org/project/node_authlink/compare/bdfdd7d...c2c1f6e             |
    | drupal/paragraphs                           | 1.15.0       | 1.16.0        | https://git.drupalcode.org/project/paragraphs/compare/1.15.0...1.16.0                  |
    | drupal/radix                                | 5.0.6        | 5.0.11        | https://git.drupalcode.org/project/radix/compare/5.0.6...5.0.11                        |
    | drupal/redirect                             | 1.8.0        | 1.9.0         | https://git.drupalcode.org/project/redirect/compare/1.8.0...1.9.0                      |
    | drupal/reroute_email                        | 2.2.0        | 2.2.1         | https://git.drupalcode.org/project/reroute_email/compare/2.2.0...2.2.1                 |
    | drupal/schema_metatag                       | 2.4.0        | 2.5.0         | https://git.drupalcode.org/project/schema_metatag/compare/2.4.0...2.5.0                |
    | drupal/stage_file_proxy                     | 2.0.2        | 2.1.1         | https://git.drupalcode.org/project/stage_file_proxy/compare/2.0.2...2.1.1              |
    | drupal/string_field_formatter               | 2.0.0        | 2.0.2         | https://git.drupalcode.org/project/string_field_formatter/compare/2.0.0...2.0.2        |
    | drupal/token                                | 1.11.0       | 1.12.0        | https://git.drupalcode.org/project/token/compare/1.11.0...1.12.0                       |
    | drupal/views_infinite_scroll                | 2.0.1        | 2.0.2         | https://git.drupalcode.org/project/views_infinite_scroll/compare/2.0.1...2.0.2         |
    | drupal/viewsreference                       | 2.0.0-beta4  | 2.0.0-beta6   | https://git.drupalcode.org/project/viewsreference/compare/2.0.0-beta4...2.0.0-beta6    |
    | drupal/xray_audit                           | 1.3.1        | 1.5.0         | https://git.drupalcode.org/project/xray_audit/compare/1.3.1...1.5.0                    |
    | drupal/yoast_seo                            | 2.0.0-alpha8 | 2.0.0-alpha10 | https://git.drupalcode.org/project/yoast_seo/compare/2.0.0-alpha8...2.0.0-alpha10      |
    | fileeye/mimemap                             | 2.0.1        | 2.0.2         | https://github.com/FileEye/MimeMap/compare/2.0.1...2.0.2                               |
    | kint-php/kint                               | 5.0.5        | 5.0.7         | https://github.com/kint-php/kint/compare/5.0.5...5.0.7                                 |
    | laminas/laminas-feed                        | 2.20.0       | 2.21.0        | https://github.com/laminas/laminas-feed/compare/2.20.0...2.21.0                        |
    | laminas/laminas-servicemanager              | 3.21.0       | REMOVED       |                                                                                        |
    | laminas/laminas-stdlib                      | 3.17.0       | 3.18.0        | https://github.com/laminas/laminas-stdlib/compare/3.17.0...3.18.0                      |
    | lsolesen/pel                                | 0.9.12       | REMOVED       |                                                                                        |
    | masterminds/html5                           | 2.8.0        | 2.8.1         | https://github.com/Masterminds/html5-php/compare/2.8.0...2.8.1                         |
    | nikic/php-parser                            | v4.15.5      | v4.17.1       | https://github.com/nikic/PHP-Parser/compare/v4.15.5...v4.17.1                          |
    | psr/http-client                             | 1.0.2        | 1.0.3         | https://github.com/php-fig/http-client/compare/1.0.2...1.0.3                           |
    | psy/psysh                                   | v0.11.18     | v0.11.21      | https://github.com/bobthecow/psysh/compare/v0.11.18...v0.11.21                         |
    | symfony/polyfill-ctype                      | v1.27.0      | v1.28.0       | https://github.com/symfony/polyfill-ctype/compare/v1.27.0...v1.28.0                    |
    | symfony/polyfill-iconv                      | v1.27.0      | v1.28.0       | https://github.com/symfony/polyfill-iconv/compare/v1.27.0...v1.28.0                    |
    | symfony/polyfill-intl-grapheme              | v1.27.0      | v1.28.0       | https://github.com/symfony/polyfill-intl-grapheme/compare/v1.27.0...v1.28.0            |
    | symfony/polyfill-intl-idn                   | v1.27.0      | v1.28.0       | https://github.com/symfony/polyfill-intl-idn/compare/v1.27.0...v1.28.0                 |
    | symfony/polyfill-intl-normalizer            | v1.27.0      | v1.28.0       | https://github.com/symfony/polyfill-intl-normalizer/compare/v1.27.0...v1.28.0          |
    | symfony/polyfill-mbstring                   | v1.27.0      | v1.28.0       | https://github.com/symfony/polyfill-mbstring/compare/v1.27.0...v1.28.0                 |
    | symfony/polyfill-php72                      | v1.27.0      | v1.28.0       | https://github.com/symfony/polyfill-php72/compare/v1.27.0...v1.28.0                    |
    | symfony/polyfill-php73                      | v1.27.0      | v1.28.0       | https://github.com/symfony/polyfill-php73/compare/v1.27.0...v1.28.0                    |
    | symfony/polyfill-php80                      | v1.27.0      | v1.28.0       | https://github.com/symfony/polyfill-php80/compare/v1.27.0...v1.28.0                    |
    | symfony/string                              | v6.3.0       | v6.3.5        | https://github.com/symfony/string/compare/v6.3.0...v6.3.5                              |
    | symfony/var-dumper                          | v5.4.24      | v5.4.29       | https://github.com/symfony/var-dumper/compare/v5.4.24...v5.4.29                        |
    | fileeye/pel                                 | NEW          | 0.9.20        |                                                                                        |
    +---------------------------------------------+--------------+---------------+----------------------------------------------------------------------------------------+
    +------------------------------------+----------+----------+-----------------------------------------------------------------------------------+
    | Dev Changes                        | From     | To       | Compare                                                                           |
    +------------------------------------+----------+----------+-----------------------------------------------------------------------------------+
    | composer/composer                  | 2.2.21   | 2.2.22   | https://github.com/composer/composer/compare/2.2.21...2.2.22                      |
    | drupal/coder                       | 8.3.20   | 8.3.21   | https://github.com/pfrenssen/coder/compare/8.3.20...8.3.21                        |
    | friends-of-behat/mink-extension    | v2.7.2   | v2.7.4   | https://github.com/FriendsOfBehat/MinkExtension/compare/v2.7.2...v2.7.4           |
    | justinrainbow/json-schema          | 5.2.12   | v5.2.13  | https://github.com/justinrainbow/json-schema/compare/5.2.12...v5.2.13             |
    | metadrop/behat-contexts            | v1.13.1  | v1.13.5  | https://github.com/Metadrop/behat-contexts/compare/v1.13.1...v1.13.5              |
    | metadrop/drupal-updater            | 1.7.0    | 1.8.0    | https://github.com/Metadrop/drupal-updater/compare/1.7.0...1.8.0                  |
    | metadrop/scripthor                 | v2.5.0   | v2.6.0   | https://github.com/Metadrop/scripthor/compare/v2.5.0...v2.6.0                     |
    | mglaman/phpstan-drupal             | 1.1.35   | 1.2.0    | https://github.com/mglaman/phpstan-drupal/compare/1.1.35...1.2.0                  |
    | pdepend/pdepend                    | 2.14.0   | 2.15.1   | https://github.com/pdepend/pdepend/compare/2.14.0...2.15.1                        |
    | phpcompatibility/php-compatibility | 1f82405  | 302dffe  | https://github.com/PHPCompatibility/PHPCompatibility/compare/1f82405...302dffe    |
    | phpcsstandards/phpcsutils          | 1.0.6    | 1.0.8    | https://github.com/PHPCSStandards/PHPCSUtils/compare/1.0.6...1.0.8                |
    | phpdocumentor/type-resolver        | 1.7.2    | 1.7.3    | https://github.com/phpDocumentor/TypeResolver/compare/1.7.2...1.7.3               |
    | phpmd/phpmd                        | 2.13.0   | 2.14.1   | https://github.com/phpmd/phpmd/compare/2.13.0...2.14.1                            |
    | phpstan/phpdoc-parser              | 1.20.4   | 1.24.2   | https://github.com/phpstan/phpdoc-parser/compare/1.20.4...1.24.2                  |
    | phpstan/phpstan                    | 1.10.19  | 1.10.37  | https://github.com/phpstan/phpstan/compare/1.10.19...1.10.37                      |
    | phpstan/phpstan-deprecation-rules  | 1.1.3    | 1.1.4    | https://github.com/phpstan/phpstan-deprecation-rules/compare/1.1.3...1.1.4        |
    | phpunit/php-code-coverage          | 9.2.26   | 9.2.29   | https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.26...9.2.29    |
    | phpunit/phpunit                    | 9.6.9    | 9.6.13   | https://github.com/sebastianbergmann/phpunit/compare/9.6.9...9.6.13               |
    | sebastian/global-state             | 5.0.5    | 5.0.6    | https://github.com/sebastianbergmann/global-state/compare/5.0.5...5.0.6           |
    | sirbrillig/phpcs-variable-analysis | v2.11.16 | v2.11.17 | https://github.com/sirbrillig/phpcs-variable-analysis/compare/v2.11.16...v2.11.17 |
    | slevomat/coding-standard           | 8.12.1   | 8.13.4   | https://github.com/slevomat/coding-standard/compare/8.12.1...8.13.4               |
    | symfony/phpunit-bridge             | v5.4.23  | v5.4.26  | https://github.com/symfony/phpunit-bridge/compare/v5.4.23...v5.4.26               |
    | symfony/polyfill-php81             | v1.27.0  | v1.28.0  | https://github.com/symfony/polyfill-php81/compare/v1.27.0...v1.28.0               |
    +------------------------------------+----------+----------+-----------------------------------------------------------------------------------+
    /// Not Updated Packages (Direct): ///
    drupal-composer/drupal-security-advisories 9.x-dev 9cfc00d ! 9.x-dev 0625017
    drupal/allowed_formats                     2.0.0           ~ 3.0.0
    drupal/core                                9.5.11          ~ 10.1.5
    drupal/core-composer-scaffold              9.5.11          ~ 10.1.5
    drupal/datalayer                           1.0.0           ~ 2.0.1
    drupal/google_tag                          1.6.0           ~ 2.0.2
    drupal/inline_entity_form                  1.0.0-rc15      ~ 2.0.0-rc9
    drupal/metatag                             1.26.0          ~ 2.0.0
    drupal/schema_metatag                      2.5.0           ~ 3.0.1
    drush/drush                                11.6.0          ~ 12.2.0
    metadrop/drupal-dev                        v0.3.0          ~ v1.1.0
    phpro/grumphp                              v1.5.1          ~ v2.1.0
    
    /// Not Updated Packages (ALL): ///
    Direct dependencies required in composer.json:
    drupal-composer/drupal-security-advisories     9.x-dev 9cfc00d ! 9.x-dev 0625017
    drupal/allowed_formats                         2.0.0           ~ 3.0.0
    drupal/core                                    9.5.11          ~ 10.1.5
    drupal/core-composer-scaffold                  9.5.11          ~ 10.1.5
    drupal/datalayer                               1.0.0           ~ 2.0.1
    drupal/google_tag                              1.6.0           ~ 2.0.2
    drupal/inline_entity_form                      1.0.0-rc15      ~ 2.0.0-rc9
    drupal/metatag                                 1.26.0          ~ 2.0.0
    drupal/schema_metatag                          2.5.0           ~ 3.0.1
    drush/drush                                    11.6.0          ~ 12.2.0
    metadrop/drupal-dev                            v0.3.0          ~ v1.1.0
    phpro/grumphp                                  v1.5.1          ~ v2.1.0
    Transitive dependencies not required in composer.json:
    amphp/amp                                      v2.6.2          ~ v3.0.0
    amphp/byte-stream                              v1.8.1          ~ v2.0.2
    amphp/parallel                                 v1.4.3          ~ v2.2.2
    amphp/parallel-functions                       v1.0.0          ! v1.1.0
    amphp/process                                  v1.1.4          ~ v2.0.1
    amphp/sync                                     v1.4.2          ~ v2.1.0
    asm89/stack-cors                               1.3.0           ~ v2.1.1
    behat/mink-browserkit-driver                   v1.4.1          ~ v2.1.0
    behat/mink-goutte-driver                       v1.3.0          ~ v2.0.0
    Package behat/mink-goutte-driver is abandoned, you should avoid using it. Use behat/mink-browserkit-driver instead.
    chi-teck/drupal-code-generator                 2.6.2           ~ 3.2.0
    composer/composer                              2.2.22          ! 2.6.4
    composer/pcre                                  1.0.1           ~ 3.1.0
    consolidation/log                              2.1.1           ~ 3.0.0
    consolidation/robo                             4.0.2           ! 4.0.6
    consolidation/site-alias                       3.1.7           ~ 4.0.1
    consolidation/site-process                     4.2.1           ~ 5.2.0
    dealerdirect/phpcodesniffer-composer-installer v0.7.2          ~ v1.0.0
    doctrine/annotations                           1.14.3          ~ 2.0.1
    doctrine/collections                           1.8.0           ~ 2.1.4
    doctrine/lexer                                 2.1.0           ~ 3.0.0
    doctrine/reflection                            1.2.4           = 1.2.4
    Package doctrine/reflection is abandoned, you should avoid using it. Use roave/better-reflection instead.
    drupal/core-dev                                9.1.15          ~ 10.1.5
    drupal/file_mdm                                2.6.0           ~ 3.0.0
    drupal/sophron                                 1.3.0           ~ 2.0.1
    egulias/email-validator                        3.2.6           ~ 4.0.1
    fabpot/goutte                                  v3.3.1          ~ v4.0.3
    Package fabpot/goutte is abandoned, you should avoid using it. Use symfony/browser-kit instead.
    grasmash/expander                              2.0.3           ~ 3.0.0
    guzzlehttp/guzzle                              6.5.8           ~ 7.8.0
    guzzlehttp/promises                            1.5.3           ~ 2.0.1
    guzzlehttp/psr7                                1.9.1           ~ 2.6.1
    metadrop/scripthor                             v2.6.0          ~ v3.0.0
    monolog/monolog                                2.9.1           ~ 3.4.0
    phploc/phploc                                  7.0.2           = 7.0.2
    Package phploc/phploc is abandoned, you should avoid using it. No replacement was suggested.
    phpunit/php-code-coverage                      9.2.29          ~ 10.1.7
    phpunit/php-file-iterator                      3.0.6           ~ 4.1.0
    phpunit/php-invoker                            3.1.1           ~ 4.0.0
    phpunit/php-text-template                      2.0.4           ~ 3.0.1
    phpunit/php-timer                              5.0.3           ~ 6.0.0
    phpunit/phpunit                                9.6.13          ~ 10.3.5
    psr/container                                  1.1.2           ~ 2.0.2
    psr/http-message                               1.1             ~ 2.0
    psr/log                                        1.1.4           ~ 3.0.0
    react/promise                                  v2.10.0         ~ v3.0.0
    sebastian/cli-parser                           1.0.1           ~ 2.0.0
    sebastian/code-unit                            1.0.8           ~ 2.0.0
    sebastian/code-unit-reverse-lookup             2.0.3           ~ 3.0.0
    sebastian/comparator                           4.0.8           ~ 5.0.1
    sebastian/complexity                           2.0.2           ~ 3.1.0
    sebastian/diff                                 4.0.5           ~ 5.0.3
    sebastian/environment                          5.1.5           ~ 6.0.1
    sebastian/exporter                             4.0.5           ~ 5.1.1
    sebastian/global-state                         5.0.6           ~ 6.0.1
    sebastian/lines-of-code                        1.0.3           ~ 2.0.1
    sebastian/object-enumerator                    4.0.4           ~ 5.0.0
    sebastian/object-reflector                     2.0.4           ~ 3.0.0
    sebastian/phpcpd                               6.0.3           = 6.0.3
    Package sebastian/phpcpd is abandoned, you should avoid using it. No replacement was suggested.
    sebastian/recursion-context                    4.0.5           ~ 5.0.0
    sebastian/type                                 3.2.1           ~ 4.0.0
    sebastian/version                              3.0.2           ~ 4.0.1
    symfony-cmf/routing                            2.3.4           ~ 3.0.1
    symfony/browser-kit                            v4.4.44         ~ v6.3.2
    symfony/config                                 v4.4.44         ~ v6.3.2
    symfony/console                                v4.4.49         ~ v6.3.4
    symfony/css-selector                           v4.4.44         ~ v6.3.2
    symfony/debug                                  v4.4.44         = v4.4.44
    Package symfony/debug is abandoned, you should avoid using it. Use symfony/error-handler instead.
    symfony/dependency-injection                   v4.4.49         ~ v6.3.5
    symfony/dom-crawler                            v4.4.45         ~ v6.3.4
    symfony/dotenv                                 v5.4.22         ~ v6.3.0
    symfony/error-handler                          v4.4.44         ~ v6.3.5
    symfony/event-dispatcher                       v4.4.44         ~ v6.3.2
    symfony/event-dispatcher-contracts             v1.1.13         ~ v3.3.0
    symfony/filesystem                             v4.4.42         ~ v6.3.1
    symfony/finder                                 v4.4.44         ~ v6.3.5
    symfony/http-client-contracts                  v2.5.2          ~ v3.3.0
    symfony/http-foundation                        v4.4.49         ~ v6.3.5
    symfony/http-kernel                            v4.4.50         ~ v6.3.5
    symfony/lock                                   v4.4.46         ~ v6.3.2
    symfony/mime                                   v5.4.13         ~ v6.3.5
    symfony/options-resolver                       v5.4.21         ~ v6.3.0
    symfony/phpunit-bridge                         v5.4.26         ~ v6.3.2
    symfony/process                                v4.4.44         ~ v6.3.4
    symfony/psr-http-message-bridge                v2.1.4          ! v2.3.1
    symfony/routing                                v4.4.44         ~ v6.3.5
    symfony/serializer                             v4.4.47         ~ v6.3.5
    symfony/service-contracts                      v2.5.2          ~ v3.3.0
    symfony/translation                            v4.4.47         ~ v6.3.3
    symfony/translation-contracts                  v2.5.2          ~ v3.3.0
    symfony/validator                              v4.4.48         ~ v6.3.5
    symfony/var-dumper                             v5.4.29         ~ v6.3.5
    symfony/yaml                                   v4.4.45         ~ v6.3.3
    twig/twig                                      v2.15.5         ~ v3.7.1
    webmozart/path-util                            2.3.0           = 2.3.0
    Package webmozart/path-util is abandoned, you should avoid using it. Use symfony/filesystem instead.
    /// Not Updated Securities (ALL): ///
    /// Unsupported Drupal modules: ///
    No obsolete modules have been found. Perhaps Update module is not installed?

Automating the Full Process

To streamline the entire update process, we leverage Jenkins to automate the Drupal Updater. Here's an overview of how  the automation process works:

  1. Scheduled Updates: Jenkins is configured to run the Drupal Updater tool automatically at regular intervals or specific trigger events.
  2. Launch the project: release your code and launch a new instance of your project.
  3. Branch Creation: Create a new branch to isolate the updates from the main development branch, ensuring a controlled environment for testing.
  4. Run the tool
  5. Push the code to the repository and create a new Merge Request
  6. Let the Automated Testing run: A suite of automated tests (e.g. PhpUnit, Behat, BackstopJs)  is executed to verify the stability and functionality of the updated project.
  7. Code Review: After the automated tests pass successfully, the development team reviews the changes and ensures they meet the project's quality standards.
  8. Merge and Release: Once the updates are approved, they are merged into the main development branch and deployed to the production environment.

 

Drupal Update Helper - Jenkins Pipelines

Jenkins Pipeline

Drupal Updater - Commits

GitLab Commits on Update Branch

Conclusions

Updating a PHP project based on Composer, especially Drupal projects, can be a challenging task for developers. Dependency conflicts, configuration issues, multisite challenges, and the time-consuming nature and error-prone of the update process are just some of the difficulties that developers face when done manually.

The Drupal Updater provides an efficient solution to this problem, automating package updates, configuration management, and dependency handling. By integrating this tool into your development workflow and automating it with your CI/CD tool (optional), you can ensure that your Drupal projects are always up to date, secure, and ready for new features.

In summary, the Drupal updater package is a great ally for developers working on Drupal projects. It simplifies the update process and helps ensure that the project remains up-to-date, secure, and reliable. By using the Drupal updater package, developers can focus on developing great features for their projects instead of spending hours dealing with update issues that can be easily automated.

Future Work / References

The Drupal Updater is a valuable tool for Drupal maintenance we love to share with the community. We have been using it internally for more than a year, first as Bash scripts and later ported to PHP. It greatly helps us to maintain our Drupal projects and we think it can help others too. There is always room for improvement, we encourage you to provide feedback and help evolve this awesome tool in Github.

Jorge Tutor

Jorge Tutor

CIO