Go Tool for Review Bot
Review Request #11240 — Created Oct. 22, 2020 and submitted
This tool's ability to format was removed and placed into another tool,
that tool is tentatively known as the GofmtTool. This was done because,
go fmt
is rather lightweight and does not rely on other files in order
to carry out its function. However,go test
andgo vet
require more
information in order to work consistently. In particular they need
access to the entire repository so that patched code can be fully
analyzed against the package code. Therefore GofmtTool inherits from
Tool
, whereas GoTool inherits fromRepositoryTool
and is generally
a much more computationally heavy tool.
Manual testing was done to confirm that
go test
is working correctly.
As of now it just creates general comments based on which tests have
failed.
Manual testing was done to confirm thatgo vet
is working and known
issues about failures when used against test files have been resolved.
Description | From | Last Updated |
---|---|---|
Go/Go Tools? |
david | |
gofmt still exists, but I believe the modern recommendation is to use go fmt. Can we do that here to … |
david | |
Perhaps "This file contains formatting errors and should be run through go fmt" ? Also, shouldn't this be checking the … |
david | |
Since we have the output already in a variable, it's kind of silly to write it out to a file … |
david | |
The imports should be in alphabetical order. So import json should be placed before import logging. |
ceciliawei | |
Using the string's "split" method isn't portable (for example, windows doesn't use "/" as a path splitter). That said, there's … |
david | |
It looks like we're running this for every single file, which means that if you have multiple changed files in … |
david | |
Let's pull the result of dest_file.lower() out into a variable so we don't have to call it twice in these … |
chipx86 | |
Blank line between statements and the start of new blocks. |
chipx86 | |
Same here. |
chipx86 | |
This will scan the entirety of packages every iteration of files. If packages is a set, this will be faster, … |
chipx86 | |
This can fail, so we'll want to check for exceptions, just as we do further down. |
chipx86 | |
It's generally better to use %-formatted strings to join in variables, as this is faster in Python. |
chipx86 | |
We prefer %-formatted strings, rather than .format(), as it's technically faster and more consistent with the rest of our codebase. … |
chipx86 | |
When spanning lines, we prefer the % on the line with the variables, as it gives more room for the … |
chipx86 | |
No blank line here. |
chipx86 | |
Can you incorporate the package name in here, or something to help debug this if this comes up in production? |
chipx86 | |
Same as above regarding %-formatted strings. |
chipx86 | |
Let's use single quotes here, since the inner string doesn't use them. We prefer single quotes in Python strings wherever … |
chipx86 | |
If we compile this regex before we do the outer loop, it'll speed this part up. |
chipx86 | |
While common in Python, we shouldn't ever override _. That's because _ is commonly used as an alias to ugettext … |
chipx86 | |
Rather than putting this into a variable and pulling the indexes out, let's just unpack with: filename, line_num = \ … |
chipx86 | |
You can put the format argument on the same line, since it fits. No need for parens there either, since … |
chipx86 | |
No blank line here. |
chipx86 | |
Same comment as above regarding having identifying information in the message. |
chipx86 | |
Things within here are getting pretty deeply nested. Maybe break out the test and vet implementations into their own methods? |
david | |
This should be wrapped in a try/except. |
david | |
Would it be possible to add a comment showing an example of what the JSON output from go vet looks … |
david | |
This is potentially running a lot of times, since it's deeply nested inside several loops. At the top level, can … |
david |
Commit: |
|
||||
---|---|---|---|---|---|
Diff: |
Revision 2 (+69) |
Checks run (2 succeeded)
-
-
-
bot/reviewbot/tools/gotool.py (Diff revision 2) It looks like you're leaning towards making the different uses of
go
optional, which is good. We should probably default totrue
for everything exceptgo test
, which should default tofalse
(test suites can often be cumbersome and long-running).
Description: |
|
|||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Testing Done: |
|
|||||||||||||||||||||
Commit: |
|
|||||||||||||||||||||
Diff: |
Revision 3 (+110) |
Checks run (2 succeeded)
-
-
bot/reviewbot/tools/gotool.py (Diff revision 3) gofmt
still exists, but I believe the modern recommendation is to usego fmt
. Can we do that here to be more future-proof? -
bot/reviewbot/tools/gotool.py (Diff revision 3) Perhaps "This file contains formatting errors and should be run through
go fmt
" ?Also, shouldn't this be checking the output or return value from the format command? Seems like it just unconditionally adds the comment now (maybe that's still part of the WIP?)
-
bot/reviewbot/tools/gotool.py (Diff revision 3) Since we have the output already in a variable, it's kind of silly to write it out to a file and load it back in. We can just do:
try: json_data = json.loads(cleaned_output) except Exception as e: ...
Summary: |
|
|||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Description: |
|
|||||||||||||||||||||||||||||||||||||||
Testing Done: |
|
|||||||||||||||||||||||||||||||||||||||
Commit: |
|
|||||||||||||||||||||||||||||||||||||||
Diff: |
Revision 4 (+138) |
Checks run (2 succeeded)
-
-
bot/reviewbot/tools/gotool.py (Diff revision 4) The imports should be in alphabetical order. So
import json
should be placed beforeimport logging
.
-
-
bot/reviewbot/tools/gotool.py (Diff revision 4) Using the string's "split" method isn't portable (for example, windows doesn't use "/" as a path splitter). That said, there's both a portable and easier way to do this:
package = os.path.dirname(path)
-
bot/reviewbot/tools/gotool.py (Diff revision 4) It looks like we're running this for every single file, which means that if you have multiple changed files in a given package, we'll add the test failures multiple times.
Instead of overriding
handle_file
, can we instead overridehandle_files
, and use the file list to build a list of changed packages? We can then run the tests once per package.
Commit: |
|
||||
---|---|---|---|---|---|
Diff: |
Revision 5 (+156) |
-
File Captions:
gotool_success.png: - go_vet_success.png + go_tool.png
Checks run (2 succeeded)
-
-
bot/reviewbot/tools/gotool.py (Diff revision 5) Let's pull the result of
dest_file.lower()
out into a variable so we don't have to call it twice in these checks. -
bot/reviewbot/tools/gotool.py (Diff revision 5) Blank line between statements and the start of new blocks.
-
-
bot/reviewbot/tools/gotool.py (Diff revision 5) This will scan the entirety of
packages
every iteration offiles
. Ifpackages
is aset
, this will be faster, though then we lose the ordering. Perhaps that's okay, and we can sort the results when iterating it?If so, we can safely
.add()
into aset
without needing to check existence first. -
bot/reviewbot/tools/gotool.py (Diff revision 5) This can fail, so we'll want to check for exceptions, just as we do further down.
-
bot/reviewbot/tools/gotool.py (Diff revision 5) It's generally better to use
%
-formatted strings to join in variables, as this is faster in Python. -
bot/reviewbot/tools/gotool.py (Diff revision 5) We prefer
%
-formatted strings, rather than.format()
, as it's technically faster and more consistent with the rest of our codebase.This can also be combiend with the previous line:
formatted_output = '[%s]' % ','.join(gotest_output)
-
bot/reviewbot/tools/gotool.py (Diff revision 5) When spanning lines, we prefer the
%
on the line with the variables, as it gives more room for the strings and helps more clearly indicate that we're formatting variables in. -
-
bot/reviewbot/tools/gotool.py (Diff revision 5) Can you incorporate the package name in here, or something to help debug this if this comes up in production?
-
-
bot/reviewbot/tools/gotool.py (Diff revision 5) Let's use single quotes here, since the inner string doesn't use them. We prefer single quotes in Python strings wherever possible.
-
bot/reviewbot/tools/gotool.py (Diff revision 5) If we compile this regex before we do the outer loop, it'll speed this part up.
-
bot/reviewbot/tools/gotool.py (Diff revision 5) While common in Python, we shouldn't ever override
_
. That's because_
is commonly used as an alias tougettext
orugettext_lazy
, and this can have unintentional side-effects.Also for
items
, we need to usesix.iteritems()
to get consistent behavior between Python 2 and 3. -
bot/reviewbot/tools/gotool.py (Diff revision 5) Rather than putting this into a variable and pulling the indexes out, let's just unpack with:
filename, line_num = \ os.path.basename(key['posn']).split(':', 2)
Could you also put a comment above this showing the general format of what we should expect here, so it's documented?
-
bot/reviewbot/tools/gotool.py (Diff revision 5) You can put the format argument on the same line, since it fits. No need for parens there either, since we're not building a tuple (only one arg, and also
(message)
is equivalent tomessage
since there's no tuple indicator, like a trailing comma or a second value). -
-
bot/reviewbot/tools/gotool.py (Diff revision 5) Same comment as above regarding having identifying information in the message.
Change Summary:
Addressed most of Christian's comments, though I would like some clarification on 2 of them.
Commit: |
|
||||
---|---|---|---|---|---|
People: |
|
||||
Diff: |
Revision 6 (+162) |
Checks run (2 succeeded)
Change Summary:
Addressed more comments by Christian, now only 1 comments requires a check.
Summary: |
|
||||
---|---|---|---|---|---|
Commit: |
|
||||
Diff: |
Revision 7 (+162) |
Checks run (2 succeeded)
-
-
bot/reviewbot/tools/gotool.py (Diff revision 7) Things within here are getting pretty deeply nested. Maybe break out the test and vet implementations into their own methods?
-
-
bot/reviewbot/tools/gotool.py (Diff revision 7) Would it be possible to add a comment showing an example of what the JSON output from
go vet
looks like? That way people looking at the code can see how it maps to what it's parsing. -
bot/reviewbot/tools/gotool.py (Diff revision 7) This is potentially running a lot of times, since it's deeply nested inside several loops.
At the top level, can we create a new dict that maps the patched file path back to f? That way we can just index into it instead of looping every time.
Change Summary:
Addressed David's comments and updated code to include sample JSON in the comments, as well as a dictionary to decrease execution time.
Commit: |
|
||||
---|---|---|---|---|---|
Diff: |
Revision 8 (+192) |
Checks run (2 succeeded)
Change Summary:
Fixed
logger.exception
formatting.
Commit: |
|
||||
---|---|---|---|---|---|
Diff: |
Revision 9 (+192) |