This project is not covered by Drupal’s security advisory policy.

"Profile Updates" lets site administrators review the optional configuration updates shipped by an install profile (or its modules) and decide — one by one, or in bulk — which ones to apply. Unlike a forced hook_post_update_N(), applying a profile update is always a deliberate action taken in the admin UI (or via Drush); nothing runs automatically on drush updb / drush deploy:hook.

The problem it solves

Distributions hit this the moment they have real clients on real sites: not every site wants every profile change. Sites carry local customizations, and forced update hooks can overwrite site-specific work — yet the site owner has no say in the matter. Profile Updates gives them one, while still letting the distribution ship a steady stream of improvements.

It is a lightweight alternative to Config Distro (config_distro)

How it works

  • A developer changes configuration and ships an update task: a small YAML file naming the changed config item(s), with a human-readable label and description.
  • Tasks are auto-discovered as plugins from EXTENSION/update_tasks/*.yml, re-scanned on every cache clear — no import step, no stale registry.
  • Administrators with the Administer profile updates permission open Configuration » Development » Profile updates and see what actually needs attention on this site.
  • They Apply (through the Batch API, so it scales) or Skip updates. Every choice is recorded as an audit-trail entry that stays readable even if the originating task later changes or disappears.

Per-site, computed state

Each update's state is worked out live by diffing the shipped config against the site's active config and consulting the log:

  • Pending — shipped config differs from active; actionable now.
  • Blocked — actionable, but a required module or another update must come first.
  • Up to date — already in sync; nothing to apply.
  • Applied / Skipped — recorded decisions, browsable on their own tabs (un-skipping is simply removing a record from the Skipped tab).

Key features

  • Nothing forced on deploy — applying is always an explicit, per-update decision.
  • Version-aware — state is keyed to a content hash of the shipped config, so a re-released update re-appears as pending automatically instead of being silently missed.
  • Diff on every row — see exactly what an update would change; the Applied tab even shows the historical before/after captured at apply time.
  • Dependencies — a task can require modules to be enabled or other tasks to be applied first, and stays blocked until they are.
  • Transactional apply of multi-config tasks, an ordering weight, and a full audit log.
  • Drush supportpu:list, pu:apply, pu:skip — for CI and automation.

For distribution maintainers

The optional Profile Updates: Export submodule (dev-only) generates update tasks straight from a diff of your active configuration, grouped per module or profile. It can alternatively generate forced hook_post_update_N() hooks for changes that genuinely must not be optional. The runtime module has no dependency on it — any module can ship tasks by hand.

Everything runs through a single Drush command once the submodule is enabled:

  • drush profile-updates-export — re-export active config back into the profile/module config/install \ config/optional files.
  • --diff — dry run; --module=a,b — scope to extensions; --no-new — existing files only.
  • --with-update-tasks — also generate optional update tasks (enable profile_updates_export_update_tasks); add --group=slug --label="…" to bundle everything into one.
  • --with-update-hooks — also generate forced post_update hooks (enable profile_updates_export_update_hooks).

Setup: the export writes back into the profile as the running site sees it, so the profile must be your editable source under the docroot — either living in the docroot directly (developing in the profile's own repo) or symlinked into it (e.g. a Composer path repository, or a git submodule). A profile copied in by Composer as a normal package works too, but those writes are untracked and get overwritten on the next composer install.

Requirements

Project information

Releases