Migrations are extremely error-prone, and don't scale well #35663
Replies: 4 comments 11 replies
-
cc @WordPress/gutenberg-core |
Beta Was this translation helpful? Give feedback.
-
Another thing we should discuss is a way to handle deprecations in dynamic blocks as well. Use cases for this has already risen like here, here and here and I believe more and more are going to appear with the introduction of many new dynamic blocks (Post blocks). Another difficult problem - which might be related to dev design decisions/guidelines - is the increasing use of |
Beta Was this translation helpful? Give feedback.
-
I opened a related issue and draft PR last week, which doesn't answer the question of having to update each deprecation, but looks at making them easier to manage over time by at least splitting them out into separate files. |
Beta Was this translation helpful? Give feedback.
-
Hi @glendaviesnz , I've created a versioning diagram for the [What is unclear to me is...]
I don't understand this deprecation mechanism correctly yet, so the question itself may be gibberish, but I would be glad if I can discuss this topic 👍 |
Beta Was this translation helpful? Give feedback.
-
Description
I've brought this up before in Slack IIRC, but this time around, I think I have a clearer idea of the problem, and I think it's worth discussing it, so I'm filing this issue.
Migrations are really hard to get right: they're hard to write, to review, and to test. I think that this is mostly because, as the docs state,
Consider the following case (found while reviewing #31910):
In the button block, we have two migrations that we'll have a closer look at:
migrateBorderRadius
turns a "flat"{"borderRadius":25}
(with no unit) attribute into a nested{"style":{"border":{"radius":"25px"}}}
.migrateFontFamily
(introduced by Font family: switch from CSS Custom Property to classes #31910) turns a nested{"style":{"typography":{"fontFamily":"var:preset|font-family|cambria-georgia"}}}
into a flat{"fontFamily":"cambria-georgia"}
. This migration is also added to the Group, Image, Pullquote, and Search blocks, since they also have block support for the font family setting.There's existing test coverage for
migrateBorderRadius
, and the PR adds coverage formigrateFontFamily
. Both tests pass. So what's the problem?The problem is that (per the state of #31910 as of this writing) for a block that has attributes in both the old
borderRadius
, and the old{"style":{"typography":{"fontFamily":"..."}}}
format, one of them won't be migrated. The reason for this is that we have a deprecation for the oldborderRadius
, and one for the old font family format there, but none for both.This can be proven by using the following test fixture
and running
npm run fixtures:regenerate test/integration/full-content/full-content.test.js
, which will produceNote that the border radius has been migrated, but the font family hasn't.
Which brings us back to
This means that it turns out that it's not enough to simply add a new deprecation that runs the
migrateFontFamily
migration; instead, we also need to change existing deprecations, such as the one that runsmigrateBorderRadius
, to also runmigrateFontFamily
, like so:Diff
The Button block's
deprecated.js
file alone has six deprecations that currently callmigrateBorderRadius
, so I addedmigrateFontFamily
to all of them. (That might be overkill, since some of those deprecations might predate the introduction of the nested font family attribute; to find out which, I'd have to go through them one by one.)The block also has a number of other deprecations that run migrations such as
migrateCustomColorsAndGradients
, etc. So basically, we need to go through all of these and change the ones where the "original" attribute format might have contained the old font family attribute style to runmigrateFontFamily
as part of their migrations. And then we should probably go through all the other migrations we're invoking in that file's deprecations, and make sure that they're included in all the places where they're required.And as we've seen earlier, our tests don't protect us from that problem: Since those migrations are orthogonal, and we have dedicated tests for each, we didn't notice that those deprecations yielded the wrong result when a block needed both migrations.
In conclusion, I think that the current concept of deprecations that are supposed to map from any block and attribute format to the current one becomes untenably hard to maintain and review when scaling to multiple orthogonal migrations; plus our tests cannot guarantee that they're working properly.
These issues might not be apparent in a development setting, where we're dealing with little test content that is "throwaway" anyway, and where we constantly update our Gutenberg versions, so it's almost guaranteed that all the latest migrations are constantly run, thus keeping our test content well-formed. However, in a more real-world scenario, where the GB version is updated less frequently (through plugin, or even only Core updates), it becomes rather likely that some migrations are missed, and blocks lose (some of) their customization, or -- worse -- break altogether. (It'd be great if we could get some numbers on how often either of those things happen after a GB update.)
I believe that most of these things could be fixed by adopting an actual "incremental" migration model, where each migration is only required to update blocks from their previous format. This would significantly decrease the cognitive load of figuring out which migration is needed where, and it would make testing each individual migration separately actually sufficient to guarantee that they also work when run more of them need to be run. However, it would be a ton of work to change existing deprecations to that effect 😬
Step-by-step reproduction instructions
This space intentionally left blank.
Screenshots, screen recording, code snippet
No response
Environment info
No response
Please confirm that you have searched existing issues in the repo.
Yes
Please confirm that you have tested with all plugins deactivated except Gutenberg.
Yes
Beta Was this translation helpful? Give feedback.
All reactions