summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--morphlib/builder.py112
-rw-r--r--morphlib/stagingarea.py19
-rw-r--r--morphlib/util.py15
-rw-r--r--tests.build/build-chunk-failures-dump-log.stdout2
4 files changed, 80 insertions, 68 deletions
diff --git a/morphlib/builder.py b/morphlib/builder.py
index 038fd5ba..58667159 100644
--- a/morphlib/builder.py
+++ b/morphlib/builder.py
@@ -30,7 +30,6 @@ import cliapp
import morphlib
from morphlib.artifactcachereference import ArtifactCacheReference
-from morphlib.util import error_message_for_containerised_commandline
import morphlib.gitversion
SYSTEM_INTEGRATION_PATH = os.path.join('baserock', 'system-integration')
@@ -297,7 +296,7 @@ class ChunkBuilder(BuilderBase):
if os.path.isfile(temppath):
with open(temppath) as f:
for line in f:
- logging.error('OUTPUT FROM FAILED BUILD: %s' %
+ logging.error('BUILD OUTPUT: %s' %
line.rstrip('\n'))
os.rename(temppath, logpath)
@@ -362,31 +361,37 @@ class ChunkBuilder(BuilderBase):
else:
extra_env['MAKEFLAGS'] = '-j1'
- try:
- # flushing is needed because writes from python and
- # writes from being the output in Popen have different
- # buffers, but flush handles both
- if stdout:
- stdout.flush()
-
- with open(os.devnull) as devnull:
- self.runcmd(['sh', '-x', '-c', cmd],
- extra_env=extra_env,
- cwd=relative_builddir,
- stdin=devnull,
- stdout=stdout or subprocess.PIPE,
- stderr=subprocess.STDOUT,
- logfile=logfilepath,
- ccache_dir=ccache_dir)
-
- if stdout:
- stdout.flush()
- except cliapp.AppException as e:
+ # flushing is needed because writes from python and
+ # writes from being the output in Popen have different
+ # buffers, but flush handles both
+ if stdout:
+ stdout.flush()
+
+ with open(os.devnull) as devnull:
+ exit_code = self.runcmd(['sh', '-x', '-c', cmd],
+ extra_env=extra_env,
+ cwd=relative_builddir,
+ stdin=devnull,
+ stdout=stdout or
+ subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ logfile=logfilepath,
+ ccache_dir=ccache_dir)
+
+ if stdout:
+ stdout.flush()
+
+ if exit_code != 0:
if not stdout:
with open(logfilepath, 'r') as log:
- self.app.output.write("%s failed\n" % step)
shutil.copyfileobj(log, self.app.output)
- raise e
+ self.app.output.write("\n")
+ shutil.copyfile(
+ logfilepath,
+ self.staging_area.dirname + '.log')
+ raise cliapp.AppException(
+ "In staging area %s: %s failed (exit_code=%s)" %
+ (self.staging_area.dirname, step, exit_code))
def write_system_integration_commands(self, destdir,
integration_commands, artifact_name): # pragma: no cover
@@ -565,8 +570,6 @@ class SystemBuilder(BuilderBase): # pragma: no cover
tar.close()
except BaseException as e:
logging.error(traceback.format_exc())
- self.app.status(msg='Error while building system',
- error=True)
handle.abort()
raise
else:
@@ -674,26 +677,45 @@ class SystemBuilder(BuilderBase): # pragma: no cover
('dev/shm', 'tmpfs', 'none'),
('tmp', 'tmpfs', 'none'),
)
- try:
- for bin in sorted(os.listdir(sys_integration_dir)):
- argv = [os.path.join(SYSTEM_INTEGRATION_PATH, bin)]
- container_config = dict(
- root=rootdir, mounts=to_mount, mount_proc=True)
- cmdline = morphlib.util.containerised_cmdline(
- argv, **container_config)
- exit, out, err = self.app.runcmd_unchecked(
- cmdline, env=env)
- if exit != 0:
- logging.debug('Command returned code %i', exit)
- msg = error_message_for_containerised_commandline(
- argv, err, container_config)
- raise cliapp.AppException(msg)
- except BaseException as e:
- self.app.status(
- msg='Error while running system integration commands',
- error=True)
- raise
+ for bin in sorted(os.listdir(sys_integration_dir)):
+ argv = [os.path.join(SYSTEM_INTEGRATION_PATH, bin)]
+ container_config = dict(
+ root=rootdir, mounts=to_mount, mount_proc=True)
+ cmdline = morphlib.util.containerised_cmdline(
+ argv, **container_config)
+
+ logfilepath = os.path.dirname(rootdir) + '.log'
+ teecmd = ['tee', '-a', logfilepath]
+ exit_code, out, err = self.app.runcmd_unchecked(
+ cmdline, teecmd, env=env,
+ stderr=subprocess.STDOUT)
+
+ if exit_code != 0:
+ logging.debug('Command returned code %i', exit_code)
+
+ chroot_script = os.path.dirname(rootdir) + '.sh'
+ shell_command = ['env', '-i', '--']
+ for k, v in env.iteritems():
+ shell_command += ["%s=%s" % (k, v)]
+ shell_command += [os.path.join(os.sep, 'bin', 'sh')]
+ with open(chroot_script, 'w') as f:
+ cmdline = morphlib.util.containerised_cmdline(
+ shell_command, **container_config)
+ f.write(' '.join(map(cliapp.shell_quote, cmdline)))
+
+ with open(logfilepath, 'r') as log:
+ shutil.copyfileobj(log, self.app.output)
+ self.app.output.write("\n")
+ log.seek(0)
+ for line in log:
+ logging.error('INTEGRATION OUTPUT: %s' %
+ line.rstrip('\n'))
+
+ raise cliapp.AppException(
+ "In staging area %s: system integration "
+ "commands failed (exit_code=%s)"
+ % (os.path.dirname(rootdir), exit_code))
class Builder(object): # pragma: no cover
diff --git a/morphlib/stagingarea.py b/morphlib/stagingarea.py
index c8c77229..e244a8d2 100644
--- a/morphlib/stagingarea.py
+++ b/morphlib/stagingarea.py
@@ -314,12 +314,17 @@ class StagingArea(object):
else:
exit, out, err = self._app.runcmd_unchecked(cmdline, **kwargs)
- if exit == 0:
- return out
- else:
+ if exit != 0:
logging.debug('Command returned code %i', exit)
- msg = morphlib.util.error_message_for_containerised_commandline(
- argv, err, container_config)
- raise cliapp.AppException(
- 'In staging area %s: %s' % (self.dirname, msg))
+ chroot_script = self.dirname + '.sh'
+ shell_command = ['env', '-i', '--']
+ for k, v in kwargs['env'].iteritems():
+ shell_command += ["%s=%s" % (k, v)]
+ shell_command += [os.path.join(os.sep, 'bin', 'sh')]
+ cmdline = morphlib.util.containerised_cmdline(
+ shell_command, **container_config)
+ with open(chroot_script, 'w') as f:
+ f.write(' '.join(map(cliapp.shell_quote, cmdline)))
+ return exit
+
diff --git a/morphlib/util.py b/morphlib/util.py
index 2bce6f31..a92b7f37 100644
--- a/morphlib/util.py
+++ b/morphlib/util.py
@@ -649,21 +649,6 @@ def containerised_cmdline(args, cwd='.', root='/', binds=(),
return unshared_cmdline(cmdargs, root=root, **kwargs)
-def error_message_for_containerised_commandline(
- argv, err, container_kwargs): # pragma: no cover
- '''Return a semi-readable error message for a containerised command.'''
-
- # This function should do some formatting of the container_kwargs dict,
- # rather than just dumping it in the error message, but that is better than
- # nothing.
-
- argv_string = ' '.join(map(pipes.quote, argv))
- return 'Command failed: %s:\n' \
- 'Containerisation settings: %s\n' \
- 'Error output:\n%s' \
- % (argv_string, container_kwargs, err)
-
-
def write_from_dict(filepath, d, validate=lambda x, y: True): #pragma: no cover
'''Takes a dictionary and appends the contents to a file
diff --git a/tests.build/build-chunk-failures-dump-log.stdout b/tests.build/build-chunk-failures-dump-log.stdout
index 83c67420..c4d4bf93 100644
--- a/tests.build/build-chunk-failures-dump-log.stdout
+++ b/tests.build/build-chunk-failures-dump-log.stdout
@@ -1,4 +1,3 @@
-build failed
### CONFIGURE-COMMANDS ###
+ echo dummy configure
dummy configure
@@ -6,3 +5,4 @@ dummy configure
+ echo The next command will fail
The next command will fail
+ false
+