f50bb8a1ce
This change fixes the build manager ephemeral executor to tell the overall build server to call set_phase when a build never starts. Before this change, we'd properly adjust the queue item, but not the repo build row or the logs, which is why users just saw "Preparing Build Node", with no indicating the node failed to start. Fixes #1904
78 lines
2.4 KiB
Python
78 lines
2.4 KiB
Python
from data.database import BUILD_PHASE
|
|
from data import model
|
|
from redis import RedisError
|
|
|
|
import datetime
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class StatusHandler(object):
|
|
""" Context wrapper for writing status to build logs. """
|
|
|
|
def __init__(self, build_logs, repository_build_uuid):
|
|
self._current_phase = None
|
|
self._current_command = None
|
|
self._uuid = repository_build_uuid
|
|
self._build_logs = build_logs
|
|
|
|
self._status = {
|
|
'total_commands': 0,
|
|
'current_command': None,
|
|
'push_completion': 0.0,
|
|
'pull_completion': 0.0,
|
|
}
|
|
|
|
# Write the initial status.
|
|
self.__exit__(None, None, None)
|
|
|
|
def _append_log_message(self, log_message, log_type=None, log_data=None):
|
|
log_data = log_data or {}
|
|
log_data['datetime'] = str(datetime.datetime.now())
|
|
|
|
try:
|
|
self._build_logs.append_log_message(self._uuid, log_message, log_type, log_data)
|
|
except RedisError:
|
|
logger.exception('Could not save build log for build %s: %s', self._uuid, log_message)
|
|
|
|
def append_log(self, log_message, extra_data=None):
|
|
if log_message is None:
|
|
return
|
|
|
|
self._append_log_message(log_message, log_data=extra_data)
|
|
|
|
def set_command(self, command, extra_data=None):
|
|
if self._current_command == command:
|
|
return
|
|
|
|
self._current_command = command
|
|
self._append_log_message(command, self._build_logs.COMMAND, extra_data)
|
|
|
|
def set_error(self, error_message, extra_data=None, internal_error=False, requeued=False):
|
|
self.set_phase(BUILD_PHASE.INTERNAL_ERROR if internal_error and requeued else BUILD_PHASE.ERROR)
|
|
|
|
extra_data = extra_data or {}
|
|
extra_data['internal_error'] = internal_error
|
|
self._append_log_message(error_message, self._build_logs.ERROR, extra_data)
|
|
|
|
def set_phase(self, phase, extra_data=None):
|
|
if phase == self._current_phase:
|
|
return False
|
|
|
|
self._current_phase = phase
|
|
self._append_log_message(phase, self._build_logs.PHASE, extra_data)
|
|
|
|
# Update the repository build with the new phase
|
|
repo_build = model.build.get_repository_build(self._uuid)
|
|
repo_build.phase = phase
|
|
repo_build.save()
|
|
return True
|
|
|
|
def __enter__(self):
|
|
return self._status
|
|
|
|
def __exit__(self, exc_type, value, traceback):
|
|
try:
|
|
self._build_logs.set_status(self._uuid, self._status)
|
|
except RedisError:
|
|
logger.exception('Could not set status of build %s to %s', self._uuid, self._status)
|