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
					Zack Galbreath
				
			
				
					committed by
					
						 Todd Gamblin
						Todd Gamblin
					
				
			
			
				
	
			
			
			 Todd Gamblin
						Todd Gamblin
					
				
			
						parent
						
							a474d83d58
						
					
				
				
					commit
					30eda8b837
				
			| @@ -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: | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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,9 +89,6 @@ 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 |  | ||||||
|                         else: |  | ||||||
|                             if beginning_of_phase: |  | ||||||
|                             cdash_phase = \ |                             cdash_phase = \ | ||||||
|                                 map_phases_to_cdash[current_phase] |                                 map_phases_to_cdash[current_phase] | ||||||
|                             if cdash_phase not in phases_encountered: |                             if cdash_phase not in phases_encountered: | ||||||
| @@ -98,10 +96,17 @@ def build_report(self, filename, report_data): | |||||||
|                             report_data[cdash_phase]['log'] += \ |                             report_data[cdash_phase]['log'] += \ | ||||||
|                                 text_type("{0} output for {1}:\n".format( |                                 text_type("{0} output for {1}:\n".format( | ||||||
|                                     cdash_phase, package['name'])) |                                     cdash_phase, package['name'])) | ||||||
|                                 beginning_of_phase = False |                         elif cdash_phase: | ||||||
|                             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()) | ||||||
|   | |||||||
| @@ -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(): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user