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:
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.specs = specs
with reporter:

View file

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

View file

@ -81,6 +81,7 @@ def build_report(self, filename, report_data):
for package in spec['packages']:
if 'stdout' in package:
current_phase = ''
cdash_phase = ''
for line in package['stdout'].splitlines():
match = phase_regexp.search(line)
if match:
@ -88,20 +89,24 @@ def build_report(self, filename, report_data):
if current_phase not in map_phases_to_cdash:
current_phase = ''
continue
beginning_of_phase = True
else:
if beginning_of_phase:
cdash_phase = \
map_phases_to_cdash[current_phase]
if cdash_phase not in phases_encountered:
phases_encountered.append(cdash_phase)
report_data[cdash_phase]['log'] += \
text_type("{0} output for {1}:\n".format(
cdash_phase, package['name']))
beginning_of_phase = False
cdash_phase = \
map_phases_to_cdash[current_phase]
if cdash_phase not in phases_encountered:
phases_encountered.append(cdash_phase)
report_data[cdash_phase]['log'] += \
text_type("{0} output for {1}:\n".format(
cdash_phase, package['name']))
elif cdash_phase:
report_data[cdash_phase]['log'] += \
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:
errors, warnings = parse_log_events(
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
@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
def test_build_error_output(tmpdir, mock_fetch, install_mockery, capfd):
with capfd.disabled():