Skip to content

Config management

FedMS uses a deliberate config-management discipline. Every piece of configuration has one owner module and a predictable flow from edit → export → commit → deploy → import.

The toolchain

Module Role
config_devel Each module declares the config it owns; that config is automatically captured on export.
config_split Splits config between environments — develop, live, test, this_site.
config_ignore Ignores changes to certain config (e.g. site UUID).
config_rewrite Applies non-destructive declarative tweaks to upstream config on install.
config_update (UI) Visual diff and revert tools for admins.

The four splits

Every tenant has four config_split profiles:

Split Purpose
develop Dev-only — e.g. null mail transport, debug enabled, dev-friendly stage_file_proxy.
live Production-only — production transport, debug off.
test Test environment-only.
this_site Site-specific overrides that don't fit the other three (theme tweaks, helpdesk integration credentials, etc.).

The right split is auto-activated based on $config['system.site']['settings'] (or environment variables on managed SaaS).

How config flows

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
┌──────────────────────────────────────────────────────────────────────┐
│                                                                      │
│   1. Edit in Drupal admin UI on a dev environment                    │
│                            │                                         │
│                            ▼                                         │
│   2. Drupal writes the change to active config storage (DB)          │
│                            │                                         │
│                            ▼                                         │
│   3. l3d ahoy fedms export-config                                    │
│      Iterates over the profile + 7 modules, running                  │
│      drush config:devel-export on each.                              │
│                            │                                         │
│                            ▼                                         │
│   4. config_devel writes YAML files into                             │
│      the OWNING module's config/install/ or config/optional/         │
│                            │                                         │
│                            ▼                                         │
│   5. cd <module>/ && l3d git diff                                    │
│      Inspect the diff, prune unrelated changes.                      │
│                            │                                         │
│                            ▼                                         │
│   6. l3d git add <files> && l3d git commit -m "..." && l3d git push  │
│      Open an MR on the module's repo.                                │
│                            │                                         │
│                            ▼                                         │
│   7. MR review → merge → next release                                │
│                            │                                         │
│                            ▼                                         │
│   8. Tenant pulls the new release via composer                       │
│                            │                                         │
│                            ▼                                         │
│   9. l3d ahoy fedms update-config (idempotent)                       │
│      runs the apply step.                                            │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

Module-level config

Each module declares its owned config in its <module>.info.yml under a config_devel: section:

1
2
3
4
5
6
7
8
config_devel:
  install:
    - some.config.id
    - another.config.id
  optional:
    - optional.config.id
  rewrite:
    - some.upstream.config.id
  • install — installed when the module is enabled, no dependencies.
  • optional — installed when the module is enabled and the config's dependencies are present. Used heavily by fedms_federation for the group-relationship types.
  • rewrite — non-destructive tweaks applied via config_rewrite.

The export command

l3d ahoy fedms export-config runs this for every FedMS module:

1
2
3
4
5
6
7
drush config:devel-export fedms
drush config:devel-export fedms_attachment
drush config:devel-export fedms_content
drush config:devel-export fedms_eca
drush config:devel-export fedms_federation
drush config:devel-export fedms_locale
drush config:devel-export fedms_task

After running, you usually need to prune the diff — config_devel exports a lot more than you intended. The pattern is:

  1. Run the export.
  2. cd into the module repo and l3d git diff.
  3. Add only the files you intentionally changed.
  4. Discard the rest with l3d git checkout -- ..

What lives where

A rough partitioning:

Owner Examples
fedms (profile) Site-wide baseline: date formats, default editors, user profile fields, dashboard, theme.
fedms_federation Group types and their fields, group_relationship types, federation-level views, pathauto for groups.
fedms_content Event/session entity types, paragraph types, their displays, pathauto for events/sessions.
fedms_attachment Attachment entity type, default attachment-type bundle, its displays.
fedms_task Task views, milestone vocabulary. (Task patterns are also fedms_task_pattern.* config but they are typically tenant-owned.)
fedms_eca All 10 ECA models.
fedms_locale Language entities and rewrite of language.entity.en.

If you change a config item, ask "which module owns this?" and commit the change to that module's repo.

Site-level config

A tenant site has its own config that doesn't belong to any framework module — typically:

  • Tenant-specific event types, session types, attachment types.
  • Tenant-specific task patterns.
  • Tenant-specific webforms.
  • Tenant-specific theme overrides.
  • The this_site config split's content.

Tenant config lives in the tenant repo, under config/sync/ (or the equivalent path on the active split).

Anti-patterns

  • Don't dump module config into the site's config/sync/. It silently overrides the module's owned config.
  • Don't edit eca.eca.*.yml files by hand — go through the modeler.
  • Don't rewrite upstream config destructively in config_devel.rewrite — use additive merges only.
  • Don't mix unrelated changes in one config export.

When update-config is needed beyond config sync

Sometimes a release needs imperative steps that config sync can't handle: cache invalidation, search-index reindex, ECA re-enable. Those steps go in:

1
vendor/fedms/scripts/config.sh

Run via l3d ahoy fedms update-config. The script is idempotent — it can be re-run safely.

Next steps

  • Profile — for the install pipeline.
  • Testing — for what should run before committing config.
  • Contributing — for the MR workflow.