Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upAdd test to verify if all homu builders are listed in the buildbot config #571
Conversation
highfive
commented
Jan 2, 2017
|
Thanks for the pull request, and welcome! The Servo team is excited to review your changes, and you should hear from @aneeshusa (or someone else) soon. |
9eb326e
to
4c42c60
|
The tests are failing because buildbot is installed in the python3 library folder and not the python2 but buildbot is a python2 package which is required to import
Or maybe another idea I didn't think of ? |
|
The approach overall looks good; thanks for tackling a less-easy issue! |
| import sys | ||
|
|
||
| if __name__ == '__main__': | ||
| sys.path.append('/home/servo/buildbot/master/') |
This comment has been minimized.
This comment has been minimized.
|
|
||
| config = imp.load_source( | ||
| 'config', | ||
| '/home/servo/buildbot/master/master.cfg' |
This comment has been minimized.
This comment has been minimized.
| for sched in config.c['schedulers']: | ||
| if sched.name == 'servo-auto': | ||
| out = {'builders': sched.builderNames} | ||
| print(json.dumps(out)) |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 2, 2017
Member
Add a return 0 after printing to indicate success and exit early. After the loop (meaning servo-auto was not found, print an error message to sys.stderr (e.g. error: 'servo-auto' scheduler not found) and add a return 1`.
| from tests.util import Failure, Success | ||
|
|
||
|
|
||
| def is_builders_valid(buildbot, homu): |
This comment has been minimized.
This comment has been minimized.
| homu_buildbot = homu_cfg['repo']['servo']['buildbot'] | ||
|
|
||
| ret = subprocess.run( | ||
| ['python2', 'tests/sls/homu/get_buildbot_cfg.py'], |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 2, 2017
•
Member
You'll need to use /usr/bin/python2. This is because Travis's only has one "mega" Trusty image, on which it installs all its Pythons, Rubies, etc., and the $PATH always contains all of those Pythons before the main /usr/bin, etc. entries. Hence, just python2 invokes a Python from /opt, not the main Python that we want.
(This will fix the tests currently failing.)
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 2, 2017
Member
Also, right now the rest of the test suite is agnostic to CWD, so I'd prefer to refer to the get_buildbot_cfg.py file differently, likely using __file__.
| ) | ||
| if not is_builders_valid(buildbot_builders, homu_buildbot['try_builders']): | ||
| return Failure( | ||
| 'Homu config is not in sync with the buildbot config', '' |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 2, 2017
Member
Have this and the previous message be different (ie. reference builders vs try_builders) to the error message is immediately helpful.
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 2, 2017
Member
Additionally, we should make use of the second argument to Failure. To check validity, cast the homu builders and buildbot builders to lists, then subtract the sets to perform a diff. If the len() of the diff is non-zero, then pretty-print the mismatched (i.e. remaining in the diff) values to use for the second argument to Failure().
| 'Homu config is not in sync with the buildbot config', '' | ||
| ) | ||
|
|
||
| return Success('Buildbot and homu configs are synced.') |
This comment has been minimized.
This comment has been minimized.
| BUILDBOT_MASTER_PATH = '/home/servo/buildbot/master/' | ||
|
|
||
| if __name__ == '__main__': | ||
| sys.path.append(BUILDBOT_MASTER_PATH) |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 6, 2017
Member
Let's move this code into a main() function and use return instead of exit in main(); here it can be called as sys.exit(main()).
| print(json.dumps(out)) | ||
| exit(0) | ||
|
|
||
| sys.stderr.write('error: "servo-auto" scheduler not found\n') |
This comment has been minimized.
This comment has been minimized.
|
|
||
|
|
||
| def get_script_path(): | ||
| dirname = os.path.dirname(__file__) |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 6, 2017
Member
This can be inlined into the next line (should fit within 80 char limit).
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 6, 2017
Member
It would also be nice to add a comment about why we need to invoke a Python2 subprocess to run the separate script.
|
|
||
| def are_builders_valid(buildbot, homu_cfg, buildertype): | ||
| for builder in homu_cfg[buildertype]: | ||
| if builder not in buildbot: |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 6, 2017
Member
The set differencing subsumes the need to loop over each builder and check if it is present or not, so these first two lines aren't needed.
| from tests.util import Failure, Success | ||
|
|
||
|
|
||
| def are_builders_valid(buildbot, homu_cfg, buildertype): |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 6, 2017
Member
Inline are_builders_valid into run(), which allows removing a bunch of duplicated error checking.
| def are_builders_valid(buildbot, homu_cfg, buildertype): | ||
| for builder in homu_cfg[buildertype]: | ||
| if builder not in buildbot: | ||
| diff = list(set(homu_cfg[buildertype]) - set(buildbot)) |
This comment has been minimized.
This comment has been minimized.
| diff = list(set(homu_cfg[buildertype]) - set(buildbot)) | ||
| diff_print = '' | ||
| if len(diff) != 0: | ||
| diff_print = 'Difference: {}'.format(diff) |
This comment has been minimized.
This comment has been minimized.
| diff_print = 'Difference: {}'.format(diff) | ||
|
|
||
| fail = Failure( | ||
| 'Homu "{}" config isn\'t sync with buildbot config' |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 6, 2017
Member
nit: sync -> synced
Also, using double quotes for this string will make it easier to read (no need to escape the apostrophe).
|
|
||
| def run(): | ||
| homu_cfg = toml.load('/home/servo/homu/cfg.toml') | ||
| homu_buildbot = homu_cfg['repo']['servo']['buildbot'] |
This comment has been minimized.
This comment has been minimized.
|
|
||
| buildbot_builders = json.loads(ret.stdout.decode('utf-8'))['builders'] | ||
|
|
||
| resp = are_builders_valid(buildbot_builders, homu_buildbot, 'builders') |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 6, 2017
Member
You can use a loop to cut down on some duplication:
for builder_type in ['builders', 'try_builders']:
diff = ....
if diff:
return Failure(...)
return Success(..)
|
@aneeshusa This should be OK now! Sorry for the long review process |
|
I was testing this out and we can make the error reporting more helpful. Currently, we early return if any builder set has invalid builders, but we should buffer all differences and return them together at the end. |
|
|
||
| buildbot_builders = json.loads(ret.stdout.decode('utf-8'))['builders'] | ||
|
|
||
| for buildertype in ['builders', 'try_builders']: |
This comment has been minimized.
This comment has been minimized.
| diff = set(homu_builders[buildertype]) - set(buildbot_builders) | ||
| if diff: | ||
| return Failure( | ||
| "Homu {} config isn't synced with buildbot config" |
This comment has been minimized.
This comment has been minimized.
| return Failure( | ||
| "Homu {} config isn't synced with buildbot config" | ||
| .format(buildertype), | ||
| 'Difference: {}'.format(diff) |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 7, 2017
Member
Before the for loop, initialize a string var (e.g. failure_msg) to an empty string. In the loop, if the if diff: condition is true, append information about the diff to failure_msg.
After the loop, if failure_msg then return a Failure passing failure_msg for the second argument. This way if there invalid builders for builders and try_builders they're both reported.
Prose changes:
- Keep the same title (first arg) for the Failure, but don't mention the builder set
- Use a more descriptive prefix than
Difference, maybeInvalid builders for {builder_set}:(this gets added tofailure_msgiteratively)
| ) | ||
| if ret.returncode != 0: | ||
| return Failure( | ||
| 'Unable to retrieve buildbot builders name:', ret.stderr |
This comment has been minimized.
This comment has been minimized.
| homu_builders = homu_cfg['repo']['servo']['buildbot'] | ||
|
|
||
| # We need to invoke a new process to read the buildbot master config | ||
| # because buildbot is written in python2. |
This comment has been minimized.
This comment has been minimized.
|
Sorry about the long review, you're almost there! |
| if diff: | ||
| if failure_msg: | ||
| failure_msg += '\n' | ||
| failure_msg += 'Invalid builders for "{}": {}'.format(builder_set, diff) |
This comment has been minimized.
This comment has been minimized.
| diff = set(homu_builders[builder_set]) - set(buildbot_builders) | ||
| if diff: | ||
| if failure_msg: | ||
| failure_msg += '\n' |
This comment has been minimized.
This comment has been minimized.
aneeshusa
Jan 10, 2017
Member
You can actually include the \n unconditionally as part of the format string - the outputter is smart and will strip the last trailing newline.
|
Thanks for tackling this! @bors-servo r+ |
|
|
|
|
Add test to verify if all homu builders are listed in the buildbot config That should resolve the #443. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/saltfs/571) <!-- Reviewable:end -->
charlesvdv commentedJan 2, 2017
•
edited by larsbergstrom
That should resolve the #443.
This change is