-
Notifications
You must be signed in to change notification settings - Fork 823
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NEW: Static validation for relationships. #9874
NEW: Static validation for relationships. #9874
Conversation
This seems really interesting - could we also add |
Is there any reason we wouldn't enable this in dev/build by default? At least as a warning? |
@sminnee I would enable this by default in an ideal world but the reality is that many modules do not have properly setup relationships (back relation is either ambiguous or missing). This would force bespoke developers to fix configuration of modules they don't value that much. The biggest value we've got out of this tool was to validate the code we maintain. Other reason for having this configurable is that some project may not care too much about relationship configuration. The main benefit is probably on larger projects where having properly defined relations allows:
@madmatt I'll review the configuration and check if I can provide a setup which can be enabled by default. The challenge here is to set it up in a way that bespoke code is covered but module code is not. This line is a bit blurry because for example you may want to target |
Another alternative would be to only throw a warning by default, so it shows up for those cases but doesn't break dev/build... |
Yeah, I think that's reasonable - warning for the dev/build and if you want to have a strict validation you can hook it up to your unit tests. |
f19d0cf
to
c0871ee
Compare
c0871ee
to
b7b7c09
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@silverstripe/core-team Before we do a detailed peer review on this, I just want to make sure we have an agreement in principle that this is a good idea worth merging.
I for one am in favour of shipping this feature as a warning that people can ignore. Maybe some projects can opt-in to fail their builds if this is something they care deeply about.
db3a158
to
ce576ca
Compare
@maxime-rainville Moved the code under |
I like what this tool does, we just need to think about how this is triggered so that it's provides value and not just annoyance within peoples workflow Currently it's enabled by default on
Which means it's limited only regular app pages, though means that regular dataobjects in custom code aren't checked which will probably be the bulk of custom object for most projects. If find this pretty strange. Some people will find this tool useful, for instance I can see it being great new projects where there's a strong focus on maintaining standards For others it think this just unnecessary noise, such as dev being assigned to serveral years old project to do a sprints worth of work on a single feature. They're not going to get any value from being told there's a bunch of missing belongsTo relationships for parts of the system they're not working on. I'd also expect that the deployment log on the majority of projects will have a bunch of warnings triggered, which is just going to be annoying noise. Myself coming mainly from a maintenance perspective I think in most cases this tool will be perceived as a negative if it's on by default What I think would be useful is:
|
Hey @emteknetnz , thanks for feedback. Some clarifications:
The check condition is limited to the The rest of the suggestions are very reasonable. I can definitely see how this can produce a lot of uneeded noise on older projects but it's really useful for new ones. Setting the right defaults is the key. Happy to make adjustments as required 👍 |
Ah ok, I see how this works now. Possible the trigger point being in requireDefaultRecords is a bit odd . It may make sense to move the trigger point to a class that |
07aff3a
to
cd3ecd8
Compare
This is ready for a review @emteknetnz . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good contribution. Needs to be opt-in configurable though.
The CLI output on dev/build flush is a little suboptimal, on my local it looks like this:
* SilverStripe\ElementalFileBlock\Block\FileBlock
* SilverStripe\ElementalBannerBlock\Block\BannerBlock
* Page
* BlocksPage
* SilverStripe\ErrorPage\ErrorPage
* RelationValidationService : 2 issues found (listed below)
* Page / MyFile : Back relation not found or ambiguous (needs class.relation format)
* BlocksPage / ElementalArea : Back relation not found or ambiguous (needs class.relation format)
+ 404 error page refreshed
* RelationValidationService : 2 issues found (listed below)
* Page / MyFile : Back relation not found or ambiguous (needs class.relation format)
* BlocksPage / ElementalArea : Back relation not found or ambiguous (needs class.relation format)
+ 500 error page refreshed
* SilverStripe\CMS\Model\RedirectorPage
* SilverStripe\CMS\Model\VirtualPage
The RelationValidationService is kind of jammed in the middle of ErrorPage being built and it's indentation doesn't seem right
public function inspectClasses(array $classes): array | ||
{ | ||
self::reset(); | ||
$this->ignoreConfig = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should $this->ignoreConfig = false; be called after calling
$this->validateClasses($classes);` ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It needs to be called before the validation as configuration potentially narrows down the scope of the covered classes. This is meant to be used for debugging / figuring out configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understand that, I'm just wondering if there's a need to revert it to false
afterwards, or if because it's just a "one-off run" per flush request it can just stay set to true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reset to previous state of this flag is covered by self::reset()
so there is no need to set it back.
@emteknetnz I've pushed up changes as requested:
I'm not sure how to improve the dev/build output though. I can see that the validation runs twice during dev/build as well: The output looks correct when running flush via dev/tasks though: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cheers. Still need to default the config to off + document
Is there anyway we can get the output to not be done seemingly at the same time as the Error pages being created when running dev/build flush ?
I've debugged this and the reasons it's showing here on dev/build flush before each of the 404 + 500 pages is:
ErrorPage::requireDefaultRecords()
ErrorPage::requireDefaultRecordFixture()
ErrorPage::writeStaticPage()
Director::test()
Presumably the Director::test() is used to generate HTML output for the error pages using templates etc.
I'm not sure how, though ideally we'd want to defer turning on / running this flushable service until after everything else
public function inspectClasses(array $classes): array | ||
{ | ||
self::reset(); | ||
$this->ignoreConfig = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understand that, I'm just wondering if there's a need to revert it to false
afterwards, or if because it's just a "one-off run" per flush request it can just stay set to true
* | ||
* @var bool | ||
*/ | ||
private static $flush_output_enabled = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private static $flush_output_enabled = true; | |
private static $flush_output_enabled = false; |
Need to default this to off otherwise it'll be very annoying for the majority of people
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, I left this value there from my testing run.
*/ | ||
public function executeValidation(): void | ||
{ | ||
if (!$this->config()->get('flush_output_enabled')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This config check should be in the flush()
method. The idea with the config is that it disables automatic running on every flush. However if we have the config here, we cannot $service = new RelationValidationService(); $service->executeValidation();
which someone might want to do as a one-off for a custom linting setup
*/ | ||
protected $errors = []; | ||
|
||
public function flushErrors(): void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function flushErrors(): void | |
public function clearErrors(): void |
Probably best to avoid the word 'flush' since this is already a 'flusable' class
public static function reset(): void | ||
{ | ||
$service = self::singleton(); | ||
$service->flushErrors(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$service->flushErrors(); | |
$service->clearErrors(); |
I've pushed up new changes @emteknetnz :
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, looking much better. No longer runs by default and output is no longer happening at the same time as Errorpage creation
dev/build flush
...
* BlocksPage
* SilverStripe\ErrorPage\ErrorPage
+ 404 error page refreshed
+ 500 error page refreshed
* SilverStripe\CMS\Model\RedirectorPage
* SilverStripe\CMS\Model\VirtualPage
Database build completed!
! RelationValidationService : 2 issues found (listed below)
! Page / MyFile : Back relation not found or ambiguous (needs class.relation format)
! BlocksPage / ElementalArea : Back relation not found or ambiguous (needs class.relation format)
* NEW: Static validation for relationships. * Unit tests added. * PR fixes * PR feedback: Execute validation on flush. * PR fixes. * PR fixes.
Issue #10008
Static validation for relationships
This is a new tool for static validation of relations. Very helpful if you are keen on keeping your relationship setup correct at all times. Especially useful for large projects with lot of models and relations.
Details