Skip to content

Deploy changes to a populated compound

A shared compound definition affects every field that uses it. Changing its structure can change database columns on current and historical revisions. Rehearse the change on a copy of the site and retain a database backup.

For an individual deletion through Field UI, use Remove a populated sub-field.

Preview a change

These commands run from the Drupal project. Replace session with your compound ID.

drush compound-field:remove-field session note --dry-run

Read the affected fields, row counts and any refusals. A dry run changes nothing. If the intended deletion includes all those fields and their history:

drush compound-field:remove-field session note --acknowledge

Removing columns cannot be undone by reverting a content revision.

Task Command
Add a sub-field compound-field:add-field session nickname string
Rename a sub-field compound-field:rename-field session note internal_note
Remove a sub-field compound-field:remove-field session note --acknowledge
Change settings compound-field:change-settings session title --storage-settings='{"max_length":512}'
Raise a sub-field cap compound-field:change-settings session topics --cardinality=4
Check configuration against storage compound-field:drift

Prefix each command with drush. Add --dry-run to preview changes. Lowering a cap can delete values and requires --acknowledge.

Export and import the change

Additions, reordering and widening can travel in the compound's ordinary configuration export. Renames, removals and cap reductions need a separate declaration that identifies the intended change.

For a rename, create its declaration before applying it locally. Run the following from the source Drupal project, in one shell with failure handling enabled. Set config_dir to the absolute path of the configuration directory you deploy (the example assumes config/sync under the project root). Keep the temporary declaration copy outside that directory: applying the rename locally consumes its active declaration, and the next export removes its exported file.

set -eu
config_dir="$(pwd)/config/sync"
declaration=compound_field.structural_change.rename_session_note.yml
saved_declaration_dir=$(mktemp -d)

drush compound-field:rename-field session note internal_note --declare=rename_session_note
drush config:export --destination="$config_dir"
cp "$config_dir/$declaration" "$saved_declaration_dir/$declaration"
drush compound-field:rename-field session note internal_note
drush config:export --destination="$config_dir"
cp "$saved_declaration_dir/$declaration" "$config_dir/$declaration"

# Inspect both deployment files before committing.
cat "$config_dir/compound_field.compound_field.session.yml"
cat "$config_dir/$declaration"
rm "$saved_declaration_dir/$declaration"
rmdir "$saved_declaration_dir"

Verify that the compound's fields map contains internal_note instead of note and the declaration has compound: session with a renames entry whose from is note and to is internal_note. Commit both files together. If a command fails, retain the temporary copy until the final export and restore succeed; then remove it as shown above.

On the target environment, run from its Drupal project. Set config_dir to the absolute path where those committed configuration files were deployed:

config_dir="$(pwd)/config/sync"
drush config:import --source="$config_dir"
drush compound-field:migration-run
drush compound-field:migration-status --pending
drush compound-field:drift

The import consumes the declaration. Remove its exported file in a follow-up commit; otherwise configuration status reports it as a pending creation.

Removals and cap reductions are declared the same way, with --acknowledge and --declare on compound-field:remove-field or on compound-field:change-settings --cardinality. Each declaration is bound to the change it authorises:

  • A removals entry names the sub_field and the storage_uuid of its field storage.
  • A cardinality_reductions entry names the sub_field, its storage_uuid, and the caps from and to.

Write the declaration before applying the change locally, so the binding describes the storage as it is before the change. An import applies a declaration only to that exact change. A sub-field removed and later re-added under the same name gets a new storage UUID, and a reduction between two other caps is a different change, so a declaration file left in the configuration directory authorises neither. The import refuses such a change and names the stale file. It also refuses an entry that lacks its binding.

Deploy changes separately and review all declarations for the same compound. Their permissions combine during an import. Do not leave an unrelated removal declared while deploying a rename.

If your site deploys through update hooks, generate one instead:

drush compound-field:rename-field session note internal_note \
  --dry-run --update-hook --hook-module=my_deploy

Put the generated function in your own deployment module's post-update file. Do not edit Compound Field's module files or change an in-use definition by calling its configuration save directly.

Correct an allowed-value key

Changing an allowed-value label does not rewrite stored keys. To correct a mistyped key that content already uses:

drush compound-field:rekey-allowed-value session state stauts status --dry-run
drush compound-field:rekey-allowed-value session state stauts status

This updates current values and the allowed-value configuration. Historical revisions retain the old key. Reverting an old revision can restore it. The command refuses to merge into a key already offered by the field.

Run this operation on each environment; it does not travel in a configuration declaration. Retiring a populated key without rewriting its values instead requires --acknowledge-rejected-storage-setting-values on the settings command.

Finish or recover an interrupted change

Only one structural change can run on a compound at a time. If another change holds its lock, inspect it before retrying:

drush compound-field:lock-status session
drush compound-field:migration-status
drush compound-field:migration-run

Cron can finish pending copy migrations. The run command finishes them now; migration-status --pending exits nonzero while work remains.

If the process holding a lock has stopped, use drush compound-field:lock-break session. Do not break a lock held by an active worker. Check migration status and drift afterward.

A destructive change interrupted between tables may already have deleted values. Rerunning can finish the schema change, but recovering deleted content requires your backup. Keep content writers stopped while resolving a partial deployment.

Completed copy migrations can retain old columns. Inspect them with migration-status; use migration-cleanup <job> only after verification. Before completion, migration-abandon <job> can stop a migration that has not switched to its new columns. Inspect its status before abandoning it.

Custom deployment code must reload content entities after changing a compound or finishing a migration. Saving an entity loaded before the change can overwrite the migrated values.