Problem/Motivation
Follow-up to #2361539: Config export key order is not predictable for sequences, add orderby property to config schema . Sequences that are not sorted can result in unexpected configuration differences whilst importing configuration. Which confuses users because they are being told something is different when it is not. Also this behaviour can result in random test fails
Proposed resolution
We should add an orderby key to all configuration schema definitions in core, remove explicit sorting code, and test for the lack of an orderby in when we check that configuration matches the schema.
We might choose to file individual followup issues to do the remove explicit sorting code as this is likely to be something that needs to be considered on a case-by-case basis.
Remaining tasks
User interface changes
None
API changes
None.
Data model changes
All sequences in configuration sorted - this is likely to have an interesting upgrade path.
Issue fork drupal-2855675
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
alexpottComment #3
alexpottI think this is going to need to be a plan because we really ought to add test coverage of everything. Also I think it is will be safer if we add one update to update all configuration for 8.4.0.
Comment #10
alexpottI had a look at making this change for filter formats - for the filters value. This is a sorted list of the plugin config. It currently is sorted in
\Drupal\filter\Entity\FilterFormat::preSave(). So the idea would be to move the sort to schema...There is a problem with this though. Doing
add removing the sort from
\Drupal\filter\Entity\FilterFormat::preSave()would change the sort function fromstrnatcasecmp()toksort()- so the IDs filter_three and filter_two will be sorted differently.Comment #13
bircherI was going to propose that we could add
orderby: key natural(or similar and also for values) but I just checked the filter formats and the FilterPluginCollection. And it is doing a much more complex sorting taking into account weight, status, the provider and finally the plugin id. So if we want to sort it exactly the same way with the schema we would have to add the option to add a static method or other function to sort with.But I wonder if that really matters? When
\Drupal\filter\Entity\FilterFormat::filtersis called the FilterPluginCollection is sorted, so the running code is sorting the filters properly, they don't need to be saved in config with the same order necessarily.In #2852557: Config export key order is not predictable, use config schema to order keys for maps we re-order config already because it is inconsistent otherwise. Most places could be updated by sorting the schema the way the code expects it, but in other places we had to do it the other way around because inherited schemas also inherit the order.
So of course in isolation the two patches (here and in #2852557) will necessarily conflict a lot since both will try to re-order things. But since the sorting can be scripted for the sake of the patch generation it can also be re-rolled relatively easily. (I just hope the tests don't conflict too much)
So my two cent RE #10: that is fine, the alternative would be to introduce a static sorting function defined in the schema. But since the different sorting just affects how the yaml is saved in git (and the array in the database) and not how it is used in code, I think it is worth the tradeoff when we can predictably sort a config array just given its schema.
Comment #14
bircherI made a little script to analyze the default config of umami and standard. here is its output:
(edited for some more de-duplication)
Comment #17
quietone commentedUpdating tag.
Comment #19
wim leersBump — this would still be very valuable to do 🤓
Comment #21
bradjones1So this is why I am still getting false-positive configuration diffs in my production deploys? I would have thought that #2361539: Config export key order is not predictable for sequences, add orderby property to config schema would have addressed this but this issue indicates to me there are some edge cases still remaining?
The weird part to me is that on export in my local development environment, I can export and then do a
drush cimand there are no changes. But deploy that same code to production and I get the same set of consistent config entities that appear changed but actually aren't.It's more noisy than anything but it would also be nice to have my CD logs only reflect actual changes. Or am I missing something here?
Comment #22
wim leersHunch: different PHP versions sort certain arrays differently? What PHP version are you using in prod vs local?
Comment #23
bradjones1Hi Wim, thanks for chiming in. This is containerized so everything "should" be the same and I just did a pull of my image locally to confirm and yes, same PHP versions locally and on production. I also thought perhaps the host environment was like, changing some sort of localization settings but I don't see any
LC*environment variables... though I'm way out of my area of expertise there.Comment #24
freelockI was looking into this for a few annoying instances in our sites, and am not finding PHP differences. I'm thinking perhaps database differences? SELECTs with no ORDER BY...
We most often hit this issue on text format filters and static menu overrides. Today I'm seeing it on an entity_view_display layout builder settings.
Comment #25
wim leersI propose to add a new method to
ConfigEntityValidationTestBase(and perhaps also\Drupal\Tests\jsonapi\Functional\ConfigEntityResourceTestBaseto test it in an end-to-end/integration test). That way we don't have to start from scratch.Most (but not all)
type: sequenceoccurs in config entities anyway. For simple config, I think #2952037: [meta] Add constraints to all simple configuration is relevant.Comment #26
daffie commentedI think that we should make sure that we have an database index for every query we add
orderby().Comment #27
wim leers@daffie Hah, I get that that triggered you but … it's completely unrelated 😅 This is about
\Drupal\Core\Config\Schema\SequenceDataDefinition::getOrderBy(), which is used only in\Drupal\Core\Config\StorableConfigBase::castValue(). It never relates to database queries.Comment #28
daffie commented@Wim Leers: Ok, than it is fine. Just want to make sure that Drupal does not get slower. :)
Comment #29
claudiu.cristeaCould we start adding predictability, at least, to config entity dependencies? See #3050223: Index configurations are changing from export to export.
Comment #30
longwaveOn a large site with multiple developers I see the order of block visibility plugins switching around quite a lot. I have a CI step that ensures that config can be exported cleanly after import, which catches a bunch of issues, but sometimes block visibility order is different between developer laptops and CI for no obvious reason.
What do we need to do to move this forward?
Comment #31
bircherI think the easiest would be to add some option to Wim Leers' config inspector to surface sequences that have no orderby setting.
Then the medium hard part is to find out which are the easy ones that could just have one of the currently available options of "key" or "value".
Then the hard part is to identify new "orderby" options (like key-then-value which core.extension:module is using) or strnatcasecmp for filter formats (see #10)
Maybe another one could by "property:weight" for sequence items that are sorted by weight.
Maybe we should also add "none" for sequences where the sort order in-itself is important data, which would allow us to tell other systems to leave it alone.
And after identifying more sort options we need to convert the sorting on save to a sorting by config schema
And finally we celebrate!
Note that adding a callback as a sorting option was dismissed because it would make the config schema more dependent on having a running drupal instance.
Comment #32
longwaveThanks, opened #3479107: Identify sequences that have no orderby setting
Comment #33
wim leersComment #34
wim leersWouldn't it be preferable to deprecate the absence of
orderby? 🤔 (Perhaps only for config schemas defined in Drupal core initially?)I don't see what doing this in the Config Inspector module would do to help move this forward in a way that it won't regress again.
Comment #38
trackleft2Currently working through issues
Comment #39
quietone commentedComment #41
donquixote commentedI see that this issue about 'sequence' configuration.
But is there a similar issue about 'mapping' or mapping-like records like config_entity?
It would be quite safe to order these by key, I reckon.
Comment #42
bircherRE 41
The mappings are sorted by the order in which they are defined in the schema, so mappings are and can be completely predictable.
Comment #43
donquixote commentedRe #42 (bircher)
This would make sense.
And yet I see these keys getting shuffled.
Maybe the order is not working correctly in some operations.
I should collect more information and open a new issue.
EDIT: Seems if you import from a config/install/ where keys have the wrong order, that wrong order remains when you then export to config/sync. I notice this in a core.entity_form_display.*.*.*:content.*, where the keys like type, weight, region can be in the wrong order. (I don't know why the original import file was not ordered properly.)
Comment #44
donquixote commentedI created #3576316: Config keys sometimes not ordered by schema on export.
I will do some more investigation there.
Comment #45
alexpott@donquixote the schema will not apply if the we pass TRUE to the trusted data argument. There have been efforts to remove the concept of trusted data but then we have to deal with the performance implications which were hard for the installer. But actually now we install multiple modules this actually might not be as big an issue now.