Problem/Motivation
This is spun off from #3390919-12: Create a config storage backend that can set "checkpoints", recording the changes to config that happen in between them.
Right now, when a recipe imports config (either from modules or from its own config directory), that config is not validated in any way.
Proposed resolution
RecipeConfigInstaller should validate each piece of config it imports, through the typed config manager, after actually creating it. If there are any violations, an exception should be thrown and the recipe should be rolled back to the backup checkpoint.
Remaining tasks
Implement that, with tests.
User interface changes
None, although a recipe might fail mid-way with a different message/exception.
API changes
Potentially. A new exception will likely be introduced.
Issue fork distributions_recipes-3401867
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
phenaproximaThis blocks #3401723: Config modified by action plugins should be validated after it is saved.
Comment #3
phenaproximaThis also blocks #3401925: [PP-2] After a recipe is successfully applied, validate all of the config that was imported or modified by config actions.
Comment #5
phenaproximaI think this is ready for initial review. It has test coverage and everything!
Comment #6
wim leersRTBC per https://git.drupalcode.org/project/distributions_recipes/-/merge_request... — AFAICT this is a net improvement.
Comment #7
wim leersThis blocks three issues.
Comment #8
wim leersSee MR.
Comment #9
phenaproximaBack to review here; if it looks good then I think we might need to postpone this issue on #3390919: Create a config storage backend that can set "checkpoints", recording the changes to config that happen in between them. I tried to explain why in https://git.drupalcode.org/project/distributions_recipes/-/merge_request....
Comment #10
phenaproximaI discussed this with @alexpott. He confirmed that my understanding in https://git.drupalcode.org/project/distributions_recipes/-/merge_request... is correct.
We probably need to ultimately do something like this:
validateDependencies().createConfiguration().validate()on all the config we just created. If any of it fails, throw the new ConfigValidationException, and let the recipe runner revert everything back to its pre-recipe state.Therefore, this issue is postponed on #3390919: Create a config storage backend that can set "checkpoints", recording the changes to config that happen in between them.
Comment #11
wim leersI was wrong, you were right! 😊
Now eagerly following #3390919: Create a config storage backend that can set "checkpoints", recording the changes to config that happen in between them 😄
Comment #12
wim leersOne question though:
We could already do that today, even without #3390919: Create a config storage backend that can set "checkpoints", recording the changes to config that happen in between them. But rather than an automatic revert, we'd have to tell the user something like "Either manually fix the configuration or revert both the code and the database to the previous state."
To @bircher's point in #3390919-23: Create a config storage backend that can set "checkpoints", recording the changes to config that happen in between them — we may need to support that anyway.
So AFAICT this is hard blocked, but it just make more sense to do the other issue first. Is my understanding corect?
Comment #13
phenaproximaThat's correct!
Comment #14
wim leersUnderstanding this
So this is built on:
* 6cc95f1b6f5286b93198ef36f678a88005045d80 Make core dispatch config events for non-default collections.aka #3405800: Config collections do not trigger configuration events consistentlyaka #3390919: Create a config storage backend that can set "checkpoints", recording the changes to config that happen in between them, but note that this is causing one of the PHPStan level 9 violations: https://git.drupalcode.org/project/distributions_recipes/-/merge_request...
Could you in the future please state precisely which commit you've applied from those issues? 🙏
The other PHPStan level 9 error is https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iter... — not quite sure how to fix it.
Review
To review this, look at
git diff 9270b7d97ab43e644942ff13d6548eec49f91934.Overall: very nice start! 😄
Comment #15
phenaproximaThis is also blocked by #3407956: Create a config storage checkpoint before applying a recipe, which will alter the code in this MR.
Comment #16
phenaproximaI was able to manually test this and I have some confirmation that it does what we intend, based on the situation detailed in #3390919: Create a config storage backend that can set "checkpoints", recording the changes to config that happen in between them! Here's what I did:
You'll see something like this:
That's what we'd expect to see. But here's the proof that all changes were rolled back: if you run
../vendor/bin/drush cex, it should tell you that there are no config changes!!Comment #17
wim leersComment #22
wim leersClosed/hid https://git.drupalcode.org/project/distributions_recipes/-/merge_request..., created https://git.drupalcode.org/project/distributions_recipes/-/merge_request... instead, because #3405800: Config collections do not trigger configuration events consistently and #3390919: Create a config storage backend that can set "checkpoints", recording the changes to config that happen in between them have both landed.
(Also made sure the MR was created correctly this time, so now only 27 commits show up instead of Drupal core commits that we didn't do — MUCH easier to review👍)
Comment #23
wim leersSo we went from postponed on 2 to postponed on 0 … but AFAICT #3407956: Create a config storage checkpoint before applying a recipe is the new blocker here, because that's where we'll add the checkpointing first, without actually doing anything with it just yet.
Comment #24
phenaproximaI think we can say this is, in fact, postponed. It's hard-blocked by #3407956: Create a config storage checkpoint before applying a recipe.
Comment #25
phenaproximaAnnnd, blocker is in!
Comment #26
phenaproximaUpdated the issue summary to clarify what will actually happen if a recipe imports invalid config.
Comment #27
phenaproximaComment #28
wim leersA small amount of MR simplification is possible and will make it easier to land this MR, so let's do that? 😊
Comment #29
phenaproximaI think all feedback thus far is addressed. Back to you!
Comment #30
wim leersAgreed, this looks great now! 🤩
Overview of the changes:
RecipeCommandclass'::boot()became slightly more resilient …Comment #32
alexpottRemoved the boot() changes. We need to handle container the container better in \Drupal\Core\Recipe\RecipeRunner::processRecipe too... - it's a hard problem. The solution is probably to pass the kernel object around but I think we should address all of this in one issue and not do anything piecemeal.
Comment #33
alexpottCommitted and pushed 21216ed8d00 to 11.x and 76055eeffe1 to 10.2.x. Thanks!
Comment #38
alexpottThis was reverted from the 10.2.x patch