cdash: report clean results to CDash server (#9564)

* Record stdout for packages without errors

  Previously our reporter only stored stdout if something went wrong
  while installing a package.  This prevented us from properly reporting
  on steps where everything went as expected.

* More robustly report all phases to CDash

  Previously if a phase generated no output it would not be reported to CDash.
  For example, consider the following output:

    ==> Executing phase: 'configure'
    ==> Executing phase: 'build'

  This would not generate a report for the configure phase. Now it does.

* Add test case for CDash reporting clean builds

* Fix default directory for CDash reports

  The default 'cdash_report' directory name was getting overwritten
  by 'junit-report'.

* Upload the build phase first to CDash

  Older versions of CDash expect Build.xml to be the first file uploaded
  for any given build.

* Define cdash_phase before referring to it
This commit is contained in:
Zack Galbreath 2018-11-06 19:09:47 -05:00 committed by Todd Gamblin
parent a474d83d58
commit 30eda8b837
4 changed files with 38 additions and 12 deletions

View File

@ -213,7 +213,7 @@ def install(parser, args, **kwargs):
if len(specs) == 0: if len(specs) == 0:
tty.die('The `spack install` command requires a spec to install.') tty.die('The `spack install` command requires a spec to install.')
if not args.log_file: if not args.log_file and not reporter.filename:
reporter.filename = default_log_file(specs[0]) reporter.filename = default_log_file(specs[0])
reporter.specs = specs reporter.specs = specs
with reporter: with reporter:

View File

@ -135,6 +135,7 @@ def wrapper(pkg, *args, **kwargs):
value = do_install(pkg, *args, **kwargs) value = do_install(pkg, *args, **kwargs)
package['result'] = 'success' package['result'] = 'success'
package['stdout'] = fetch_package_log(pkg)
if installed_on_entry: if installed_on_entry:
return return

View File

@ -81,6 +81,7 @@ def build_report(self, filename, report_data):
for package in spec['packages']: for package in spec['packages']:
if 'stdout' in package: if 'stdout' in package:
current_phase = '' current_phase = ''
cdash_phase = ''
for line in package['stdout'].splitlines(): for line in package['stdout'].splitlines():
match = phase_regexp.search(line) match = phase_regexp.search(line)
if match: if match:
@ -88,20 +89,24 @@ def build_report(self, filename, report_data):
if current_phase not in map_phases_to_cdash: if current_phase not in map_phases_to_cdash:
current_phase = '' current_phase = ''
continue continue
beginning_of_phase = True cdash_phase = \
else: map_phases_to_cdash[current_phase]
if beginning_of_phase: if cdash_phase not in phases_encountered:
cdash_phase = \ phases_encountered.append(cdash_phase)
map_phases_to_cdash[current_phase] report_data[cdash_phase]['log'] += \
if cdash_phase not in phases_encountered: text_type("{0} output for {1}:\n".format(
phases_encountered.append(cdash_phase) cdash_phase, package['name']))
report_data[cdash_phase]['log'] += \ elif cdash_phase:
text_type("{0} output for {1}:\n".format(
cdash_phase, package['name']))
beginning_of_phase = False
report_data[cdash_phase]['log'] += \ report_data[cdash_phase]['log'] += \
xml.sax.saxutils.escape(line) + "\n" xml.sax.saxutils.escape(line) + "\n"
# Move the build phase to the front of the list if it occurred.
# This supports older versions of CDash that expect this phase
# to be reported before all others.
if "build" in phases_encountered:
build_pos = phases_encountered.index("build")
phases_encountered.insert(0, phases_encountered.pop(build_pos))
for phase in phases_encountered: for phase in phases_encountered:
errors, warnings = parse_log_events( errors, warnings = parse_log_events(
report_data[phase]['log'].splitlines()) report_data[phase]['log'].splitlines())

View File

@ -412,6 +412,26 @@ def test_cdash_upload_build_error(tmpdir, mock_fetch, install_mockery,
assert '<Text>configure: error: in /path/to/some/file:</Text>' in content assert '<Text>configure: error: in /path/to/some/file:</Text>' in content
@pytest.mark.disable_clean_stage_check
def test_cdash_upload_clean_build(tmpdir, mock_fetch, install_mockery,
capfd):
# capfd interferes with Spack's capturing
with capfd.disabled():
with tmpdir.as_cwd():
with pytest.raises((HTTPError, URLError)):
install(
'--log-file=cdash_reports',
'--cdash-upload-url=http://localhost/fakeurl/submit.php?project=Spack',
'a')
report_dir = tmpdir.join('cdash_reports')
assert report_dir in tmpdir.listdir()
report_file = report_dir.join('Build.xml')
assert report_file in report_dir.listdir()
content = report_file.open().read()
assert '</Build>' in content
assert '<Text>' not in content
@pytest.mark.disable_clean_stage_check @pytest.mark.disable_clean_stage_check
def test_build_error_output(tmpdir, mock_fetch, install_mockery, capfd): def test_build_error_output(tmpdir, mock_fetch, install_mockery, capfd):
with capfd.disabled(): with capfd.disabled():