blob: 3231a6ed79d13eae3a50093c3a5e7e40906c5550 [file] [log] [blame]
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Provide a BuilderRun class for collecting info on one builder run."""
import os
from chromite.buildbot import manifest_version
class RunAttributes(object):
"""Hold all run attributes for a particular builder run."""
# A word of warning about the way run attributes currently work. The
# value set (or altered) by a given stage can be seen by any subsequent
# stage, including stages on child processes. Any value set (or
# altered) by a stage in a subprocess will not be seen by co-subprocesses
# (other stages being run in parallel at the same time) and will
# be *discarded* when that subprocess ends (and parent process resumes).
# This is expected behavior for forked processes.
# TODO(mtennant): Possibly design a mechanism to preserve run attribute
# changes in subprocess stages for subsequent stages (but probably not for
# co-subprocess stages).
__slots__ = (
'manifest_manager', # Set by ManifestVersionedSyncStage.
'release_tag', # Set by ManifestVersionedSyncStage.
)
class BuilderRun(object):
"""Class to represent one run of a builder."""
# Class-level dict of RunAttributes objects to make it less
# problematic to send BuilderRun objects between processes through
# pickle. The 'attrs' attribute on a BuilderRun object will look
# up the RunAttributes for that particular BuilderRun here.
_ATTRS = {}
__slots__ = (
'config', # BuildConfig for this run.
'options', # The cbuildbot options object for this run.
# Run attributes set/accessed by stages during the run. To add support
# for a new run attribute add it to the RunAttributes class above.
'_attrs_id',
# Some pre-computed run configuration values.
'buildnumber', # The build number for this run.
'buildroot', # The build root path for this run.
'manifest_branch', # The manifest branch to build and test for this run.
# TODO(mtennant): Other candidates here include:
# trybot, buildbot, remote_trybot, chrome_root, chrome_version,
# test = (config build_tests AND option tests)
)
def __init__(self, options, build_config):
self.options = options
self.config = build_config
# Create the RunAttributes object for this BuilderRun and save
# the id number for it in order to look it up via attrs property.
attrs = RunAttributes()
self._ATTRS[id(attrs)] = attrs
self._attrs_id = id(attrs)
# Fill in values for all pre-computed "run configs" now, which are frozen
# by this time.
# TODO(mtennant): Should this use os.path.abspath like builderstage does?
self.buildroot = self.options.buildroot
self.buildnumber = self.options.buildnumber
self.manifest_branch = self.options.branch
@property
def attrs(self):
"""Look up the RunAttributes object for this BuilderRun object."""
return self._ATTRS[self._attrs_id]
def ShouldUploadPrebuilts(self):
"""Return True if this run should upload prebuilts."""
return self.options.prebuilts and self.config.prebuilts
def ShouldReexecAfterSync(self):
"""Return True if this run should re-exec itself after sync stage."""
if self.options.postsync_reexec and self.config.postsync_reexec:
# Return True if this source is not in designated buildroot.
abs_buildroot = os.path.abspath(self.buildroot)
return not os.path.abspath(__file__).startswith(abs_buildroot)
return False
def ShouldPatchAfterSync(self):
"""Return True if this run should patch changes after sync stage."""
return self.options.postsync_patch and self.config.postsync_patch
@classmethod
def GetVersionInfo(cls, buildroot):
"""Helper for picking apart various version bits.
This method only exists so that tests can override it.
"""
return manifest_version.VersionInfo.from_repo(buildroot)
def GetVersion(self):
"""Calculate full R<chrome_version>-<chromeos_version> version string."""
verinfo = self.GetVersionInfo(self.buildroot)
if hasattr(self.attrs, 'release_tag'):
calc_version = 'R%s-%s' % (verinfo.chrome_branch,
self.attrs.release_tag)
else:
# Non-versioned builds need the build number to uniquify the image.
calc_version = 'R%s-%s-b%s' % (verinfo.chrome_branch,
verinfo.VersionString(),
self.buildnumber)
return calc_version
class ChildBuilderRun(object):
"""A BuilderRun for a "child" build config, overriding self.config."""
__slots__ = BuilderRun.__slots__ + (
'_builder_run', # The full (master) BuilderRun.
'config', # The child BuildConfig for this ChildBuilderRun.
'child_index', # Index into self.full_config.child_configs.
)
def __init__(self, builder_run, child_index):
self._builder_run = builder_run
self.child_index = child_index
self.config = builder_run.config.child_configs[child_index]
def __getattr__(self, attr):
# Remember, __getattr__ only called if attribute was not found normally.
# Point at self._builder_run, but access self._builder_run in a way that
# does not cause infinite recursion.
full_builder_run = self.__getattribute__('_builder_run')
return getattr(full_builder_run, attr)