-
Notifications
You must be signed in to change notification settings - Fork 29.7k
[flutter_tools] Deferred components setup validator #75739
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
[flutter_tools] Deferred components setup validator #75739
Conversation
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.
At a high level, having a single method that calls other methods based on a list of enums set in the object's constructor is confusing. Some of the checks aren't really checks either, like clear temp dir.
I would start by making each of these tasks performed by a public method, which documents what it is doing and named appropriately whether it is performing some cleanup or verification. I would also leave out this enum setup, at least for now, and we can discuss that more when you're further along the integration side of things.
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.
(That would also remove a lot of the confusion about arguments that are only required conditionally)
packages/flutter_tools/lib/src/android/deferred_components_setup_validator.dart
Outdated
Show resolved
Hide resolved
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.
In general RegExps should be hoisted into statics and extensively documented as to what they are intended to match.
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.
Do you need a specific diff format here, or is there a way to do this in Dart? In general, we need to be really careful about introducing new runtime dependencies.
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.
I prefer unidiff so that I can recommend a patch command to quickly apply all diffs, but if that is not possible the diff can still be displayed in other formats for developer reference. Overall, this step is not necessary for the function of this feature, but it provides helpful quality of life improvements.
I am not aware of any fully-dart ways to do this. The diff commands are more complex than it seems. For unix, diff should always be available. On windows however, fc is less powerful and doesn't generate the diffs I want. I am exploring using git diff instead. Since flutter requires git, git diff seems to be a relatively safe dependency.
In the worst case, if the commands for some reason cannot be run successfully, the diff step can be skipped without any material impact on the results of this validation.
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.
I'm actually going to remove the diff task from this PR. I'll land a more fully developed version of it in the future. Meanwhile I'd like to get the rest of the PR moving along.
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 would need to be done before this feature is landed
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.
Prefer to inject globals into the constructor
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.
If you use printError that will end up with error/red text. I would not spend too much time specifically formatting the errors
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 is a dangerous pattern because forgetting to clear might lead to future tests passing inadvertently
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.
I'll use the setup method to avoid this.
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.
out of date comment.
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.
Can you link to an example/docs on what structure this is looking for in settings.gradle?
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.
Isn't this a user-owned file? How can we be sure that it can be safely deleted, and that the parsing will work correctly on valid but differently formatted files?
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.
ahh, misread settingsGradle and settingsGradleOutput
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.
prefer to write the file all at once, since it is not particularly big and to prevent cases where the tool getting killed would leave a partial file.
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 seems like a very fragile check. Can you document the structure that you are trying to parse here? Is there any guarantee that this logic will continue to be valid?
|
How much of the automation that this PR is doing (reading/writing strings.xml/settings.gradle) is strictly necessary for an initial version of this feature? I'm concerned that there is actually no good way to parse a settings.gradle (that I am aware of) - writing to user owned files in general is a bit of a trap. |
packages/flutter_tools/lib/src/android/deferred_components_setup_validator.dart
Outdated
Show resolved
Hide resolved
packages/flutter_tools/lib/src/android/deferred_components_setup_validator.dart
Outdated
Show resolved
Hide resolved
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.
The tool should correctly throw errors for permissions into tool exits, so you might only hit a fse if the file is missing.
packages/flutter_tools/lib/src/android/deferred_components_setup_validator.dart
Outdated
Show resolved
Hide resolved
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.
Could you expand on this a little more, what string resources are required, what is the expected format, et cetera
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.
Shouldn't the xml parser give you access to names/properties in a way that doesn't require looking at raw lines?
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.
The idea is that I want to maintain the original formatting and comments in the file, and the xml parser consumes all of this and collapses it into a format-less xmldocument/xmlelement. This manual parsing is able to maintain any developer formatting/comments.
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.
Moved to xml package based system.
|
https://gist.github.com/GaryQian/9786e287b3c00406fa3c12fa62a30d7b is a snapshot of the validator before switching away from the RegExp based system for future reference. |
zanderso
left a comment
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.
High level comment to think about what happens when input files are malformed, and what happens when file system operations fail.
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.
nit: Alphabetize.
packages/flutter_tools/lib/src/android/deferred_components_setup_validator.dart
Outdated
Show resolved
Hide resolved
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 parameter be @required?
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 property can be null. If null, it will just use the default templates directory. I can document this.
packages/flutter_tools/lib/src/android/deferred_components_setup_validator.dart
Outdated
Show resolved
Hide resolved
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 there be a check here that this file exists, or is it already known to exist at this point?
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.
Added an _invalidFiles system to report errors like this.
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.
See: ErrorHandlingFileSystem.deleteIfExists
packages/flutter_tools/lib/src/android/deferred_components_setup_validator.dart
Outdated
Show resolved
Hide resolved
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.
Can these be testWithoutContext?
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.
If this yaml can be provided by users by hand, then there should be tests that the tool does an appropriate throwToolExit when it is malformed.
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.
Same idea here. If settings.gradle is under user control, then it should not crash the tool (from the new code in this PR) if it is malformed, and there should be unit tests of that.
|
I added systems to track and report file i/o and validity checking. Since this is an optional validator, any errors of this sort are reported in the validation output and are treated as if the check had failed (triggers tool exit) |
jonahwilliams
left a comment
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 PR is approaching the point where I don't think I could feasibly review it anymore. If each of the validations is fairly stand-alone - could you stage the PR so that each of them is added in a separate commit.
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.
These methods can be made fairly standalone, by having each method individually return its inputs/outputs - then letting the caller be responsible for combining them.
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.
So I actually want the class to handle the check result internally. I don't really want the caller to be handling the results of the validation directly since there are specific behaviors that should happen based off of the results of each check, which is handled by displayResults. Letting the caller combine/handle the check results directly can easily miss a lot of nuance and result in incorrect recommendations to the developer.
These checks are not intended be run independently of the overall validator class. Making them dependent on the class discourages/prevents this unintended use.
2099347 to
8c25c7c
Compare
8c25c7c to
b24b155
Compare
|
Restructured commits to have each check added as a separate commit. |
packages/flutter_tools/lib/src/android/deferred_components_setup_validator.dart
Outdated
Show resolved
Hide resolved
Recursive delete directory
|
I'm really concerned about the parsing of the gradle settings file. I would feel more comfortable if we had better parsing, or at least knew what some of the edge cases were? |
|
Ok, I'll just remove it for this version then. Consider it gone. |
jonahwilliams
left a comment
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.
LGTM (if gradle.settings parsing is removed for now)
Split off from #63773
Part of series of PRs for #73345 and #57617
This PR contains the
DeferredComponentsSetupValidatorwhich implements various checks and tasks that are used to verify the developer has a properly configured app for deferred components.Most checks will look for the existence or particular entries inside of the android directory and if the file is not satisfactory, it will output the correct/expected file in a temporary directory under
build/android_deferred_components_setup_files. Due to regex based parsers being unreliable and difficult to maintain, I will be switching to a Xml packaged based system to generate new additions to the xml files.Example usage:
The validator is used in an upcoming PR based off of #63773.